# Fossil

Check-in Differences

## Difference From release To trunk

 2020-01-22 19:08 Update the built-in SQLite to version 3.31.0. Leaf check-in: eee161e8 user: drh tags: trunk 00:44 Added missing APPNAME to Makefile.classic, as reported in the forum. check-in: a6ee6add user: stephan tags: trunk 2019-10-04 22:20 Fix the date on the 2.10 change log. check-in: 80ea65af user: drh tags: trunk 21:41 Version 2.10 check-in: 9d9ef822 user: drh tags: trunk, release, version-2.10 15:44 Update the built-in SQLite to the 3.30.0 release version. check-in: fc19d369 user: drh tags: trunk

Changes to .editorconfig.

 6 7 8 9 10 11 12 # Defaults for all files [*] end_of_line = lf insert_final_newline = true indent_style = space indent_size = 2 > > 6 7 8 9 10 11 12 13 14 # Defaults for all files [*] end_of_line = lf insert_final_newline = true indent_style = space indent_size = 2 [{Makefile,Makefile.*,*.mk}] indent_style = tab

Changes to Makefile.classic.

 97 98 99 100 101 102 103 104 105 LIB += $(LIB.$(HOST_OS)) TCC.DragonFly += -DUSE_PREAD TCC.FreeBSD += -DUSE_PREAD TCC.NetBSD += -DUSE_PREAD TCC.OpenBSD += -DUSE_PREAD TCC += $(TCC.$(HOST_OS)) include $(SRCDIR)/main.mk > > 97 98 99 100 101 102 103 104 105 106 107 LIB +=$(LIB.$(HOST_OS)) TCC.DragonFly += -DUSE_PREAD TCC.FreeBSD += -DUSE_PREAD TCC.NetBSD += -DUSE_PREAD TCC.OpenBSD += -DUSE_PREAD TCC +=$(TCC.$(HOST_OS)) APPNAME = fossil$(E) include (SRCDIR)/main.mk Changes to VERSION.  1 2.1 | 1 2.11 Changes to skins/ardoise/css.txt.  800 801 802 803 804 805 806 807 808 809 810 811 812 813 ul.browser li.file:hover, ul.browser li.file:hover * { background-color: #333 } td.browser, td.tktDescLabel { vertical-align: top } div.filetreeline { display: table; width: 100%; white-space: nowrap } .filetree { > > > > > > 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 ul.browser li.file:hover, ul.browser li.file:hover * { background-color: #333 } td.browser, td.tktDescLabel { vertical-align: top } td.tktTlOpen { color: #ffa0a0; } td.tktTlClosed { color: #555; } div.filetreeline { display: table; width: 100%; white-space: nowrap } .filetree { Changes to skins/eagle/css.txt.  286 287 288 289 290 291 292 293 294 295 296 297 298 299 /* format for values on ticket display page */ td.tktDspValue { text-align: left; vertical-align: top; background-color: #485D7B; } /* format for example table cells on the report edit page */ td.rpteditex { border-width: thin; border-color: white; border-style: solid; } > > > > > > > > 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 /* format for values on ticket display page */ td.tktDspValue { text-align: left; vertical-align: top; background-color: #485D7B; } /* Ticket display on timelines */ td.tktTlOpen { color: #ffc0c0; } td.tktTlClose { color: #c0c0c0; } /* format for example table cells on the report edit page */ td.rpteditex { border-width: thin; border-color: white; border-style: solid; } Changes to skins/xekri/css.txt.  693 694 695 696 697 698 699 700 701 702 703 704 705 706 /* format for values on ticket display page */ td.tktDspValue { background-color: #111; text-align: left; vertical-align: top; } /* format for ticket error messages */ span.tktError { color: #f00; font-weight: bold; } > > > > > 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 /* format for values on ticket display page */ td.tktDspValue { background-color: #111; text-align: left; vertical-align: top; } /* Tickets on timelines */ td.tktTlOpen { color: #ffa0a0; } /* format for ticket error messages */ span.tktError { color: #f00; font-weight: bold; } Changes to src/add.c.  934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 ... 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 int nOrig; file_tree_name(g.argv[i], &orig, 0, 1); zOrig = blob_str(&orig); nOrig = blob_size(&orig); db_prepare(&q, "SELECT pathname FROM vfile" " WHERE vid=%d" " AND (pathname='%q' %s OR (pathname>'%q/' %s AND pathname<'%q0' %s))" " ORDER BY 1", vid, zOrig, filename_collation(), zOrig, filename_collation(), zOrig, filename_collation() ); while( db_step(&q)==SQLITE_ROW ){ const char *zPath = db_column_text(&q, 0); int nPath = db_column_bytes(&q, 0); ................................................................................ while( db_step(&q)==SQLITE_ROW ){ const char *zFrom = db_column_text(&q, 0); const char *zTo = db_column_text(&q, 1); mv_one_file(vid, zFrom, zTo, dryRunFlag); if( moveFiles ) add_file_to_move(zFrom, zTo); } db_finalize(&q); db_end_transaction(0); if( moveFiles ) process_files_to_move(dryRunFlag); } /* ** Function for stash_apply to be able to restore a file and indicate ** newly ADDED state. */ int stash_add_files_in_sfile(int vid){ return add_files_in_sfile(vid); } | > 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 ... 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 int nOrig; file_tree_name(g.argv[i], &orig, 0, 1); zOrig = blob_str(&orig); nOrig = blob_size(&orig); db_prepare(&q, "SELECT pathname FROM vfile" " WHERE vid=%d" " AND (pathname='%q' %s OR (pathname>'%q/' %s AND pathname<'%q0' %s))" " ORDER BY 1", vid, zOrig, filename_collation(), zOrig, filename_collation(), zOrig, filename_collation() ); while( db_step(&q)==SQLITE_ROW ){ const char *zPath = db_column_text(&q, 0); int nPath = db_column_bytes(&q, 0); ................................................................................ while( db_step(&q)==SQLITE_ROW ){ const char *zFrom = db_column_text(&q, 0); const char *zTo = db_column_text(&q, 1); mv_one_file(vid, zFrom, zTo, dryRunFlag); if( moveFiles ) add_file_to_move(zFrom, zTo); } db_finalize(&q); undo_reset(); db_end_transaction(0); if( moveFiles ) process_files_to_move(dryRunFlag); } /* ** Function for stash_apply to be able to restore a file and indicate ** newly ADDED state. */ int stash_add_files_in_sfile(int vid){ return add_files_in_sfile(vid); } Changes to src/alerts.c.  2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 const char *zFrom; const char *zSub; /* First do non-forum post events */ db_prepare(&q, "SELECT" " blob.uuid," /* 0 */ " datetime(event.mtime)," /* 1 */ " coalesce(ecomment,comment)" " || ' (user: ' || coalesce(euser,user,'?')" " || (SELECT case when length(x)>0 then ' tags: ' || x else '' end" " FROM (SELECT group_concat(substr(tagname,5), ', ') AS x" " FROM tag, tagxref" " WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid" | > > > 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 const char *zFrom; const char *zSub; /* First do non-forum post events */ db_prepare(&q, "SELECT" " CASE WHEN event.type='t'" " THEN (SELECT substr(tagname,5) FROM tag" " WHERE tagid=event.tagid AND tagname LIKE 'tkt-%%')" " ELSE blob.uuid END," /* 0 */ " datetime(event.mtime)," /* 1 */ " coalesce(ecomment,comment)" " || ' (user: ' || coalesce(euser,user,'?')" " || (SELECT case when length(x)>0 then ' tags: ' || x else '' end" " FROM (SELECT group_concat(substr(tagname,5), ', ') AS x" " FROM tag, tagxref" " WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid" Changes to src/bag.c.  46 47 48 49 50 51 52 53 54 55 56 57 58 59 */ struct Bag { int cnt; /* Number of integers in the bag */ int sz; /* Number of slots in a[] */ int used; /* Number of used slots in a[] */ int *a; /* Hash table of integers that are in the bag */ }; #endif /* ** Initialize a Bag structure */ void bag_init(Bag *p){ memset(p, 0, sizeof(*p)); > > > > > > 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 */ struct Bag { int cnt; /* Number of integers in the bag */ int sz; /* Number of slots in a[] */ int used; /* Number of used slots in a[] */ int *a; /* Hash table of integers that are in the bag */ }; /* ** An expression for statically initializing a Bag instance, to be ** assigned to Bag instances at their declaration point. It has ** the same effect as passing the Bag to bag_init(). */ #define Bag_INIT {0,0,0,0} #endif /* ** Initialize a Bag structure */ void bag_init(Bag *p){ memset(p, 0, sizeof(*p)); Changes to src/cgi.c.  348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 ... 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 .... 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 .... 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 .... 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 .... 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 size = blob_size(&cgiContent[i]); if( size>0 ){ fwrite(blob_buffer(&cgiContent[i]), 1, size, g.httpOut); } } } fflush(g.httpOut); CGIDEBUG(("DONE\n")); /* After the webpage has been sent, do any useful background ** processing. */ g.cgiOutput = 2; if( g.db!=0 && iReplyStatus==200 ){ backoffice_check_if_needed(); ................................................................................ char *z; const char *zType; char *zSemi; int len; const char *zRequestUri = cgi_parameter("REQUEST_URI",0); const char *zScriptName = cgi_parameter("SCRIPT_NAME",0); const char *zPathInfo = cgi_parameter("PATH_INFO",0); #ifdef FOSSIL_ENABLE_JSON int noJson = P("no_json")!=0; if( noJson==0 ){ json_main_bootstrap(); } #endif g.isHTTP = 1; cgi_destination(CGI_BODY); if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME"); if( zRequestUri==0 ){ const char *z = zPathInfo; if( zPathInfo==0 ){ malformed_request("missing PATH_INFO and/or REQUEST_URI"); } if( z[0]=='/' ) z++; zRequestUri = mprintf("%s/%s", zScriptName, z); ................................................................................ if( j\n", zName, aParamQP[i].zValue); } } } /* ** Export all untagged query parameters (but not cookies or environment ** variables) as hidden values of a form. ................................................................................ return mprintf(""); }else{ return mprintf("%s, %d %s %02d %02d:%02d:%02d +0000", azDays[pTm->tm_wday], pTm->tm_mday, azMonths[pTm->tm_mon], pTm->tm_year+1900, pTm->tm_hour, pTm->tm_min, pTm->tm_sec); } } /* ** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return ** a Unix epoch time. <= zero is returned on failure. ** ** Note that this won't handle all the _allowed_ HTTP formats, just the ** most popular one (the one generated by cgi_rfc822_datestamp(), actually). | > > > > > > > > > > > > > > > > > > > > > | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > | | > > > > > | < > > > | > > > > > > > > > > > > > > > > > > > > > > 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 ... 995 996 997 998 999 1000 1001 1002 1003 1004 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 .... 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 .... 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 .... 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 .... 2123 2124 2125 2126 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 size = blob_size(&cgiContent[i]); if( size>0 ){ fwrite(blob_buffer(&cgiContent[i]), 1, size, g.httpOut); } } } fflush(g.httpOut); CGIDEBUG(("-------- END cgi ---------\n")); /* After the webpage has been sent, do any useful background ** processing. */ g.cgiOutput = 2; if( g.db!=0 && iReplyStatus==200 ){ backoffice_check_if_needed(); ................................................................................ char *z; const char *zType; char *zSemi; int len; const char *zRequestUri = cgi_parameter("REQUEST_URI",0); const char *zScriptName = cgi_parameter("SCRIPT_NAME",0); const char *zPathInfo = cgi_parameter("PATH_INFO",0); #ifdef _WIN32 const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0); #endif #ifdef FOSSIL_ENABLE_JSON int noJson = P("no_json")!=0; if( noJson==0 ){ json_main_bootstrap(); } #endif g.isHTTP = 1; cgi_destination(CGI_BODY); if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME"); #ifdef _WIN32 /* The Microsoft IIS web server does not define REQUEST_URI, instead it uses ** PATH_INFO for virtually the same purpose. Define REQUEST_URI the same as ** PATH_INFO and redefine PATH_INFO with SCRIPT_NAME removed from the ** beginning. */ if( zServerSoftware && strstr(zServerSoftware, "Microsoft-IIS") ){ int i, j; cgi_set_parameter("REQUEST_URI", zPathInfo); for(i=0; zPathInfo[i]==zScriptName[i] && zPathInfo[i]; i++){} for(j=i; zPathInfo[j] && zPathInfo[j]!='?'; j++){} zPathInfo = mprintf("%.*s", j-i, zPathInfo+i); cgi_replace_parameter("PATH_INFO", zPathInfo); } #endif if( zRequestUri==0 ){ const char *z = zPathInfo; if( zPathInfo==0 ){ malformed_request("missing PATH_INFO and/or REQUEST_URI"); } if( z[0]=='/' ) z++; zRequestUri = mprintf("%s/%s", zScriptName, z); ................................................................................ if( j\n", zName, aParamQP[i].zValue); break; } case 1: { fossil_trace("%s = %s\n", zName, aParamQP[i].zValue); break; } case 2: { cgi_debug("%s = %s\n", zName, aParamQP[i].zValue); break; } } } } /* ** Export all untagged query parameters (but not cookies or environment ** variables) as hidden values of a form. ................................................................................ return mprintf(""); }else{ return mprintf("%s, %d %s %02d %02d:%02d:%02d +0000", azDays[pTm->tm_wday], pTm->tm_mday, azMonths[pTm->tm_mon], pTm->tm_year+1900, pTm->tm_hour, pTm->tm_min, pTm->tm_sec); } } /* ** Returns an ISO8601-formatted time string suitable for debugging ** purposes. ** ** The value returned is always a string obtained from mprintf() and must ** be freed using fossil_free() to avoid a memory leak. */ char *cgi_iso8601_datestamp(void){ struct tm *pTm; time_t now = time(0); pTm = gmtime(&now); if( pTm==0 ){ return mprintf(""); }else{ return mprintf("%04d-%02d-%02d %02d:%02d:%02d", pTm->tm_year+1900, pTm->tm_mon, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec); } } /* ** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return ** a Unix epoch time. <= zero is returned on failure. ** ** Note that this won't handle all the _allowed_ HTTP formats, just the ** most popular one (the one generated by cgi_rfc822_datestamp(), actually). Changes to src/config.h.  175 176 177 178 179 180 181 182 183 184 185 186 187 188 #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION) /* ** MSVC does not include the "stdint.h" header file until 2010. */ #if defined(_MSC_VER) && _MSC_VER<1600 typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #else # include #endif > > 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION) /* ** MSVC does not include the "stdint.h" header file until 2010. */ #if defined(_MSC_VER) && _MSC_VER<1600 typedef __int8 int8_t; typedef unsigned __int8 uint8_t; typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #else # include #endif Changes to src/content.c.  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 contentCache.szTotal += blob_size(pBlob); p->content = *pBlob; blob_zero(pBlob); bag_insert(&contentCache.inCache, rid); } /* ** Clear the content cache. */ void content_clear_cache(void){ int i; for(i=0; i > | > > > > > 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 contentCache.szTotal += blob_size(pBlob); p->content = *pBlob; blob_zero(pBlob); bag_insert(&contentCache.inCache, rid); } /* ** Clear the content cache. If it is passed true, it ** also frees all associated memory, otherwise it may ** retain parts for future uses of the cache. */ void content_clear_cache(int bFreeIt){ int i; for(i=0; i Changes to src/db.c.  1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 .... 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 .... 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 .... 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 .... 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 const char *db_repository_filename(void){ static char *zRepo = 0; assert( g.localOpen ); assert( g.zLocalRoot ); if( zRepo==0 ){ zRepo = db_lget("repository", 0); if( zRepo && !file_is_absolute_path(zRepo) ){ zRepo = mprintf("%s%s", g.zLocalRoot, zRepo); } } return zRepo; } /* ** Returns non-zero if the default value for the "allow-symlinks" setting ................................................................................ db_swap_connections(); z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName); db_swap_connections(); } if( pSetting!=0 && pSetting->versionable ){ /* This is a versionable setting, try and get the info from a ** checked out file */ z = db_get_versioned(zName, z); } if( z==0 ){ if( zDefault==0 && pSetting && pSetting->def[0] ){ z = fossil_strdup(pSetting->def); }else{ z = fossil_strdup(zDefault); } ................................................................................ /* ** Define all settings, which can be controlled via the set/unset ** command. ** ** var is the name of the internal configuration name for db_(un)set. ** If var is 0, the settings name is used. ** ** width is the length for the edit field on the behavior page, 0 ** is used for on/off checkboxes. ** ** The behaviour page doesn't use a special layout. It lists all ** set-commands and displays the 'set'-help as info. */ struct Setting { const char *name; /* Name of the setting */ const char *var; /* Internal variable name used by db_set() */ int width; /* Width of display. 0 for boolean values. */ int versionable; /* Is this setting versionable? */ int forceTextArea; /* Force using a text area for display? */ const char *def; /* Default value */ }; #endif /* INTERFACE */ /* ................................................................................ /* ** SETTING: proxy width=32 default=off ** URL of the HTTP proxy. If undefined or "off" then ** the "http_proxy" environment variable is consulted. ** If the http_proxy environment variable is undefined ** then a direct HTTP connection is used. */ /* ** SETTING: relative-paths boolean default=on ** When showing changes and extras, report paths relative ** to the current working directory. */ /* ** SETTING: repo-cksum boolean default=on ................................................................................ int rcvid = 0; db_find_and_open_repository(OPEN_ANY_SCHEMA,0); if( g.argc==3 ){ rcvid = atoi(g.argv[2]); }else if( g.argc!=2 ){ fossil_fatal("wrong number of arguments"); } fossil_print("legecy: %z\n", db_fingerprint(rcvid, 0)); fossil_print("version-1: %z\n", db_fingerprint(rcvid, 1)); if( g.localOpen ){ fossil_print("localdb: %z\n", db_lget("fingerprint","(none)")); fossil_print("db_fingerprint_ok(): %d\n", db_fingerprint_ok()); } } /* ** Set the value of the "checkout" entry in the VVAR table. ** ** Also set "fingerprint" and "checkout-hash". */ void db_set_checkout(int rid){ char *z; db_lset_int("checkout", rid); z = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid); db_lset("checkout-hash", z); fossil_free(z); z = db_fingerprint(0, 1); db_lset("fingerprint", z); fossil_free(z); } /* ** Verify that the fingerprint recorded in the "fingerprint" entry ** of the VVAR table matches the fingerprint on the currently ** connected repository. Return true if the fingerprint is ok, and ** return false if the fingerprint does not match. */ int db_fingerprint_ok(void){ char *zCkout; /* The fingerprint recorded in the checkout database */ char *zRepo; /* The fingerprint of the repository */ int rc; /* Result */ zCkout = db_text(0,"SELECT value FROM localdb.vvar WHERE name='fingerprint'"); if( zCkout==0 ){ /* This is an older checkout that does not record a fingerprint. ** We have to assume everything is ok */ return 2; } zRepo = db_fingerprint(atoi(zCkout), 1); > > > > > > | | > > > | > > > > > > > > > | > > > | | | | | | > > > > > 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 .... 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 .... 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 .... 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 .... 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 const char *db_repository_filename(void){ static char *zRepo = 0; assert( g.localOpen ); assert( g.zLocalRoot ); if( zRepo==0 ){ zRepo = db_lget("repository", 0); if( zRepo && !file_is_absolute_path(zRepo) ){ char * zFree = zRepo; zRepo = mprintf("%s%s", g.zLocalRoot, zRepo); fossil_free(zFree); } } return zRepo; } /* ** Returns non-zero if the default value for the "allow-symlinks" setting ................................................................................ db_swap_connections(); z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName); db_swap_connections(); } if( pSetting!=0 && pSetting->versionable ){ /* This is a versionable setting, try and get the info from a ** checked out file */ char * zZ = z; z = db_get_versioned(zName, z); if(zZ != z){ fossil_free(zZ); } } if( z==0 ){ if( zDefault==0 && pSetting && pSetting->def[0] ){ z = fossil_strdup(pSetting->def); }else{ z = fossil_strdup(zDefault); } ................................................................................ /* ** Define all settings, which can be controlled via the set/unset ** command. ** ** var is the name of the internal configuration name for db_(un)set. ** If var is 0, the settings name is used. ** ** width is the length for the edit field on the behavior page, 0 is ** used for on/off checkboxes. A negative value indicates that that ** page should not render this setting. Such values may be rendered ** separately/manually on another page, e.g., /setup_access, and are ** exposed via the CLI settings command. ** ** The behaviour page doesn't use a special layout. It lists all ** set-commands and displays the 'set'-help as info. */ struct Setting { const char *name; /* Name of the setting */ const char *var; /* Internal variable name used by db_set() */ int width; /* Width of display. 0 for boolean values and ** negative for values which should not appear ** on the /setup_settings page. */ int versionable; /* Is this setting versionable? */ int forceTextArea; /* Force using a text area for display? */ const char *def; /* Default value */ }; #endif /* INTERFACE */ /* ................................................................................ /* ** SETTING: proxy width=32 default=off ** URL of the HTTP proxy. If undefined or "off" then ** the "http_proxy" environment variable is consulted. ** If the http_proxy environment variable is undefined ** then a direct HTTP connection is used. */ /* ** SETTING: redirect-to-https default=0 width=-1 ** Specifies whether or not to redirect http:// requests to ** https:// URIs. A value of 0 (the default) means not to ** redirect, 1 means to redirect only the /login page, and 2 ** means to always redirect. */ /* ** SETTING: relative-paths boolean default=on ** When showing changes and extras, report paths relative ** to the current working directory. */ /* ** SETTING: repo-cksum boolean default=on ................................................................................ int rcvid = 0; db_find_and_open_repository(OPEN_ANY_SCHEMA,0); if( g.argc==3 ){ rcvid = atoi(g.argv[2]); }else if( g.argc!=2 ){ fossil_fatal("wrong number of arguments"); } fossil_print("legacy: %z\n", db_fingerprint(rcvid, 0)); fossil_print("version-1: %z\n", db_fingerprint(rcvid, 1)); if( g.localOpen ){ fossil_print("localdb: %z\n", db_lget("fingerprint","(none)")); fossil_print("db_fingerprint_ok(): %d\n", db_fingerprint_ok()); } fossil_print("Fossil version: %s - %.10s %.19s\n", RELEASE_VERSION, MANIFEST_DATE, MANIFEST_UUID); } /* ** Set the value of the "checkout" entry in the VVAR table. ** ** Also set "fingerprint" and "checkout-hash". */ void db_set_checkout(int rid){ char *z; db_lset_int("checkout", rid); if (rid != 0) { z = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid); db_lset("checkout-hash", z); fossil_free(z); z = db_fingerprint(0, 1); db_lset("fingerprint", z); fossil_free(z); } } /* ** Verify that the fingerprint recorded in the "fingerprint" entry ** of the VVAR table matches the fingerprint on the currently ** connected repository. Return true if the fingerprint is ok, and ** return false if the fingerprint does not match. */ int db_fingerprint_ok(void){ char *zCkout; /* The fingerprint recorded in the checkout database */ char *zRepo; /* The fingerprint of the repository */ int rc; /* Result */ if( !db_lget_int("checkout", 0) ){ /* We have an empty checkout, fingerprint is still NULL. */ return 2; } zCkout = db_text(0,"SELECT value FROM localdb.vvar WHERE name='fingerprint'"); if( zCkout==0 ){ /* This is an older checkout that does not record a fingerprint. ** We have to assume everything is ok */ return 2; } zRepo = db_fingerprint(atoi(zCkout), 1); Changes to src/default_css.txt.  453 454 455 456 457 458 459 460 461 462 463 464 465 466 td.tktDspLabel { text-align: right; } td.tktDspValue { text-align: left; vertical-align: top; background-color: #d0d0d0; } span.tktError { color: red; font-weight: bold; } table.rpteditex { float: right; > > > > > > 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 td.tktDspLabel { text-align: right; } td.tktDspValue { text-align: left; vertical-align: top; background-color: #d0d0d0; } td.tktTlOpen { color: #800; } td.tktTlClosed { color: #888; } span.tktError { color: red; font-weight: bold; } table.rpteditex { float: right; Changes to src/doc.c.  37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 ... 267 268 269 270 271 272 273 274 275 276 277 278 279 280 ... 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 ... 624 625 626 627 628 629 630 631 632 633 634 635 636 637 ... 694 695 696 697 698 699 700 701 702 703 704 705 706 707 int n; const unsigned char *x; /* A table of mimetypes based on file content prefixes */ static const struct { const char *zPrefix; /* The file prefix */ int size; /* Length of the prefix */ const char *zMimetype; /* The corresponding mimetype */ } aMime[] = { { "GIF87a", 6, "image/gif" }, { "GIF89a", 6, "image/gif" }, { "\211PNG\r\n\032\n", 8, "image/png" }, { "\377\332\377", 3, "image/jpeg" }, { "\377\330\377", 3, "image/jpeg" }, ................................................................................ { "vcd", 3, "application/x-cdlink" }, { "vda", 3, "application/vda" }, { "viv", 3, "video/vnd.vivo" }, { "vivo", 4, "video/vnd.vivo" }, { "vrml", 4, "model/vrml" }, { "wav", 3, "audio/x-wav" }, { "wax", 3, "audio/x-ms-wax" }, { "wiki", 4, "text/x-fossil-wiki" }, { "wma", 3, "audio/x-ms-wma" }, { "wmv", 3, "video/x-ms-wmv" }, { "wmx", 3, "video/x-ms-wmx" }, { "wrl", 3, "model/vrml" }, { "wvx", 3, "video/x-ms-wvx" }, { "xbm", 3, "image/x-xbitmap" }, ................................................................................ rid = db_int(0, "SELECT rid FROM vcache" " WHERE vid=%d AND fname=%Q", vid, zName); if( rid && content_get(rid, pContent)==0 ){ rid = 0; } return rid; } /* ** Transfer content to the output. During the transfer, when text of ** the following form is seen: ** ** href="ROOT/ ** action="$ROOT/ ** ** Convert$ROOT to the root URI of the repository. Allow ' in place of " ** and any case for href or action. */ void convert_href_and_output(Blob *pIn){ int i, base; int n = blob_size(pIn); char *z = blob_buffer(pIn); for(base=0, i=7; i=9 && ((fossil_strnicmp(&z[i-6],"href=",5)==0 && fossil_isspace(z[i-7])) || (fossil_strnicmp(&z[i-8],"action=",7)==0 && fossil_isspace(z[i-9])) ) ){ blob_append(cgi_output_blob(), &z[base], i-base); blob_appendf(cgi_output_blob(), "%R"); base = i+5; } } blob_append(cgi_output_blob(), &z[base], i-base); } /* ** Render a document as the reply to the HTTP request. The body ................................................................................ ** particular check, or the name of a branch (meaning the most recent ** check-in on that branch) or one of various magic words: ** ** "tip" means the most recent check-in ** ** "ckout" means the current check-out, if the server is run from ** within a check-out, otherwise it is the same as "tip" ** ** FILE is the name of a file to delivered up as a webpage. FILE is relative ** to the root of the source tree of the repository. The FILE must ** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read ** directly from disk and need not be a managed file. ** ** The "ckout" CHECKIN is intended for development - to provide a mechanism ................................................................................ i = 0; }else{ if( zName==0 || zName[0]==0 ) zName = "tip/index.wiki"; for(i=0; zName[i] && zName[i]!='/'; i++){} zCheckin = mprintf("%.*s", i, zName); if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ zCheckin = "tip"; } } if( nMiss==count(azSuffix) ){ zName = "404.md"; zDfltTitle = "Not Found"; }else if( zName[i]==0 ){ assert( nMiss>=0 && nMiss > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 ... 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 ... 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 ... 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 ... 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 int n; const unsigned char *x; /* A table of mimetypes based on file content prefixes */ static const struct { const char *zPrefix; /* The file prefix */ const int size; /* Length of the prefix */ const char *zMimetype; /* The corresponding mimetype */ } aMime[] = { { "GIF87a", 6, "image/gif" }, { "GIF89a", 6, "image/gif" }, { "\211PNG\r\n\032\n", 8, "image/png" }, { "\377\332\377", 3, "image/jpeg" }, { "\377\330\377", 3, "image/jpeg" }, ................................................................................ { "vcd", 3, "application/x-cdlink" }, { "vda", 3, "application/vda" }, { "viv", 3, "video/vnd.vivo" }, { "vivo", 4, "video/vnd.vivo" }, { "vrml", 4, "model/vrml" }, { "wav", 3, "audio/x-wav" }, { "wax", 3, "audio/x-ms-wax" }, { "webp", 4, "image/webp" }, { "wiki", 4, "text/x-fossil-wiki" }, { "wma", 3, "audio/x-ms-wma" }, { "wmv", 3, "video/x-ms-wmv" }, { "wmx", 3, "video/x-ms-wmx" }, { "wrl", 3, "model/vrml" }, { "wvx", 3, "video/x-ms-wvx" }, { "xbm", 3, "image/x-xbitmap" }, ................................................................................ rid = db_int(0, "SELECT rid FROM vcache" " WHERE vid=%d AND fname=%Q", vid, zName); if( rid && content_get(rid, pContent)==0 ){ rid = 0; } return rid; } /* ** Check to verify that z[i] is contained within HTML markup. ** ** This works by looking backwards in the string for the most recent ** '<' or '>' character. If a '<' is found first, then we assume that ** z[i] is within markup. If a '>' is seen or neither character is seen, ** then z[i] is not within markup. */ static int isWithinHtmlMarkup(const char *z, int i){ while( i>=0 && z[i]!='>' && z[i]!='<' ){ i--; } return z[i]=='<'; } /* ** Check to see if z[i] is contained within an href='...' of markup. */ static int isWithinHref(const char *z, int i){ while( i>5 && !fossil_isspace(z[i]) && z[i]!='\'' && z[i]!='"' && z[i]!='>' ){ i--; } if( i<=6 ) return 0; if( z[i]!='\'' && z[i]!='\"' ) return 0; if( strncmp(&z[i-5],"href=",5)!=0 ) return 0; if( !fossil_isspace(z[i-6]) ) return 0; return 1; } /* ** Transfer content to the output. During the transfer, when text of ** the following form is seen: ** ** href="$ROOT/..." ** action="$ROOT/..." ** href=".../doc/$SELF/..." ** ** Convert$ROOT to the root URI of the repository, and $SELF to the ** version number of the /doc/ document currently being displayed (if any). ** Allow ' in place of " and any case for href or action. ** ** Efforts are made to limit this translation to cases where the text is ** fully contained with an HTML markup element. */ void convert_href_and_output(Blob *pIn){ int i, base; int n = blob_size(pIn); char *z = blob_buffer(pIn); for(base=0, i=7; i=9 && ((fossil_strnicmp(&z[i-6],"href=",5)==0 && fossil_isspace(z[i-7])) || (fossil_strnicmp(&z[i-8],"action=",7)==0 && fossil_isspace(z[i-9])) ) && isWithinHtmlMarkup(z, i-6) ){ blob_append(cgi_output_blob(), &z[base], i-base); blob_appendf(cgi_output_blob(), "%R"); base = i+5; }else if( z[i]=='$' && strncmp(&z[i-5],"/doc/$SELF/", 11)==0 && isWithinHref(z,i-5) && isWithinHtmlMarkup(z, i-5) && strncmp(g.zPath, "doc/",4)==0 ){ int j; for(j=4; g.zPath[j] && g.zPath[j]!='/'; j++){} blob_append(cgi_output_blob(), &z[base], i-base); blob_appendf(cgi_output_blob(), "%.*s", j-4, g.zPath+4); base = i+5; } } blob_append(cgi_output_blob(), &z[base], i-base); } /* ** Render a document as the reply to the HTTP request. The body ................................................................................ ** particular check, or the name of a branch (meaning the most recent ** check-in on that branch) or one of various magic words: ** ** "tip" means the most recent check-in ** ** "ckout" means the current check-out, if the server is run from ** within a check-out, otherwise it is the same as "tip" ** ** "latest" means use the most recent check-in for the document ** regardless of what branch it occurs on. ** ** FILE is the name of a file to delivered up as a webpage. FILE is relative ** to the root of the source tree of the repository. The FILE must ** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read ** directly from disk and need not be a managed file. ** ** The "ckout" CHECKIN is intended for development - to provide a mechanism ................................................................................ i = 0; }else{ if( zName==0 || zName[0]==0 ) zName = "tip/index.wiki"; for(i=0; zName[i] && zName[i]!='/'; i++){} zCheckin = mprintf("%.*s", i, zName); if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ zCheckin = "tip"; }else if( fossil_strcmp(zCheckin,"latest")==0 ){ char *zNewCkin = db_text(0, "SELECT uuid FROM blob, mlink, event, filename" " WHERE filename.name=%Q" " AND mlink.fnid=filename.fnid" " AND blob.rid=mlink.mid" " AND event.objid=mlink.mid" " ORDER BY event.mtime DESC LIMIT 1", zName + i + 1); if( zNewCkin ) zCheckin = zNewCkin; } } if( nMiss==count(azSuffix) ){ zName = "404.md"; zDfltTitle = "Not Found"; }else if( zName[i]==0 ){ assert( nMiss>=0 && nMiss Changes to src/event.c.  355 356 357 358 359 360 361 362 363 364 365 366 367 368 ... 412 413 414 415 416 417 418 419 420 421 422 423 424 425 ** w=TEXT Complete text of the technote. ** t=TEXT Time of the technote on the timeline (ISO 8601) ** c=TEXT Timeline comment ** g=TEXT Tags associated with this technote ** mimetype=TEXT Mimetype for w= text ** newclr Use a background color ** clr=TEXT Background color to use if newclr */ void eventedit_page(void){ char *zTag; int rid = 0; Blob event; const char *zId; int n; ................................................................................ login_needed(g.anon.Write && (rid ? g.anon.WrWiki : g.anon.NewWiki)); return; } /* Figure out the color */ if( rid ){ zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid); }else{ zClr = ""; isNew = 1; } if( P("newclr") ){ zClr = PD("clr",zClr); if( zClr[0] ) zClrFlag = " checked"; > > > > > > > > > > > > > 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 ... 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 ** w=TEXT Complete text of the technote. ** t=TEXT Time of the technote on the timeline (ISO 8601) ** c=TEXT Timeline comment ** g=TEXT Tags associated with this technote ** mimetype=TEXT Mimetype for w= text ** newclr Use a background color ** clr=TEXT Background color to use if newclr ** ** For GET requests, when editing an existing technote newclr and clr ** are implied if a custom color has been set on the previous version ** of the technote. */ void eventedit_page(void){ char *zTag; int rid = 0; Blob event; const char *zId; int n; ................................................................................ login_needed(g.anon.Write && (rid ? g.anon.WrWiki : g.anon.NewWiki)); return; } /* Figure out the color */ if( rid ){ zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid); if( zClr && zClr[0] ){ const char * zRequestMethod = P("REQUEST_METHOD"); if(zRequestMethod && 'G'==zRequestMethod[0]){ /* Apply saved color by defaut for GET requests ** (e.g., an Edit menu link). */ zClrFlag = " checked"; } } }else{ zClr = ""; isNew = 1; } if( P("newclr") ){ zClr = PD("clr",zClr); if( zClr[0] ) zClrFlag = " checked"; Changes to src/extcgi.c.  96 97 98 99 100 101 102 103 104 105 106 107 108 109 ... 118 119 120 121 122 123 124 125 126 127 128 129 130 131 ... 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 if( !fossil_isalnum(c) && c!='_' && c!='-' && c!='.' && c!='/' ){ zFailReason = "illegal character in path"; break; } } return zFailReason; } /* ** WEBPAGE: ext raw-content ** ** Relay an HTTP request to secondary CGI after first checking the ** login credentials and setting auxiliary environment variables ** so that the secondary CGI can be aware of the credentials and ................................................................................ ** static content. ** ** The path after the /ext is the path to the CGI script or static file ** relative to DIR. For security, this path may not contain characters ** other than ASCII letters or digits, ".", "-", "/", and "_". If the ** "." or "-" characters are present in the path then they may not follow ** a "/". */ void ext_page(void){ const char *zName = P("name"); /* Path information after /ext */ char *zPath = 0; /* Complete path from extroot */ int nRoot; /* Number of bytes in the extroot name */ char *zScript = 0; /* Name of the CGI script */ int nScript = 0; /* Bytes in the CGI script name */ ................................................................................ zFailReason = "???"; if( file_isdir(g.zExtRoot,ExtFILE)!=1 ){ zFailReason = "extroot is not a directory"; goto ext_not_found; } zPath = mprintf("%s/%s", g.zExtRoot, zName); nRoot = (int)strlen(g.zExtRoot); if( file_isfile(zPath, ExtFILE) ){ nScript = (int)strlen(zPath); zScript = zPath; }else{ for(i=nRoot+1; zPath[i]; i++){ char c = zPath[i]; if( c=='/' ){ int isDir, isFile; > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 ... 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 ... 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 if( !fossil_isalnum(c) && c!='_' && c!='-' && c!='.' && c!='/' ){ zFailReason = "illegal character in path"; break; } } return zFailReason; } /* ** The *pzPath input is a pathname obtained from mprintf(). ** ** If ** ** (1) zPathname is the name of a directory, and ** (2) the name ends with "/", and ** (3) the directory contains a file named index.html, index.wiki, ** or index.md (in that order) ** ** then replace the input with a revised name that includes the index.* ** file and return non-zero (true). If any condition is not met, return ** zero and leave the input pathname unchanged. */ static int isDirWithIndexFile(char **pzPath){ static const char *azIndexNames[] = { "index.html", "index.wiki", "index.md" }; int i; if( file_isdir(*pzPath, ExtFILE)!=1 ) return 0; if( sqlite3_strglob("*/", *pzPath)!=0 ) return 0; for(i=0; i Changes to src/forum.c.  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 ... 945 946 947 948 949 950 951 952 953 954 955 956 957 958 ** Edit an existing forum message. ** Query parameters: ** ** fpid=X Hash of the post to be editted. REQUIRED */ void forumedit_page(void){ int fpid; Manifest *pPost = 0; const char *zMimetype = 0; const char *zContent = 0; const char *zTitle = 0; int isCsrfSafe; int isDelete = 0; login_check_credentials(); if( !g.perm.WrForum ){ login_needed(g.anon.WrForum); return; } fpid = symbolic_name_to_rid(PD("fpid",""), "f"); if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){ webpage_error("Missing or invalid fpid query parameter"); } if( P("cancel") ){ cgi_redirectf("%R/forumpost/%S",P("fpid")); return; } isCsrfSafe = cgi_csrf_safe(1); if( g.perm.ModForum && isCsrfSafe ){ if( P("approve") ){ ................................................................................ forum_entry_widget(zTitle, zMimetype, zContent); }else{ /* Reply */ zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE); zContent = PDT("content",""); style_header("Reply"); @ Replying To: forum_render(0, pPost->zMimetype, pPost->zWiki, "forumEdit"); if( P("preview") ){ @ Preview: forum_render(0, zMimetype,zContent, "forumEdit"); } @ Enter Reply: @ > > > > > > > > > > > > > 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 ... 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 ** Edit an existing forum message. ** Query parameters: ** ** fpid=X Hash of the post to be editted. REQUIRED */ void forumedit_page(void){ int fpid; int froot; Manifest *pPost = 0; Manifest *pRootPost = 0; const char *zMimetype = 0; const char *zContent = 0; const char *zTitle = 0; char *zDate = 0; int isCsrfSafe; int isDelete = 0; login_check_credentials(); if( !g.perm.WrForum ){ login_needed(g.anon.WrForum); return; } fpid = symbolic_name_to_rid(PD("fpid",""), "f"); if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){ webpage_error("Missing or invalid fpid query parameter"); } froot = db_int(0, "SELECT froot FROM forumpost WHERE fpid=%d", fpid); if( froot==0 || (pRootPost = manifest_get(froot, CFTYPE_FORUM, 0))==0 ){ webpage_error("fpid does not appear to be a forum post: \"%d\"", fpid); } if( P("cancel") ){ cgi_redirectf("%R/forumpost/%S",P("fpid")); return; } isCsrfSafe = cgi_csrf_safe(1); if( g.perm.ModForum && isCsrfSafe ){ if( P("approve") ){ ................................................................................ forum_entry_widget(zTitle, zMimetype, zContent); }else{ /* Reply */ zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE); zContent = PDT("content",""); style_header("Reply"); @ Replying To: if( pRootPost->zThreadTitle ){ @ %h(pRootPost->zThreadTitle) } zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate); @ %h(pPost->zThreadTitle ? "Post" : "Reply") by %h(pPost->zUser) on %h(zDate) fossil_free(zDate); forum_render(0, pPost->zMimetype, pPost->zWiki, "forumEdit"); if( P("preview") ){ @ Preview: forum_render(0, zMimetype,zContent, "forumEdit"); } @ Enter Reply: @ Changes to src/fuzz.c.  49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ** fossil-fuzz cases ** ** The default is to fuzz the Fossil-wiki translator. Use the --fuzztype TYPE ** option to fuzz different aspects of the system. */ #include "config.h" #include "fuzz.h" #include #if LOCAL_INTERFACE /* ** Type of fuzzing: */ #define FUZZ_WIKI 0 /* The Fossil-Wiki formatter */ #define FUZZ_MARKDOWN 1 /* The Markdown formatter */ < 49 50 51 52 53 54 55 56 57 58 59 60 61 62 ** fossil-fuzz cases ** ** The default is to fuzz the Fossil-wiki translator. Use the --fuzztype TYPE ** option to fuzz different aspects of the system. */ #include "config.h" #include "fuzz.h" #if LOCAL_INTERFACE /* ** Type of fuzzing: */ #define FUZZ_WIKI 0 /* The Fossil-Wiki formatter */ #define FUZZ_MARKDOWN 1 /* The Markdown formatter */ Changes to src/import.c.  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 ... 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 } /* ** Use data accumulated in gg from a "tag" record to add a new ** control artifact to the BLOB table. */ static void finish_tag(void){ Blob record, cksum; if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){ blob_zero(&record); blob_appendf(&record, "D %s\n", gg.zDate); blob_appendf(&record, "T +sym-%F%F%F %s", gimport.zTagPre, gg.zTag, gimport.zTagSuf, gg.zFrom); if( gg.zComment ){ blob_appendf(&record, " %F", gg.zComment); } blob_appendf(&record, "\nU %F\n", gg.zUser); md5sum_blob(&record, &cksum); blob_appendf(&record, "Z %b\n", &cksum); fast_insert_content(&record, 0, 0, 1); blob_reset(&cksum); } import_reset(0); } /* ** Compare two ImportFile objects for sorting */ ................................................................................ ** tag or not. So make an entry in the XTAG table to record this tag ** but overwrite that entry if a later instance of the same tag appears. ** ** This behavior seems like a bug in git-fast-export, but it is easier ** to work around the problem than to fix git-fast-export. */ if( gg.tagCommit && gg.zDate && gg.zUser && gg.zFrom ){ blob_appendf(&record, "D %s\n", gg.zDate); blob_appendf(&record, "T +sym-%F%F%F %s\n", gimport.zBranchPre, gg.zBranch, gimport.zBranchSuf, gg.zPrevCheckin); blob_appendf(&record, "U %F\n", gg.zUser); md5sum_blob(&record, &cksum); blob_appendf(&record, "Z %b\n", &cksum); db_multi_exec( "INSERT OR REPLACE INTO xtag(tname, tcontent)" " VALUES(%Q,%Q)", gg.zBranch, blob_str(&record) ); blob_reset(&record); blob_reset(&cksum); } fossil_free(gg.zPrevBranch); gg.zPrevBranch = gg.zBranch; gg.zBranch = 0; import_reset(0); } /* < > > > > < > 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 ... 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 } /* ** Use data accumulated in gg from a "tag" record to add a new ** control artifact to the BLOB table. */ static void finish_tag(void){ if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){ Blob record, cksum; blob_zero(&record); blob_appendf(&record, "D %s\n", gg.zDate); blob_appendf(&record, "T +sym-%F%F%F %s", gimport.zTagPre, gg.zTag, gimport.zTagSuf, gg.zFrom); if( gg.zComment ){ blob_appendf(&record, " %F", gg.zComment); } blob_appendf(&record, "\nU %F\n", gg.zUser); md5sum_blob(&record, &cksum); blob_appendf(&record, "Z %b\n", &cksum); fast_insert_content(&record, 0, 0, 1); blob_reset(&cksum); blob_reset(&record); } import_reset(0); } /* ** Compare two ImportFile objects for sorting */ ................................................................................ ** tag or not. So make an entry in the XTAG table to record this tag ** but overwrite that entry if a later instance of the same tag appears. ** ** This behavior seems like a bug in git-fast-export, but it is easier ** to work around the problem than to fix git-fast-export. */ if( gg.tagCommit && gg.zDate && gg.zUser && gg.zFrom ){ record.nUsed = 0 /*in case fast_insert_comment() did not indirectly blob_reset() it */; blob_appendf(&record, "D %s\n", gg.zDate); blob_appendf(&record, "T +sym-%F%F%F %s\n", gimport.zBranchPre, gg.zBranch, gimport.zBranchSuf, gg.zPrevCheckin); blob_appendf(&record, "U %F\n", gg.zUser); md5sum_blob(&record, &cksum); blob_appendf(&record, "Z %b\n", &cksum); db_multi_exec( "INSERT OR REPLACE INTO xtag(tname, tcontent)" " VALUES(%Q,%Q)", gg.zBranch, blob_str(&record) ); blob_reset(&cksum); } blob_reset(&record); fossil_free(gg.zPrevBranch); gg.zPrevBranch = gg.zBranch; gg.zBranch = 0; import_reset(0); } /* Changes to src/info.c.  178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 ... 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 .... 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 ** With no arguments, provide information about the current tree. ** If an argument is specified, provide information about the object ** in the repository of the current tree that the argument refers ** to. Or if the argument is the name of a repository, show ** information about that repository. ** ** If the argument is a repository name, then the --verbose option shows ** known the check-out locations for that repository and all URLs used ** to access the repository. The --verbose is (currently) a no-op if ** the argument is the name of a object within the repository. ** ** Use the "finfo" command to get information about a specific ** file in a checkout. ** ** Options: ................................................................................ ){ @ Original User & Date: hyperlink_to_user(zOrigUser,zOrigDate," on "); hyperlink_to_date(zOrigDate, " Received From:%h(zUser) @ %h(zIpAddr) on %s(zDate) Original User & Date: hyperlink_to_user(zOrigUser,zOrigDate," on "); hyperlink_to_date(zOrigDate, " Received From:%h(zUser) @ %h(zIpAddr) on %s(zDate) \ @ (Rcvid %d(rcvid)) "); } if( g.perm.Admin ){ db_prepare(&q2, "SELECT rcvfrom.ipaddr, user.login, datetime(rcvfrom.mtime)" " FROM blob JOIN rcvfrom USING(rcvid) LEFT JOIN user USING(uid)" " WHERE blob.rid=%d", rid ); if( db_step(&q2)==SQLITE_ROW ){ const char *zIpAddr = db_column_text(&q2, 0); const char *zUser = db_column_text(&q2, 1); const char *zDate = db_column_text(&q2, 2); if( zUser==0 || zUser[0]==0 ) zUser = "unknown"; @ @ } db_finalize(&q2); } /* Only show links to read wiki pages if the users can read wiki ** and if the wiki pages already exist */ if( g.perm.RdWiki ................................................................................ ambiguous_page(); return; } rc = name_to_uuid(&uuid, -1, "*"); if( rc==1 ){ if( validate16(zName, nLen) ){ if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){ tktview_page(); return; } if( db_exists("SELECT 1 FROM tag" " WHERE tagname GLOB 'event-%q*'", zName) ){ event_page(); return; | | > > | > > 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 ... 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 .... 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 ** With no arguments, provide information about the current tree. ** If an argument is specified, provide information about the object ** in the repository of the current tree that the argument refers ** to. Or if the argument is the name of a repository, show ** information about that repository. ** ** If the argument is a repository name, then the --verbose option shows ** all known check-out locations for that repository and all URLs used ** to access the repository. The --verbose is (currently) a no-op if ** the argument is the name of a object within the repository. ** ** Use the "finfo" command to get information about a specific ** file in a checkout. ** ** Options: ................................................................................ ){ @ "); } if( g.perm.Admin ){ db_prepare(&q2, "SELECT rcvfrom.ipaddr, user.login, datetime(rcvfrom.mtime)," " blob.rcvid" " FROM blob JOIN rcvfrom USING(rcvid) LEFT JOIN user USING(uid)" " WHERE blob.rid=%d", rid ); if( db_step(&q2)==SQLITE_ROW ){ const char *zIpAddr = db_column_text(&q2, 0); const char *zUser = db_column_text(&q2, 1); const char *zDate = db_column_text(&q2, 2); int rcvid = db_column_int(&q2,3); if( zUser==0 || zUser[0]==0 ) zUser = "unknown"; @ @ } db_finalize(&q2); } /* Only show links to read wiki pages if the users can read wiki ** and if the wiki pages already exist */ if( g.perm.RdWiki ................................................................................ ambiguous_page(); return; } rc = name_to_uuid(&uuid, -1, "*"); if( rc==1 ){ if( validate16(zName, nLen) ){ if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){ cgi_set_parameter_nocopy("tl","1",0); tktview_page(); return; } if( db_exists("SELECT 1 FROM tag" " WHERE tagname GLOB 'event-%q*'", zName) ){ event_page(); return; Changes to src/main.c.  362 363 364 365 366 367 368 369 370 371 372 373 374 375 ... 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 ... 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 ... 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 .... 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 .... 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 .... 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 .... 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 cson_value_free(g.json.gc.v); memset(&g.json, 0, sizeof(g.json)); #endif free(g.zErrMsg); if(g.db){ db_close(0); } /* ** FIXME: The next two lines cannot always be enabled; however, they ** are very useful for tracking down TH1 memory leaks. */ if( fossil_getenv("TH1_DELETE_INTERP")!=0 ){ if( g.interp ){ Th_DeleteInterp(g.interp); g.interp = 0; ................................................................................ g.argv[i] = g.argv[j]; } g.argc = i; } /* ** Look for a command-line option. If present, return a pointer. ** Return NULL if missing. ** ** hasArg==0 means the option is a flag. It is either present or not. ** hasArg==1 means the option has an argument. Return a pointer to the ** argument. */ const char *find_option(const char *zLong, const char *zShort, int hasArg){ int i; int nLong; const char *zReturn = 0; assert( hasArg==0 || hasArg==1 ); nLong = strlen(zLong); ................................................................................ char *z; if( i+hasArg >= g.argc ) break; z = g.argv[i]; if( z[0]!='-' ) continue; z++; if( z[0]=='-' ){ if( z[1]==0 ){ remove_from_argv(i, 1); break; } z++; } if( strncmp(z,zLong,nLong)==0 ){ if( hasArg && z[nLong]=='=' ){ zReturn = &z[nLong+1]; ................................................................................ int has_option(const char *zOption){ int i; int n = (int)strlen(zOption); for(i=1; i > > | > > | > > > > | < > > > > > > > | > | > > > > > > | > > > > > > > > > > > > > > > | > > > > > > > | | | > < | < < < < > > > > > > > > > < < < < < < < < < < > > > > > > > > > > > > > > > 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 ... 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 ... 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 ... 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 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 .... 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 .... 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 .... 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 .... 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 cson_value_free(g.json.gc.v); memset(&g.json, 0, sizeof(g.json)); #endif free(g.zErrMsg); if(g.db){ db_close(0); } manifest_clear_cache(); content_clear_cache(1); rebuild_clear_cache(); /* ** FIXME: The next two lines cannot always be enabled; however, they ** are very useful for tracking down TH1 memory leaks. */ if( fossil_getenv("TH1_DELETE_INTERP")!=0 ){ if( g.interp ){ Th_DeleteInterp(g.interp); g.interp = 0; ................................................................................ g.argv[i] = g.argv[j]; } g.argc = i; } /* ** Look for a command-line option. If present, remove it from the ** argument list and return a pointer to either the flag's name (if ** hasArg==0), sans leading - or --, or its value (if hasArg==1). ** Return NULL if the flag is not found. ** ** zLong is the "long" form of the flag and zShort is the ** short/abbreviated form (typically a single letter, but it may be ** longer). zLong must not be NULL, but zShort may be. ** ** hasArg==0 means the option is a flag. It is either present or not. ** hasArg==1 means the option has an argument, in which case a pointer ** to the argument's value is returned. For zLong, a flag value (if ** hasValue==1) may either be in the form (--flag=value) or (--flag ** value). For zShort, only the latter form is accepted. ** ** If a standalone argument of "--" is encountered in the argument ** list while searching for the given flag(s), this routine stops ** searching and NULL is returned. */ const char *find_option(const char *zLong, const char *zShort, int hasArg){ int i; int nLong; const char *zReturn = 0; assert( hasArg==0 || hasArg==1 ); nLong = strlen(zLong); ................................................................................ char *z; if( i+hasArg >= g.argc ) break; z = g.argv[i]; if( z[0]!='-' ) continue; z++; if( z[0]=='-' ){ if( z[1]==0 ){ /* Stop processing at "--" without consuming it. verify_all_options() will consume this flag. */ break; } z++; } if( strncmp(z,zLong,nLong)==0 ){ if( hasArg && z[nLong]=='=' ){ zReturn = &z[nLong+1]; ................................................................................ int has_option(const char *zOption){ int i; int n = (int)strlen(zOption); for(i=1; i=2 ){ zFile = g.argv[1]; }else{ cgi_panic("No CGI control file specified"); } /* Read and parse the CGI control file. */ blob_read_from_file(&config, zFile, ExtFILE); while( blob_line(&config, &line) ){ if( !blob_token(&line, &key) ) continue; if( blob_buffer(&key)[0]=='#' ) continue; if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){ /* repository: FILENAME ** ................................................................................ */ blob_token(&line,&value2); fossil_setenv(blob_str(&value), blob_str(&value2)); blob_reset(&value); blob_reset(&value2); continue; } if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){ /* errorlog: FILENAME ** ** Causes messages from warnings, errors, and panics to be appended ** to FILENAME. */ g.zErrlog = mprintf("%s", blob_str(&value)); ................................................................................ ** name of the subdirectory under the skins/ directory that holds ** the elements of the built-in skin. If LABEL does not match, ** this directive is a silent no-op. */ skin_use_alternative(blob_str(&value)); blob_reset(&value); continue; } if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){ /* cgi-debug: FILENAME ** ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go ** into FILENAME. Useful for debugging CGI configuration problems. */ char *zNow = cgi_iso8601_datestamp(); cgi_load_environment(); g.fDebug = fossil_fopen(blob_str(&value), "ab"); blob_reset(&value); cgi_debug("-------- BEGIN cgi at %s --------\n", zNow); fossil_free(zNow); cgi_print_all(1,2); continue; } } blob_reset(&config); if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){ cgi_panic("Unable to find or open the project repository"); } cgi_init(); Changes to src/main.mk.  587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 ... 615 616 617 618 619 620 621 622 623 624 625 626 627 628 -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 # Setup the options used to compile the included SQLite shell. SHELL_OPTIONS = -DNDEBUG=1 \ -DSQLITE_DQS=0 \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_DEFAULT_MEMSTATUS=0 \ -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ ................................................................................ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_JSON1 \ -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_STMTVTAB \ -DSQLITE_HAVE_ZLIB \ -DSQLITE_INTROSPECTION_PRAGMAS \ -DSQLITE_ENABLE_DBPAGE_VTAB \ -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 | > > 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 ... 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 -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 # Setup the options used to compile the included SQLite shell. SHELL_OPTIONS = -DNDEBUG=1 \ -DSQLITE_DQS=0 \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_DEFAULT_MEMSTATUS=0 \ -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ ................................................................................ -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 Changes to src/makeheaders.html.  341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 ... 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 ... 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 ... 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 ... 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 ... 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 .... 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 Finally, makeheaders also includes a “-doc” option. This command line option prevents makeheaders from generating any headers at all. Instead, makeheaders will write to standard output information about every definition and declaration that it encounters in its scan of source files. The information output includes the type of the definition or declaration and any comment that preceeds the definition or declaration. The output is in a format that can be easily parsed, and is intended to be read by another program that will generate documentation about the program. We'll talk more about this feature later. ................................................................................ named “alpha.h”. For that reason, you don't want to use that name for any of the .h files you write since that will prevent makeheaders from generating the .h file automatically. The structure of a .c file intented for use with makeheaders is very simple. All you have to do is add a single “#include” to the top of the file that sources the header file that makeheaders will generate. Hence, the beginning of a source file named “alpha.c” might look something like this: ................................................................................ 3.3 How To Avoid Having To Write Any Header Files In my experience, large projects work better if all of the manually written code is placed in .c files and all .h files are generated automatically. This is slightly different for the traditional C method of placing the interface in .h files and the implementation in .c files, but it is a refreshing change that brings a noticable improvement to the coding experience. Others, I believe, share this view since I've noticed recent languages (ex: java, tcl, perl, awk) tend to support the one-file approach to coding as the only option. ................................................................................ it were a .h file by enclosing that part of the .c file within: #if INTERFACE #endif Thus any structure definitions that appear after the “#if INTERFACE” but before the corresponding “#endif” are eligable to be copied into the automatically generated .h files of other .c files. If you use the “#if INTERFACE” mechanism in a .c file, then the generated header for that .c file will contain a line ................................................................................ That isn't the complete truth, actually. The semantics of C are such that once an object becomes visible outside of a single source file, it is also visible to any user of the library that is made from the source file. Makeheaders can not prevent outsiders for using non-exported resources, but it can discourage the practice by refusing to provide prototypes and declarations for the services it does not want to export. Thus the only real effect of the making an object exportable is to include it in the output makeheaders generates when it is run using the -H command line option. This is not a perfect solution, but it works well in practice. ................................................................................ v1 = 0; } The first form is preferred because only a single declaration of the constructor is required. The second form requires two declarations, one in the class definition and one on the defintion of the constructor. 3.6.1 C++ Limitations Makeheaders does not understand more recent C++ syntax such as templates and namespaces. ................................................................................ • The name of the object. • The type of the object. (Structure, typedef, macro, etc.) • Flags to indicate if the declaration is exported (contained within an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE). • A flag to indicate if the object is declared in a C++ file. • The name of the file in which the object was declared. • The complete text of any block comment that preceeds the declarations. • If the declaration occurred inside a preprocessor conditional (“#if”) then the text of that conditional is provided. • The complete text of a declaration for the object. The exact output format will not be described here. It is simple to understand and parse and should be obvious to | | | | | | | | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 ... 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 ... 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 ... 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 ... 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 ... 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 .... 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 Finally, makeheaders also includes a “-doc” option. This command line option prevents makeheaders from generating any headers at all. Instead, makeheaders will write to standard output information about every definition and declaration that it encounters in its scan of source files. The information output includes the type of the definition or declaration and any comment that precedes the definition or declaration. The output is in a format that can be easily parsed, and is intended to be read by another program that will generate documentation about the program. We'll talk more about this feature later. ................................................................................ named “alpha.h”. For that reason, you don't want to use that name for any of the .h files you write since that will prevent makeheaders from generating the .h file automatically. The structure of a .c file intended for use with makeheaders is very simple. All you have to do is add a single “#include” to the top of the file that sources the header file that makeheaders will generate. Hence, the beginning of a source file named “alpha.c” might look something like this: ................................................................................ 3.3 How To Avoid Having To Write Any Header Files In my experience, large projects work better if all of the manually written code is placed in .c files and all .h files are generated automatically. This is slightly different from the traditional C method of placing the interface in .h files and the implementation in .c files, but it is a refreshing change that brings a noticeable improvement to the coding experience. Others, I believe, share this view since I've noticed recent languages (ex: java, tcl, perl, awk) tend to support the one-file approach to coding as the only option. ................................................................................ it were a .h file by enclosing that part of the .c file within: #if INTERFACE #endif Thus any structure definitions that appear after the “#if INTERFACE” but before the corresponding “#endif” are eligible to be copied into the automatically generated .h files of other .c files. If you use the “#if INTERFACE” mechanism in a .c file, then the generated header for that .c file will contain a line ................................................................................ That isn't the complete truth, actually. The semantics of C are such that once an object becomes visible outside of a single source file, it is also visible to any user of the library that is made from the source file. Makeheaders can not prevent outsiders from using non-exported resources, but it can discourage the practice by refusing to provide prototypes and declarations for the services it does not want to export. Thus the only real effect of the making an object exportable is to include it in the output makeheaders generates when it is run using the -H command line option. This is not a perfect solution, but it works well in practice. ................................................................................ v1 = 0; } The first form is preferred because only a single declaration of the constructor is required. The second form requires two declarations, one in the class definition and one on the definition of the constructor. 3.6.1 C++ Limitations Makeheaders does not understand more recent C++ syntax such as templates and namespaces. ................................................................................ • The name of the object. • The type of the object. (Structure, typedef, macro, etc.) • Flags to indicate if the declaration is exported (contained within an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE). • A flag to indicate if the object is declared in a C++ file. • The name of the file in which the object was declared. • The complete text of any block comment that precedes the declarations. • If the declaration occurred inside a preprocessor conditional (“#if”) then the text of that conditional is provided. • The complete text of a declaration for the object. The exact output format will not be described here. It is simple to understand and parse and should be obvious to Changes to src/makemake.tcl.  202 203 204 205 206 207 208 209 210 211 212 213 214 215 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB } #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1 #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4 #lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI #lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096 # Options used to compile the included SQLite shell. > 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 -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 } #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1 #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4 #lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI #lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096 # Options used to compile the included SQLite shell. Changes to src/manifest.c.  66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 ... 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 ... 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 ... 379 380 381 382 383 384 385 386 387 388 389 390 391 392 ... 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 ... 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 .... 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 .... 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 .... 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 .... 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 /* ** A parsed manifest or cluster. */ struct Manifest { Blob content; /* The original content blob */ int type; /* Type of artifact. One of CFTYPE_xxxxx */ int rid; /* The blob-id for this manifest */ char *zBaseline; /* Baseline manifest. The B card. */ Manifest *pBaseline; /* The actual baseline manifest */ char *zComment; /* Decoded comment. The C card. */ double rDate; /* Date and time from D card. 0.0 if no D card. */ char *zUser; /* Name of the user from the U card. */ char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ char *zWiki; /* Text of the wiki page. W card. */ char *zWikiTitle; /* Name of the wiki page. L card. */ ................................................................................ } manifestCardTypes[] = { /* Allowed Required */ /* CFTYPE_MANIFEST 1 */ { "BCDFNPQRTUZ", "DZ" }, /* Wants to be "CDUZ" ----^^^^ ** but we must limit for historical compatibility */ /* CFTYPE_CLUSTER 2 */ { "MZ", "MZ" }, /* CFTYPE_CONTROL 3 */ { "DTUZ", "DTUZ" }, /* CFTYPE_WIKI 4 */ { "DLNPUWZ", "DLUWZ" }, /* CFTYPE_TICKET 5 */ { "DJKUZ", "DJKUZ" }, /* CFTYPE_ATTACHMENT 6 */ { "ACDNUZ", "ADZ" }, /* CFTYPE_EVENT 7 */ { "CDENPTUWZ", "DEWZ" }, /* CFTYPE_FORUM 8 */ { "DGHINPUWZ", "DUWZ" }, }; /* ................................................................................ ** checksum. Return 0 if there is no Z-card. Return 1 if the Z-card ** exists and is correct. Return 2 if the Z-card exists and has the wrong ** value. ** ** 0123456789 123456789 123456789 123456789 ** Z aea84f4f863865a8d59d0384e4d2a41c */ static int verify_z_card(const char *z, int n){ if( n<35 ) return 0; if( z[n-35]!='Z' || z[n-34]!=' ' ) return 0; md5sum_init(); md5sum_step_text(z, n-35); if( memcmp(&z[n-33], md5sum_finish(0), 32)==0 ){ return 1; }else{ return 2; } } /* ** A structure used for rapid parsing of the Manifest file */ ................................................................................ return c; } /* ** Shorthand for a control-artifact parsing error */ #define SYNTAX(T) {zErr=(T); goto manifest_syntax_error;} /* ** Parse a blob into a Manifest object. The Manifest object ** takes over the input blob and will free it when the ** Manifest object is freed. Zeros are inserted into the blob ** as string terminators so that blob should not be used again. ** ................................................................................ char *z; int n; char *zUuid; int sz = 0; int isRepeat; int nSelfTag = 0; /* Number of T cards referring to this manifest */ int nSimpleTag = 0; /* Number of T cards with "+" prefix */ static Bag seen; const char *zErr = 0; unsigned int m; unsigned int seenCard = 0; /* Which card types have been seen */ char zErrBuf[100]; /* Write error messages here */ if( rid==0 ){ isRepeat = 1; }else if( bag_find(&seen, rid) ){ isRepeat = 1; }else{ isRepeat = 0; bag_insert(&seen, rid); } /* Every structural artifact ends with a '\n' character. Exit early ** if that is not the case for this artifact. */ if( !isRepeat ) g.parseCnt[0]++; z = blob_materialize(pContent); ................................................................................ if( n<10 || z[0]<'A' || z[0]>'Z' || z[1]!=' ' ){ blob_reset(pContent); blob_appendf(pErr, "line 1 not recognized"); return 0; } /* Then verify the Z-card. */ if( verify_z_card(z, n)==2 ){ blob_reset(pContent); blob_appendf(pErr, "incorrect Z-card cksum"); return 0; } /* Allocate a Manifest object to hold the parsed control artifact. */ p = fossil_malloc( sizeof(*p) ); memset(p, 0, sizeof(*p)); ................................................................................ blob_copy(&b2, &b); blob_zero(&err); p = manifest_parse(&b2, 0, &err); if( p==0 ) fossil_print("ERROR: %s\n", blob_str(&err)); blob_reset(&err); manifest_destroy(p); } } /* ** COMMAND: test-parse-all-blobs ** ** Usage: %fossil test-parse-all-blobs [--limit N] ** ................................................................................ ** ** Return the RID of the primary parent. */ static int manifest_add_checkin_linkages( int rid, /* The RID of the check-in */ Manifest *p, /* Manifest for this check-in */ int nParent, /* Number of parents for this check-in */ char **azParent /* hashes for each parent */ ){ int i; int parentid = 0; char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */ Stmt q; if( p->zBaseline ){ ................................................................................ fossil_trace("-- manifest_crosslink(%d)\n", rid); } if( (p = manifest_cache_find(rid))!=0 ){ blob_reset(pContent); }else if( (p = manifest_parse(pContent, rid, 0))==0 ){ assert( blob_is_reset(pContent) || pContent==0 ); if( (flags & MC_NO_ERRORS)==0 ){ fossil_error(1, "syntax error in manifest [%S]", db_text(0, "SELECT uuid FROM blob WHERE rid=%d",rid)); } return 0; } if( g.xlinkClusterOnly && p->type!=CFTYPE_CLUSTER ){ manifest_destroy(p); assert( blob_is_reset(pContent) ); if( (flags & MC_NO_ERRORS)==0 ) fossil_error(1, "no manifest"); ................................................................................ if( tid ){ switch( p->aTag[i].zName[0] ){ case '-': type = 0; break; /* Cancel prior occurrences */ case '+': type = 1; break; /* Apply to target only */ case '*': type = 2; break; /* Propagate to descendants */ default: fossil_error(1, "unknown tag type in manifest: %s", p->aTag); return 0; } tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue, rid, p->rDate, tid); } } if( parentid ){ | | | > > | > > > > > > > > > > > > > > < | | | < > | > | < > > 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 ... 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 ... 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 ... 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 ... 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 ... 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 .... 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 .... 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 .... 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 .... 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 /* ** A parsed manifest or cluster. */ struct Manifest { Blob content; /* The original content blob */ int type; /* Type of artifact. One of CFTYPE_xxxxx */ int rid; /* The blob-id for this manifest */ const char *zBaseline;/* Baseline manifest. The B card. */ Manifest *pBaseline; /* The actual baseline manifest */ char *zComment; /* Decoded comment. The C card. */ double rDate; /* Date and time from D card. 0.0 if no D card. */ char *zUser; /* Name of the user from the U card. */ char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ char *zWiki; /* Text of the wiki page. W card. */ char *zWikiTitle; /* Name of the wiki page. L card. */ ................................................................................ } manifestCardTypes[] = { /* Allowed Required */ /* CFTYPE_MANIFEST 1 */ { "BCDFNPQRTUZ", "DZ" }, /* Wants to be "CDUZ" ----^^^^ ** but we must limit for historical compatibility */ /* CFTYPE_CLUSTER 2 */ { "MZ", "MZ" }, /* CFTYPE_CONTROL 3 */ { "DTUZ", "DTUZ" }, /* CFTYPE_WIKI 4 */ { "CDLNPUWZ", "DLUWZ" }, /* CFTYPE_TICKET 5 */ { "DJKUZ", "DJKUZ" }, /* CFTYPE_ATTACHMENT 6 */ { "ACDNUZ", "ADZ" }, /* CFTYPE_EVENT 7 */ { "CDENPTUWZ", "DEWZ" }, /* CFTYPE_FORUM 8 */ { "DGHINPUWZ", "DUWZ" }, }; /* ................................................................................ ** checksum. Return 0 if there is no Z-card. Return 1 if the Z-card ** exists and is correct. Return 2 if the Z-card exists and has the wrong ** value. ** ** 0123456789 123456789 123456789 123456789 ** Z aea84f4f863865a8d59d0384e4d2a41c */ static int verify_z_card(const char *z, int n, Blob *pErr){ const char *zHash; if( n<35 ) return 0; if( z[n-35]!='Z' || z[n-34]!=' ' ) return 0; md5sum_init(); md5sum_step_text(z, n-35); zHash = md5sum_finish(0); if( memcmp(&z[n-33], zHash, 32)==0 ){ return 1; }else{ blob_appendf(pErr, "incorrect Z-card cksum: expected %.32s", zHash); return 2; } } /* ** A structure used for rapid parsing of the Manifest file */ ................................................................................ return c; } /* ** Shorthand for a control-artifact parsing error */ #define SYNTAX(T) {zErr=(T); goto manifest_syntax_error;} /* ** A cache of manifest IDs which manifest_parse() has seen in this ** session. */ static Bag seenManifests = Bag_INIT; /* ** Frees all memory owned by the manifest "has-seen" cache. Intended ** to be called only from the app's atexit() handler. */ void manifest_clear_cache(){ bag_clear(&seenManifests); } /* ** Parse a blob into a Manifest object. The Manifest object ** takes over the input blob and will free it when the ** Manifest object is freed. Zeros are inserted into the blob ** as string terminators so that blob should not be used again. ** ................................................................................ char *z; int n; char *zUuid; int sz = 0; int isRepeat; int nSelfTag = 0; /* Number of T cards referring to this manifest */ int nSimpleTag = 0; /* Number of T cards with "+" prefix */ const char *zErr = 0; unsigned int m; unsigned int seenCard = 0; /* Which card types have been seen */ char zErrBuf[100]; /* Write error messages here */ if( rid==0 ){ isRepeat = 1; }else if( bag_find(&seenManifests, rid) ){ isRepeat = 1; }else{ isRepeat = 0; bag_insert(&seenManifests, rid); } /* Every structural artifact ends with a '\n' character. Exit early ** if that is not the case for this artifact. */ if( !isRepeat ) g.parseCnt[0]++; z = blob_materialize(pContent); ................................................................................ if( n<10 || z[0]<'A' || z[0]>'Z' || z[1]!=' ' ){ blob_reset(pContent); blob_appendf(pErr, "line 1 not recognized"); return 0; } /* Then verify the Z-card. */ if( verify_z_card(z, n, pErr)==2 ){ blob_reset(pContent); return 0; } /* Allocate a Manifest object to hold the parsed control artifact. */ p = fossil_malloc( sizeof(*p) ); memset(p, 0, sizeof(*p)); ................................................................................ blob_copy(&b2, &b); blob_zero(&err); p = manifest_parse(&b2, 0, &err); if( p==0 ) fossil_print("ERROR: %s\n", blob_str(&err)); blob_reset(&err); manifest_destroy(p); } blob_reset(&b); } /* ** COMMAND: test-parse-all-blobs ** ** Usage: %fossil test-parse-all-blobs [--limit N] ** ................................................................................ ** ** Return the RID of the primary parent. */ static int manifest_add_checkin_linkages( int rid, /* The RID of the check-in */ Manifest *p, /* Manifest for this check-in */ int nParent, /* Number of parents for this check-in */ char * const * azParent /* hashes for each parent */ ){ int i; int parentid = 0; char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */ Stmt q; if( p->zBaseline ){ ................................................................................ fossil_trace("-- manifest_crosslink(%d)\n", rid); } if( (p = manifest_cache_find(rid))!=0 ){ blob_reset(pContent); }else if( (p = manifest_parse(pContent, rid, 0))==0 ){ assert( blob_is_reset(pContent) || pContent==0 ); if( (flags & MC_NO_ERRORS)==0 ){ char * zErrUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d",rid); fossil_error(1, "syntax error in manifest [%S]", zErrUuid); fossil_free(zErrUuid); } return 0; } if( g.xlinkClusterOnly && p->type!=CFTYPE_CLUSTER ){ manifest_destroy(p); assert( blob_is_reset(pContent) ); if( (flags & MC_NO_ERRORS)==0 ) fossil_error(1, "no manifest"); ................................................................................ if( tid ){ switch( p->aTag[i].zName[0] ){ case '-': type = 0; break; /* Cancel prior occurrences */ case '+': type = 1; break; /* Apply to target only */ case '*': type = 2; break; /* Propagate to descendants */ default: fossil_error(1, "unknown tag type in manifest: %s", p->aTag); manifest_destroy(p); return 0; } tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue, rid, p->rDate, tid); } } if( parentid ){ Changes to src/markdown.md.  98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 > For inline text, you can either use \backticks\ or the HTML >  tag. > > For blocks of text or code: > > 1. Indent the text using a tab character or at least four spaces. > 2. Precede the block with an HTML   tag and follow it with  . > 3. Surround the block by \\\ (three or more) or \~\~\~ either at the > left margin or indented no more than three spaces. > With the standard skins, verbatim text is rendered in a fixed-width font, > but that is purely a presentation matter, controlled by the skin’s CSS. ## Tables ## > | | > > > > > > 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 > For inline text, you can either use \backticks\ or the HTML >  tag. > > For blocks of text or code: > > 1. Indent the text using a tab character or at least four spaces. > 2. Precede the block with an HTML   tag and follow it with  . > 3. Surround the block by \\\ (three or more) or \~\~\~ either at the > left margin or indented no more than three spaces. The first word > on that same line (if any) is used in a “language-WORD” CSS style in > the HTML rendering of that code block and is intended for use by > code syntax highlighters. Thus \\\c would mark a block of code > in the C programming language. Text to be rendered inside the code block > should therefore start on the next line, not be cuddled up with the > backticks or tildes. > With the standard skins, verbatim text is rendered in a fixed-width font, > but that is purely a presentation matter, controlled by the skin’s CSS. ## Tables ## > Changes to src/merge.c.  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 ** If the VERSION argument is omitted, then Fossil attempts to find ** a recent fork on the current branch to merge. ** ** Only file content is merged. The result continues to use the ** file and directory names from the current checkout even if those ** names might have been changed in the branch being merged in. ** ** Other options: ** ** --baseline BASELINE Use BASELINE as the "pivot" of the merge instead ** of the nearest common ancestor. This allows ** a sequence of changes in a branch to be merged ** without having to merge the entire branch. ** ** --binary GLOBPATTERN Treat files that match GLOBPATTERN as binary ** and do not try to merge parallel changes. This ** option overrides the "binary-glob" setting. ** ** --case-sensitive BOOL Override the case-sensitive setting. If false, ** files whose names differ only in case are taken ** to be the same file. ** ** -f|--force Force the merge even if it would be a no-op. ** ** --force-missing Force the merge even if there is missing content. ** ** --integrate Merged branch will be closed when committing. ** | > > > > > > > > > 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 ** If the VERSION argument is omitted, then Fossil attempts to find ** a recent fork on the current branch to merge. ** ** Only file content is merged. The result continues to use the ** file and directory names from the current checkout even if those ** names might have been changed in the branch being merged in. ** ** Options: ** ** --backout Do a reverse cherrypick merge against VERSION. ** In other words, back out the changes that were ** added by VERSION. ** ** --baseline BASELINE Use BASELINE as the "pivot" of the merge instead ** of the nearest common ancestor. This allows ** a sequence of changes in a branch to be merged ** without having to merge the entire branch. ** ** --binary GLOBPATTERN Treat files that match GLOBPATTERN as binary ** and do not try to merge parallel changes. This ** option overrides the "binary-glob" setting. ** ** --case-sensitive BOOL Override the case-sensitive setting. If false, ** files whose names differ only in case are taken ** to be the same file. ** ** --cherrypick Do a cherrypick merge VERSION into the current ** checkout. A cherrypick merge pulls in the changes ** of the single check-in VERSION, rather than all ** changes back to the nearest common ancestor. ** ** -f|--force Force the merge even if it would be a no-op. ** ** --force-missing Force the merge even if there is missing content. ** ** --integrate Merged branch will be closed when committing. ** Changes to src/mkindex.c.  511 512 513 514 515 516 517 518 519 520 521 522 523 524 } fclose(in); nUsed = nFixed; } int main(int argc, char **argv){ int i; for(i=1; i 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 } fclose(in); nUsed = nFixed; } int main(int argc, char **argv){ int i; memset(aEntry, 0, sizeof(Entry) * N_ENTRY); for(i=1; i Changes to src/rebuild.c.  174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 ... 199 200 201 202 203 204 205 206 207 208 209 210 211 212 ... 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 ); } /* ** Variables used to store state information about an on-going "rebuild" ** or "deconstruct". */ static int totalSize; /* Total number of artifacts to process */ static int processCnt; /* Number processed so far */ static int ttyOutput; /* Do progress output */ static Bag bagDone; /* Bag of records rebuilt */ static char *zFNameFormat; /* Format string for filenames on deconstruct */ static int cchFNamePrefix; /* Length of directory prefix in zFNameFormat */ static char *zDestDir; /* Destination directory on deconstruct */ static int prefixLength; /* Length of directory prefix for deconstruct */ static int fKeepRid1; /* Flag to preserve RID=1 on de- and reconstruct */ /* ** Draw the percent-complete message. ** The input is actually the permill complete. ................................................................................ if( permill>lastOutput ){ fossil_print(" %d.%d%% complete...\r", permill/10, permill%10); fflush(stdout); lastOutput = permill; } } /* ** Called after each artifact is processed */ static void rebuild_step_done(int rid){ /* assert( bag_find(&bagDone, rid)==0 ); */ bag_insert(&bagDone, rid); ................................................................................ */ int rebuild_db(int randomize, int doOut, int doClustering){ Stmt s, q; int errCnt = 0; int incrSize; Blob sql; bag_init(&bagDone); ttyOutput = doOut; processCnt = 0; if (ttyOutput && !g.fQuiet) { percent_complete(0); } alert_triggers_disable(); rebuild_update_schema(); | | | | | > > > > > > > | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 ... 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 ... 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 ); } /* ** Variables used to store state information about an on-going "rebuild" ** or "deconstruct". */ static int totalSize; /* Total number of artifacts to process */ static int processCnt; /* Number processed so far */ static int ttyOutput; /* Do progress output */ static Bag bagDone = Bag_INIT; /* Bag of records rebuilt */ static char *zFNameFormat; /* Format string for filenames on deconstruct */ static int cchFNamePrefix; /* Length of directory prefix in zFNameFormat */ static const char *zDestDir;/* Destination directory on deconstruct */ static int prefixLength; /* Length of directory prefix for deconstruct */ static int fKeepRid1; /* Flag to preserve RID=1 on de- and reconstruct */ /* ** Draw the percent-complete message. ** The input is actually the permill complete. ................................................................................ if( permill>lastOutput ){ fossil_print(" %d.%d%% complete...\r", permill/10, permill%10); fflush(stdout); lastOutput = permill; } } /* ** Frees rebuild-level cached state. Intended only to be called by the ** app-level atexit() handler. */ void rebuild_clear_cache(){ bag_clear(&bagDone); } /* ** Called after each artifact is processed */ static void rebuild_step_done(int rid){ /* assert( bag_find(&bagDone, rid)==0 ); */ bag_insert(&bagDone, rid); ................................................................................ */ int rebuild_db(int randomize, int doOut, int doClustering){ Stmt s, q; int errCnt = 0; int incrSize; Blob sql; bag_clear(&bagDone); ttyOutput = doOut; processCnt = 0; if (ttyOutput && !g.fQuiet) { percent_complete(0); } alert_triggers_disable(); rebuild_update_schema(); Changes to src/regexp.c.  105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 717 718 719 720 721 722 723 724 725 726 727 728 729 730 ... 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 ... 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 if( (c&0xe0)==0xc0 && p->imx && (p->z[p->i]&0xc0)==0x80 ){ c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f); if( c<0x80 ) c = 0xfffd; }else if( (c&0xf0)==0xe0 && p->i+1mx && (p->z[p->i]&0xc0)==0x80 && (p->z[p->i+1]&0xc0)==0x80 ){ c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f); p->i += 2; if( c<=0x3ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd; }else if( (c&0xf8)==0xf0 && p->i+3mx && (p->z[p->i]&0xc0)==0x80 && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){ c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6) | (p->z[p->i+2]&0x3f); p->i += 3; if( c<=0xffff || c>0x10ffff ) c = 0xfffd; }else{ ................................................................................ } } /* ** Flags for grep_buffer() */ #define GREP_EXISTS 0x001 /* If any match, print only the name and stop */ /* ** Run a "grep" over a text file */ static int grep_buffer( ReCompiled *pRe, const char *zName, ................................................................................ for(i=j=ln=cnt=0; z[i]; i=j+1){ for(j=i; z[j] && z[j]!='\n'; j++){} n = j - i; ln++; if( re_match(pRe, (const unsigned char*)(z+i), j-i) ){ cnt++; if( flags & GREP_EXISTS ){ fossil_print("%s\n", zName); break; } fossil_print("%s:%d:%.*s\n", zName, ln, n, z+i); } } return cnt; } /* ** COMMAND: test-grep ................................................................................ } re_free(pRe); } /* ** COMMAND: grep ** ** Usage: %fossil grep [OPTIONS] PATTERN FILENAME ** ** Attempt to match the given POSIX extended regular expression PATTERN ** over all historic versions of FILENAME. For details of the supported ** RE dialect, see https://fossil-scm.org/fossil/doc/trunk/www/grep.md ** ** Options: ** ** -i|--ignore-case Ignore case ** -l|--files-with-matches List only checkin ID for versions that match ** -v|--verbose Show each file as it is analyzed */ void re_grep_cmd(void){ u32 flags = 0; int bVerbose = 0; ReCompiled *pRe; const char *zErr; int ignoreCase = 0; Blob fullName; if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1; if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS; if( find_option("verbose","v",0)!=0 ) bVerbose = 1; db_find_and_open_repository(0, 0); verify_all_options(); if( g.argc<4 ){ usage("REGEXP FILENAME"); } zErr = re_compile(&pRe, g.argv[2], ignoreCase); if( zErr ) fossil_fatal("%s", zErr); if( file_tree_name(g.argv[3], &fullName, 0, 0) ){ int fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", blob_str(&fullName)); if( fnid ){ Stmt q; add_content_sql_commands(g.db); db_prepare(&q, "SELECT content(ux), substr(ux,1,10) FROM (" " SELECT blob.uuid AS ux, min(event.mtime) AS mx" " FROM mlink, blob, event" " WHERE mlink.mid=event.objid" " AND mlink.fid=blob.rid" " AND mlink.fnid=%d" " GROUP BY blob.uuid" ") ORDER BY mx DESC;", fnid ); while( db_step(&q)==SQLITE_ROW ){ if( bVerbose ) fossil_print("%s:\n", db_column_text(&q,1)); grep_buffer(pRe, db_column_text(&q,1), db_column_text(&q,0), flags); } db_finalize(&q); } } } | > | | > > > > > | | > > > > > | > > | | > > > > > | > > > > > > > > > | > > > > > > > > > > > | > > > > | | | | < < > > > > > > > > > > > > > | < < < > > > > > > > | | > | | | < | | > > > > > > > > > | < > > > > > > > > > > > > > > > > | > > > > > > 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 ... 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 ... 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 if( (c&0xe0)==0xc0 && p->imx && (p->z[p->i]&0xc0)==0x80 ){ c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f); if( c<0x80 ) c = 0xfffd; }else if( (c&0xf0)==0xe0 && p->i+1mx && (p->z[p->i]&0xc0)==0x80 && (p->z[p->i+1]&0xc0)==0x80 ){ c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f); p->i += 2; if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd; }else if( (c&0xf8)==0xf0 && p->i+3mx && (p->z[p->i]&0xc0)==0x80 && (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){ c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6) | (p->z[p->i+2]&0x3f); p->i += 3; if( c<=0xffff || c>0x10ffff ) c = 0xfffd; }else{ ................................................................................ } } /* ** Flags for grep_buffer() */ #define GREP_EXISTS 0x001 /* If any match, print only the name and stop */ #define GREP_QUIET 0x002 /* Return code only */ /* ** Run a "grep" over a text file */ static int grep_buffer( ReCompiled *pRe, const char *zName, ................................................................................ for(i=j=ln=cnt=0; z[i]; i=j+1){ for(j=i; z[j] && z[j]!='\n'; j++){} n = j - i; ln++; if( re_match(pRe, (const unsigned char*)(z+i), j-i) ){ cnt++; if( flags & GREP_EXISTS ){ if( (flags & GREP_QUIET)==0 && zName ) fossil_print("%s\n", zName); break; } if( (flags & GREP_QUIET)==0 ){ if( cnt==1 && zName ){ fossil_print("== %s\n", zName); } fossil_print("%d:%.*s\n", ln, n, z+i); } } } return cnt; } /* ** COMMAND: test-grep ................................................................................ } re_free(pRe); } /* ** COMMAND: grep ** ** Usage: %fossil grep [OPTIONS] PATTERN FILENAME ... ** ** Attempt to match the given POSIX extended regular expression PATTERN ** historic versions of FILENAME. The search begins with the most recent ** version of the file and moves backwards in time. Multiple FILENAMEs can ** be specified, in which case all named files are searched in reverse ** chronological order. ** ** For details of the supported regular expression dialect, see ** https://fossil-scm.org/fossil/doc/trunk/www/grep.md ** ** Options: ** ** -c|--count Suppress normal output; instead print a count ** of the number of matching files ** -i|--ignore-case Ignore case ** -l|--files-with-matches List only hash for each match ** --once Stop searching after the first match ** -s|--no-messages Suppress error messages about nonexistant ** or unreadable files ** -v|--invert-match Invert the sense of matching. Show only ** files that have no matches. Implies -l ** --verbose Show each file as it is analyzed */ void re_grep_cmd(void){ u32 flags = 0; int bVerbose = 0; ReCompiled *pRe; const char *zErr; int ignoreCase = 0; Blob fullName; int ii; int nMatch = 0; int bNoMsg; int cntFlag; int bOnce; int bInvert; int nSearch = 0; Stmt q; if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1; if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS; if( find_option("verbose",0,0)!=0 ) bVerbose = 1; if( find_option("quiet","q",0) ) flags |= GREP_QUIET|GREP_EXISTS; bNoMsg = find_option("no-messages","s",0)!=0; bOnce = find_option("once",0,0)!=0; bInvert = find_option("invert-match","v",0)!=0; if( bInvert ){ flags |= GREP_QUIET|GREP_EXISTS; } cntFlag = find_option("count","c",0)!=0; if( cntFlag ){ flags |= GREP_QUIET|GREP_EXISTS; } db_find_and_open_repository(0, 0); verify_all_options(); if( g.argc<4 ){ usage("REGEXP FILENAME ..."); } zErr = re_compile(&pRe, g.argv[2], ignoreCase); if( zErr ) fossil_fatal("%s", zErr); add_content_sql_commands(g.db); db_multi_exec("CREATE TEMP TABLE arglist(iname,fname,fnid);"); for(ii=3; ii Changes to src/schema.c.  400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 @ -- when a check-in comment refers to a ticket) an entry is made in @ -- the following table for that hyperlink. This table is used to @ -- facilitate the display of "back links". @ -- @ CREATE TABLE backlink( @ target TEXT, -- Where the hyperlink points to @ srctype INT, -- 0: check-in 1: ticket 2: wiki @ srcid INT, -- rid for check-in or wiki. tkt_id for ticket. @ mtime TIMESTAMP, -- time that the hyperlink was added. Julian day. @ UNIQUE(target, srctype, srcid) @ ); @ CREATE INDEX backlink_src ON backlink(srcid, srctype); @ @ -- Each attachment is an entry in the following table. Only @ -- the most recent attachment (identified by the D card) is saved. | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 @ -- when a check-in comment refers to a ticket) an entry is made in @ -- the following table for that hyperlink. This table is used to @ -- facilitate the display of "back links". @ -- @ CREATE TABLE backlink( @ target TEXT, -- Where the hyperlink points to @ srctype INT, -- 0: check-in 1: ticket 2: wiki @ srcid INT, -- EVENT.OBJID for the source document @ mtime TIMESTAMP, -- time that the hyperlink was added. Julian day. @ UNIQUE(target, srctype, srcid) @ ); @ CREATE INDEX backlink_src ON backlink(srcid, srctype); @ @ -- Each attachment is an entry in the following table. Only @ -- the most recent attachment (identified by the D card) is saved. Changes to src/search.c.  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 ... 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 /* ** Register the various SQL functions (defined above) needed to implement ** full-scan search. */ void search_sql_setup(sqlite3 *db){ static int once = 0; if( once++ ) return; sqlite3_create_function(db, "search_match", -1, SQLITE_UTF8, 0, search_match_sqlfunc, 0, 0); sqlite3_create_function(db, "search_score", 0, SQLITE_UTF8, 0, search_score_sqlfunc, 0, 0); sqlite3_create_function(db, "search_snippet", 0, SQLITE_UTF8, 0, search_snippet_sqlfunc, 0, 0); sqlite3_create_function(db, "search_init", -1, SQLITE_UTF8, 0, search_init_sqlfunc, 0, 0); sqlite3_create_function(db, "stext", 3, SQLITE_UTF8, 0, search_stext_sqlfunc, 0, 0); sqlite3_create_function(db, "title", 3, SQLITE_UTF8, 0, search_title_sqlfunc, 0, 0); sqlite3_create_function(db, "body", 3, SQLITE_UTF8, 0, search_body_sqlfunc, 0, 0); sqlite3_create_function(db, "urlencode", 1, SQLITE_UTF8, 0, search_urlencode_sqlfunc, 0, 0); } /* ** Testing the search function. ** ** COMMAND: search* ................................................................................ */ static void search_indexed( const char *zPattern, /* The query pattern */ unsigned int srchFlags /* What to search over */ ){ Blob sql; if( srchFlags==0 ) return; sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8, 0, search_rank_sqlfunc, 0, 0); blob_init(&sql, 0, 0); blob_appendf(&sql, "INSERT INTO x(label,url,score,id,date,snip) " " SELECT ftsdocs.label," " ftsdocs.url," " rank(matchinfo(ftsidx,'pcsx'))," > | | | | | | | | | 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 ... 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 /* ** Register the various SQL functions (defined above) needed to implement ** full-scan search. */ void search_sql_setup(sqlite3 *db){ static int once = 0; static const int enc = SQLITE_UTF8|SQLITE_INNOCUOUS; if( once++ ) return; sqlite3_create_function(db, "search_match", -1, enc, 0, search_match_sqlfunc, 0, 0); sqlite3_create_function(db, "search_score", 0, enc, 0, search_score_sqlfunc, 0, 0); sqlite3_create_function(db, "search_snippet", 0, enc, 0, search_snippet_sqlfunc, 0, 0); sqlite3_create_function(db, "search_init", -1, enc, 0, search_init_sqlfunc, 0, 0); sqlite3_create_function(db, "stext", 3, enc, 0, search_stext_sqlfunc, 0, 0); sqlite3_create_function(db, "title", 3, enc, 0, search_title_sqlfunc, 0, 0); sqlite3_create_function(db, "body", 3, enc, 0, search_body_sqlfunc, 0, 0); sqlite3_create_function(db, "urlencode", 1, enc, 0, search_urlencode_sqlfunc, 0, 0); } /* ** Testing the search function. ** ** COMMAND: search* ................................................................................ */ static void search_indexed( const char *zPattern, /* The query pattern */ unsigned int srchFlags /* What to search over */ ){ Blob sql; if( srchFlags==0 ) return; sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0, search_rank_sqlfunc, 0, 0); blob_init(&sql, 0, 0); blob_appendf(&sql, "INSERT INTO x(label,url,score,id,date,snip) " " SELECT ftsdocs.label," " ftsdocs.url," " rank(matchinfo(ftsidx,'pcsx'))," Changes to src/setup.c.  838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 ... 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 @ } } } @ @ for(i=0, pSet=aSetting; iwidth!=0 && !pSet->forceTextArea ){ int hasVersionableValue = pSet->versionable && (db_get_versioned(pSet->name, NULL)!=0); entry_attribute("", /*pSet->width*/ 25, pSet->name, pSet->var!=0 ? pSet->var : pSet->name, (char*)pSet->def, hasVersionableValue); @ %h(pSet->name) if( pSet->versionable ){ ................................................................................ } else { @ } } } @ for(i=0, pSet=aSetting; iwidth!=0 && pSet->forceTextArea ){ int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0; @ %s(pSet->name) if( pSet->versionable ){ @ (v) } else { @ } | | 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 ... 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 @ } } } @ @ for(i=0, pSet=aSetting; iwidth>0 && !pSet->forceTextArea ){ int hasVersionableValue = pSet->versionable && (db_get_versioned(pSet->name, NULL)!=0); entry_attribute("", /*pSet->width*/ 25, pSet->name, pSet->var!=0 ? pSet->var : pSet->name, (char*)pSet->def, hasVersionableValue); @ %h(pSet->name) if( pSet->versionable ){ ................................................................................ } else { @ } } } @ for(i=0, pSet=aSetting; iwidth>0 && pSet->forceTextArea ){ int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0; @ %s(pSet->name) if( pSet->versionable ){ @ (v) } else { @ } Changes to src/sha1.c.  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 /* * blk0() and blk() perform the initial expand. * I got the idea of expanding during the round function from SSLeay * * blk0le() for little-endian and blk0be() for big-endian. */ #if __GNUC__ && (defined(__i386__) || defined(__x86_64__)) /* * GCC by itself only generates left rotates. Use right rotates if * possible to be kinder to dinky implementations with iterative rotate * instructions. */ #define SHA_ROT(op, x, k) \ ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; }) #define rol(x,k) SHA_ROT("roll", x, k) #define ror(x,k) SHA_ROT("rorl", x, k) #else /* Generic C equivalent */ #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) #define rol(x,k) SHA_ROT(x,k,32-(k)) #define ror(x,k) SHA_ROT(x,32-(k),k) #endif #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ |(rol(block[i],8)&0x00FF00FF)) #define blk0be(i) block[i] #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ ^block[(i+2)&15]^block[i&15],1)) /* < < < < < < < < < < < < < < < < < < < 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 /* * blk0() and blk() perform the initial expand. * I got the idea of expanding during the round function from SSLeay * * blk0le() for little-endian and blk0be() for big-endian. */ #define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) #define rol(x,k) SHA_ROT(x,k,32-(k)) #define ror(x,k) SHA_ROT(x,32-(k),k) #define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ |(rol(block[i],8)&0x00FF00FF)) #define blk0be(i) block[i] #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ ^block[(i+2)&15]^block[i&15],1)) /* Changes to src/shell.c.  2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 .... 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 .... 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 .... 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 .... 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 .... 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 .... 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 .... 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 .... 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 .... 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 .... 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 .... 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 .... 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 .... 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 ..... 10396 10397 10398 10399 10400 10401 10402 10403 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 ..... 11298 11299 11300 11301 11302 11303 11304 11305 11306 11307 11308 11309 11310 11311 11312 11313 11314 11315 11316 11317 11318 11319 11320 ..... 12049 12050 12051 12052 12053 12054 12055 12056 12057 12058 12059 12060 12061 12062 12063 12064 12065 ..... 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 12115 ..... 12666 12667 12668 12669 12670 12671 12672 12673 12674 12675 12676 12677 12678 12679 12680 12681 12682 12683 12684 12685 12686 12687 12688 12689 12690 12691 12692 12693 12694 12695 12696 12697 12698 ..... 13458 13459 13460 13461 13462 13463 13464 13465 13466 13467 13468 13469 13470 13471 13472 ..... 15695 15696 15697 15698 15699 15700 15701 15702 15703 15704 15705 15706 15707 15708 15709 15710 15711 15712 15713 15714 15715 15716 15717 15718 15719 15720 15721 15722 15723 15724 15725 15726 15727 15728 15729 15730 15731 15732 ..... 16299 16300 16301 16302 16303 16304 16305 16306 16307 16308 16309 16310 16311 16312 16313 16314 16315 16316 16317 16318 16319 16320 16321 16322 16323 16324 16325 16326 16327 16328 16329 16330 16331 16332 16333 16334 16335 16336 16337 ..... 16340 16341 16342 16343 16344 16345 16346 16347 16348 16349 16350 16351 16352 16353 16354 16355 16356 16357 16358 16359 16360 16361 16362 16363 16364 16365 16366 16367 16368 16369 16370 16371 16372 16373 16374 ..... 16558 16559 16560 16561 16562 16563 16564 16565 16566 16567 16568 16569 16570 16571 ..... 16572 16573 16574 16575 16576 16577 16578 16579 16580 16581 16582 16583 16584 16585 ..... 17728 17729 17730 17731 17732 17733 17734 17735 17736 17737 17738 17739 17740 17741 17742 ..... 17844 17845 17846 17847 17848 17849 17850 17851 17852 17853 17854 17855 17856 17857 17858 ..... 17861 17862 17863 17864 17865 17866 17867 17868 17869 17870 17871 17872 17873 17874 ..... 18492 18493 18494 18495 18496 18497 18498 18499 18500 18501 18502 18503 18504 18505 ..... 18802 18803 18804 18805 18806 18807 18808 18809 18810 18811 18812 18813 18814 18815 ..... 18905 18906 18907 18908 18909 18910 18911 18912 18913 18914 18915 18916 18917 18918 sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0, sha3Func, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0, sha3Func, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0, sha3QueryFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0, sha3QueryFunc, 0, 0); } return rc; } /************************* End ../ext/misc/shathree.c ********************/ /************************* Begin ../ext/misc/fileio.c ******************/ /* ................................................................................ (void)argv; (void)pzErr; rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA); if( rc==SQLITE_OK ){ pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) ); if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); } *ppVtab = (sqlite3_vtab*)pNew; return rc; } /* ** This method is the destructor for fsdir vtab objects. ................................................................................ sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0, writefileFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, lsModeFunc, 0, 0); } if( rc==SQLITE_OK ){ ................................................................................ /* Column numbers */ #define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */ #define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */ #define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */ #define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */ rc = sqlite3_declare_vtab(db, "CREATE TABLE x(" " candidate TEXT," " prefix TEXT HIDDEN," " wholeline TEXT HIDDEN," " phase INT HIDDEN" /* Used for debugging only */ ")"); ................................................................................ pNew->aBuffer = (u8*)&pNew[1]; if( zFile ){ pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE]; memcpy(pNew->zFile, zFile, nFile); zipfileDequote(pNew->zFile); } } *ppVtab = (sqlite3_vtab*)pNew; return rc; } /* ** Free the ZipfileEntry structure indicated by the only argument. */ ................................................................................ ** case. */ static int zipfileDeflate( const u8 *aIn, int nIn, /* Input */ u8 **ppOut, int *pnOut, /* Output */ char **pzErr /* OUT: Error message */ ){ sqlite3_int64 nAlloc = compressBound(nIn); u8 *aOut; int rc = SQLITE_OK; aOut = (u8*)sqlite3_malloc64(nAlloc); if( aOut==0 ){ rc = SQLITE_NOMEM; }else{ int res; z_stream str; memset(&str, 0, sizeof(str)); str.next_in = (Bytef*)aIn; str.avail_in = nIn; str.next_out = aOut; str.avail_out = nAlloc; deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); res = deflate(&str, Z_FINISH); if( res==Z_STREAM_END ){ *ppOut = aOut; *pnOut = (int)str.total_out; }else{ sqlite3_free(aOut); *pzErr = sqlite3_mprintf("zipfile: deflate() error"); rc = SQLITE_ERROR; ................................................................................ if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; if( pCons->usable==0 ){ unusable = 1; }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ idx = i; } } if( idx>=0 ){ pIdxInfo->aConstraintUsage[idx].argvIndex = 1; pIdxInfo->aConstraintUsage[idx].omit = 1; pIdxInfo->estimatedCost = 1000.0; pIdxInfo->idxNum = 1; }else if( unusable ){ return SQLITE_CONSTRAINT; } return SQLITE_OK; } ................................................................................ /* ** Both (const char*) arguments point to nul-terminated strings. Argument ** nB is the value of strlen(zB). This function returns 0 if the strings are ** identical, ignoring any trailing '/' character in either path. */ static int zipfileComparePath(const char *zA, const char *zB, int nB){ int nA = (int)strlen(zA); if( zA[nA-1]=='/' ) nA--; if( zB[nB-1]=='/' ) nB--; if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; return 1; } static int zipfileBegin(sqlite3_vtab *pVtab){ ZipfileTab *pTab = (ZipfileTab*)pVtab; int rc = SQLITE_OK; assert( pTab->pWriteFd==0 ); /* Open a write fd on the file. Also load the entire central directory ** structure into memory. During the transaction any new file data is ** appended to the archive file, but the central directory is accumulated ** in main-memory until the transaction is committed. */ pTab->pWriteFd = fopen(pTab->zFile, "ab+"); if( pTab->pWriteFd==0 ){ ................................................................................ if( rc==SQLITE_OK ){ rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg); } if( rc==SQLITE_OK ){ zPath = (const char*)sqlite3_value_text(apVal[2]); nPath = (int)strlen(zPath); mTime = zipfileGetTime(apVal[4]); } if( rc==SQLITE_OK && bIsDir ){ /* For a directory, check that the last character in the path is a ** '/'. This appears to be required for compatibility with info-zip ** (the unzip command on unix). It does not create directories ** otherwise. */ if( zPath[nPath-1]!='/' ){ zFree = sqlite3_mprintf("%s/", zPath); if( zFree==0 ){ rc = SQLITE_NOMEM; } zPath = (const char*)zFree; nPath++; } } /* Check that we're not inserting a duplicate entry -OR- updating an ** entry with a path, thereby making it into a duplicate. */ if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){ ZipfileEntry *p; ................................................................................ /* Decode the "mtime" argument. */ e.mUnixTime = zipfileGetTime(pMtime); /* If this is a directory entry, ensure that there is exactly one '/' ** at the end of the path. Or, if this is not a directory and the path ** ends in '/' it is an error. */ if( bIsDir==0 ){ if( zName[nName-1]=='/' ){ zErr = sqlite3_mprintf("non-directory name must not end with /"); rc = SQLITE_ERROR; goto zipfile_step_out; } }else{ if( zName[nName-1]!='/' ){ zName = zFree = sqlite3_mprintf("%s/", zName); nName++; if( zName==0 ){ rc = SQLITE_NOMEM; goto zipfile_step_out; } }else{ while( nName>1 && zName[nName-2]=='/' ) nName--; } } /* Assemble the ZipfileEntry object for the new zip archive entry */ e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; ................................................................................ sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0, sqlarCompressFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0, sqlarUncompressFunc, 0, 0); } return rc; } /************************* End ../ext/misc/sqlar.c ********************/ #endif ................................................................................ ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* */ /* #include "sqlite3.h" */ typedef struct sqlite3expert sqlite3expert; /* ** Create a new sqlite3expert object. ** ................................................................................ /* ** Free an (sqlite3expert*) handle and all associated resources. There ** should be one call to this function for each successful call to ** sqlite3-expert_new(). */ void sqlite3_expert_destroy(sqlite3expert*); /************************* End ../ext/expert/sqlite3expert.h ********************/ /************************* Begin ../ext/expert/sqlite3expert.c ******************/ /* ** 2017 April 09 ** ** The author disclaims copyright to this source code. In place of ................................................................................ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ u8 nEqpLevel; /* Depth of the EQP output graph */ u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ int lineno; /* Line number of last line read from in */ FILE *in; /* Read commands from this stream */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int modePrior; /* Saved mode */ int cMode; /* temporary output mode for the current query */ ................................................................................ } case MODE_Explain: case MODE_Column: { static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13}; const int *colWidth; int showHdr; char *rowSep; if( p->cMode==MODE_Column ){ colWidth = p->colWidth; showHdr = p->showHeader; rowSep = p->rowSeparator; }else{ colWidth = aExplainWidths; showHdr = 1; rowSep = SEP_Row; } if( p->cnt++==0 ){ for(i=0; icolWidth) ){ w = colWidth[i]; }else{ w = 0; } if( w==0 ){ w = strlenChar(azCol[i] ? azCol[i] : ""); if( w<10 ) w = 10; ................................................................................ sqlite3WhereTrace = savedWhereTrace; #endif } /* Create the TEMP table used to store parameter bindings */ static void bind_table_init(ShellState *p){ int wrSchema = 0; sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema); sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0); sqlite3_exec(p->db, "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n" " key TEXT PRIMARY KEY,\n" " value ANY\n" ") WITHOUT ROWID;", 0, 0, 0); sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0); } /* ** Bind parameters on a prepared statement. ** ** Parameter bindings are taken from a TEMP table of the form: ** ................................................................................ " test Show raw EXPLAIN QUERY PLAN output", " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", #endif " trigger Like \"full\" but also show trigger bytecode", ".excel Display the output of next command in spreadsheet", ".exit ?CODE? Exit this program with return-code CODE", ".expert EXPERIMENTAL. Suggest indexes for queries", /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ /*".explain ?on|off|auto? Turn EXPLAIN output mode on or off",*/ ".filectrl CMD ... Run various sqlite3_file_control() operations", " Run \".filectrl\" with no arguments for details", ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ".headers on|off Turn display of headers on or off", ".help ?-all? ?PATTERN? Show help text for PATTERN", ".import FILE TABLE Import data from FILE into TABLE", #ifndef SQLITE_OMIT_TEST_CONTROL ................................................................................ " --append Use appendvfs to append database to the end of FILE", #ifdef SQLITE_ENABLE_DESERIALIZE " --deserialize Load into memory useing sqlite3_deserialize()", " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", #endif " --new Initialize FILE to an empty database", " --readonly Open FILE readonly", " --zip FILE is a ZIP archive", ".output ?FILE? Send output to FILE or stdout if FILE is omitted", " If FILE begins with '|' then open it as a pipe.", ".parameter CMD ... Manage SQL parameter bindings", " clear Erase all bindings", " init Initialize the TEMP table that holds bindings", ................................................................................ p->openMode = (u8)deduceDatabaseType(p->zDbFilename, (openFlags & OPEN_DB_ZIPFILE)!=0); } } switch( p->openMode ){ case SHELL_OPEN_APPENDVFS: { sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "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(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0); break; } case SHELL_OPEN_UNSPEC: case SHELL_OPEN_NORMAL: { sqlite3_open(p->zDbFilename, &p->db); 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", p->zDbFilename, sqlite3_errmsg(p->db)); ................................................................................ return (a[0]<<8) + a[1]; } static unsigned int get4byteInt(unsigned char *a){ return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; } /* ** Implementation of the ".info" command. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ static const struct { const char *zName; int ofst; } aField[] = { { "file change counter:", 24 }, { "database page count:", 28 }, ................................................................................ }else if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ static const struct DbConfigChoices { const char *zName; int op; } aDbConfig[] = { { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, }; int ii, v; open_db(p, 0); for(ii=0; ii1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; if( nArg>=3 ){ sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); } sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); if( nArg>1 ) break; } if( nArg>1 && ii==ArraySize(aDbConfig) ){ utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); } }else ................................................................................ #ifndef SQLITE_UNTESTABLE if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ char *zSql; char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; int i; if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" " .imposter off\n"); rc = 1; goto meta_command_exit; } open_db(p, 0); if( nArg==2 ){ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); goto meta_command_exit; } zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master" " WHERE name='%q' AND type='index'", azArg[1]); sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( sqlite3_step(pStmt)==SQLITE_ROW ){ tnum = sqlite3_column_int(pStmt, 0); } sqlite3_finalize(pStmt); if( tnum==0 ){ utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); rc = 1; goto meta_command_exit; } zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); i = 0; while( sqlite3_step(pStmt)==SQLITE_ROW ){ char zLabel[20]; const char *zCol = (const char*)sqlite3_column_text(pStmt,2); ................................................................................ if( sqlite3_column_int(pStmt,1)==-1 ){ zCol = "_ROWID_"; }else{ sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i); zCol = zLabel; } } if( zCollist==0 ){ zCollist = sqlite3_mprintf("\"%w\"", zCol); }else{ zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol); } } sqlite3_finalize(pStmt); zSql = sqlite3_mprintf( "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID", azArg[2], zCollist, zCollist); sqlite3_free(zCollist); rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); if( rc==SQLITE_OK ){ rc = sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); if( rc ){ utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); }else{ utf8_printf(stdout, "%s;\n", zSql); raw_printf(stdout, "WARNING: writing to an imposter table will corrupt the index!\n" ); } }else{ raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); rc = 1; } sqlite3_free(zSql); ................................................................................ session_close_all(p); close_db(p->db); p->db = 0; p->zDbFilename = 0; sqlite3_free(p->zFreeOnClose); p->zFreeOnClose = 0; p->openMode = SHELL_OPEN_UNSPEC; p->szMax = 0; /* Check for command-line arguments */ for(iName=1; iNameopenMode = SHELL_OPEN_ZIPFILE; #endif }else if( optionMatch(z, "append") ){ p->openMode = SHELL_OPEN_APPENDVFS; }else if( optionMatch(z, "readonly") ){ p->openMode = SHELL_OPEN_READONLY; #ifdef SQLITE_ENABLE_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+1szMax = integerValue(azArg[++iName]); ................................................................................ { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, #ifdef YYCOVERAGE { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, #endif { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, ................................................................................ isOk = 3; } break; /* sqlite3_test_control(int, int) */ case SQLITE_TESTCTRL_ASSERT: case SQLITE_TESTCTRL_ALWAYS: case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 1; } break; ................................................................................ case SQLITE_TESTCTRL_NEVER_CORRUPT: if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 3; } break; case SQLITE_TESTCTRL_IMPOSTER: if( nArg==5 ){ rc2 = sqlite3_test_control(testctrl, p->db, azArg[2], integerValue(azArg[3]), integerValue(azArg[4])); ................................................................................ #endif " -memtrace trace all memory allocations and deallocations\n" " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif " -newline SEP set output row separator. Default: '\\n'\n" " -nullvalue TEXT set text string for NULL values. Default ''\n" " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" " -quote set output mode to 'quote'\n" " -readonly open the database read-only\n" " -separator SEP set output column separator. Default: '|'\n" #ifdef SQLITE_ENABLE_SORTER_REFERENCES " -sorterref SIZE sorter references threshold size\n" ................................................................................ }else if( strcmp(z,"-deserialize")==0 ){ data.openMode = SHELL_OPEN_DESERIALIZE; }else if( strcmp(z,"-maxsize")==0 && i+1 | | > | | > | | > | > | > | > > > > | > < > > > > > > < < < < < < < > < | | > > > > > | < > > | > > > | | < > | > | > | | | > > > > | > > > > < < | > | | > | > | > > > > > > < < | > < < < | > > > > > > > > > | > | > > > > > > > < < < < < > > > > > > > > > > | | | > > > > | < > > > > > > > > > > > 2003 2004 2005 2006 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 .... 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 .... 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 .... 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 .... 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 .... 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 .... 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 .... 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 .... 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 .... 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 .... 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 .... 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 .... 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 .... 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 ..... 10417 10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 10442 10443 10444 10445 10446 ..... 11322 11323 11324 11325 11326 11327 11328 11329 11330 11331 11332 11333 11334 11335 11336 11337 11338 11339 11340 11341 11342 11343 11344 11345 11346 11347 11348 ..... 12077 12078 12079 12080 12081 12082 12083 12084 12085 12086 12087 12088 12089 12090 12091 ..... 12128 12129 12130 12131 12132 12133 12134 12135 12136 12137 12138 12139 12140 12141 12142 ..... 12693 12694 12695 12696 12697 12698 12699 12700 12701 12702 12703 12704 12705 12706 12707 12708 12709 12710 12711 12712 12713 12714 12715 12716 12717 12718 12719 12720 12721 12722 12723 12724 12725 12726 12727 ..... 13487 13488 13489 13490 13491 13492 13493 13494 13495 13496 13497 13498 13499 13500 13501 ..... 15724 15725 15726 15727 15728 15729 15730 15731 15732 15733 15734 15735 15736 15737 15738 15739 15740 15741 15742 15743 15744 15745 15746 15747 15748 15749 15750 15751 15752 15753 15754 15755 15756 15757 15758 15759 15760 15761 15762 15763 ..... 16330 16331 16332 16333 16334 16335 16336 16337 16338 16339 16340 16341 16342 16343 16344 16345 16346 16347 16348 16349 16350 16351 16352 16353 16354 16355 16356 16357 16358 16359 16360 16361 16362 16363 16364 16365 16366 16367 16368 16369 16370 16371 16372 16373 16374 16375 16376 16377 16378 16379 16380 ..... 16383 16384 16385 16386 16387 16388 16389 16390 16391 16392 16393 16394 16395 16396 16397 16398 16399 16400 16401 16402 16403 16404 16405 16406 16407 16408 16409 16410 16411 16412 16413 16414 16415 16416 16417 16418 16419 16420 16421 16422 16423 16424 16425 16426 16427 16428 ..... 16612 16613 16614 16615 16616 16617 16618 16619 16620 16621 16622 16623 16624 16625 16626 ..... 16627 16628 16629 16630 16631 16632 16633 16634 16635 16636 16637 16638 16639 16640 16641 16642 ..... 17785 17786 17787 17788 17789 17790 17791 17792 17793 17794 17795 17796 17797 17798 17799 ..... 17901 17902 17903 17904 17905 17906 17907 17908 17909 17910 17911 17912 17913 17914 ..... 17917 17918 17919 17920 17921 17922 17923 17924 17925 17926 17927 17928 17929 17930 17931 17932 17933 17934 17935 17936 ..... 18554 18555 18556 18557 18558 18559 18560 18561 18562 18563 18564 18565 18566 18567 18568 ..... 18865 18866 18867 18868 18869 18870 18871 18872 18873 18874 18875 18876 18877 18878 18879 18880 ..... 18970 18971 18972 18973 18974 18975 18976 18977 18978 18979 18980 18981 18982 18983 18984 18985 sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, 0, sha3Func, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, 0, sha3Func, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8 | SQLITE_DIRECTONLY, 0, sha3QueryFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8 | SQLITE_DIRECTONLY, 0, sha3QueryFunc, 0, 0); } return rc; } /************************* End ../ext/misc/shathree.c ********************/ /************************* Begin ../ext/misc/fileio.c ******************/ /* ................................................................................ (void)argv; (void)pzErr; rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA); if( rc==SQLITE_OK ){ pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) ); if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); } *ppVtab = (sqlite3_vtab*)pNew; return rc; } /* ** This method is the destructor for fsdir vtab objects. ................................................................................ sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8|SQLITE_DIRECTONLY, 0, readfileFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8|SQLITE_DIRECTONLY, 0, writefileFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, lsModeFunc, 0, 0); } if( rc==SQLITE_OK ){ ................................................................................ /* Column numbers */ #define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */ #define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */ #define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */ #define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */ sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); rc = sqlite3_declare_vtab(db, "CREATE TABLE x(" " candidate TEXT," " prefix TEXT HIDDEN," " wholeline TEXT HIDDEN," " phase INT HIDDEN" /* Used for debugging only */ ")"); ................................................................................ pNew->aBuffer = (u8*)&pNew[1]; if( zFile ){ pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE]; memcpy(pNew->zFile, zFile, nFile); zipfileDequote(pNew->zFile); } } sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); *ppVtab = (sqlite3_vtab*)pNew; return rc; } /* ** Free the ZipfileEntry structure indicated by the only argument. */ ................................................................................ ** case. */ static int zipfileDeflate( const u8 *aIn, int nIn, /* Input */ u8 **ppOut, int *pnOut, /* Output */ char **pzErr /* OUT: Error message */ ){ int rc = SQLITE_OK; sqlite3_int64 nAlloc; z_stream str; u8 *aOut; memset(&str, 0, sizeof(str)); str.next_in = (Bytef*)aIn; str.avail_in = nIn; deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); nAlloc = deflateBound(&str, nIn); aOut = (u8*)sqlite3_malloc64(nAlloc); if( aOut==0 ){ rc = SQLITE_NOMEM; }else{ int res; str.next_out = aOut; str.avail_out = nAlloc; res = deflate(&str, Z_FINISH); if( res==Z_STREAM_END ){ *ppOut = aOut; *pnOut = (int)str.total_out; }else{ sqlite3_free(aOut); *pzErr = sqlite3_mprintf("zipfile: deflate() error"); rc = SQLITE_ERROR; ................................................................................ if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; if( pCons->usable==0 ){ unusable = 1; }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ idx = i; } } pIdxInfo->estimatedCost = 1000.0; if( idx>=0 ){ pIdxInfo->aConstraintUsage[idx].argvIndex = 1; pIdxInfo->aConstraintUsage[idx].omit = 1; pIdxInfo->idxNum = 1; }else if( unusable ){ return SQLITE_CONSTRAINT; } return SQLITE_OK; } ................................................................................ /* ** Both (const char*) arguments point to nul-terminated strings. Argument ** nB is the value of strlen(zB). This function returns 0 if the strings are ** identical, ignoring any trailing '/' character in either path. */ static int zipfileComparePath(const char *zA, const char *zB, int nB){ int nA = (int)strlen(zA); if( nA>0 && zA[nA-1]=='/' ) nA--; if( nB>0 && zB[nB-1]=='/' ) nB--; if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; return 1; } static int zipfileBegin(sqlite3_vtab *pVtab){ ZipfileTab *pTab = (ZipfileTab*)pVtab; int rc = SQLITE_OK; assert( pTab->pWriteFd==0 ); if( pTab->zFile==0 || pTab->zFile[0]==0 ){ pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename"); return SQLITE_ERROR; } /* Open a write fd on the file. Also load the entire central directory ** structure into memory. During the transaction any new file data is ** appended to the archive file, but the central directory is accumulated ** in main-memory until the transaction is committed. */ pTab->pWriteFd = fopen(pTab->zFile, "ab+"); if( pTab->pWriteFd==0 ){ ................................................................................ if( rc==SQLITE_OK ){ rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg); } if( rc==SQLITE_OK ){ zPath = (const char*)sqlite3_value_text(apVal[2]); if( zPath==0 ) zPath = ""; nPath = (int)strlen(zPath); mTime = zipfileGetTime(apVal[4]); } if( rc==SQLITE_OK && bIsDir ){ /* For a directory, check that the last character in the path is a ** '/'. This appears to be required for compatibility with info-zip ** (the unzip command on unix). It does not create directories ** otherwise. */ if( nPath<=0 || zPath[nPath-1]!='/' ){ zFree = sqlite3_mprintf("%s/", zPath); zPath = (const char*)zFree; if( zFree==0 ){ rc = SQLITE_NOMEM; nPath = 0; }else{ nPath = (int)strlen(zPath); } } } /* Check that we're not inserting a duplicate entry -OR- updating an ** entry with a path, thereby making it into a duplicate. */ if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){ ZipfileEntry *p; ................................................................................ /* Decode the "mtime" argument. */ e.mUnixTime = zipfileGetTime(pMtime); /* If this is a directory entry, ensure that there is exactly one '/' ** at the end of the path. Or, if this is not a directory and the path ** ends in '/' it is an error. */ if( bIsDir==0 ){ if( nName>0 && zName[nName-1]=='/' ){ zErr = sqlite3_mprintf("non-directory name must not end with /"); rc = SQLITE_ERROR; goto zipfile_step_out; } }else{ if( nName==0 || zName[nName-1]!='/' ){ zName = zFree = sqlite3_mprintf("%s/", zName); if( zName==0 ){ rc = SQLITE_NOMEM; goto zipfile_step_out; } nName = (int)strlen(zName); }else{ while( nName>1 && zName[nName-2]=='/' ) nName--; } } /* Assemble the ZipfileEntry object for the new zip archive entry */ e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; ................................................................................ sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0, sqlarCompressFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8|SQLITE_INNOCUOUS, 0, sqlarUncompressFunc, 0, 0); } return rc; } /************************* End ../ext/misc/sqlar.c ********************/ #endif ................................................................................ ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* */ #if !defined(SQLITEEXPERT_H) #define SQLITEEXPERT_H 1 /* #include "sqlite3.h" */ typedef struct sqlite3expert sqlite3expert; /* ** Create a new sqlite3expert object. ** ................................................................................ /* ** Free an (sqlite3expert*) handle and all associated resources. There ** should be one call to this function for each successful call to ** sqlite3-expert_new(). */ void sqlite3_expert_destroy(sqlite3expert*); #endif /* !defined(SQLITEEXPERT_H) */ /************************* End ../ext/expert/sqlite3expert.h ********************/ /************************* Begin ../ext/expert/sqlite3expert.c ******************/ /* ** 2017 April 09 ** ** The author disclaims copyright to this source code. In place of ................................................................................ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ u8 nEqpLevel; /* Depth of the EQP output graph */ u8 eTraceType; /* SHELL_TRACE_* value for type of trace */ unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ int lineno; /* Line number of last line read from in */ int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */ FILE *in; /* Read commands from this stream */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int modePrior; /* Saved mode */ int cMode; /* temporary output mode for the current query */ ................................................................................ } case MODE_Explain: case MODE_Column: { static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13}; const int *colWidth; int showHdr; char *rowSep; int nWidth; if( p->cMode==MODE_Column ){ colWidth = p->colWidth; nWidth = ArraySize(p->colWidth); showHdr = p->showHeader; rowSep = p->rowSeparator; }else{ colWidth = aExplainWidths; nWidth = ArraySize(aExplainWidths); showHdr = 1; rowSep = SEP_Row; } if( p->cnt++==0 ){ for(i=0; idb, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode); sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0); sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema); sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0); sqlite3_exec(p->db, "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n" " key TEXT PRIMARY KEY,\n" " value ANY\n" ") WITHOUT ROWID;", 0, 0, 0); sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0); sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0); } /* ** Bind parameters on a prepared statement. ** ** Parameter bindings are taken from a TEMP table of the form: ** ................................................................................ " test Show raw EXPLAIN QUERY PLAN output", " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", #endif " trigger Like \"full\" but also show trigger bytecode", ".excel Display the output of next command in spreadsheet", ".exit ?CODE? Exit this program with return-code CODE", ".expert EXPERIMENTAL. Suggest indexes for queries", ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto", ".filectrl CMD ... Run various sqlite3_file_control() operations", " Run \".filectrl\" with no arguments for details", ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ".headers on|off Turn display of headers on or off", ".help ?-all? ?PATTERN? Show help text for PATTERN", ".import FILE TABLE Import data from FILE into TABLE", #ifndef SQLITE_OMIT_TEST_CONTROL ................................................................................ " --append Use appendvfs to append database to the end of FILE", #ifdef SQLITE_ENABLE_DESERIALIZE " --deserialize Load into memory useing sqlite3_deserialize()", " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", #endif " --new Initialize FILE to an empty database", " --nofollow Do not follow symbolic links", " --readonly Open FILE readonly", " --zip FILE is a ZIP archive", ".output ?FILE? Send output to FILE or stdout if FILE is omitted", " If FILE begins with '|' then open it as a pipe.", ".parameter CMD ... Manage SQL parameter bindings", " clear Erase all bindings", " init Initialize the TEMP table that holds bindings", ................................................................................ p->openMode = (u8)deduceDatabaseType(p->zDbFilename, (openFlags & OPEN_DB_ZIPFILE)!=0); } } switch( p->openMode ){ case SHELL_OPEN_APPENDVFS: { sqlite3_open_v2(p->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(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY|p->openFlags, 0); break; } case SHELL_OPEN_UNSPEC: case SHELL_OPEN_NORMAL: { sqlite3_open_v2(p->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", p->zDbFilename, sqlite3_errmsg(p->db)); ................................................................................ return (a[0]<<8) + a[1]; } static unsigned int get4byteInt(unsigned char *a){ return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; } /* ** Implementation of the ".dbinfo" command. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ static const struct { const char *zName; int ofst; } aField[] = { { "file change counter:", 24 }, { "database page count:", 28 }, ................................................................................ }else if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ static const struct DbConfigChoices { const char *zName; int op; } aDbConfig[] = { { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA }, { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, }; int ii, v; open_db(p, 0); for(ii=0; ii1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; if( nArg>=3 ){ sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); } sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); if( nArg>1 ) break; } if( nArg>1 && ii==ArraySize(aDbConfig) ){ utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); } }else ................................................................................ #ifndef SQLITE_UNTESTABLE if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ char *zSql; char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ int i; if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" " .imposter off\n"); /* Also allowed, but not documented: ** ** .imposter TABLE IMPOSTER ** ** where TABLE is a WITHOUT ROWID table. In that case, the ** imposter is another WITHOUT ROWID table with the columns in ** storage order. */ rc = 1; goto meta_command_exit; } open_db(p, 0); if( nArg==2 ){ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); goto meta_command_exit; } zSql = sqlite3_mprintf( "SELECT rootpage, 0 FROM sqlite_master" " WHERE name='%q' AND type='index'" "UNION ALL " "SELECT rootpage, 1 FROM sqlite_master" " WHERE name='%q' AND type='table'" " AND sql LIKE '%%without%%rowid%%'", azArg[1], azArg[1] ); sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( sqlite3_step(pStmt)==SQLITE_ROW ){ tnum = sqlite3_column_int(pStmt, 0); isWO = sqlite3_column_int(pStmt, 1); } sqlite3_finalize(pStmt); zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); i = 0; while( sqlite3_step(pStmt)==SQLITE_ROW ){ char zLabel[20]; const char *zCol = (const char*)sqlite3_column_text(pStmt,2); ................................................................................ if( sqlite3_column_int(pStmt,1)==-1 ){ zCol = "_ROWID_"; }else{ sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i); zCol = zLabel; } } if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){ lenPK = (int)strlen(zCollist); } if( zCollist==0 ){ zCollist = sqlite3_mprintf("\"%w\"", zCol); }else{ zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol); } } sqlite3_finalize(pStmt); if( i==0 || tnum==0 ){ utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]); rc = 1; sqlite3_free(zCollist); goto meta_command_exit; } if( lenPK==0 ) lenPK = 100000; zSql = sqlite3_mprintf( "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID", azArg[2], zCollist, lenPK, zCollist); sqlite3_free(zCollist); rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum); if( rc==SQLITE_OK ){ rc = sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); if( rc ){ utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); }else{ utf8_printf(stdout, "%s;\n", zSql); raw_printf(stdout, "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n", azArg[1], isWO ? "table" : "index" ); } }else{ raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); rc = 1; } sqlite3_free(zSql); ................................................................................ session_close_all(p); close_db(p->db); p->db = 0; p->zDbFilename = 0; sqlite3_free(p->zFreeOnClose); p->zFreeOnClose = 0; p->openMode = SHELL_OPEN_UNSPEC; p->openFlags = 0; p->szMax = 0; /* Check for command-line arguments */ for(iName=1; iNameopenMode = 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; #ifdef SQLITE_ENABLE_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+1szMax = integerValue(azArg[++iName]); ................................................................................ { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" }, { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, #ifdef YYCOVERAGE { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, #endif { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, ................................................................................ isOk = 3; } break; /* sqlite3_test_control(int, int) */ case SQLITE_TESTCTRL_ASSERT: case SQLITE_TESTCTRL_ALWAYS: if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 1; } break; ................................................................................ case SQLITE_TESTCTRL_NEVER_CORRUPT: if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 3; } break; /* sqlite3_test_control(sqlite3*) */ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: rc2 = sqlite3_test_control(testctrl, p->db); isOk = 3; break; case SQLITE_TESTCTRL_IMPOSTER: if( nArg==5 ){ rc2 = sqlite3_test_control(testctrl, p->db, azArg[2], integerValue(azArg[3]), integerValue(azArg[4])); ................................................................................ #endif " -memtrace trace all memory allocations and deallocations\n" " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif " -newline SEP set output row separator. Default: '\\n'\n" " -nofollow refuse to open symbolic links to database files\n" " -nullvalue TEXT set text string for NULL values. Default ''\n" " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" " -quote set output mode to 'quote'\n" " -readonly open the database read-only\n" " -separator SEP set output column separator. Default: '|'\n" #ifdef SQLITE_ENABLE_SORTER_REFERENCES " -sorterref SIZE sorter references threshold size\n" ................................................................................ }else if( strcmp(z,"-deserialize")==0 ){ data.openMode = SHELL_OPEN_DESERIALIZE; }else if( strcmp(z,"-maxsize")==0 && i+1 Changes to src/smtp.c.  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 ** ** Use SMTP to send the email message contained in the file named EMAIL ** to the list of users TO. FROM is the sender of the email. ** ** Options: ** ** --direct Go directly to the TO domain. Bypass MX lookup ** --port N Use TCP port N instead of 25 ** --trace Show the SMTP conversation on the console */ void test_smtp_send(void){ SmtpSession *p; const char *zFrom; int nTo; const char *zToDomain; const char *zFromDomain; const char **azTo; int smtpPort = 25; const char *zPort; Blob body; u32 smtpFlags = SMTP_PORT; if( find_option("trace",0,0)!=0 ) smtpFlags |= SMTP_TRACE_STDOUT; if( find_option("direct",0,0)!=0 ) smtpFlags |= SMTP_DIRECT; zPort = find_option("port",0,1); if( zPort ) smtpPort = atoi(zPort); verify_all_options(); if( g.argc<5 ) usage("EMAIL FROM TO ..."); blob_read_from_file(&body, g.argv[2], ExtFILE); zFrom = g.argv[3]; nTo = g.argc-4; azTo = (const char**)g.argv+4; zFromDomain = domainOfAddr(zFrom); zToDomain = domainOfAddr(azTo[0]); p = smtp_session_new(zFromDomain, zToDomain, smtpFlags, smtpPort); if( p->zErr ){ fossil_fatal("%s", p->zErr); } fossil_print("Connection to \"%s\"\n", p->zHostname); smtp_client_startup(p); smtp_send_msg(p, zFrom, nTo, azTo, blob_str(&body)); > > > > > > > | > 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 ** ** Use SMTP to send the email message contained in the file named EMAIL ** to the list of users TO. FROM is the sender of the email. ** ** Options: ** ** --direct Go directly to the TO domain. Bypass MX lookup ** --relayhost R Use R as relay host directly for delivery. ** --port N Use TCP port N instead of 25 ** --trace Show the SMTP conversation on the console */ void test_smtp_send(void){ SmtpSession *p; const char *zFrom; int nTo; const char *zToDomain; const char *zFromDomain; const char *zRelay; const char **azTo; int smtpPort = 25; const char *zPort; Blob body; u32 smtpFlags = SMTP_PORT; if( find_option("trace",0,0)!=0 ) smtpFlags |= SMTP_TRACE_STDOUT; if( find_option("direct",0,0)!=0 ) smtpFlags |= SMTP_DIRECT; zPort = find_option("port",0,1); if( zPort ) smtpPort = atoi(zPort); zRelay = find_option("relayhost",0,1); verify_all_options(); if( g.argc<5 ) usage("EMAIL FROM TO ..."); blob_read_from_file(&body, g.argv[2], ExtFILE); zFrom = g.argv[3]; nTo = g.argc-4; azTo = (const char**)g.argv+4; zFromDomain = domainOfAddr(zFrom); if( zRelay!=0 && zRelay[0]!= 0) { smtpFlags |= SMTP_DIRECT; zToDomain = zRelay; }else{ zToDomain = domainOfAddr(azTo[0]); } p = smtp_session_new(zFromDomain, zToDomain, smtpFlags, smtpPort); if( p->zErr ){ fossil_fatal("%s", p->zErr); } fossil_print("Connection to \"%s\"\n", p->zHostname); smtp_client_startup(p); smtp_send_msg(p, zFrom, nTo, azTo, blob_str(&body)); Changes to src/sqlite3.c. more than 10,000 changes Changes to src/sqlite3.h.  119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 ... 512 513 514 515 516 517 518 519 520 521 522 523 524 525 ... 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 ... 564 565 566 567 568 569 570 571 572 573 574 575 576 577 ... 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 .... 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 .... 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 .... 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 .... 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 .... 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 .... 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 .... 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 .... 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 .... 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 .... 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 .... 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 .... 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 .... 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 .... 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 .... 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 .... 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 .... 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 .... 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 .... 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 .... 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 .... 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 .... 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 .... 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 .... 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 .... 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 .... 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 .... 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 .... 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 .... 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 .... 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 .... 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 .... 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 .... 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 .... 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 .... 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 .... 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 .... 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 .... 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 .... 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 .... 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 .... 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 .... 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 .... 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 .... 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 .... 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 .... 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 .... 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 .... 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 .... 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 .... 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 .... 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 ..... 10125 10126 10127 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 ..... 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 10551 10552 10553 10554 10555 10556 ..... 10717 10718 10719 10720 10721 10722 10723 10724 10725 10726 10727 10728 10729 10730 10731 ..... 11027 11028 11029 11030 11031 11032 11033 11034 11035 11036 11037 11038 11039 11040 11041 ..... 11435 11436 11437 11438 11439 11440 11441 11442 11443 11444 11445 11446 11447 11448 11449 ..... 11677 11678 11679 11680 11681 11682 11683 11684 11685 11686 11687 11688 11689 11690 11691 11692 ** 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.30.0" #define SQLITE_VERSION_NUMBER 3030000 #define SQLITE_SOURCE_ID "2019-10-04 15:03:17 c20a35336432025445f9f7e289d0cc3e4003fb17f45a4ce74c6269c407c6e09f" /* ** 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 ................................................................................ #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<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_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<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)) #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) ................................................................................ #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) #define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. ................................................................................ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ /* Reserved: 0x00F00000 */ /* ** CAPI3REF: Device Characteristics ** ** The xDeviceCharacteristics method of the [sqlite3_io_methods] ................................................................................ ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. ** ** • [[SQLITE_FCNTL_BUSYHANDLER]] ** ^The [SQLITE_FCNTL_BUSYHANDLER] ** file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points ** to a function of type (int (*)(void *)). In order to invoke the connections ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. ** ** • [[SQLITE_FCNTL_TEMPFILENAME]] ** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control ** to have SQLite generate a ** temporary filename using the same algorithm that is followed to generate ** temporary filenames for TEMP tables and other internal uses. The ** argument should be a char** which will be filled with the filename ** written into memory obtained from [sqlite3_malloc()]. The caller should ** invoke [sqlite3_free()] on the result to avoid a memory leak. ** ................................................................................ ** connection or through transactions committed by separate database ** connections possibly in other processes. The [sqlite3_total_changes()] ** interface can be used to find if any database on the connection has changed, ** but that interface responds to changes on TEMP as well as MAIN and does ** not provide a mechanism to detect changes to MAIN only. Also, the ** [sqlite3_total_changes()] interface responds to internal changes only and ** omits changes made by other database connections. The ** [PRAGMA data_version] command provide a mechanism to detect changes to ** a single attached database that occur due to other database connections, ** but omits changes implemented by the database connection on which it is ** called. This file control is the only mechanism to detect changes that ** happen either internally or externally and that are associated with ** a particular attached database. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 ................................................................................ #define SQLITE_FCNTL_PDB 30 #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 #define SQLITE_FCNTL_LOCK_TIMEOUT 34 #define SQLITE_FCNTL_DATA_VERSION 35 #define SQLITE_FCNTL_SIZE_LIMIT 36 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO ................................................................................ ** the end. Each time such an extension occurs, the iVersion field ** is incremented. The iVersion value started out as 1 in ** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 ** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased ** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields ** may be appended to the sqlite3_vfs object and the iVersion value ** may increase again in future versions of SQLite. ** Note that the structure ** of the sqlite3_vfs object changes in the transition from ** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] ** and yet the iVersion field was not modified. ** ** The szOsFile field is the size of the subclassed [sqlite3_file] ** structure used by this VFS. mxPathname is the maximum length of ** a pathname in this VFS. ** ** Registered sqlite3_vfs objects are kept on a linked list formed by ** the pNext pointer. The [sqlite3_vfs_register()] ................................................................................ ** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the ** SQLITE_OPEN_CREATE, is used to indicate that file should always ** be created, and that it is an error if it already exists. ** It is not used to indicate the file should be opened ** for exclusive access. ** ** ^At least szOsFile bytes of memory are allocated by SQLite ** to hold the [sqlite3_file] structure passed as the third ** argument to xOpen. The xOpen method does not have to ** allocate the structure; it should just fill it in. Note that ** the xOpen method must set the sqlite3_file.pMethods to either ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods ** element will be valid after xOpen returns regardless of the success ** or failure of the xOpen call. ................................................................................ ** allocators round up memory allocations at least to the next multiple ** of 8. Some allocators round up to a larger multiple or to a power of 2. ** Every memory allocation request coming in through [sqlite3_malloc()] ** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, ** that causes the corresponding memory allocation to fail. ** ** The xInit method initializes the memory allocator. For example, ** it might allocate any require mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite3_shutdown()] and should deallocate any resources acquired ** by xInit. The pAppData pointer is used as the only parameter to ** xInit and xShutdown. ** ** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes ** the xInit method, so the xInit method need not be threadsafe. The ................................................................................ ** ** [[SQLITE_CONFIG_MEMSTATUS]] SQLITE_CONFIG_MEMSTATUS ** ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: ** ** • [sqlite3_memory_used()] ** • [sqlite3_memory_highwater()] ** • [sqlite3_soft_heap_limit64()] ** • [sqlite3_status64()] ** )^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory ................................................................................ ** The SQLITE_CONFIG_SCRATCH option is no longer used. ** ** ** [[SQLITE_CONFIG_PAGECACHE]] SQLITE_CONFIG_PAGECACHE ** ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration option is a no-op if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to ** 8-byte aligned memory (pMem), the size of each page cache line (sz), ** and the number of cache lines (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 65536) plus some extra bytes for each ** page header. ^The number of extra bytes needed by the page header ................................................................................ ** additional information. This feature can also be turned on and off ** using the [PRAGMA legacy_alter_table] statement. ** ** ** [[SQLITE_DBCONFIG_DQS_DML]] ** SQLITE_DBCONFIG_DQS_DML ** The SQLITE_DBCONFIG_DQS_DML option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DML statement ** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The ** default value of this setting is determined by the [-DSQLITE_DQS] ** compile-time option. ** ** ** [[SQLITE_DBCONFIG_DQS_DDL]] ** SQLITE_DBCONFIG_DQS_DDL ** The SQLITE_DBCONFIG_DQS option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DDL statements, ** such as CREATE TABLE and CREATE INDEX. The ** default value of this setting is determined by the [-DSQLITE_DQS] ** compile-time option. ** ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ ................................................................................ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ #define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ #define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ #define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ #define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ #define SQLITE_DBCONFIG_MAX 1015 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result ................................................................................ ** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE ** that is inside an explicit transaction, then the entire transaction ** will be rolled back automatically. ** ** ^The sqlite3_interrupt(D) call is in effect until all currently running ** SQL statements on [database connection] D complete. ^Any new SQL statements ** that are started after the sqlite3_interrupt() call and before the ** running statements reaches zero are interrupted as if they had been ** running prior to the sqlite3_interrupt() call. ^New SQL statements ** that are started after the running statement count reaches zero are ** not effected by the sqlite3_interrupt(). ** ^A call to sqlite3_interrupt(D) that occurs when there are no running ** SQL statements is a no-op and has no effect on SQL statements ** that are started after the sqlite3_interrupt() call returns. */ ................................................................................ ** Name | Age ** ----------------------- ** Alice | 43 ** Bob | 28 ** Cindy | 21 ** ** ** There are two column (M==2) and three rows (N==3). Thus the ** result table has 8 entries. Suppose the result table is stored ** in an array names azResult. Then azResult holds this content: ** ** ** azResult[0] = "Name"; ** azResult[1] = "Age"; ** azResult[2] = "Alice"; ** azResult[3] = "43"; ** azResult[4] = "Bob"; ................................................................................ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem ** ** The SQLite core uses these three routines for all of its own ** internal memory allocation needs. "Core" in the previous sentence ** does not include operating-system specific VFS implementation. The ** Windows VFS uses native malloc() and free() for some operations. ** ** ^The sqlite3_malloc() routine returns a pointer to a block ** of memory at least N bytes in length, where N is the parameter. ** ^If sqlite3_malloc() is unable to obtain sufficient free ** memory, it returns a NULL pointer. ^If the parameter N to ** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns ................................................................................ ** ** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), ** sqlite3_malloc64(), and sqlite3_realloc64() ** is always aligned to at least an 8 byte boundary, or to a ** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time ** option is used. ** ** In SQLite version 3.5.0 and 3.5.1, it was possible to define ** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in ** implementation of these routines to be omitted. That capability ** is no longer provided. Only built-in memory allocators can be used. ** ** Prior to SQLite version 3.7.10, the Windows OS interface layer called ** the system malloc() and free() directly when converting ** filenames between the UTF-8 encoding used by SQLite ** and whatever filename encoding is used by the particular Windows ** installation. Memory allocation errors were detected, but ** they were reported back as [SQLITE_CANTOPEN] or ** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. ** ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] ** must be either NULL or else pointers obtained from a prior ** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have ** not yet been released. ** ** The application must not read or write any part of ** a block of memory after it has been released using ................................................................................ /* ** CAPI3REF: Pseudo-Random Number Generator ** ** SQLite contains a high-quality pseudo-random number generator (PRNG) used to ** select random [ROWID | ROWIDs] when inserting new records into a table that ** already uses the largest possible [ROWID]. The PRNG is also used for ** the build-in random() and randomblob() SQL functions. This interface allows ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. ** ^The P parameter can be a NULL pointer. ** ** ^If this routine has not been previously called or if the previous ** call had N less than one or a NULL pointer for P, then the PRNG is ................................................................................ ** Whether or not an error occurs when it is opened, resources ** associated with the [database connection] handle should be released by ** passing it to [sqlite3_close()] when it is no longer required. ** ** The sqlite3_open_v2() interface works like sqlite3_open() ** except that it accepts two additional parameters for additional control ** over the new database connection. ^(The flags parameter to ** sqlite3_open_v2() can take one of ** the following three values, optionally combined with the ** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], ** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ ** ** ** ^( [SQLITE_OPEN_READONLY] ** The database is opened in read-only mode. If the database does not ** already exist, an error is returned. )^ ** ** ^( [SQLITE_OPEN_READWRITE] ................................................................................ ** case the database must already exist, otherwise an error is returned.)^ ** ** ^( [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] ** The database is opened for reading and writing, and is created if ** it does not already exist. This is the behavior that is always used for ** sqlite3_open() and sqlite3_open16(). )^ ** ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. ** ** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection ** opens in the multi-thread [threading mode] as long as the single-thread ** mode has not been set at compile-time or start-time. ^If the ** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens ** in the serialized [threading mode] unless single-thread was ** previously selected at compile-time or start-time. ** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be ** eligible to use [shared cache mode], regardless of whether or not shared ** cache is enabled using [sqlite3_enable_shared_cache()]. ^The ** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not ** participate in [shared cache mode] even if it is enabled. ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. ** ** ^If the filename is ":memory:", then a private, temporary in-memory database ** is created for the connection. ^This in-memory database will vanish when ................................................................................ int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ); /* ** CAPI3REF: Obtain Values For URI Parameters ** ** These are utility routines, useful to VFS implementations, that check ** to see if a database file was a URI that contained a specific query ** parameter, and if so obtains the value of that query parameter. ** ** If F is the database filename pointer passed into the xOpen() method of ** a VFS implementation when the flags parameter to xOpen() has one or ** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and ** P is the name of the query parameter, then ** sqlite3_uri_parameter(F,P) returns the value of the P ** parameter if it exists or a NULL pointer if P does not appear as a ** query parameter on F. If P is a query parameter of F ** has no explicit value, then sqlite3_uri_parameter(F,P) returns ** a pointer to an empty string. ** ** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean ** parameter and returns true (1) or false (0) according to the value ** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the ** value of query parameter P is one of "yes", "true", or "on" in any ** case or if the value begins with a non-zero number. The ** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of ** query parameter P is one of "no", "false", or "off" in any case or ** if the value begins with a numeric zero. If P is not a query ** parameter on F or if the value of P is does not match any of the ** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). ** ** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a ** 64-bit signed integer and returns that integer, or D if P does not ** exist. If the value of P is something other than an integer, then ** zero is returned. ** ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and ** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and ** is not a database file pathname pointer that SQLite passed into the xOpen ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. ** ** See the [URI filename] documentation for additional information. */ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Error Codes And Messages ** METHOD: sqlite3 ** ** ^If the most recent sqlite3_* API call associated with ................................................................................ ** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code ** and the application would have to make a second call to [sqlite3_reset()] ** in order to find the underlying cause of the problem. With the "v2" prepare ** interfaces, the underlying reason for the error is returned immediately. ** • ** ** • ** ^If the specific value bound to [parameter | host parameter] in the ** WHERE clause might influence the choice of query plan for a statement, ** then the statement will be automatically recompiled, as if there had been ** a schema change, on the first [sqlite3_step()] call following any change ** to the [sqlite3_bind_text | bindings] of that [parameter]. ** ^The specific value of WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled. ** • ** ** ** ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having ................................................................................ ** ^The first argument to these interfaces is a [prepared statement]. ** ^These functions return information about the Nth result column returned by ** the statement, where N is the second function argument. ** ^The left-most column is column 0 for these routines. ** ** ^If the Nth column returned by the statement is an expression or ** subquery and is not a column value, then all of these functions return ** NULL. ^These routine might also return NULL if a memory allocation error ** occurs. ^Otherwise, they return the name of the attached database, table, ** or column that query result column was extracted from. ** ** ^As with all other SQLite APIs, those whose names end with "16" return ** UTF-16 encoded strings and the other functions return UTF-8. ** ** ^These APIs are only available if the library was compiled with the ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. ** ** If two or more threads call one or more of these routines against the same ** prepared statement and column at the same time then the results are ** undefined. ** ** If two or more threads call one or more ** [sqlite3_column_database_name | column metadata interfaces] ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); ................................................................................ /* ** CAPI3REF: Number of columns in a result set ** METHOD: sqlite3_stmt ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. ** ^If prepared statement P does not have results ready to return ** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of ** interfaces) then sqlite3_data_count(P) returns 0. ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. ** ^The sqlite3_data_count(P) routine returns 0 if the previous call to ** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) ** will return non-zero if previous call to [sqlite3_step](P) returned ** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] ** where it always returns zero since each step of that multi-step ................................................................................ ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} ** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior ** of existing SQL functions or aggregates. The only differences between ** the three "sqlite3_create_function*" routines are the text encoding ** expected for the second parameter (the name of the function being ................................................................................ ** deterministic. The built-in [random()] SQL function is an example of a ** function that is not deterministic. The SQLite query planner is able to ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs or TRIGGERs. For security reasons, the [SQLITE_DIRECTONLY] ** flag is recommended for any application-defined SQL function that has ** side-effects. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** ** ^The sixth, seventh and eighth parameters passed to the three ** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or ................................................................................ ** CAPI3REF: Function Flags ** ** These constants may be ORed together with the ** [SQLITE_UTF8 | preferred text encoding] as the fourth argument ** to [sqlite3_create_function()], [sqlite3_create_function16()], or ** [sqlite3_create_function_v2()]. ** ** The SQLITE_DETERMINISTIC flag means that the new function will always ** maps the same inputs into the same output. The abs() function is ** deterministic, for example, but randomblob() is not. ** ** The SQLITE_DIRECTONLY flag means that the function may only be invoked ** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. This is ** a security feature which is recommended for all ** [application-defined SQL functions] that have side-effects. This flag ** prevents an attacker from adding triggers and views to a schema then ** tricking a high-privilege application into causing unintended side-effects ** while performing ordinary queries. ** ** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. ** Specifying this flag makes no difference for scalar or aggregate user ** functions. However, if it is not specified for a user-defined window ** function, then any sub-types belonging to arguments passed to the window ** function may be discarded before the window function is called (i.e. ** sqlite3_value_subtype() will always return 0). */ #define SQLITE_DETERMINISTIC 0x000000800 #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 /* ** CAPI3REF: Deprecated Functions ** DEPRECATED ** ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ................................................................................ ** → True if value originated from a [bound parameter] ** ** ** Details: ** ** These routines extract type, size, and content information from ** [protected sqlite3_value] objects. Protected sqlite3_value objects ** are used to pass parameter information into implementation of ** [application-defined SQL functions] and [virtual tables]. ** ** These routines work only with [protected sqlite3_value] objects. ** Any attempt to use these routines on an [unprotected sqlite3_value] ** is not threadsafe. ** ** ^These routines work just like the corresponding [column access functions] ** except that these routines take a single [protected sqlite3_value] object ................................................................................ ** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other ** than within an [xUpdate] method call for an UPDATE statement, then ** the return value is arbitrary and meaningless. ** ** ^The sqlite3_value_frombind(X) interface returns non-zero if the ** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] ** interfaces. ^If X comes from an SQL literal value, or a table column, ** and expression, then sqlite3_value_frombind(X) returns zero. ** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** ................................................................................ ** CAPI3REF: Obtain Aggregate Function Context ** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. ** ** ^The first time the sqlite3_aggregate_context(C,N) routine is called ** for a particular aggregate function, SQLite ** allocates N of memory, zeroes out that memory, and returns a pointer ** to the new memory. ^On second and subsequent calls to ** sqlite3_aggregate_context() for the same aggregate function instance, ** the same buffer is returned. Sqlite3_aggregate_context() is normally ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ................................................................................ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer ** when first called if N is less than or equal to zero or if a memory ** allocate error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the ** value of N in subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ Within the xFinal callback, it is customary to set ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no ** pointless memory allocations occur. ** ** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes. ................................................................................ ** • [SQLITE_UTF8], ** • [SQLITE_UTF16LE], ** • [SQLITE_UTF16BE], ** • [SQLITE_UTF16], or ** • [SQLITE_UTF16_ALIGNED]. ** )^ ** ^The eTextRep argument determines the encoding of strings passed ** to the collating function callback, xCallback. ** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep ** force strings to be UTF16 with native byte order. ** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin ** on an even byte address. ** ** ^The fourth argument, pArg, is an application data pointer that is passed ** through as the first argument to the collating function callback. ** ** ^The fifth argument, xCallback, is a pointer to the collating function. ** ^Multiple collating functions can be registered using the same name but ** with different eTextRep parameters and SQLite will use whichever ** function requires the least amount of data transformation. ** ^If the xCallback argument is NULL then the collating function is ** deleted. ^When all collating functions having the same name are deleted, ** that collation is no longer usable. ** ** ^The collating function callback is invoked with a copy of the pArg ** application data pointer and with two strings in the encoding specified ** by the eTextRep argument. The collating function must return an ** integer that is negative, zero, or positive ** if the first string is less than, equal to, or greater than the second, ** respectively. A collating function must always return the same answer ** given the same inputs. If two or more collating functions are registered ** to the same collation name (using different eTextRep values) then all ** must give an equivalent answer when invoked with equivalent strings. ** The collating function must obey the following properties for all ** strings A, B, and C: ................................................................................ ** • If A==B then B==A. ** • If A==B and B==C then A==C. ** • If A<B THEN B>A. ** • If A<B and B<C then A<C. ** ** ** If a collating function fails any of the above constraints and that ** collating function is registered and used, then the behavior of SQLite ** is undefined. ** ** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() ** with the addition that the xDestroy callback is invoked on pArg when ** the collating function is deleted. ** ^Collating functions are deleted when they are overridden by later ** calls to the collation creation functions or when the ................................................................................ */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename ** associated with database N of connection D. ^The main database file ** has the name "main". If there is no attached database N on the database ** connection D, or if database N is a temporary or in-memory database, then ** this function will return either a NULL pointer or an empty string. ** ** ^The filename returned by this function is the output of the ** xFullPathname method of the [VFS]. ^In other words, the filename ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only ** METHOD: sqlite3 ** ................................................................................ ** ^Cache sharing is enabled and disabled for an entire process. ** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). ** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent ** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. ** Existing database connections continue use the sharing mode ** that was in effect at the time they were opened.)^ ** ** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled ** successfully. An [error code] is returned otherwise.)^ ** ** ^Shared cache is disabled by default. But this might change in ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** ** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 ** and will always return SQLITE_MISUSE. On those systems, ** shared cache mode should be enabled per-database connection via ** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. ** ** This interface is threadsafe on processors where writing a ................................................................................ ** ** See also: [sqlite3_release_memory()] */ SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size ** ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the ** soft limit on the amount of heap memory that may be allocated by SQLite. ** ^SQLite strives to keep heap memory utilization below the soft heap ** limit by reducing the number of pages held in the page cache ** as heap memory usages approaches the limit. ** ^The soft heap limit is "soft" because even though SQLite strives to stay ** below the limit, it will exceed the limit rather than generate ** an [SQLITE_NOMEM] error. In other words, the soft heap limit ** is advisory only. ** ** ^The return value from sqlite3_soft_heap_limit64() is the size of ** the soft heap limit prior to the call, or negative in the case of an ** error. ^If the argument N is negative ** then no change is made to the soft heap limit. Hence, the current ** size of the soft heap limit can be determined by invoking ** sqlite3_soft_heap_limit64() with a negative argument. ** ** ^If the argument N is zero then the soft heap limit is disabled. ** ** ^(The soft heap limit is not enforced in the current implementation ** if one or more of following conditions are true: ** ** ** • The soft heap limit is set to zero. ** • Memory accounting is disabled using a combination of the ** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and ** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. ** • An alternative page cache implementation is specified using ** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). ** • The page cache allocates from its own memory pool supplied ** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than ** from the heap. ** )^ ** ** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]), ** the soft heap limit is enforced ** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] ** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], ** the soft heap limit is enforced on every memory allocation. Without ** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced ** when memory is allocated by the page cache. Testing suggests that because ** the page cache is the predominate memory user in SQLite, most ** applications will achieve adequate soft heap limit enforcement without ** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. ** ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface ** DEPRECATED ** ** This is a deprecated version of the [sqlite3_soft_heap_limit64()] ** interface. This routine is provided for historical compatibility ................................................................................ ** ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns ** information about column C of table T in database D ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() ** interface returns SQLITE_OK and fills in the non-NULL pointers in ** the final five arguments with appropriate values if the specified ** column exists. ^The sqlite3_table_column_metadata() interface returns ** SQLITE_ERROR and if the specified column does not exist. ** ^If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then this routine simply checks for the existence of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it ** does not. If the table name parameter T in a call to ** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is ** undefined behavior. ** ................................................................................ ** ** ^This interface enables or disables both the C-API ** [sqlite3_load_extension()] and the SQL function [load_extension()]. ** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) ** to enable or disable only the C-API.)^ ** ** Security warning: It is recommended that extension loading ** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method ** rather than this interface, so the [load_extension()] SQL function ** remains disabled. This will prevent SQL injections from giving attackers ** access to extension loading capabilities. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ................................................................................ typedef struct sqlite3_module sqlite3_module; /* ** CAPI3REF: Virtual Table Object ** KEYWORDS: sqlite3_module {virtual table module} ** ** This structure, sometimes called a "virtual table module", ** defines the implementation of a [virtual tables]. ** This structure consists mostly of methods for the module. ** ** ^A virtual table module is created by filling in a persistent ** instance of this structure and passing a pointer to that instance ** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. ** ^The registration remains valid until it is replaced by a different ** module or until the [database connection] closes. The content ................................................................................ ** non-zero. ** ** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the ** virtual table and is not checked again by SQLite.)^ ** ** ^The idxNum and idxPtr values are recorded and passed into the ** [xFilter] method. ** ^[sqlite3_free()] is used to free idxPtr if and only if ** needToFreeIdxPtr is true. ** ** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in ................................................................................ ** the xUpdate method are automatically rolled back by SQLite. ** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info ** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). ** If a virtual table extension is ** used with an SQLite version earlier than 3.8.2, the results of attempting ** to read or write the estimatedRows field are undefined (but are likely ** to included crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a ** value greater than or equal to 3008002. Similarly, the idxFlags field ** was added for [version 3.9.0] ([dateof:3.9.0]). ** It may therefore only be used if ** sqlite3_libversion_number() returns a value greater than or equal to ** 3009000. */ ................................................................................ ** these bits. */ #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** ** These macros defined the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents ** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. */ #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 ................................................................................ ** • [sqlite3_mutex_held()] • ** • [sqlite3_mutex_notheld()] • ** )^ ** ** The only difference is that the public sqlite3_XXX functions enumerated ** above silently ignore any invocations that pass a NULL pointer instead ** of a valid mutex handle. The implementations of the methods defined ** by this structure are not required to handle this case, the results ** of passing a NULL pointer instead of a valid mutex handle are undefined ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). ** ** The xMutexInit() method must be threadsafe. It must be harmless to ** invoke xMutexInit() multiple times within the same process and without ** intervening calls to xMutexEnd(). Second and subsequent calls to ................................................................................ ** returned value includes allocations that overflowed because they ** where too large (they were larger than the "sz" parameter to ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because ** no space was left in the page cache.)^ ** ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^( SQLITE_STATUS_PAGECACHE_SIZE ** This parameter records the largest memory allocation request ** handed to [pagecache memory allocator]. Only the value returned in the ** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined. )^ ** ** [[SQLITE_STATUS_SCRATCH_USED]] SQLITE_STATUS_SCRATCH_USED ** No longer used. ** ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^( SQLITE_STATUS_SCRATCH_OVERFLOW ................................................................................ ** ** ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^( SQLITE_DBSTATUS_LOOKASIDE_USED ** This parameter returns the number of lookaside memory slots currently ** checked out. )^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^( SQLITE_DBSTATUS_LOOKASIDE_HIT ** This parameter returns the number malloc attempts that were ** satisfied using lookaside memory. Only the high-water value is meaningful; ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] ** ^( SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE ** This parameter returns the number malloc attempts that might have ** been satisfied using lookaside memory but failed due to the amount of ................................................................................ ** ** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^( SQLITE_DBSTATUS_CACHE_SPILL ** This parameter returns the number of dirty cache entries that have ** been written to disk in the middle of a transaction due to the page ** cache overflowing. Transactions are more efficient if they are written ** to disk all at once. When pages spill mid-transaction, that introduces ** additional overhead. This parameter can be used help identify ** inefficiencies that can be resolve by increasing the cache size. ** ** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^( SQLITE_DBSTATUS_DEFERRED_FKS ** This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been ** resolved.)^ ^The highwater mark is always 0. ** ................................................................................ ** to 2147483647. The number of virtual machine operations can be ** used as a proxy for the total work done by the prepared statement. ** If the number of virtual machine operations exceeds 2147483647 ** then the value returned by this statement status code is undefined. ** ** [[SQLITE_STMTSTATUS_REPREPARE]] SQLITE_STMTSTATUS_REPREPARE ** ^This is the number of times that the prepare statement has been ** automatically regenerated due to schema changes or change to ** [bound parameters] that might affect the query plan. ** ** [[SQLITE_STMTSTATUS_RUN]] SQLITE_STMTSTATUS_RUN ** ^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ................................................................................ ** Otherwise return NULL. ** 2 Make every effort to allocate a new page. Only return ** NULL if allocating a new page is effectively impossible. ** ** ** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite ** will only use a createFlag of 2 after a prior call with a createFlag of 1 ** failed.)^ In between the to xFetch() calls, SQLite may ** attempt to unpin one or more cache pages by spilling the content of ** pinned pages to disk and synching the operating system disk cache. ** ** [[the xUnpin() page cache method]] ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page ** as its second argument. If the third parameter, discard, is non-zero, ** then the page must be evicted from the cache. ................................................................................ ** identity of the database connection (the blocking connection) that ** has locked the required resource is stored internally. ^After an ** application receives an SQLITE_LOCKED error, it may call the ** sqlite3_unlock_notify() method with the blocked connection handle as ** the first argument to register for a callback that will be invoked ** when the blocking connections current transaction is concluded. ^The ** callback is invoked from within the [sqlite3_step] or [sqlite3_close] ** call that concludes the blocking connections transaction. ** ** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, ** there is a chance that the blocking connection will have already ** concluded its transaction by the time sqlite3_unlock_notify() is invoked. ** If this happens, then the specified callback is invoked immediately, ** from within the call to sqlite3_unlock_notify().)^ ** ................................................................................ ** When an unlock-notify callback is registered, the application provides a ** single void* pointer that is passed to the callback when it is invoked. ** However, the signature of the callback function allows SQLite to pass ** it an array of void* context pointers. The first argument passed to ** an unlock-notify callback is a pointer to an array of void* pointers, ** and the second is the number of entries in the array. ** ** When a blocking connections transaction is concluded, there may be ** more than one blocked connection that has registered for an unlock-notify ** callback. ^If two or more such blocked connections have specified the ** same callback function, then instead of invoking the callback function ** multiple times, it is invoked once with the set of void* context pointers ** specified by the blocked connections bundled together into an array. ** This gives the application an opportunity to prioritize any actions ** related to the set of unblocked database connections. ................................................................................ ** This function may be called by either the [xConnect] or [xCreate] method ** of a [virtual table] implementation to configure ** various facets of the virtual table interface. ** ** If this interface is invoked outside the context of an xConnect or ** xCreate virtual table method then the behavior is undefined. ** ** At present, there is only one option that may be configured using ** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options ** may be added in the future. */ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options ** ** These macros define the various options to the ** [sqlite3_vtab_config()] interface that [virtual table] implementations ** can use to customize and optimize their behavior. ** ** ** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] ** SQLITE_VTAB_CONSTRAINT_SUPPORT ** Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** where X is an integer. If X is zero, then the [virtual table] whose ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not ** support constraints. In this configuration (which is the default) if ** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire ** statement is rolled back as if [ON CONFLICT | OR ABORT] had been ................................................................................ ** must do so within the [xUpdate] method. If a call to the ** [sqlite3_vtab_on_conflict()] function indicates that the current ON ** CONFLICT policy is REPLACE, the virtual table implementation should ** silently replace the appropriate rows within the xUpdate callback and ** return SQLITE_OK. Or, if this is not possible, it may return ** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT ** constraint handling. ** */ #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 /* ** CAPI3REF: Determine The Virtual Table Conflict Policy ** ** This function may only be called from within a call to the [xUpdate] method ** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The ** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], ................................................................................ ** ** When the value returned to V is a string, space to hold that string is ** managed by the prepared statement S and will be automatically freed when ** S is finalized. ** ** ** [[SQLITE_SCANSTAT_NLOOP]] SQLITE_SCANSTAT_NLOOP ** ^The [sqlite3_int64] variable pointed to by the T parameter will be ** set to the total number of times that the X-th loop has run. ** ** [[SQLITE_SCANSTAT_NVISIT]] SQLITE_SCANSTAT_NVISIT ** ^The [sqlite3_int64] variable pointed to by the T parameter will be set ** to the total number of rows examined by all iterations of the X-th loop. ** ** [[SQLITE_SCANSTAT_EST]] SQLITE_SCANSTAT_EST ** ^The "double" variable pointed to by the T parameter will be set to the ** query planner's estimate for the average number of rows output from each ** iteration of the X-th loop. If the query planner's estimates was accurate, ** then this value will approximate the quotient NVISIT/NLOOP and the ** product of this value for all prior loops with the same SELECTID will ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]] SQLITE_SCANSTAT_NAME ** ^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the name of the index or table ** used for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]] SQLITE_SCANSTAT_EXPLAIN ** ^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] ** description for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]] SQLITE_SCANSTAT_SELECT ** ^The "int" variable pointed to by the T parameter will be set to the ** "select-id" for the X-th loop. The select-id identifies which query or ** subquery the loop is part of. The main query has a select-id of zero. ** The select-id is the same value as is output in the first column ** of an [EXPLAIN QUERY PLAN] query. ** */ #define SQLITE_SCANSTAT_NLOOP 0 ................................................................................ /* ** CAPI3REF: Set a table filter on a Session Object. ** METHOD: sqlite3_session ** ** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called ** to determine whether changes to the table's rows should be tracked or not. ** If xFilter returns 0, changes is not tracked. Note that once a table is ** attached, xFilter will not be called again. */ SQLITE_API void sqlite3session_table_filter( sqlite3_session *pSession, /* Session object */ int(*xFilter)( void *pCtx, /* Copy of third arg to _filter_table() */ const char *zTab /* Table name */ ................................................................................ ** using [sqlite3session_changeset()], then after applying that changeset to ** database zFrom the contents of the two compatible tables would be ** identical. ** ** It an error if database zFrom does not exist or does not contain the ** required compatible table. ** ** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite ** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg ** may be set to point to a buffer containing an English language error ** message. It is the responsibility of the caller to free this buffer using ** sqlite3_free(). */ SQLITE_API int sqlite3session_diff( sqlite3_session *pSession, ................................................................................ #define SQLITE_CHANGESETSTART_INVERT 0x0002 /* ** CAPI3REF: Advance A Changeset Iterator ** METHOD: sqlite3_changeset_iter ** ** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to ** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE ** is returned and the call has no effect. ** ** Immediately after an iterator is created by sqlite3changeset_start(), it ** does not point to any change in the changeset. Assuming the changeset ** is not empty, the first call to this function advances the iterator to ................................................................................ ** ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the ** case, this function fails with SQLITE_SCHEMA. If the input changeset ** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is ** returned. Or, if an out-of-memory condition occurs during processing, this ** function returns SQLITE_NOMEM. In all cases, if an error occurs the ** final contents of the changegroup is undefined. ** ** If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup ................................................................................ ** This includes the case where the UPDATE operation is attempted after ** an earlier call to the conflict handler function returned ** [SQLITE_CHANGESET_REPLACE]. ** ** ** It is safe to execute SQL statements, including those that write to the ** table that the callback related to, from within the xConflict callback. ** This can be used to further customize the applications conflict ** resolution strategy. ** ** All changes made by these functions are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. ................................................................................ /* ** CAPI3REF: Rebase a changeset ** EXPERIMENTAL ** ** Argument pIn must point to a buffer containing a changeset nIn bytes ** in size. This function allocates and populates a buffer with a copy ** of the changeset rebased rebased according to the configuration of the ** rebaser object passed as the first argument. If successful, (*ppOut) ** is set to point to the new buffer containing the rebased changeset and ** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the ** responsibility of the caller to eventually free the new buffer using ** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) ** are set to zero and an SQLite error code returned. */ ................................................................................ ** If the query runs to completion without incident, SQLITE_OK is returned. ** Or, if some error occurs before the query completes or is aborted by ** the callback, an SQLite error code is returned. ** ** ** xSetAuxdata(pFts5, pAux, xDelete) ** ** Save the pointer passed as the second argument as the extension functions ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of ** the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for ** each FTS query (MATCH expression). If the extension function is invoked ** more than once for a single FTS query, then all invocations share a ................................................................................ ** of "first place" within the document set, but not alternative forms ** such as "1st place". In some applications, it would be better to match ** all instances of "first place" or "1st place" regardless of which form ** the user specified in the MATCH query text. ** ** There are several ways to approach this in FTS5: ** ** 1. By mapping all synonyms to a single token. In this case, the ** In the above example, this means that the tokenizer returns the ** same token for inputs "first" and "1st". Say that token is in ** fact "first", so that when the user inserts the document "I won ** 1st place" entries are added to the index for tokens "i", "won", ** "first" and "place". If the user then queries for '1st + place', ** the tokenizer substitutes "first" for "1st" and the query works ** as expected. ** | | | > > > > | | | | > > > > > > > | | | | | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | < < < < < < < < < < < < < | | | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < | | | < | | | > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | < < < < | < < | > > > > | < > > > > > > > > > > | < > | > > > > > > | > | > > | | < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | > | | | | | > > > > > > > > > > > > > > > | | | | > > > > > > > > > > > > > > | | | | | < > > > > > > > > > > > > > > > | | < < < < < < < < < < < | > | | | | > > > > > > | | | | | | | | | | | | | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 ... 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 ... 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 ... 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 ... 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 .... 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 .... 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 .... 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 .... 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 .... 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 .... 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 .... 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 .... 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 .... 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 .... 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 .... 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 .... 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 .... 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 .... 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 .... 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 .... 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 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 .... 3525 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 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 .... 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 .... 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 .... 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 .... 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 .... 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 .... 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 .... 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 .... 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 .... 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 .... 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 .... 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 .... 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 .... 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 .... 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 .... 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 .... 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 .... 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 .... 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 .... 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 .... 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 .... 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 .... 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 .... 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 .... 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 .... 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 .... 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 .... 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 .... 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 .... 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 .... 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 .... 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 .... 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 ..... 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 ..... 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 ..... 10352 10353 10354 10355 10356 10357 10358 10359 10360 10361 10362 10363 10364 10365 10366 ..... 10768 10769 10770 10771 10772 10773 10774 10775 10776 10777 10778 10779 10780 10781 10782 10783 ..... 10944 10945 10946 10947 10948 10949 10950 10951 10952 10953 10954 10955 10956 10957 10958 ..... 11254 11255 11256 11257 11258 11259 11260 11261 11262 11263 11264 11265 11266 11267 11268 ..... 11662 11663 11664 11665 11666 11667 11668 11669 11670 11671 11672 11673 11674 11675 11676 ..... 11904 11905 11906 11907 11908 11909 11910 11911 11912 11913 11914 11915 11916 11917 11918 11919 ** 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.31.0" #define SQLITE_VERSION_NUMBER 3031000 #define SQLITE_SOURCE_ID "2020-01-22 18:38:59 f6affdd41608946fcfcea914ece149038a8b25a62bbe719ed2561c649b86d824" /* ** 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 ................................................................................ #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<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_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)) #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) ................................................................................ #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) #define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) #define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) #define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. ................................................................................ #define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ /* Reserved: 0x00F00000 */ /* ** CAPI3REF: Device Characteristics ** ** The xDeviceCharacteristics method of the [sqlite3_io_methods] ................................................................................ ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. ** ** 2. [[SQLITE_FCNTL_BUSYHANDLER]] ** ^The [SQLITE_FCNTL_BUSYHANDLER] ** file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connection's busy-handler callback. The argument is of type (void**) ** - an array of two (void *) values. The first (void *) actually points ** to a function of type (int (*)(void *)). In order to invoke the connection's ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. ** ** 3. [[SQLITE_FCNTL_TEMPFILENAME]] ** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control ** to have SQLite generate a ** temporary filename using the same algorithm that is followed to generate ** temporary filenames for TEMP tables and other internal uses. The ** argument should be a char** which will be filled with the filename ** written into memory obtained from [sqlite3_malloc()]. The caller should ** invoke [sqlite3_free()] on the result to avoid a memory leak. ** ................................................................................ ** connection or through transactions committed by separate database ** connections possibly in other processes. The [sqlite3_total_changes()] ** interface can be used to find if any database on the connection has changed, ** but that interface responds to changes on TEMP as well as MAIN and does ** not provide a mechanism to detect changes to MAIN only. Also, the ** [sqlite3_total_changes()] interface responds to internal changes only and ** omits changes made by other database connections. The ** [PRAGMA data_version] command provides a mechanism to detect changes to ** a single attached database that occur due to other database connections, ** but omits changes implemented by the database connection on which it is ** called. This file control is the only mechanism to detect changes that ** happen either internally or externally and that are associated with ** a particular attached database. ** ** 4. [[SQLITE_FCNTL_CKPT_DONE]] ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 ................................................................................ #define SQLITE_FCNTL_PDB 30 #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 #define SQLITE_FCNTL_LOCK_TIMEOUT 34 #define SQLITE_FCNTL_DATA_VERSION 35 #define SQLITE_FCNTL_SIZE_LIMIT 36 #define SQLITE_FCNTL_CKPT_DONE 37 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO ................................................................................ ** the end. Each time such an extension occurs, the iVersion field ** is incremented. The iVersion value started out as 1 in ** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 ** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased ** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields ** may be appended to the sqlite3_vfs object and the iVersion value ** may increase again in future versions of SQLite. ** Note that due to an oversight, the structure ** of the sqlite3_vfs object changed in the transition from ** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] ** and yet the iVersion field was not increased. ** ** The szOsFile field is the size of the subclassed [sqlite3_file] ** structure used by this VFS. mxPathname is the maximum length of ** a pathname in this VFS. ** ** Registered sqlite3_vfs objects are kept on a linked list formed by ** the pNext pointer. The [sqlite3_vfs_register()] ................................................................................ ** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the ** SQLITE_OPEN_CREATE, is used to indicate that file should always ** be created, and that it is an error if it already exists. ** It is not used to indicate the file should be opened ** for exclusive access. ** ** ^At least szOsFile bytes of memory are allocated by SQLite ** to hold the [sqlite3_file] structure passed as the third ** argument to xOpen. The xOpen method does not have to ** allocate the structure; it should just fill it in. Note that ** the xOpen method must set the sqlite3_file.pMethods to either ** a valid [sqlite3_io_methods] object or to NULL. xOpen must do ** this even if the open fails. SQLite expects that the sqlite3_file.pMethods ** element will be valid after xOpen returns regardless of the success ** or failure of the xOpen call. ................................................................................ ** allocators round up memory allocations at least to the next multiple ** of 8. Some allocators round up to a larger multiple or to a power of 2. ** Every memory allocation request coming in through [sqlite3_malloc()] ** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, ** that causes the corresponding memory allocation to fail. ** ** The xInit method initializes the memory allocator. For example, ** it might allocate any required mutexes or initialize internal data ** structures. The xShutdown method is invoked (indirectly) by ** [sqlite3_shutdown()] and should deallocate any resources acquired ** by xInit. The pAppData pointer is used as the only parameter to ** xInit and xShutdown. ** ** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes ** the xInit method, so the xInit method need not be threadsafe. The ................................................................................ ** ** [[SQLITE_CONFIG_MEMSTATUS]] SQLITE_CONFIG_MEMSTATUS ** ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: ** ** • [sqlite3_hard_heap_limit64()] ** • [sqlite3_memory_used()] ** • [sqlite3_memory_highwater()] ** • [sqlite3_soft_heap_limit64()] ** • [sqlite3_status64()] ** )^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory ................................................................................ ** The SQLITE_CONFIG_SCRATCH option is no longer used. ** ** ** [[SQLITE_CONFIG_PAGECACHE]] SQLITE_CONFIG_PAGECACHE ** ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration option is a no-op if an application-defined page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to ** 8-byte aligned memory (pMem), the size of each page cache line (sz), ** and the number of cache lines (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 65536) plus some extra bytes for each ** page header. ^The number of extra bytes needed by the page header ................................................................................ ** additional information. This feature can also be turned on and off ** using the [PRAGMA legacy_alter_table] statement. ** ** ** [[SQLITE_DBCONFIG_DQS_DML]] ** SQLITE_DBCONFIG_DQS_DML → True if value originated from a [bound parameter] ** ** ** Details: ** ** These routines extract type, size, and content information from ** [protected sqlite3_value] objects. Protected sqlite3_value objects ** are used to pass parameter information into the functions that ** implement [application-defined SQL functions] and [virtual tables]. ** ** These routines work only with [protected sqlite3_value] objects. ** Any attempt to use these routines on an [unprotected sqlite3_value] ** is not threadsafe. ** ** ^These routines work just like the corresponding [column access functions] ** except that these routines take a single [protected sqlite3_value] object ................................................................................ ** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other ** than within an [xUpdate] method call for an UPDATE statement, then ** the return value is arbitrary and meaningless. ** ** ^The sqlite3_value_frombind(X) interface returns non-zero if the ** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] ** interfaces. ^If X comes from an SQL literal value, or a table column, ** or an expression, then sqlite3_value_frombind(X) returns zero. ** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** ................................................................................ ** CAPI3REF: Obtain Aggregate Function Context ** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. ** ** ^The first time the sqlite3_aggregate_context(C,N) routine is called ** for a particular aggregate function, SQLite allocates ** N bytes of memory, zeroes out that memory, and returns a pointer ** to the new memory. ^On second and subsequent calls to ** sqlite3_aggregate_context() for the same aggregate function instance, ** the same buffer is returned. Sqlite3_aggregate_context() is normally ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ................................................................................ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer ** when first called if N is less than or equal to zero or if a memory ** allocate error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the ** value of N in any subsequents call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ Within the xFinal callback, it is customary to set ** N=0 in calls to sqlite3_aggregate_context(C,N) so that no ** pointless memory allocations occur. ** ** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes. ................................................................................ ** • [SQLITE_UTF8], ** • [SQLITE_UTF16LE], ** • [SQLITE_UTF16BE], ** • [SQLITE_UTF16], or ** • [SQLITE_UTF16_ALIGNED]. ** )^ ** ^The eTextRep argument determines the encoding of strings passed ** to the collating function callback, xCompare. ** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep ** force strings to be UTF16 with native byte order. ** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin ** on an even byte address. ** ** ^The fourth argument, pArg, is an application data pointer that is passed ** through as the first argument to the collating function callback. ** ** ^The fifth argument, xCompare, is a pointer to the collating function. ** ^Multiple collating functions can be registered using the same name but ** with different eTextRep parameters and SQLite will use whichever ** function requires the least amount of data transformation. ** ^If the xCompare argument is NULL then the collating function is ** deleted. ^When all collating functions having the same name are deleted, ** that collation is no longer usable. ** ** ^The collating function callback is invoked with a copy of the pArg ** application data pointer and with two strings in the encoding specified ** by the eTextRep argument. The two integer parameters to the collating ** function callback are the length of the two strings, in bytes. The collating ** function must return an integer that is negative, zero, or positive ** if the first string is less than, equal to, or greater than the second, ** respectively. A collating function must always return the same answer ** given the same inputs. If two or more collating functions are registered ** to the same collation name (using different eTextRep values) then all ** must give an equivalent answer when invoked with equivalent strings. ** The collating function must obey the following properties for all ** strings A, B, and C: ................................................................................ ** • If A==B then B==A. ** • If A==B and B==C then A==C. ** • If A<B THEN B>A. ** • If A<B and B<C then A<C. ** ** ** If a collating function fails any of the above constraints and that ** collating function is registered and used, then the behavior of SQLite ** is undefined. ** ** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() ** with the addition that the xDestroy callback is invoked on pArg when ** the collating function is deleted. ** ^Collating functions are deleted when they are overridden by later ** calls to the collation creation functions or when the ................................................................................ */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename ** associated with database N of connection D. ** ^If there is no attached database N on the database ** connection D, or if database N is a temporary or in-memory database, then ** this function will return either a NULL pointer or an empty string. ** ** ^The string value returned by this routine is owned and managed by ** the database connection. ^The value will be valid until the database N ** is [DETACH]-ed or until the database connection closes. ** ** ^The filename returned by this function is the output of the ** xFullPathname method of the [VFS]. ^In other words, the filename ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. ** ** If the filename pointer returned by this routine is not NULL, then it ** can be used as the filename input parameter to these routines: ** ** • [sqlite3_uri_parameter()] ** • [sqlite3_uri_boolean()] ** • [sqlite3_uri_int64()] ** • [sqlite3_filename_database()] ** • [sqlite3_filename_journal()] ** • [sqlite3_filename_wal()] ** */ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only ** METHOD: sqlite3 ** ................................................................................ ** ^Cache sharing is enabled and disabled for an entire process. ** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). ** In prior versions of SQLite, ** sharing was enabled or disabled for each thread separately. ** ** ^(The cache sharing mode set by this interface effects all subsequent ** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. ** Existing database connections continue to use the sharing mode ** that was in effect at the time they were opened.)^ ** ** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled ** successfully. An [error code] is returned otherwise.)^ ** ** ^Shared cache is disabled by default. It is recommended that it stay ** that way. In other words, do not use this routine. This interface ** continues to be provided for historical compatibility, but its use is ** discouraged. Any use of shared cache is discouraged. If shared cache ** must be used, it is recommended that shared cache only be enabled for ** individual database connections using the [sqlite3_open_v2()] interface ** with the [SQLITE_OPEN_SHAREDCACHE] flag. ** ** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 ** and will always return SQLITE_MISUSE. On those systems, ** shared cache mode should be enabled per-database connection via ** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. ** ** This interface is threadsafe on processors where writing a ................................................................................ ** ** See also: [sqlite3_release_memory()] */ SQLITE_API int sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size ** ** These interfaces impose limits on the amount of heap memory that will be ** by all database connections within a single process. ** ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the ** soft limit on the amount of heap memory that may be allocated by SQLite. ** ^SQLite strives to keep heap memory utilization below the soft heap ** limit by reducing the number of pages held in the page cache ** as heap memory usages approaches the limit. ** ^The soft heap limit is "soft" because even though SQLite strives to stay ** below the limit, it will exceed the limit rather than generate ** an [SQLITE_NOMEM] error. In other words, the soft heap limit ** is advisory only. ** ** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of ** N bytes on the amount of memory that will be allocated. ^The ** sqlite3_hard_heap_limit64(N) interface is similar to ** sqlite3_soft_heap_limit64(N) except that memory allocations will fail ** when the hard heap limit is reached. ** ** ^The return value from both sqlite3_soft_heap_limit64() and ** sqlite3_hard_heap_limit64() is the size of ** the heap limit prior to the call, or negative in the case of an ** error. ^If the argument N is negative ** then no change is made to the heap limit. Hence, the current ** size of heap limits can be determined by invoking ** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1). ** ** ^Setting the heap limits to zero disables the heap limiter mechanism. ** ** ^The soft heap limit may not be greater than the hard heap limit. ** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N) ** is invoked with a value of N that is greater than the hard heap limit, ** the the soft heap limit is set to the value of the hard heap limit. ** ^The soft heap limit is automatically enabled whenever the hard heap ** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and ** the soft heap limit is outside the range of 1..N, then the soft heap ** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the ** hard heap limit is enabled makes the soft heap limit equal to the ** hard heap limit. ** ** The memory allocation limits can also be adjusted using ** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit]. ** ** ^(The heap limits are not enforced in the current implementation ** if one or more of following conditions are true: ** ** ** • The limit value is set to zero. ** • Memory accounting is disabled using a combination of the ** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and ** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. ** • An alternative page cache implementation is specified using ** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). ** • The page cache allocates from its own memory pool supplied ** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than ** from the heap. ** )^ ** ** The circumstances under which SQLite will enforce the heap limits may ** changes in future releases of SQLite. */ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface ** DEPRECATED ** ** This is a deprecated version of the [sqlite3_soft_heap_limit64()] ** interface. This routine is provided for historical compatibility ................................................................................ ** ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns ** information about column C of table T in database D ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() ** interface returns SQLITE_OK and fills in the non-NULL pointers in ** the final five arguments with appropriate values if the specified ** column exists. ^The sqlite3_table_column_metadata() interface returns ** SQLITE_ERROR if the specified column does not exist. ** ^If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then this routine simply checks for the existence of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it ** does not. If the table name parameter T in a call to ** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is ** undefined behavior. ** ................................................................................ ** ** ^This interface enables or disables both the C-API ** [sqlite3_load_extension()] and the SQL function [load_extension()]. ** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) ** to enable or disable only the C-API.)^ ** ** Security warning: It is recommended that extension loading ** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method ** rather than this interface, so the [load_extension()] SQL function ** remains disabled. This will prevent SQL injections from giving attackers ** access to extension loading capabilities. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ................................................................................ typedef struct sqlite3_module sqlite3_module; /* ** CAPI3REF: Virtual Table Object ** KEYWORDS: sqlite3_module {virtual table module} ** ** This structure, sometimes called a "virtual table module", ** defines the implementation of a [virtual table]. ** This structure consists mostly of methods for the module. ** ** ^A virtual table module is created by filling in a persistent ** instance of this structure and passing a pointer to that instance ** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. ** ^The registration remains valid until it is replaced by a different ** module or until the [database connection] closes. The content ................................................................................ ** non-zero. ** ** The [xBestIndex] method must fill aConstraintUsage[] with information ** about what parameters to pass to xFilter. ^If argvIndex>0 then ** the right-hand side of the corresponding aConstraint[] is evaluated ** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit ** is true, then the constraint is assumed to be fully handled by the ** virtual table and might not be checked again by the byte code.)^ ^(The ** aConstraintUsage[].omit flag is an optimization hint. When the omit flag ** is left in its default setting of false, the constraint will always be ** checked separately in byte code. If the omit flag is change to true, then ** the constraint may or may not be checked in byte code. In other words, ** when the omit flag is true there is no guarantee that the constraint will ** not be checked again using byte code.)^ ** ** ^The idxNum and idxPtr values are recorded and passed into the ** [xFilter] method. ** ^[sqlite3_free()] is used to free idxPtr if and only if ** needToFreeIdxPtr is true. ** ** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in ................................................................................ ** the xUpdate method are automatically rolled back by SQLite. ** ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info ** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). ** If a virtual table extension is ** used with an SQLite version earlier than 3.8.2, the results of attempting ** to read or write the estimatedRows field are undefined (but are likely ** to include crashing the application). The estimatedRows field should ** therefore only be used if [sqlite3_libversion_number()] returns a ** value greater than or equal to 3008002. Similarly, the idxFlags field ** was added for [version 3.9.0] ([dateof:3.9.0]). ** It may therefore only be used if ** sqlite3_libversion_number() returns a value greater than or equal to ** 3009000. */ ................................................................................ ** these bits. */ #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ /* ** CAPI3REF: Virtual Table Constraint Operator Codes ** ** These macros define the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents ** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. */ #define SQLITE_INDEX_CONSTRAINT_EQ 2 #define SQLITE_INDEX_CONSTRAINT_GT 4 #define SQLITE_INDEX_CONSTRAINT_LE 8 ................................................................................ ** • [sqlite3_mutex_held()] • ** • [sqlite3_mutex_notheld()] • ** )^ ** ** The only difference is that the public sqlite3_XXX functions enumerated ** above silently ignore any invocations that pass a NULL pointer instead ** of a valid mutex handle. The implementations of the methods defined ** by this structure are not required to handle this case. The results ** of passing a NULL pointer instead of a valid mutex handle are undefined ** (i.e. it is acceptable to provide an implementation that segfaults if ** it is passed a NULL pointer). ** ** The xMutexInit() method must be threadsafe. It must be harmless to ** invoke xMutexInit() multiple times within the same process and without ** intervening calls to xMutexEnd(). Second and subsequent calls to ................................................................................ ** returned value includes allocations that overflowed because they ** where too large (they were larger than the "sz" parameter to ** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because ** no space was left in the page cache.)^ ** ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^( SQLITE_STATUS_PAGECACHE_SIZE ** This parameter records the largest memory allocation request ** handed to the [pagecache memory allocator]. Only the value returned in the ** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined. )^ ** ** [[SQLITE_STATUS_SCRATCH_USED]] SQLITE_STATUS_SCRATCH_USED ** No longer used. ** ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^( SQLITE_STATUS_SCRATCH_OVERFLOW ................................................................................ ** ** ** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^( SQLITE_DBSTATUS_LOOKASIDE_USED ** This parameter returns the number of lookaside memory slots currently ** checked out. )^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^( SQLITE_DBSTATUS_LOOKASIDE_HIT ** This parameter returns the number of malloc attempts that were ** satisfied using lookaside memory. Only the high-water value is meaningful; ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] ** ^( SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE ** This parameter returns the number malloc attempts that might have ** been satisfied using lookaside memory but failed due to the amount of ................................................................................ ** ** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^( SQLITE_DBSTATUS_CACHE_SPILL ** This parameter returns the number of dirty cache entries that have ** been written to disk in the middle of a transaction due to the page ** cache overflowing. Transactions are more efficient if they are written ** to disk all at once. When pages spill mid-transaction, that introduces ** additional overhead. This parameter can be used help identify ** inefficiencies that can be resolved by increasing the cache size. ** ** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^( SQLITE_DBSTATUS_DEFERRED_FKS ** This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been ** resolved.)^ ^The highwater mark is always 0. ** ................................................................................ ** to 2147483647. The number of virtual machine operations can be ** used as a proxy for the total work done by the prepared statement. ** If the number of virtual machine operations exceeds 2147483647 ** then the value returned by this statement status code is undefined. ** ** [[SQLITE_STMTSTATUS_REPREPARE]] SQLITE_STMTSTATUS_REPREPARE ** ^This is the number of times that the prepare statement has been ** automatically regenerated due to schema changes or changes to ** [bound parameters] that might affect the query plan. ** ** [[SQLITE_STMTSTATUS_RUN]] SQLITE_STMTSTATUS_RUN ** ^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ................................................................................ ** Otherwise return NULL. ** 2 Make every effort to allocate a new page. Only return ** NULL if allocating a new page is effectively impossible. ** ** ** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite ** will only use a createFlag of 2 after a prior call with a createFlag of 1 ** failed.)^ In between the xFetch() calls, SQLite may ** attempt to unpin one or more cache pages by spilling the content of ** pinned pages to disk and synching the operating system disk cache. ** ** [[the xUnpin() page cache method]] ** ^xUnpin() is called by SQLite with a pointer to a currently pinned page ** as its second argument. If the third parameter, discard, is non-zero, ** then the page must be evicted from the cache. ................................................................................ ** identity of the database connection (the blocking connection) that ** has locked the required resource is stored internally. ^After an ** application receives an SQLITE_LOCKED error, it may call the ** sqlite3_unlock_notify() method with the blocked connection handle as ** the first argument to register for a callback that will be invoked ** when the blocking connections current transaction is concluded. ^The ** callback is invoked from within the [sqlite3_step] or [sqlite3_close] ** call that concludes the blocking connection's transaction. ** ** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, ** there is a chance that the blocking connection will have already ** concluded its transaction by the time sqlite3_unlock_notify() is invoked. ** If this happens, then the specified callback is invoked immediately, ** from within the call to sqlite3_unlock_notify().)^ ** ................................................................................ ** When an unlock-notify callback is registered, the application provides a ** single void* pointer that is passed to the callback when it is invoked. ** However, the signature of the callback function allows SQLite to pass ** it an array of void* context pointers. The first argument passed to ** an unlock-notify callback is a pointer to an array of void* pointers, ** and the second is the number of entries in the array. ** ** When a blocking connection's transaction is concluded, there may be ** more than one blocked connection that has registered for an unlock-notify ** callback. ^If two or more such blocked connections have specified the ** same callback function, then instead of invoking the callback function ** multiple times, it is invoked once with the set of void* context pointers ** specified by the blocked connections bundled together into an array. ** This gives the application an opportunity to prioritize any actions ** related to the set of unblocked database connections. ................................................................................ ** This function may be called by either the [xConnect] or [xCreate] method ** of a [virtual table] implementation to configure ** various facets of the virtual table interface. ** ** If this interface is invoked outside the context of an xConnect or ** xCreate virtual table method then the behavior is undefined. ** ** In the call sqlite3_vtab_config(D,C,...) the D parameter is the ** [database connection] in which the virtual table is being created and ** which is passed in as the first argument to the [xConnect] or [xCreate] ** method that is invoking sqlite3_vtab_config(). The C parameter is one ** of the [virtual table configuration options]. The presence and meaning ** of parameters after C depend on which [virtual table configuration option] ** is used. */ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); /* ** CAPI3REF: Virtual Table Configuration Options ** KEYWORDS: {virtual table configuration options} ** KEYWORDS: {virtual table configuration option} ** ** These macros define the various options to the ** [sqlite3_vtab_config()] interface that [virtual table] implementations ** can use to customize and optimize their behavior. ** ** ** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] ** SQLITE_VTAB_CONSTRAINT_SUPPORT ** Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** where X is an integer. If X is zero, then the [virtual table] whose ** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not ** support constraints. In this configuration (which is the default) if ** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire ** statement is rolled back as if [ON CONFLICT | OR ABORT] had been ................................................................................ ** must do so within the [xUpdate] method. If a call to the ** [sqlite3_vtab_on_conflict()] function indicates that the current ON ** CONFLICT policy is REPLACE, the virtual table implementation should ** silently replace the appropriate rows within the xUpdate callback and ** return SQLITE_OK. Or, if this is not possible, it may return ** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT ** constraint handling. ** ** ** [[SQLITE_VTAB_DIRECTONLY]] SQLITE_VTAB_DIRECTONLY ** Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the ** the [xConnect] or [xCreate] methods of a [virtual table] implmentation ** prohibits that virtual table from being used from within triggers and ** views. ** ** ** [[SQLITE_VTAB_INNOCUOUS]] SQLITE_VTAB_INNOCUOUS ** Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the ** the [xConnect] or [xCreate] methods of a [virtual table] implmentation ** identify that virtual table as being safe to use from within triggers ** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the ** virtual table can do no serious harm even if it is controlled by a ** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS ** flag unless absolutely necessary. ** ** */ #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 #define SQLITE_VTAB_INNOCUOUS 2 #define SQLITE_VTAB_DIRECTONLY 3 /* ** CAPI3REF: Determine The Virtual Table Conflict Policy ** ** This function may only be called from within a call to the [xUpdate] method ** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The ** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], ................................................................................ ** ** When the value returned to V is a string, space to hold that string is ** managed by the prepared statement S and will be automatically freed when ** S is finalized. ** ** ** [[SQLITE_SCANSTAT_NLOOP]] SQLITE_SCANSTAT_NLOOP ** ^The [sqlite3_int64] variable pointed to by the V parameter will be ** set to the total number of times that the X-th loop has run. ** ** [[SQLITE_SCANSTAT_NVISIT]] SQLITE_SCANSTAT_NVISIT ** ^The [sqlite3_int64] variable pointed to by the V parameter will be set ** to the total number of rows examined by all iterations of the X-th loop. ** ** [[SQLITE_SCANSTAT_EST]] SQLITE_SCANSTAT_EST ** ^The "double" variable pointed to by the V parameter will be set to the ** query planner's estimate for the average number of rows output from each ** iteration of the X-th loop. If the query planner's estimates was accurate, ** then this value will approximate the quotient NVISIT/NLOOP and the ** product of this value for all prior loops with the same SELECTID will ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]] SQLITE_SCANSTAT_NAME ** ^The "const char *" variable pointed to by the V parameter will be set ** to a zero-terminated UTF-8 string containing the name of the index or table ** used for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]] SQLITE_SCANSTAT_EXPLAIN ** ^The "const char *" variable pointed to by the V parameter will be set ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] ** description for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]] SQLITE_SCANSTAT_SELECT ** ^The "int" variable pointed to by the V parameter will be set to the ** "select-id" for the X-th loop. The select-id identifies which query or ** subquery the loop is part of. The main query has a select-id of zero. ** The select-id is the same value as is output in the first column ** of an [EXPLAIN QUERY PLAN] query. ** */ #define SQLITE_SCANSTAT_NLOOP 0 ................................................................................ /* ** CAPI3REF: Set a table filter on a Session Object. ** METHOD: sqlite3_session ** ** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called ** to determine whether changes to the table's rows should be tracked or not. ** If xFilter returns 0, changes are not tracked. Note that once a table is ** attached, xFilter will not be called again. */ SQLITE_API void sqlite3session_table_filter( sqlite3_session *pSession, /* Session object */ int(*xFilter)( void *pCtx, /* Copy of third arg to _filter_table() */ const char *zTab /* Table name */ ................................................................................ ** using [sqlite3session_changeset()], then after applying that changeset to ** database zFrom the contents of the two compatible tables would be ** identical. ** ** It an error if database zFrom does not exist or does not contain the ** required compatible table. ** ** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite ** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg ** may be set to point to a buffer containing an English language error ** message. It is the responsibility of the caller to free this buffer using ** sqlite3_free(). */ SQLITE_API int sqlite3session_diff( sqlite3_session *pSession, ................................................................................ #define SQLITE_CHANGESETSTART_INVERT 0x0002 /* ** CAPI3REF: Advance A Changeset Iterator ** METHOD: sqlite3_changeset_iter ** ** This function may only be used with iterators created by the function ** [sqlite3changeset_start()]. If it is called on an iterator passed to ** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE ** is returned and the call has no effect. ** ** Immediately after an iterator is created by sqlite3changeset_start(), it ** does not point to any change in the changeset. Assuming the changeset ** is not empty, the first call to this function advances the iterator to ................................................................................ ** ** If the new changeset contains changes to a table that is already present ** in the changegroup, then the number of columns and the position of the ** primary key columns for the table must be consistent. If this is not the ** case, this function fails with SQLITE_SCHEMA. If the input changeset ** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is ** returned. Or, if an out-of-memory condition occurs during processing, this ** function returns SQLITE_NOMEM. In all cases, if an error occurs the state ** of the final contents of the changegroup is undefined. ** ** If no error occurs, SQLITE_OK is returned. */ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup ................................................................................ ** This includes the case where the UPDATE operation is attempted after ** an earlier call to the conflict handler function returned ** [SQLITE_CHANGESET_REPLACE]. ** ** ** It is safe to execute SQL statements, including those that write to the ** table that the callback related to, from within the xConflict callback. ** This can be used to further customize the application's conflict ** resolution strategy. ** ** All changes made by these functions are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. ................................................................................ /* ** CAPI3REF: Rebase a changeset ** EXPERIMENTAL ** ** Argument pIn must point to a buffer containing a changeset nIn bytes ** in size. This function allocates and populates a buffer with a copy ** of the changeset rebased according to the configuration of the ** rebaser object passed as the first argument. If successful, (*ppOut) ** is set to point to the new buffer containing the rebased changeset and ** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the ** responsibility of the caller to eventually free the new buffer using ** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) ** are set to zero and an SQLite error code returned. */ ................................................................................ ** If the query runs to completion without incident, SQLITE_OK is returned. ** Or, if some error occurs before the query completes or is aborted by ** the callback, an SQLite error code is returned. ** ** ** xSetAuxdata(pFts5, pAux, xDelete) ** ** Save the pointer passed as the second argument as the extension function's ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of ** the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for ** each FTS query (MATCH expression). If the extension function is invoked ** more than once for a single FTS query, then all invocations share a ................................................................................ ** of "first place" within the document set, but not alternative forms ** such as "1st place". In some applications, it would be better to match ** all instances of "first place" or "1st place" regardless of which form ** the user specified in the MATCH query text. ** ** There are several ways to approach this in FTS5: ** ** 1. By mapping all synonyms to a single token. In this case, using ** the above example, this means that the tokenizer returns the ** same token for inputs "first" and "1st". Say that token is in ** fact "first", so that when the user inserts the document "I won ** 1st place" entries are added to the index for tokens "i", "won", ** "first" and "place". If the user then queries for '1st + place', ** the tokenizer substitutes "first" for "1st" and the query works ** as expected. ** ** The SQLITE_DBCONFIG_DQS_DML option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DML statements ** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The ** default value of this setting is determined by the [-DSQLITE_DQS] ** compile-time option. ** ** ** [[SQLITE_DBCONFIG_DQS_DDL]] ** SQLITE_DBCONFIG_DQS_DDL ** The SQLITE_DBCONFIG_DQS option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DDL statements, ** such as CREATE TABLE and CREATE INDEX. The ** default value of this setting is determined by the [-DSQLITE_DQS] ** compile-time option. ** ** ** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] ** SQLITE_DBCONFIG_TRUSTED_SCHEMA ** The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to ** assume that database schemas (the contents of the [sqlite_master] tables) ** are untainted by malicious content. ** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite ** takes additional defensive steps to protect the application from harm ** including: ** ** • Prohibit the use of SQL functions inside triggers, views, ** CHECK constraints, DEFAULT clauses, expression indexes, ** partial indexes, or generated columns ** unless those functions are tagged with [SQLITE_INNOCUOUS]. ** • Prohibit the use of virtual tables inside of triggers or views ** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS]. ** ** This setting defaults to "on" for legacy compatibility, however ** all applications are advised to turn it off if possible. This setting ** can also be controlled using the [PRAGMA trusted_schema] statement. ** ** ** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] ** SQLITE_DBCONFIG_LEGACY_FILE_FORMAT ** The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates ** the legacy file format flag. When activated, this flag causes all newly ** created database file to have a schema format version number (the 4-byte ** integer found at offset 44 into the database header) of 1. This in turn ** means that the resulting database file will be readable and writable by ** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, ** newly created databases are generally not understandable by SQLite versions ** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there ** is now scarcely any need to generated database files that are compatible ** all the way back to version 3.0.0, and so this setting is of little ** practical use, but is provided so that SQLite can continue to claim the ** ability to generate new database files that are compatible with version ** 3.0.0. ** Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on, ** the [VACUUM] command will fail with an obscure error when attempting to ** process a table with generated columns and a descending index. This is ** not considered a bug since SQLite versions 3.3.0 and earlier do not support ** either generated columns or decending indexes. ** ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ ................................................................................ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ #define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ #define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ #define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ #define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ #define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */ #define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */ #define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result ................................................................................ ** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE ** that is inside an explicit transaction, then the entire transaction ** will be rolled back automatically. ** ** ^The sqlite3_interrupt(D) call is in effect until all currently running ** SQL statements on [database connection] D complete. ^Any new SQL statements ** that are started after the sqlite3_interrupt() call and before the ** running statement count reaches zero are interrupted as if they had been ** running prior to the sqlite3_interrupt() call. ^New SQL statements ** that are started after the running statement count reaches zero are ** not effected by the sqlite3_interrupt(). ** ^A call to sqlite3_interrupt(D) that occurs when there are no running ** SQL statements is a no-op and has no effect on SQL statements ** that are started after the sqlite3_interrupt() call returns. */ ................................................................................ ** Name | Age ** ----------------------- ** Alice | 43 ** Bob | 28 ** Cindy | 21 ** ** ** There are two columns (M==2) and three rows (N==3). Thus the ** result table has 8 entries. Suppose the result table is stored ** in an array named azResult. Then azResult holds this content: ** ** ** azResult[0] = "Name"; ** azResult[1] = "Age"; ** azResult[2] = "Alice"; ** azResult[3] = "43"; ** azResult[4] = "Bob"; ................................................................................ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem ** ** The SQLite core uses these three routines for all of its own ** internal memory allocation needs. "Core" in the previous sentence ** does not include operating-system specific [VFS] implementation. The ** Windows VFS uses native malloc() and free() for some operations. ** ** ^The sqlite3_malloc() routine returns a pointer to a block ** of memory at least N bytes in length, where N is the parameter. ** ^If sqlite3_malloc() is unable to obtain sufficient free ** memory, it returns a NULL pointer. ^If the parameter N to ** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns ................................................................................ ** ** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), ** sqlite3_malloc64(), and sqlite3_realloc64() ** is always aligned to at least an 8 byte boundary, or to a ** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time ** option is used. ** ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] ** must be either NULL or else pointers obtained from a prior ** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have ** not yet been released. ** ** The application must not read or write any part of ** a block of memory after it has been released using ................................................................................ /* ** CAPI3REF: Pseudo-Random Number Generator ** ** SQLite contains a high-quality pseudo-random number generator (PRNG) used to ** select random [ROWID | ROWIDs] when inserting new records into a table that ** already uses the largest possible [ROWID]. The PRNG is also used for ** the built-in random() and randomblob() SQL functions. This interface allows ** applications to access the same PRNG for other purposes. ** ** ^A call to this routine stores N bytes of randomness into buffer P. ** ^The P parameter can be a NULL pointer. ** ** ^If this routine has not been previously called or if the previous ** call had N less than one or a NULL pointer for P, then the PRNG is ................................................................................ ** Whether or not an error occurs when it is opened, resources ** associated with the [database connection] handle should be released by ** passing it to [sqlite3_close()] when it is no longer required. ** ** The sqlite3_open_v2() interface works like sqlite3_open() ** except that it accepts two additional parameters for additional control ** over the new database connection. ^(The flags parameter to ** sqlite3_open_v2() must include, at a minimum, one of the following ** three flag combinations:)^ ** ** ** ^( [SQLITE_OPEN_READONLY] ** The database is opened in read-only mode. If the database does not ** already exist, an error is returned. )^ ** ** ^( [SQLITE_OPEN_READWRITE] ................................................................................ ** case the database must already exist, otherwise an error is returned.)^ ** ** ^( [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] ** The database is opened for reading and writing, and is created if ** it does not already exist. This is the behavior that is always used for ** sqlite3_open() and sqlite3_open16(). )^ ** ** ** In addition to the required flags, the following optional flags are ** also supported: ** ** ** ^( [SQLITE_OPEN_URI] ** The filename can be interpreted as a URI if this flag is set. )^ ** ** ^( [SQLITE_OPEN_MEMORY] ** The database will be opened as an in-memory database. The database ** is named by the "filename" argument for the purposes of cache-sharing, ** if shared cache mode is enabled, but the "filename" is otherwise ignored. ** )^ ** ** ^( [SQLITE_OPEN_NOMUTEX] ** The new database connection will use the "multi-thread" ** [threading mode].)^ This means that separate threads are allowed ** to use SQLite at the same time, as long as each thread is using ** a different [database connection]. ** ** ^( [SQLITE_OPEN_FULLMUTEX] ** The new database connection will use the "serialized" ** [threading mode].)^ This means the multiple threads can safely ** attempt to use the same database connection at the same time. ** (Mutexes will block any actual concurrency, but in this mode ** there is no harm in trying.) ** ** ^( [SQLITE_OPEN_SHAREDCACHE] ** The database is opened [shared cache] enabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** ^( [SQLITE_OPEN_PRIVATECACHE] ** The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^( [SQLITE_OPEN_NOFOLLOW] ** The database filename is not allowed to be a symbolic link ** )^ ** ** 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. ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. ** ** ^If the filename is ":memory:", then a private, temporary in-memory database ** is created for the connection. ^This in-memory database will vanish when ................................................................................ int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ); /* ** CAPI3REF: Obtain Values For URI Parameters ** ** These are utility routines, useful to [VFS|custom VFS implementations], ** that check if a database file was a URI that contained a specific query ** parameter, and if so obtains the value of that query parameter. ** ** If F is the database filename pointer passed into the xOpen() method of ** a VFS implementation or it is the return value of [sqlite3_db_filename()] ** and if P is the name of the query parameter, then ** sqlite3_uri_parameter(F,P) returns the value of the P ** parameter if it exists or a NULL pointer if P does not appear as a ** query parameter on F. If P is a query parameter of F and it ** has no explicit value, then sqlite3_uri_parameter(F,P) returns ** a pointer to an empty string. ** ** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean ** parameter and returns true (1) or false (0) according to the value ** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the ** value of query parameter P is one of "yes", "true", or "on" in any ** case or if the value begins with a non-zero number. The ** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of ** query parameter P is one of "no", "false", or "off" in any case or ** if the value begins with a numeric zero. If P is not a query ** parameter on F or if the value of P does not match any of the ** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). ** ** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a ** 64-bit signed integer and returns that integer, or D if P does not ** exist. If the value of P is something other than an integer, then ** zero is returned. ** ** The sqlite3_uri_key(F,N) returns a pointer to the name (not ** the value) of the N-th query parameter for filename F, or a NULL ** pointer if N is less than zero or greater than the number of query ** parameters minus 1. The N value is zero-based so N should be 0 to obtain ** the name of the first query parameter, 1 for the second parameter, and ** so forth. ** ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and ** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and ** is not a database file pathname pointer that the SQLite core passed ** into the xOpen VFS method, then the behavior of this routine is undefined ** and probably undesirable. ** ** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F ** parameter can also be the name of a rollback journal file or WAL file ** in addition to the main database file. Prior to version 3.31.0, these ** routines would only work if F was the name of the main database file. ** When the F parameter is the name of the rollback journal or WAL file, ** it has access to all the same query parameters as were found on the ** main database file. ** ** See the [URI filename] documentation for additional information. */ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N); /* ** CAPI3REF: Translate filenames ** ** These routines are available to [VFS|custom VFS implementations] for ** translating filenames between the main database file, the journal file, ** and the WAL file. ** ** If F is the name of an sqlite database file, journal file, or WAL file ** passed by the SQLite core into the VFS, then sqlite3_filename_database(F) ** returns the name of the corresponding database file. ** ** If F is the name of an sqlite database file, journal file, or WAL file ** passed by the SQLite core into the VFS, or if F is a database filename ** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F) ** returns the name of the corresponding rollback journal file. ** ** If F is the name of an sqlite database file, journal file, or WAL file ** that was passed by the SQLite core into the VFS, or if F is a database ** filename obtained from [sqlite3_db_filename()], then ** sqlite3_filename_wal(F) returns the name of the corresponding ** WAL file. ** ** In all of the above, if F is not the name of a database, journal or WAL ** filename passed into the VFS from the SQLite core and F is not the ** return value from [sqlite3_db_filename()], then the result is ** undefined and is likely a memory access violation. */ SQLITE_API const char *sqlite3_filename_database(const char*); SQLITE_API const char *sqlite3_filename_journal(const char*); SQLITE_API const char *sqlite3_filename_wal(const char*); /* ** CAPI3REF: Error Codes And Messages ** METHOD: sqlite3 ** ** ^If the most recent sqlite3_* API call associated with ................................................................................ ** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code ** and the application would have to make a second call to [sqlite3_reset()] ** in order to find the underlying cause of the problem. With the "v2" prepare ** interfaces, the underlying reason for the error is returned immediately. ** ** ** • ** ^If the specific value bound to a [parameter | host parameter] in the ** WHERE clause might influence the choice of query plan for a statement, ** then the statement will be automatically recompiled, as if there had been ** a schema change, on the first [sqlite3_step()] call following any change ** to the [sqlite3_bind_text | bindings] of that [parameter]. ** ^The specific value of a WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled. ** • ** ** ** ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having ................................................................................ ** ^The first argument to these interfaces is a [prepared statement]. ** ^These functions return information about the Nth result column returned by ** the statement, where N is the second function argument. ** ^The left-most column is column 0 for these routines. ** ** ^If the Nth column returned by the statement is an expression or ** subquery and is not a column value, then all of these functions return ** NULL. ^These routines might also return NULL if a memory allocation error ** occurs. ^Otherwise, they return the name of the attached database, table, ** or column that query result column was extracted from. ** ** ^As with all other SQLite APIs, those whose names end with "16" return ** UTF-16 encoded strings and the other functions return UTF-8. ** ** ^These APIs are only available if the library was compiled with the ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. ** ** If two or more threads call one or more ** [sqlite3_column_database_name | column metadata interfaces] ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); ................................................................................ /* ** CAPI3REF: Number of columns in a result set ** METHOD: sqlite3_stmt ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. ** ^If prepared statement P does not have results ready to return ** (via calls to the [sqlite3_column_int | sqlite3_column()] family of ** interfaces) then sqlite3_data_count(P) returns 0. ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. ** ^The sqlite3_data_count(P) routine returns 0 if the previous call to ** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) ** will return non-zero if previous call to [sqlite3_step](P) returned ** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] ** where it always returns zero since each step of that multi-step ................................................................................ ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); /* ** CAPI3REF: Create Or Redefine SQL Functions ** KEYWORDS: {function creation routines} ** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior ** of existing SQL functions or aggregates. The only differences between ** the three "sqlite3_create_function*" routines are the text encoding ** expected for the second parameter (the name of the function being ................................................................................ ** deterministic. The built-in [random()] SQL function is an example of a ** function that is not deterministic. The SQLite query planner is able to ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** index expressions, or the WHERE clause of partial indexes. ** ** ** For best security, the [SQLITE_DIRECTONLY] flag is recommended for ** all application-defined SQL functions that do not need to be ** used inside of triggers, view, CHECK constraints, or other elements of ** the database schema. This flags is especially recommended for SQL ** functions that have side effects or reveal internal application state. ** Without this flag, an attacker might be able to modify the schema of ** a database file to include invocations of the function with parameters ** chosen by the attacker, which the application will then execute when ** the database file is opened and read. ** ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** ** ^The sixth, seventh and eighth parameters passed to the three ** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or ................................................................................ ** CAPI3REF: Function Flags ** ** These constants may be ORed together with the ** [SQLITE_UTF8 | preferred text encoding] as the fourth argument ** to [sqlite3_create_function()], [sqlite3_create_function16()], or ** [sqlite3_create_function_v2()]. ** ** ** [[SQLITE_DETERMINISTIC]] SQLITE_DETERMINISTIC ** The SQLITE_DETERMINISTIC flag means that the new function always gives ** the same output when the input parameters are the same. ** The [abs|abs() function] is deterministic, for example, but ** [randomblob|randomblob()] is not. Functions must ** be deterministic in order to be used in certain contexts such as ** with the WHERE clause of [partial indexes] or in [generated columns]. ** SQLite might also optimize deterministic functions by factoring them ** out of inner loops. ** ** ** [[SQLITE_DIRECTONLY]] SQLITE_DIRECTONLY ** The SQLITE_DIRECTONLY flag means that the function may only be invoked ** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in ** schema structures such as [CHECK constraints], [DEFAULT clauses], ** [expression indexes], [partial indexes], or [generated columns]. ** The SQLITE_DIRECTONLY flags is a security feature which is recommended ** for all [application-defined SQL functions], and especially for functions ** that have side-effects or that could potentially leak sensitive ** information. ** ** ** [[SQLITE_INNOCUOUS]] SQLITE_INNOCUOUS ** The SQLITE_INNOCUOUS flag means that the function is unlikely ** to cause problems even if misused. An innocuous function should have ** no side effects and should not depend on any values other than its ** input parameters. The [abs|abs() function] is an example of an ** innocuous function. ** The [load_extension() SQL function] is not innocuous because of its ** side effects. ** SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not ** exactly the same. The [random|random() function] is an example of a ** function that is innocuous but not deterministic. ** Some heightened security settings ** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF]) ** disable the use of SQL functions inside views and triggers and in ** schema structures such as [CHECK constraints], [DEFAULT clauses], ** [expression indexes], [partial indexes], and [generated columns] unless ** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions ** are innocuous. Developers are advised to avoid using the ** SQLITE_INNOCUOUS flag for application-defined functions unless the ** function has been carefully audited and found to be free of potentially ** security-adverse side-effects and information-leaks. ** ** ** [[SQLITE_SUBTYPE]] SQLITE_SUBTYPE ** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call ** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. ** Specifying this flag makes no difference for scalar or aggregate user ** functions. However, if it is not specified for a user-defined window ** function, then any sub-types belonging to arguments passed to the window ** function may be discarded before the window function is called (i.e. ** sqlite3_value_subtype() will always return 0). ** ** */ #define SQLITE_DETERMINISTIC 0x000000800 #define SQLITE_DIRECTONLY 0x000080000 #define SQLITE_SUBTYPE 0x000100000 #define SQLITE_INNOCUOUS 0x000200000 /* ** CAPI3REF: Deprecated Functions ** DEPRECATED ** ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ................................................................................ ** Changes to src/stat.c.  604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 ... 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 } db_multi_exec( "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" "INSERT INTO trans(name,tabname)" " SELECT name, tbl_name FROM repository.sqlite_master;" "CREATE TEMP TABLE piechart(amt REAL, label TEXT);" "INSERT INTO piechart(amt,label)" " SELECT count(*), " " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" " FROM dbstat('repository')" " GROUP BY 2 ORDER BY 2;" ); nPageFree = db_int(0, "PRAGMA repository.freelist_count"); if( nPageFree>0 ){ db_multi_exec( "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", nPageFree ................................................................................ if( g.localOpen ){ db_multi_exec( "DELETE FROM trans;" "INSERT INTO trans(name,tabname)" " SELECT name, tbl_name FROM localdb.sqlite_master;" "DELETE FROM piechart;" "INSERT INTO piechart(amt,label)" " SELECT count(*), " " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" " FROM dbstat('localdb')" " GROUP BY 2 ORDER BY 2;" ); nPageFree = db_int(0, "PRAGMA localdb.freelist_count"); if( nPageFree>0 ){ db_multi_exec( "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", nPageFree | | | | 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 ... 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 } db_multi_exec( "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" "INSERT INTO trans(name,tabname)" " SELECT name, tbl_name FROM repository.sqlite_master;" "CREATE TEMP TABLE piechart(amt REAL, label TEXT);" "INSERT INTO piechart(amt,label)" " SELECT sum(pageno)," " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" " FROM dbstat('repository',TRUE)" " GROUP BY 2 ORDER BY 2;" ); nPageFree = db_int(0, "PRAGMA repository.freelist_count"); if( nPageFree>0 ){ db_multi_exec( "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", nPageFree ................................................................................ if( g.localOpen ){ db_multi_exec( "DELETE FROM trans;" "INSERT INTO trans(name,tabname)" " SELECT name, tbl_name FROM localdb.sqlite_master;" "DELETE FROM piechart;" "INSERT INTO piechart(amt,label)" " SELECT sum(pageno), " " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" " FROM dbstat('localdb',TRUE)" " GROUP BY 2 ORDER BY 2;" ); nPageFree = db_int(0, "PRAGMA localdb.freelist_count"); if( nPageFree>0 ){ db_multi_exec( "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", nPageFree Changes to src/style.c.  486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 .... 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 @ @ @ @ @<project_name>: $<title> @ @ @ @ ; /* ** Initialize all the default TH1 variables */ ................................................................................ ** For administators, or if the test_env_enable setting is true, then ** details of the request environment are displayed. Otherwise, just ** the error message is shown. ** ** If zFormat is an empty string, then this is the /test_env page. */ void webpage_error(const char *zFormat, ...){ int i; int showAll; char *zErr = 0; int isAuth = 0; char zCap[100]; static const char *const azCgiVars[] = { "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE", "SCGI", "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION", "HTTP_CONNECTION", "HTTP_HOST", "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE", "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED", "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", "REMOTE_USER", "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL", "HOME", "FOSSIL_HOME", "USERNAME", "USER", "FOSSIL_USER", "SQLITE_TMPDIR", "TMPDIR", "TEMP", "TMP", "FOSSIL_VFS", "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION", "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS", "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST", }; login_check_credentials(); if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ isAuth = 1; } for(i=0; i/%h(g.zPath): %h(zErr) | < < < < < < < < < < < < < < < < < < < | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 .... 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 @ @ @ @ @$<project_name>: $<title> @ @ @ @ ; /* ** Initialize all the default TH1 variables */ ................................................................................ ** For administators, or if the test_env_enable setting is true, then ** details of the request environment are displayed. Otherwise, just ** the error message is shown. ** ** If zFormat is an empty string, then this is the /test_env page. */ void webpage_error(const char *zFormat, ...){ int showAll; char *zErr = 0; int isAuth = 0; char zCap[100]; login_check_credentials(); if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ isAuth = 1; } cgi_load_environment(); if( zFormat[0] ){ va_list ap; va_start(ap, zFormat); zErr = vmprintf(zFormat, ap); va_end(ap); style_header("Bad Request"); @ /%h(g.zPath): %h(zErr) Changes to src/sync.c.  198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 ... 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 } /* ** COMMAND: pull ** ** Usage: %fossil pull ?URL? ?options? ** ** Pull all sharable changes from a remote repository into the local repository. ** Sharable changes include public check-ins, and wiki, ticket, and tech-note ** edits. Add the --private option to pull private branches. Use the ** "configuration pull" command to pull website configuration details. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote-url, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** ** Options: ................................................................................ } /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?options? ** ** Push all sharable changes from the local repository to a remote repository. ** Sharable changes include public check-ins, and wiki, ticket, and tech-note ** edits. Use --private to also push private branches. Use the ** "configuration push" command to push website configuration details. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote-url, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** ** Options: ** | | > | | | > | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 ... 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 } /* ** COMMAND: pull ** ** Usage: %fossil pull ?URL? ?options? ** ** Pull all sharable changes from a remote repository into the local ** repository. Sharable changes include public check-ins, edits to ** wiki pages, tickets, and tech-notes, as well as forum content. Add ** the --private option to pull private branches. Use the ** "configuration pull" command to pull website configuration details. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote-url, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** ** Options: ................................................................................ } /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?options? ** ** Push all sharable changes from the local repository to a remote ** repository. Sharable changes include public check-ins, edits to ** wiki pages, tickets, and tech-notes, as well as forum content. Use ** --private to also push private branches. Use the "configuration ** push" command to push website configuration details. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote-url, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** ** Options: ** Changes to src/th_main.c.  527 528 529 530 531 532 533 534 535 536 537 538 539 540 .... 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 ){ if( argc!=1 ){ return Th_WrongNumArgs(interp, "verifyCsrf"); } login_verify_csrf_secret(); return TH_OK; } /* ** TH1 command: markdown STRING ** ** Renders the input string as markdown. The result is a two-element list. ** The first element is the text-only title string. The second element ** contains the body, rendered as HTML. ................................................................................ {"styleScript", styleScriptCmd, 0}, {"tclReady", tclReadyCmd, 0}, {"trace", traceCmd, 0}, {"stime", stimeCmd, 0}, {"unversioned", unversionedCmd, 0}, {"utime", utimeCmd, 0}, {"verifyCsrf", verifyCsrfCmd, 0}, {"wiki", wikiCmd, (void*)&aFlags[0]}, {0, 0, 0} }; if( g.thTrace ){ Th_Trace("th1-init 0x%x => 0x%x \n", g.th1Flags, flags); } if( needConfig ){ > > > > > > > > > > > > > > > > > > > > > > > > > > > > 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 .... 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 ){ if( argc!=1 ){ return Th_WrongNumArgs(interp, "verifyCsrf"); } login_verify_csrf_secret(); return TH_OK; } /* ** TH1 command: verifyLogin ** ** Returns non-zero if the specified user name and password represent a ** valid login for the repository. */ static int verifyLoginCmd( Th_Interp *interp, void *p, int argc, const char **argv, int *argl ){ const char *zUser; const char *zPass; int uid; if( argc!=3 ){ return Th_WrongNumArgs(interp, "verifyLogin userName password"); } zUser = argv[1]; zPass = argv[2]; uid = login_search_uid(&zUser, zPass); Th_SetResultInt(interp, uid!=0); if( uid==0 ) sqlite3_sleep(100); return TH_OK; } /* ** TH1 command: markdown STRING ** ** Renders the input string as markdown. The result is a two-element list. ** The first element is the text-only title string. The second element ** contains the body, rendered as HTML. ................................................................................ {"styleScript", styleScriptCmd, 0}, {"tclReady", tclReadyCmd, 0}, {"trace", traceCmd, 0}, {"stime", stimeCmd, 0}, {"unversioned", unversionedCmd, 0}, {"utime", utimeCmd, 0}, {"verifyCsrf", verifyCsrfCmd, 0}, {"verifyLogin", verifyLoginCmd, 0}, {"wiki", wikiCmd, (void*)&aFlags[0]}, {0, 0, 0} }; if( g.thTrace ){ Th_Trace("th1-init 0x%x => 0x%x \n", g.th1Flags, flags); } if( needConfig ){ Changes to src/timeline.c.  112 113 114 115 116 117 118 119 120 121 122 123 124 125 ... 322 323 324 325 326 327 328 329 330 331 332 333 334 335 ... 402 403 404 405 406 407 408 409 410 411 412 413 414 415 ... 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 ... 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 ... 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 ... 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 .... 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 .... 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 .... 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 .... 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 .... 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 .... 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 .... 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 .... 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 .... 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 #define TIMELINE_CLASSIC 0x0010000 /* Use the "classic" view style */ #define TIMELINE_VIEWS 0x001f000 /* Mask for all of the view styles */ #define TIMELINE_NOSCROLL 0x0100000 /* Don't scroll to the selection */ #define TIMELINE_FILEDIFF 0x0200000 /* Show File differences, not ckin diffs */ #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 */ #endif /* ** Hash a string and use the hash to determine a background color. */ char *hash_color(const char *z){ int i; /* Loop counter */ ................................................................................ const char *zBr = 0; /* Branch */ int commentColumn = 3; /* Column containing comment text */ int modPending; /* Pending moderation */ char *zDateLink; /* URL for the link on the timestamp */ int drawDetailEllipsis; /* True to show ellipsis in place of detail */ int gidx = 0; /* Graph row identifier */ int isSelectedOrCurrent = 0; /* True if current row is selected */ char zTime[20]; if( zDate==0 ){ zDate = "YYYY-MM-DD HH:MM:SS"; /* Something wrong with the repo */ } modPending = moderation_pending(rid); if( tagid ){ ................................................................................ @ }else{ @ } if( pGraph && zType[0]!='c' ){ @ • } if( modPending ){ @ (Awaiting Moderator Approval) } ................................................................................ @ (%d(rid)) } } } if( zType[0]!='c' ){ /* Comments for anything other than a check-in are generated by ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ if( zType[0]=='w' ) wiki_hyperlink_override(zUuid); wiki_convert(&comment, 0, WIKI_INLINE); wiki_hyperlink_override(0); }else{ if( bCommentGitStyle ){ /* Truncate comment at first blank line */ int ii, jj; int n = blob_size(&comment); char *z = blob_str(&comment); for(ii=0; ii... } if( tmFlags & TIMELINE_COLUMNAR ){ if( !isSelectedOrCurrent ){ @ }else{ @ } } if( tmFlags & TIMELINE_COMPACT ){ cgi_printf("",rid); } cgi_printf("", zStyle); if( (tmFlags & (TIMELINE_CLASSIC|TIMELINE_VERBOSE|TIMELINE_COMPACT))!=0 ){ ................................................................................ cgi_printf("check-in: %z%S ",href("%R/info/%!S",zUuid),zUuid); }else if( zType[0]=='e' && tagid ){ cgi_printf("technote: "); hyperlink_to_event_tagid(tagid<0?-tagid:tagid); }else{ cgi_printf("artifact: %z%S ",href("%R/info/%!S",zUuid),zUuid); } }else if( zType[0]=='g' || zType[0]=='w' || zType[0]=='t' || zType[0]=='f'){ cgi_printf("artifact: %z%S ",href("%R/info/%!S",zUuid),zUuid); } if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){ char *zLink = mprintf("%R/timeline?u=%h&c=%t&y=a", zDispUser, zDate); cgi_printf("user: %z%h", href("%z",zLink), zDispUser); }else{ ................................................................................ /* ** Add the select/option box to the timeline submenu that is used to ** set the y= parameter that determines which elements to display ** on the timeline. */ static void timeline_y_submenu(int isDisabled){ static int i = 0; static const char *az[14]; if( i==0 ){ az[0] = "all"; az[1] = "Any Type"; i = 2; if( g.perm.Read ){ az[i++] = "ci"; az[i++] = "Check-ins"; ................................................................................ if( g.perm.RdWiki ){ az[i++] = "e"; az[i++] = "Tech Notes"; } if( g.perm.RdTkt ){ az[i++] = "t"; az[i++] = "Tickets"; } if( g.perm.RdWiki ){ az[i++] = "w"; az[i++] = "Wiki"; } if( g.perm.RdForum ){ az[i++] = "f"; ................................................................................ ** t=TAG Show only check-ins with the given TAG ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel ** rel Show related check-ins as well as those matching t=TAG ** mionly Limit rel to show ancestors but not descendants ** nowiki Do not show wiki associated with branch or tag ** ms=MATCHSTYLE Set tag match style to EXACT, GLOB, LIKE, REGEXP ** u=USER Only show items associated with USER ** y=TYPE 'ci', 'w', 't', 'e', 'f', or 'all'. ** ss=VIEWSTYLE c: "Compact" v: "Verbose" m: "Modern" j: "Columnar" ** advm Use the "Advanced" or "Busy" menu design. ** ng No Graph. ** ncp Omit cherrypick merges ** nd Do not highlight the focus check-in ** v Show details of files changed ** f=CHECKIN Show family (immediate parents and children) of CHECKIN ................................................................................ " WHERE mlink.fid=(SELECT rid FROM blob WHERE uuid LIKE '%q%%')" " AND event.objid=mlink.mid" " ORDER BY event.mtime LIMIT 1", P("cf") ); } /* r=TAG works like a combination of t=TAG & rel */ if( zBrName && !related ){ zTagName = zBrName; related = 1; zType = "ci"; } /* Ignore empty tag query strings. */ if( zTagName && !*zTagName ){ ................................................................................ db_multi_exec( "CREATE TABLE IF NOT EXISTS temp.pathnode(x INTEGER PRIMARY KEY);" ); if( p ){ blob_init(&ins, 0, 0); blob_append_sql(&ins, "INSERT INTO pathnode(x) VALUES(%d)", p->rid); p = p->u.pTo; nNodeOnPath = 1; while( p ){ blob_append_sql(&ins, ",(%d)", p->rid); p = p->u.pTo; nNodeOnPath++; } } path_reset(); db_multi_exec("%s", blob_str(&ins)/*safe-for-%s*/); blob_reset(&ins); if( related ){ db_multi_exec( ................................................................................ " SELECT childid FROM cherrypick WHERE parentid IN pathnode;" ); } } db_multi_exec("INSERT OR IGNORE INTO pathnode SELECT x FROM related"); } blob_append_sql(&sql, " AND event.objid IN pathnode"); addFileGlobExclusion(zChng, &sql); tmFlags |= TIMELINE_DISJOINT; tmFlags &= ~TIMELINE_CHPICK; db_multi_exec("%s", blob_sql_text(&sql)); if( advancedMenu ){ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0); } blob_appendf(&desc, "%d check-ins going from ", nNodeOnPath); blob_appendf(&desc, "%z[%h]", href("%R/info/%h", zFrom), zFrom); blob_append(&desc, " to ", -1); blob_appendf(&desc, "%z[%h]", href("%R/info/%h",zTo), zTo); if( related ){ int nRelated = db_int(0, "SELECT count(*) FROM timeline") - nNodeOnPath; if( nRelated>0 ){ ................................................................................ TAG_HIDDEN ); } } } if( (zType[0]=='w' && !g.perm.RdWiki) || (zType[0]=='t' && !g.perm.RdTkt) || (zType[0]=='e' && !g.perm.RdWiki) || (zType[0]=='c' && !g.perm.Read) || (zType[0]=='g' && !g.perm.Read) || (zType[0]=='f' && !g.perm.RdForum) ){ zType = "all"; } ................................................................................ if( g.perm.RdForum ){ blob_append_sql(&cond, "%c'f'", cSep); cSep = ','; } blob_append_sql(&cond, ")"); } }else{ /* zType!="all" */ blob_append_sql(&cond, " AND event.type=%Q", zType); if( zType[0]=='c' ){ zEType = "check-in"; }else if( zType[0]=='w' ){ zEType = "wiki"; }else if( zType[0]=='t' ){ zEType = "ticket change"; }else if( zType[0]=='e' ){ zEType = "technical note"; }else if( zType[0]=='g' ){ zEType = "tag"; }else if( zType[0]=='f' ){ zEType = "forum post"; } ................................................................................ desc.aData[0] = fossil_toupper(desc.aData[0]); } if( zBrName ){ if( !PB("nowiki") && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL) ){ @ %b(&desc) } style_submenu_element("Diff", "%R/vdiff?branch=%T", zBrName); }else if( zTagName && matchStyle==MS_EXACT && zBrName==0 && !PB("nowiki") > > > > > > > > > > > > > > > | | > | | | > > > | | | > | > > | | > > > < < | > > > > > > > > > > > > > > | > > > > > 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 ... 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 ... 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 ... 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 ... 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 ... 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 ... 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 .... 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 .... 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 .... 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 .... 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 .... 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 .... 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 .... 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 .... 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 .... 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 #define TIMELINE_CLASSIC 0x0010000 /* Use the "classic" view style */ #define TIMELINE_VIEWS 0x001f000 /* Mask for all of the view styles */ #define TIMELINE_NOSCROLL 0x0100000 /* Don't scroll to the selection */ #define TIMELINE_FILEDIFF 0x0200000 /* Show File differences, not ckin diffs */ #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 */ #endif /* ** Hash a string and use the hash to determine a background color. */ char *hash_color(const char *z){ int i; /* Loop counter */ ................................................................................ const char *zBr = 0; /* Branch */ int commentColumn = 3; /* Column containing comment text */ int modPending; /* Pending moderation */ char *zDateLink; /* URL for the link on the timestamp */ int drawDetailEllipsis; /* True to show ellipsis in place of detail */ int gidx = 0; /* Graph row identifier */ int isSelectedOrCurrent = 0; /* True if current row is selected */ const char *zExtraClass = ""; char zTime[20]; if( zDate==0 ){ zDate = "YYYY-MM-DD HH:MM:SS"; /* Something wrong with the repo */ } modPending = moderation_pending(rid); if( tagid ){ ................................................................................ @ }else{ @ } if( pGraph && zType[0]!='c' ){ @ • } if( modPending ){ @ (Awaiting Moderator Approval) } ................................................................................ @ (%d(rid)) } } } if( zType[0]!='c' ){ /* Comments for anything other than a check-in are generated by ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ if( zType[0]=='w' ){ wiki_hyperlink_override(zUuid); wiki_convert(&comment, 0, WIKI_INLINE); wiki_hyperlink_override(0); }else{ wiki_convert(&comment, 0, WIKI_INLINE); } }else{ if( bCommentGitStyle ){ /* Truncate comment at first blank line */ int ii, jj; int n = blob_size(&comment); char *z = blob_str(&comment); for(ii=0; ii... } if( tmFlags & TIMELINE_COLUMNAR ){ if( !isSelectedOrCurrent ){ @ }else{ @ } } if( tmFlags & TIMELINE_COMPACT ){ cgi_printf("",rid); } cgi_printf("", zStyle); if( (tmFlags & (TIMELINE_CLASSIC|TIMELINE_VERBOSE|TIMELINE_COMPACT))!=0 ){ ................................................................................ cgi_printf("check-in: %z%S ",href("%R/info/%!S",zUuid),zUuid); }else if( zType[0]=='e' && tagid ){ cgi_printf("technote: "); hyperlink_to_event_tagid(tagid<0?-tagid:tagid); }else{ cgi_printf("artifact: %z%S ",href("%R/info/%!S",zUuid),zUuid); } }else if( zType[0]=='g' || zType[0]=='w' || zType[0]=='t' || zType[0]=='n' || zType[0]=='f'){ cgi_printf("artifact: %z%S ",href("%R/info/%!S",zUuid),zUuid); } if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){ char *zLink = mprintf("%R/timeline?u=%h&c=%t&y=a", zDispUser, zDate); cgi_printf("user: %z%h", href("%z",zLink), zDispUser); }else{ ................................................................................ /* ** Add the select/option box to the timeline submenu that is used to ** set the y= parameter that determines which elements to display ** on the timeline. */ static void timeline_y_submenu(int isDisabled){ static int i = 0; static const char *az[16]; if( i==0 ){ az[0] = "all"; az[1] = "Any Type"; i = 2; if( g.perm.Read ){ az[i++] = "ci"; az[i++] = "Check-ins"; ................................................................................ if( g.perm.RdWiki ){ az[i++] = "e"; az[i++] = "Tech Notes"; } if( g.perm.RdTkt ){ az[i++] = "t"; az[i++] = "Tickets"; az[i++] = "n"; az[i++] = "New Tickets"; } if( g.perm.RdWiki ){ az[i++] = "w"; az[i++] = "Wiki"; } if( g.perm.RdForum ){ az[i++] = "f"; ................................................................................ ** t=TAG Show only check-ins with the given TAG ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel ** rel Show related check-ins as well as those matching t=TAG ** mionly Limit rel to show ancestors but not descendants ** nowiki Do not show wiki associated with branch or tag ** ms=MATCHSTYLE Set tag match style to EXACT, GLOB, LIKE, REGEXP ** u=USER Only show items associated with USER ** y=TYPE 'ci', 'w', 't', 'n', 'e', 'f', or 'all'. ** ss=VIEWSTYLE c: "Compact" v: "Verbose" m: "Modern" j: "Columnar" ** advm Use the "Advanced" or "Busy" menu design. ** ng No Graph. ** ncp Omit cherrypick merges ** nd Do not highlight the focus check-in ** v Show details of files changed ** f=CHECKIN Show family (immediate parents and children) of CHECKIN ................................................................................ " WHERE mlink.fid=(SELECT rid FROM blob WHERE uuid LIKE '%q%%')" " AND event.objid=mlink.mid" " ORDER BY event.mtime LIMIT 1", P("cf") ); } /* Convert r=TAG to t=TAG&rel in order to populate the UI style widgets. */ if( zBrName && !related ){ cgi_delete_query_parameter("r"); cgi_set_query_parameter("t", zBrName); cgi_set_query_parameter("rel", "1"); zTagName = zBrName; related = 1; zType = "ci"; } /* Ignore empty tag query strings. */ if( zTagName && !*zTagName ){ ................................................................................ db_multi_exec( "CREATE TABLE IF NOT EXISTS temp.pathnode(x INTEGER PRIMARY KEY);" ); if( p ){ blob_init(&ins, 0, 0); blob_append_sql(&ins, "INSERT INTO pathnode(x) VALUES(%d)", p->rid); p = p->u.pTo; while( p ){ blob_append_sql(&ins, ",(%d)", p->rid); p = p->u.pTo; } } path_reset(); db_multi_exec("%s", blob_str(&ins)/*safe-for-%s*/); blob_reset(&ins); if( related ){ db_multi_exec( ................................................................................ " SELECT childid FROM cherrypick WHERE parentid IN pathnode;" ); } } db_multi_exec("INSERT OR IGNORE INTO pathnode SELECT x FROM related"); } blob_append_sql(&sql, " AND event.objid IN pathnode"); if( zChng && zChng[0] ){ db_multi_exec( "DELETE FROM pathnode " " WHERE NOT EXISTS(SELECT 1 FROM mlink, filename" " WHERE mlink.mid=x" " AND mlink.fnid=filename.fnid AND %s)", glob_expr("filename.name", zChng) ); } tmFlags |= TIMELINE_DISJOINT; tmFlags &= ~TIMELINE_CHPICK; db_multi_exec("%s", blob_sql_text(&sql)); if( advancedMenu ){ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0); } nNodeOnPath = db_int(0, "SELECT count(*) FROM temp.pathnode"); blob_appendf(&desc, "%d check-ins going from ", nNodeOnPath); blob_appendf(&desc, "%z[%h]", href("%R/info/%h", zFrom), zFrom); blob_append(&desc, " to ", -1); blob_appendf(&desc, "%z[%h]", href("%R/info/%h",zTo), zTo); if( related ){ int nRelated = db_int(0, "SELECT count(*) FROM timeline") - nNodeOnPath; if( nRelated>0 ){ ................................................................................ TAG_HIDDEN ); } } } if( (zType[0]=='w' && !g.perm.RdWiki) || (zType[0]=='t' && !g.perm.RdTkt) || (zType[0]=='n' && !g.perm.RdTkt) || (zType[0]=='e' && !g.perm.RdWiki) || (zType[0]=='c' && !g.perm.Read) || (zType[0]=='g' && !g.perm.Read) || (zType[0]=='f' && !g.perm.RdForum) ){ zType = "all"; } ................................................................................ if( g.perm.RdForum ){ blob_append_sql(&cond, "%c'f'", cSep); cSep = ','; } blob_append_sql(&cond, ")"); } }else{ /* zType!="all" */ if( zType[0]=='n' ){ blob_append_sql(&cond, " AND event.type='t' AND event.comment GLOB 'New ticket*'"); }else{ blob_append_sql(&cond, " AND event.type=%Q", zType); } if( zType[0]=='c' ){ zEType = "check-in"; }else if( zType[0]=='w' ){ zEType = "wiki"; }else if( zType[0]=='t' ){ zEType = "ticket change"; }else if( zType[0]=='n' ){ zEType = "new tickets"; }else if( zType[0]=='e' ){ zEType = "technical note"; }else if( zType[0]=='g' ){ zEType = "tag"; }else if( zType[0]=='f' ){ zEType = "forum post"; } ................................................................................ desc.aData[0] = fossil_toupper(desc.aData[0]); } if( zBrName ){ if( !PB("nowiki") && wiki_render_associated("branch", zBrName, WIKIASSOC_ALL) ){ @ %b(&desc) } else{ @ %b(&desc) } style_submenu_element("Diff", "%R/vdiff?branch=%T", zBrName); }else if( zTagName && matchStyle==MS_EXACT && zBrName==0 && !PB("nowiki") isSelectedOrCurrent = 1; }else if( rid==vid ){ @ isSelectedOrCurrent = 1; }else { @ } if( zType[0]=='e' && tagid ){ if( bTimestampLinksToInfo ){ char *zId; zId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", tagid); zDateLink = href("%R/technote/%s",zId); ................................................................................ ** not actually draw anything on the graph, but it will set the ** background color of the timeline entry */ gidx = graph_add_row(pGraph, rid, -1, 0, 0, zBr, zBgClr, zUuid, 0); @ } @ if( !isSelectedOrCurrent ){ @ isSelectedOrCurrent = 1; }else if( rid==vid ){ @ isSelectedOrCurrent = 1; }else { @ } if( zType[0]=='t' && tagid && (tmFlags & TIMELINE_NOTKT)==0 ){ char *zTktid = db_text(0, "SELECT substr(tagname,5) FROM tag" " WHERE tagid=%d", tagid); if( zTktid ){ int isClosed = 0; if( is_ticket(zTktid, &isClosed) && isClosed ){ zExtraClass = " tktTlClosed"; }else{ zExtraClass = " tktTlOpen"; } fossil_free(zTktid); } } if( zType[0]=='e' && tagid ){ if( bTimestampLinksToInfo ){ char *zId; zId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", tagid); zDateLink = href("%R/technote/%s",zId); ................................................................................ ** not actually draw anything on the graph, but it will set the ** background color of the timeline entry */ gidx = graph_add_row(pGraph, rid, -1, 0, 0, zBr, zBgClr, zUuid, 0); @ } @ if( !isSelectedOrCurrent ){ @ Changes to src/tkt.c.  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 ... 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 ... 474 475 476 477 478 479 480 481 482 483 484 485 486 487 ... 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 ... 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 return Th_Eval(g.interp, 0, zConfig, -1); } /* ** Recreate the TICKET and TICKETCHNG tables. */ void ticket_create_table(int separateConnection){ const char *zSql; db_multi_exec( "DROP TABLE IF EXISTS ticket;" "DROP TABLE IF EXISTS ticketchng;" ); zSql = ticket_table_schema(); if( separateConnection ){ if( db_transaction_nesting_depth() ) db_end_transaction(0); db_init_database(g.zRepositoryName, zSql, 0); }else{ db_multi_exec("%s", zSql/*safe-for-%s*/); } } /* ** Repopulate the TICKET and TICKETCHNG tables from scratch using all ** available ticket artifacts. */ void ticket_rebuild(void){ ................................................................................ @ mUsed = %d(aField[i].mUsed); } @ } /* ** WEBPAGE: tktview ** URL: tktview?name=UUID ** ** View a ticket identified by the name= query parameter. */ void tktview_page(void){ const char *zScript; char *zFullName; const char *zUuid = PD("name",""); login_check_credentials(); if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } if( g.anon.WrTkt || g.anon.ApndTkt ){ style_submenu_element("Edit", "%s/tktedit?name=%T", g.zTop, PD("name","")); } if( g.perm.Hyperlink ){ style_submenu_element("History", "%s/tkthistory/%T", g.zTop, zUuid); style_submenu_element("Timeline", "%s/tkttimeline/%T", g.zTop, zUuid); style_submenu_element("Check-ins", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); } if( g.anon.NewTkt ){ style_submenu_element("New Ticket", "%s/tktnew", g.zTop); } if( g.anon.ApndTkt && g.anon.Attach ){ style_submenu_element("Attach", "%s/attachadd?tkt=%T&from=%s/tktview/%t", ................................................................................ } if( P("plaintext") ){ style_submenu_element("Formatted", "%R/tktview/%s", zUuid); }else{ style_submenu_element("Plaintext", "%R/tktview/%s?plaintext", zUuid); } style_header("View Ticket"); if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW \n", -1); ticket_init(); initializeVariablesFromCGI(); getAllTicketFields(); initializeVariablesFromDb(); zScript = ticket_viewpage_code(); if( P("showfields")!=0 ) showAllFields(); ................................................................................ "table containing all required fields"); } } sqlite3_close(db); } return zErr; } /* ** WEBPAGE: tkttimeline ** URL: /tkttimeline?name=TICKETUUID&y=TYPE ** ** Show the change history for a single ticket in timeline format. */ void tkttimeline_page(void){ Stmt q; char *zTitle; char *zSQL; const char *zUuid; char *zFullUuid; int tagid; char zGlobPattern[50]; const char *zType; login_check_credentials(); if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(g.anon.Hyperlink && g.anon.RdTkt); ................................................................................ canonical16(zGlobPattern, strlen(zGlobPattern)); tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); if( tagid==0 ){ @ No such ticket: %h(zUuid) style_footer(); return; } zFullUuid = db_text(0, "SELECT substr(tagname, 5) FROM tag WHERE tagid=%d", tagid); if( zType[0]=='c' ){ zSQL = mprintf( "%s AND event.objid IN " " (SELECT srcid FROM backlink WHERE target GLOB '%.4s*' " "AND '%s' GLOB (target||'*')) " "ORDER BY mtime DESC", timeline_query_for_www(), zFullUuid, zFullUuid ); }else{ zSQL = mprintf( "%s AND event.objid IN " " (SELECT rid FROM tagxref WHERE tagid=%d" " UNION SELECT srcid FROM backlink" " WHERE target GLOB '%.4s*'" " AND '%s' GLOB (target||'*')" " UNION SELECT attachid FROM attachment" " WHERE target=%Q) " "ORDER BY mtime DESC", timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid ); } db_prepare(&q, "%z", zSQL/*safe-for-%s*/); www_print_timeline(&q, TIMELINE_ARTID|TIMELINE_DISJOINT|TIMELINE_GRAPH, 0, 0, 0, 0, 0, 0); db_finalize(&q); style_footer(); } /* ** WEBPAGE: tkthistory ** URL: /tkthistory?name=TICKETUUID ** | > | > > > > < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < 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 ... 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 ... 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 ... 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 ... 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 return Th_Eval(g.interp, 0, zConfig, -1); } /* ** Recreate the TICKET and TICKETCHNG tables. */ void ticket_create_table(int separateConnection){ char *zSql; db_multi_exec( "DROP TABLE IF EXISTS ticket;" "DROP TABLE IF EXISTS ticketchng;" ); zSql = ticket_table_schema(); if( separateConnection ){ if( db_transaction_nesting_depth() ) db_end_transaction(0); db_init_database(g.zRepositoryName, zSql, 0); }else{ db_multi_exec("%s", zSql/*safe-for-%s*/); } fossil_free(zSql); } /* ** Repopulate the TICKET and TICKETCHNG tables from scratch using all ** available ticket artifacts. */ void ticket_rebuild(void){ ................................................................................ @ mUsed = %d(aField[i].mUsed); } @ } /* ** WEBPAGE: tktview ** URL: tktview?name=HASH ** ** View a ticket identified by the name= query parameter. ** Other query parameters: ** ** tl Show a timeline of the ticket above the status */ void tktview_page(void){ const char *zScript; char *zFullName; const char *zUuid = PD("name",""); int showTimeline = P("tl")!=0; login_check_credentials(); if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } if( g.anon.WrTkt || g.anon.ApndTkt ){ style_submenu_element("Edit", "%s/tktedit?name=%T", g.zTop, PD("name","")); } if( g.perm.Hyperlink ){ style_submenu_element("History", "%s/tkthistory/%T", g.zTop, zUuid); style_submenu_element("Check-ins", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); } if( g.anon.NewTkt ){ style_submenu_element("New Ticket", "%s/tktnew", g.zTop); } if( g.anon.ApndTkt && g.anon.Attach ){ style_submenu_element("Attach", "%s/attachadd?tkt=%T&from=%s/tktview/%t", ................................................................................ } if( P("plaintext") ){ style_submenu_element("Formatted", "%R/tktview/%s", zUuid); }else{ style_submenu_element("Plaintext", "%R/tktview/%s?plaintext", zUuid); } style_header("View Ticket"); if( showTimeline ){ int tagid = db_int(0,"SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'", zUuid); if( tagid ){ tkt_draw_timeline(tagid, "a"); @ }else{ showTimeline = 0; } } if( !showTimeline && g.perm.Hyperlink ){ style_submenu_element("Timeline", "%s/info/%T", g.zTop, zUuid); } if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW \n", -1); ticket_init(); initializeVariablesFromCGI(); getAllTicketFields(); initializeVariablesFromDb(); zScript = ticket_viewpage_code(); if( P("showfields")!=0 ) showAllFields(); ................................................................................ "table containing all required fields"); } } sqlite3_close(db); } return zErr; } /* ** Draw a timeline for a ticket with tag.tagid given by the tagid ** parameter. */ void tkt_draw_timeline(int tagid, const char *zType){ Stmt q; char *zFullUuid; char *zSQL; zFullUuid = db_text(0, "SELECT substr(tagname, 5) FROM tag WHERE tagid=%d", tagid); if( zType[0]=='c' ){ zSQL = mprintf( "%s AND event.objid IN " " (SELECT srcid FROM backlink WHERE target GLOB '%.4s*' " "AND '%s' GLOB (target||'*')) " "ORDER BY mtime DESC", timeline_query_for_www(), zFullUuid, zFullUuid ); }else{ zSQL = mprintf( "%s AND event.objid IN " " (SELECT rid FROM tagxref WHERE tagid=%d" " UNION SELECT srcid FROM backlink" " WHERE target GLOB '%.4s*'" " AND '%s' GLOB (target||'*')" " UNION SELECT attachid FROM attachment" " WHERE target=%Q) " "ORDER BY mtime DESC", timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid ); } db_prepare(&q, "%z", zSQL/*safe-for-%s*/); www_print_timeline(&q, TIMELINE_ARTID | TIMELINE_DISJOINT | TIMELINE_GRAPH | TIMELINE_NOTKT, 0, 0, 0, 0, 0, 0); db_finalize(&q); fossil_free(zFullUuid); } /* ** WEBPAGE: tkttimeline ** URL: /tkttimeline?name=TICKETUUID&y=TYPE ** ** Show the change history for a single ticket in timeline format. */ void tkttimeline_page(void){ char *zTitle; const char *zUuid; int tagid; char zGlobPattern[50]; const char *zType; login_check_credentials(); if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(g.anon.Hyperlink && g.anon.RdTkt); ................................................................................ canonical16(zGlobPattern, strlen(zGlobPattern)); tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); if( tagid==0 ){ @ No such ticket: %h(zUuid) style_footer(); return; } tkt_draw_timeline(tagid, zType); style_footer(); } /* ** WEBPAGE: tkthistory ** URL: /tkthistory?name=TICKETUUID ** Changes to src/tktsetup.c.  94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 ... 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 ... 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 ... 375 376 377 378 379 380 381 382 383 384 385 386 387 388 ... 539 540 541 542 543 544 545 546 547 548 549 550 551 552 ... 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 ... 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 ... 656 657 658 659 660 661 662 663 664 665 666 667 668 669 ... 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 @ mimetype TEXT, @ icomment TEXT @ ); @ CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime); ; /* ** Return the ticket table definition */ const char *ticket_table_schema(void){ return db_get("ticket-table", zDefaultTicketTable); } /* ** Common implementation for the ticket setup editor pages. */ static void tktsetup_generic( ................................................................................ 0, 30 ); } static const char zDefaultNew[] = @ @ if {![info exists mutype]} {set mutype {[links only]}} @ if {[info exists submit]} { @ set status Open @ if {$mutype eq "HTML"} { @ set mimetype "text/html" @ } elseif {$mutype eq "Wiki"} { @ set mimetype "text/x-fossil-wiki" @ } elseif {$mutype eq {[links only]}} { @ set mimetype "text/x-fossil-plain" @ } else { @ set mimetype "text/plain" @ } @ submit_ticket @ set preview 1 ................................................................................ @ @
@ Enter a detailed description of the problem. @ For code defects, be sure to provide details on exactly how @ the problem can be reproduced. Provide as much detail as @ possible. Format: @ combobox mutype {Wiki HTML {Plain Text} {[links only]}} 1 @
@ set nline [linecount $comment 50 10] @ @ Version Found In: @ @ @ Append Remark with format @ combobox mutype {Wiki HTML {Plain Text} {[links only]}} 1 @ from @ : @ @ @ Enter a detailed description of the problem. @ For code defects, be sure to provide details on exactly how @ the problem can be reproduced. Provide as much detail as @ possible. Format: @ combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki}} 1 @ @ set nline [linecount$comment 50 10] @
@
Version Found In: @ @
@ Append Remark with format @ combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki} 1 @ from @ :
@ @
@ @ @ enable_output [info exists preview] ................................................................................ @ Description Preview:

@ @ if {$mutype eq "Wiki"} { @ wiki$icomment @ } elseif {$mutype eq "Plain Text"} { @ set r [randhex] @ wiki "[string trimright$icomment]\n" @ } elseif {$mutype eq {[links only]}} { @ set r [randhex] @ wiki "[string trimright$icomment]\n" @ } else { @ wiki "$icomment\n" @ } @ ................................................................................ @ html " added on$xdate:\n" @ if {$alwaysPlaintext ||$xmimetype eq "text/plain"} { @ set r [randhex] @ if {$xmimetype ne "text/plain"} {html "([htmlize$xmimetype])\n"} @ wiki "[string trimright $xcomment]\n" @ } elseif {$xmimetype eq "text/x-fossil-wiki"} { @ wiki "

\n[string trimright $xcomment]\n \n" @ } elseif {$xmimetype eq "text/html"} { @ wiki "

\n[string trimright $xcomment]\n\n" @ } else { @ set r [randhex] @ wiki "[string trimright$xcomment]\n" @ } @ } ................................................................................ 0, 40 ); } static const char zDefaultEdit[] = @ @ if {![info exists mutype]} {set mutype {[links only]}} @ if {![info exists icomment]} {set icomment {}} @ if {![info exists username]} {set username $login} @ if {[info exists submit]} { @ if {$mutype eq "Wiki"} { @ set mimetype text/x-fossil-wiki @ } elseif {$mutype eq "HTML"} { @ set mimetype text/html @ } elseif {$mutype eq {[links only]}} { @ set mimetype text/x-fossil-plain @ } else { @ set mimetype text/plain @ } ................................................................................ @ @

@ @ @ @ enable_output [info exists preview] ................................................................................ @ Description Preview:

@ @ if {$mutype eq "Wiki"} { @ wiki$icomment @ } elseif {$mutype eq "Plain Text"} { @ set r [randhex] @ wiki "\n[string trimright$icomment]\n" @ } elseif {$mutype eq {[links only]}} { @ set r [randhex] @ wiki "\n[string trimright$icomment]" @ } else { @ wiki "\n[string trimright $icomment]\n" @ } @ ................................................................................ @ login_insert_csrf_secret(); @ entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title", 0); @ An SQL expression in a query against the TICKET table that will @ return the title of the ticket for display purposes. @ entry_attribute("Ticket Status", 40, "ticket-status-column", "s", "status", 0); @ The name of the column in the TICKET table that contains the ticket @ status in human-readable form. Case sensitive. @ entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c", "status='Closed'", 0); @ An SQL expression that evaluates to true in a TICKET table query if @ the ticket is closed. @ @ @ @ @ @ db_end_transaction(0); style_footer(); } | > | | > > | > > > > | > > | > > | > | > | > 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ... 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 ... 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 ... 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 ... 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 ... 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 ... 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 ... 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 ... 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 @ mimetype TEXT, @ icomment TEXT @ ); @ CREATE INDEX ticketchng_idx1 ON ticketchng(tkt_id, tkt_mtime); ; /* ** Return the ticket table definition in heap-allocated ** memory owned by the caller. */ char *ticket_table_schema(void){ return db_get("ticket-table", zDefaultTicketTable); } /* ** Common implementation for the ticket setup editor pages. */ static void tktsetup_generic( ................................................................................ 0, 30 ); } static const char zDefaultNew[] = @ @ if {![info exists mutype]} {set mutype Markdown} @ if {[info exists submit]} { @ set status Open @ if {$mutype eq "HTML"} { @ set mimetype "text/html" @ } elseif {$mutype eq "Wiki"} { @ set mimetype "text/x-fossil-wiki" @ } elseif {$mutype eq "Markdown"} { @ set mimetype text/x-markdown @ } elseif {$mutype eq {[links only]}} { @ set mimetype "text/x-fossil-plain" @ } else { @ set mimetype "text/plain" @ } @ submit_ticket @ set preview 1 ................................................................................ @ @ @ @ @ enable_output [info exists preview] ................................................................................ @ Description Preview: @ @ if {$mutype eq "Wiki"} { @ wiki $icomment @ } elseif {$mutype eq "Plain Text"} { @ set r [randhex] @ wiki "[string trimright $icomment]\n" @ } elseif {$mutype eq "Markdown"} { @ html [lindex [markdown "$icomment\n"] 1] @ } elseif {$mutype eq {[links only]}} { @ set r [randhex] @ wiki "[string trimright $icomment]\n" @ } else { @ wiki "$icomment\n" @ } @ ................................................................................ @ html " added on $xdate:\n" @ if {$alwaysPlaintext || $xmimetype eq "text/plain"} { @ set r [randhex] @ if {$xmimetype ne "text/plain"} {html "([htmlize $xmimetype])\n"} @ wiki "[string trimright$xcomment]\n" @ } elseif {$xmimetype eq "text/x-fossil-wiki"} { @ wiki " \n[string trimright$xcomment]\n

\n" @ } elseif {$xmimetype eq "text/x-markdown"} { @ html [lindex [markdown$xcomment] 1] @ } elseif {$xmimetype eq "text/html"} { @ wiki " \n[string trimright$xcomment]\n\n" @ } else { @ set r [randhex] @ wiki "[string trimright $xcomment]\n" @ } @ } ................................................................................ 0, 40 ); } static const char zDefaultEdit[] = @ @ if {![info exists mutype]} {set mutype Markdown} @ if {![info exists icomment]} {set icomment {}} @ if {![info exists username]} {set username$login} @ if {[info exists submit]} { @ if {$mutype eq "Wiki"} { @ set mimetype text/x-fossil-wiki @ } elseif {$mutype eq "Markdown"} { @ set mimetype text/x-markdown @ } elseif {$mutype eq "HTML"} { @ set mimetype text/html @ } elseif {$mutype eq {[links only]}} { @ set mimetype text/x-fossil-plain @ } else { @ set mimetype text/plain @ } ................................................................................ @ @

@ @ @ @ enable_output [info exists preview] ................................................................................ @ Description Preview:

@ @ if {$mutype eq "Wiki"} { @ wiki$icomment @ } elseif {$mutype eq "Plain Text"} { @ set r [randhex] @ wiki "\n[string trimright$icomment]\n" @ } elseif {$mutype eq "Markdown"} { @ html [lindex [markdown "$icomment\n"] 1] @ } elseif {$mutype eq {[links only]}} { @ set r [randhex] @ wiki "\n[string trimright$icomment]" @ } else { @ wiki "\n[string trimright $icomment]\n" @ } @ ................................................................................ @ login_insert_csrf_secret(); @ entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title", 0); @ An SQL expression in a query against the TICKET table that will @ return the title of the ticket for display purposes. @ (Property: ticket-title-expr) @ entry_attribute("Ticket Status", 40, "ticket-status-column", "s", "status", 0); @ The name of the column in the TICKET table that contains the ticket @ status in human-readable form. Case sensitive. @ (Property: ticket-status-column) @ entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c", "status='Closed'", 0); @ An SQL expression that evaluates to true in a TICKET table query if @ the ticket is closed. @ (Property: ticket-closed-expr) @ @ @ @ @ @ db_end_transaction(0); style_footer(); } Changes to src/undo.c.  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 /* ** COMMAND: undo ** COMMAND: redo* ** ** Usage: %fossil undo ?OPTIONS? ?FILENAME...? ** or: %fossil redo ?OPTIONS? ?FILENAME...? ** ** Undo the changes to the working checkout caused by the most recent ** of the following operations: ** ** (1) fossil update (5) fossil stash apply ** (2) fossil merge (6) fossil stash drop ** (3) fossil revert (7) fossil stash goto ** (4) fossil stash pop ** ** The "fossil clean" operation can also be undone; however, this is ** currently limited to files that are less than 10MiB in size. ** ** If FILENAME is specified then restore the content of the named ** file(s) but otherwise leave the update or merge or revert in effect. ** The redo command undoes the effect of the most recent undo. ** ** If the -n|--dry-run option is present, no changes are made and instead ** the undo or redo command explains what actions the undo or redo would ** have done had the -n|--dry-run been omitted. ** ** A single level of undo/redo is supported. The undo/redo stack ** is cleared by the commit and checkout commands. ** ** Options: ** -n|--dry-run do not make changes but show what would be done ** ** See also: commit, status */ void undo_cmd(void){ | | | | | > > > > > > > | > > > > 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 /* ** COMMAND: undo ** COMMAND: redo* ** ** Usage: %fossil undo ?OPTIONS? ?FILENAME...? ** or: %fossil redo ?OPTIONS? ?FILENAME...? ** ** The undo command reverts the changes caused by the previous command ** if the previous command is one of the following: ** ** (1) fossil update (5) fossil stash apply ** (2) fossil merge (6) fossil stash drop ** (3) fossil revert (7) fossil stash goto ** (4) fossil stash pop (8) fossil clean (*see note*) ** ** Note: The "fossil clean" command only saves state for files less than ** 10MiB in size and so if fossil clean deleted files larger than that, ** then "fossil undo" will not recover the larger files. ** ** If FILENAME is specified then restore the content of the named ** file(s) but otherwise leave the update or merge or revert in effect. ** The redo command undoes the effect of the most recent undo. ** ** If the -n|--dry-run option is present, no changes are made and instead ** the undo or redo command explains what actions the undo or redo would ** have done had the -n|--dry-run been omitted. ** ** If the most recent command is not one of those listed as undoable, ** then the undo command might try to restore the state to be what it was ** prior to the last undoable command, or it might be a no-op. If in ** doubt about what the undo command will do, first run it with the -n ** option. ** ** A single level of undo/redo is supported. The undo/redo stack ** is cleared by the commit and checkout commands. Other commands may ** or may not clear the undo stack. ** ** Future versions of Fossil might add new commands to the set of commands ** that are undoable. ** ** Options: ** -n|--dry-run do not make changes but show what would be done ** ** See also: commit, status */ void undo_cmd(void){ Changes to src/unversioned.c.  289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 const char *zError = 0; const char *zIn; const char *zAs; Blob file; int i; zAs = find_option("as",0,1); if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); verify_all_options(); db_begin_transaction(); content_rcvid_init("#!fossil unversioned add"); for(i=3; i 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 const char *zError = 0; const char *zIn; const char *zAs; Blob file; int i; zAs = find_option("as",0,1); verify_all_options(); if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); db_begin_transaction(); content_rcvid_init("#!fossil unversioned add"); for(i=3; i Changes to src/verify.c.  66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 ** This routine is called just prior to each commit operation. ** ** Invoke verify_rid() on every record that has been added or modified ** in the repository, in order to make sure that the repository is sane. */ static int verify_at_commit(void){ int rid; content_clear_cache(); inFinalVerify = 1; rid = bag_first(&toVerify); while( rid>0 ){ verify_rid(rid); rid = bag_next(&toVerify, rid); } bag_clear(&toVerify); | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 ** This routine is called just prior to each commit operation. ** ** Invoke verify_rid() on every record that has been added or modified ** in the repository, in order to make sure that the repository is sane. */ static int verify_at_commit(void){ int rid; content_clear_cache(0); inFinalVerify = 1; rid = bag_first(&toVerify); while( rid>0 ){ verify_rid(rid); rid = bag_next(&toVerify, rid); } bag_clear(&toVerify); Changes to src/wikiformat.c.  1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 /* ** zTarget is guaranteed to be a UUID. It might be the UUID of a ticket. ** If it is, store in *pClosed a true or false depending on whether or not ** the ticket is closed and return true. If zTarget ** is not the UUID of a ticket, return false. */ static int is_ticket( const char *zTarget, /* Ticket UUID */ int *pClosed /* True if the ticket is closed */ ){ static Stmt q; int n; int rc; char zLower[HNAME_MAX+1]; | 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 /* ** zTarget is guaranteed to be a UUID. It might be the UUID of a ticket. ** If it is, store in *pClosed a true or false depending on whether or not ** the ticket is closed and return true. If zTarget ** is not the UUID of a ticket, return false. */ int is_ticket( const char *zTarget, /* Ticket UUID */ int *pClosed /* True if the ticket is closed */ ){ static Stmt q; int n; int rc; char zLower[HNAME_MAX+1]; Changes to test/th1.test.  1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 set base_commands {anoncap anycap array artifact break breakpoint catch\ cgiHeaderLine checkout combobox continue date decorate dir enable_output \ encode64 error expr for getParameter glob_match globalState hascap \ hasfeature html htmlize http httpize if info insertCsrf lindex linecount \ list llength lsearch markdown nonce proc puts query randhex redirect\ regexp reinitialize rename render repository return searchable set\ setParameter setting stime string styleFooter styleHeader styleScript\ tclReady trace unset unversioned uplevel upvar utime verifyCsrf wiki} set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} if {$th1Tcl} { test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} } else { test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} } | > 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 set base_commands {anoncap anycap array artifact break breakpoint catch\ cgiHeaderLine checkout combobox continue date decorate dir enable_output \ encode64 error expr for getParameter glob_match globalState hascap \ hasfeature html htmlize http httpize if info insertCsrf lindex linecount \ list llength lsearch markdown nonce proc puts query randhex redirect\ regexp reinitialize rename render repository return searchable set\ setParameter setting stime string styleFooter styleHeader styleScript\ tclReady trace unset unversioned uplevel upvar utime verifyCsrf\ verifyLogin wiki} set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} if {$th1Tcl} { test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} } else { test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} } Changes to win/Makefile.PellesCGMake.  81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) SQLITEDEFINES=-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_GET_TABLE -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_WIN32_NO_ANSI # define the SQLite shell files, which need special flags on compile SQLITESHELLSRC=shell.c ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) SQLITESHELLDEFINES=-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_GET_TABLE -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 -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 # define the th scripting files, which need special flags on compile THSRC=th.c th_lang.c ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf)) THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj)) # define the zlib files, needed by this compile | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) SQLITEDEFINES=-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_GET_TABLE -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 -DSQLITE_WIN32_NO_ANSI # define the SQLite shell files, which need special flags on compile SQLITESHELLSRC=shell.c ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) SQLITESHELLDEFINES=-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_GET_TABLE -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 # define the th scripting files, which need special flags on compile THSRC=th.c th_lang.c ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf)) THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj)) # define the zlib files, needed by this compile Changes to win/Makefile.dmc.  22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 SSL = CFLAGS = -o BCC =$(DMDIR)\bin\dmc $(CFLAGS) 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_GET_TABLE -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 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_GET_TABLE -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 -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 alerts_.c allrepo_.c attach_.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 checkin_.c checkout_.c clearsign_.c clone_.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 finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c 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 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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$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)\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)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$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)\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)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 SSL = CFLAGS = -o BCC =$(DMDIR)\bin\dmc $(CFLAGS) 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_GET_TABLE -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_GET_TABLE -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 alerts_.c allrepo_.c attach_.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 checkin_.c checkout_.c clearsign_.c clone_.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 finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c 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 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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$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)\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)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$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)\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)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc Changes to win/Makefile.mingw.  2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 .... 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_JSON1 \ -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_STMTVTAB \ -DSQLITE_HAVE_ZLIB \ -DSQLITE_INTROSPECTION_PRAGMAS \ -DSQLITE_ENABLE_DBPAGE_VTAB \ -DSQLITE_WIN32_NO_ANSI \$(MINGW_OPTIONS) \ -DSQLITE_USE_MALLOC_H \ -DSQLITE_USE_MSIZE SHELL_OPTIONS = -DNDEBUG=1 \ -DSQLITE_DQS=0 \ ................................................................................ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_JSON1 \ -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_STMTVTAB \ -DSQLITE_HAVE_ZLIB \ -DSQLITE_INTROSPECTION_PRAGMAS \ -DSQLITE_ENABLE_DBPAGE_VTAB \ -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 \ > > 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 .... 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 -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 \ -DSQLITE_WIN32_NO_ANSI \$(MINGW_OPTIONS) \ -DSQLITE_USE_MALLOC_H \ -DSQLITE_USE_MSIZE SHELL_OPTIONS = -DNDEBUG=1 \ -DSQLITE_DQS=0 \ ................................................................................ -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 \ Changes to win/Makefile.msc.  298 299 300 301 302 303 304 305 306 307 308 309 310 311 ... 325 326 327 328 329 330 331 332 333 334 335 336 337 338 /DSQLITE_ENABLE_DBSTAT_VTAB \ /DSQLITE_ENABLE_JSON1 \ /DSQLITE_ENABLE_FTS5 \ /DSQLITE_ENABLE_STMTVTAB \ /DSQLITE_HAVE_ZLIB \ /DSQLITE_INTROSPECTION_PRAGMAS \ /DSQLITE_ENABLE_DBPAGE_VTAB \ /DSQLITE_WIN32_NO_ANSI SHELL_OPTIONS = /DNDEBUG=1 \ /DSQLITE_DQS=0 \ /DSQLITE_THREADSAFE=0 \ /DSQLITE_DEFAULT_MEMSTATUS=0 \ /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ ................................................................................ /DSQLITE_ENABLE_DBSTAT_VTAB \ /DSQLITE_ENABLE_JSON1 \ /DSQLITE_ENABLE_FTS5 \ /DSQLITE_ENABLE_STMTVTAB \ /DSQLITE_HAVE_ZLIB \ /DSQLITE_INTROSPECTION_PRAGMAS \ /DSQLITE_ENABLE_DBPAGE_VTAB \ /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 \ > > 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 ... 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 /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 \ /DSQLITE_WIN32_NO_ANSI SHELL_OPTIONS = /DNDEBUG=1 \ /DSQLITE_DQS=0 \ /DSQLITE_THREADSAFE=0 \ /DSQLITE_DEFAULT_MEMSTATUS=0 \ /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ ................................................................................ /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 \ Changes to www/blockchain.md.  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 block, a timestamp, and transaction data..." [(1)][] By that definition, Fossil is clearly an implementation of blockchain. The blocks are ["manifests" artifacts](./fileformat.wiki#manifest). Each manifest has a SHA1 or SHA3 hash of its parent or parents, a timestamp, and other transactional data. The repository grows by add new manifests onto the list. Some people have come to associate blockchain with cryptocurrency, however, and since Fossil has nothing to do with cryptocurrency, the claim that Fossil is build around blockchain is met with skepticism. The key thing to note here is that cryptocurrency implementations like BitCoin are built around blockchain, but they are not synonymous with blockchain. Blockchain is a much broader concept. Blockchain is a mechanism for constructed a distributed ledger of transactions. Yes, you can use a distributed ledger to implement a cryptocurrency, but you can also use a distributed ledger to implement a version control system, and probably many other kinds of applications as well. Blockchain is a much broader idea than cryptocurrency. [(1)]: https://en.wikipedia.org/wiki/Blockchain | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 block, a timestamp, and transaction data..." [(1)][] By that definition, Fossil is clearly an implementation of blockchain. The blocks are ["manifests" artifacts](./fileformat.wiki#manifest). Each manifest has a SHA1 or SHA3 hash of its parent or parents, a timestamp, and other transactional data. The repository grows by adding new manifests onto the list. Some people have come to associate blockchain with cryptocurrency, however, and since Fossil has nothing to do with cryptocurrency, the claim that Fossil is built around blockchain is met with skepticism. The key thing to note here is that cryptocurrency implementations like BitCoin are built around blockchain, but they are not synonymous with blockchain. Blockchain is a much broader concept. Blockchain is a mechanism for constructing a distributed ledger of transactions. Yes, you can use a distributed ledger to implement a cryptocurrency, but you can also use a distributed ledger to implement a version control system, and probably many other kinds of applications as well. Blockchain is a much broader idea than cryptocurrency. [(1)]: https://en.wikipedia.org/wiki/Blockchain Changes to www/build.wiki.  227 228 229 230 231 232 233 TCC += -DSQLITE_WITHOUT_ZONEMALLOC TCC += -D_BSD_SOURCE TCC += -DWITHOUT_ICONV TCC += -Dsocketlen_t=int TCC += -DSQLITE_MAX_MMAP_SIZE=0 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 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 TCC += -DSQLITE_WITHOUT_ZONEMALLOC TCC += -D_BSD_SOURCE TCC += -DWITHOUT_ICONV TCC += -Dsocketlen_t=int TCC += -DSQLITE_MAX_MMAP_SIZE=0 5.0 Building a Static Binary on Linux using Docker Building a static binary on Linux is not as straightforward as it could be because the GNU C library requires that certain components be dynamically loadable. That can be worked around by building against a different C library, which is simplest to do by way of a container environment like [https://www.docker.com/ | Docker]. The following instructions for building fossil using Docker were adapted from [https://fossil-scm.org/forum/forumpost/5dd2d61e5f | forumpost/5dd2d61e5f]. These instructions assume that docker is installed and that the user running these instructions has permission to do so (i.e., they are root or are a member of the docker group). First, create a file named Dockerfile with the following contents: FROM alpine:edge RUN apk update \ && apk upgrade \ \ && apk add --no-cache \ curl gcc make tcl \ musl-dev \ openssl-dev zlib-dev \ openssl-libs-static zlib-static \ \ && curl \ "https://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=trunk" \ -o fossil-src.tar.gz \ \ && tar xf fossil-src.tar.gz \ && cd fossil-src \ \ && ./configure \ --static \ --disable-fusefs \ --with-th1-docs \ --with-th1-hooks \ \ && make Be sure to modify the configure flags, if desired. e.g., add --json for JSON support. From the directory containing that file, build it with docker: # docker build -t fossil_static . If you get permissions errors when running that as a non-root user, be sure to add the user to the docker group before trying again. That creates a docker image and builds a static fossil binary inside it. That step will take several minutes or more, depending on the speed of the build environment. Next, create a docker container to host the image we just created: # docker create --name fossil fossil_static Then copy the fossil binary from that container: # docker cp fossil:/fossil-src/fossil fossil The resulting binary will be huge because it is built with debug info. To strip that information, reducing the size greatly: # strip fossil To delete the Docker container and image (if desired), run: # docker container rm fossil # docker image ls Note the IDs of the images named fossil_static and alpine, then: docker image rm THE_FOSSIL_ID THE_ALPINE_ID Changes to www/cgi.wiki.  134 135 136 137 138 139 140 This parameter causes additional environment variable NAME to have VALUE. This parameter can be repeated as many times as necessary. HOME: PATH This parameter is a short-hand for "setenv HOME PATH". > > > > > 134 135 136 137 138 139 140 141 142 143 144 145 This parameter causes additional environment variable NAME to have VALUE. This parameter can be repeated as many times as necessary. HOME: PATH This parameter is a short-hand for "setenv HOME PATH". cgi-debug: FILE Cause CGI-related debugging information to be appended in FILE. Use this to help debug CGI problems. Changes to www/changes.wiki.  1 2 3 4 5 6 7 8 9 10 11 Change Log Changes for Version 2.10 (pending) * Added support for [./serverext.wiki|CGI-based Server Extensions]. * Added the [/help?cmd=repolist-skin|repolist-skin] setting used to add style to repository list pages. * Enhance the hierarchical display of Forum threads to do less indentation and to provide links back to the previous message in the thread. Provide sequential numbers for all messages in > > > > > > > > > > > > > > > | 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 Change Log Changes for Version 2.11 (pending) * Support Markdown in the default ticket configuration. * Rework the "[/help?cmd=grep|fossil grep]" command to be more useful. * Expose the [/help?cmd=redirect-to-https|redirect-to-https] setting to the [/help?cmd=settings|settings] command. * Improve support for CGI on IIS web servers. * The [/help?cmd=/ext|/ext page] can now render index files, analog to how the embedded docs do. * Most commands now support the Unix-conventional "--" flag to treat all following arguments as filenames instead of flags. * Several minor enhancements to existing features. Changes for Version 2.10 (2019-10-04) * Added support for [./serverext.wiki|CGI-based Server Extensions]. * Added the [/help?cmd=repolist-skin|repolist-skin] setting used to add style to repository list pages. * Enhance the hierarchical display of Forum threads to do less indentation and to provide links back to the previous message in the thread. Provide sequential numbers for all messages in Changes to www/checkin_names.wiki.  7 8 9 10 11 12 13 14 15 16 17 18 19 20 names: • Cryptographic hash prefix • Tag or branchname • Timestamp: YYYY-MM-DD HH:MM:SS • tag-name : timestamp • root : branchname • Special names: • tip • current • next • previous or prev • ckout for embedded docs > 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 names: • Cryptographic hash prefix • Tag or branchname • Timestamp: YYYY-MM-DD HH:MM:SS • tag-name : timestamp • root : branchname • merge-in : branchname • Special names: • tip • current • next • previous or prev • ckout for embedded docs Changes to www/customskin.md.  23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 And the footer looks like this: Notice that there are no  or  elements in the header, nor is there an  closing tag in the footer. Fossil generates this material automatically unless it sees that you have provided your own HTML document header within the skin’s Header section. | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 And the footer looks like this: Notice that there are no  or  elements in the header, nor is there an  closing tag in the footer. Fossil generates this material automatically unless it sees that you have provided your own HTML document header within the skin’s Header section. Changes to www/fileformat.wiki.  341 342 343 344 345 346 347 348 349 350 351 352 353 354 ... 364 365 366 367 368 369 370 371 372 373 374 375 376 377 ... 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 A wiki artifact defines a single version of a single wiki page. Wiki artifacts accept the following card types: D time-and-date-stamp L wiki-title N mimetype P parent-artifact-id+ U user-name W size \n text \n Z checksum ................................................................................ the usual checksum over the entire artifact and is required. The W card is used to specify the text of the wiki page. The argument to the W card is an integer which is the number of bytes of text in the wiki page. That text follows the newline character that terminates the W card. The wiki text is always followed by one extra newline. An example wiki artifact can be seen [/artifact?name=7b2f5fd0e0&txt=1 | here]. 2.5 Ticket Changes ................................................................................ C comment-text 1 0-1 0-1 D date-time-stamp C comment-text 1 0-1 0-1 0-1 D date-time-stamp > > > > > > > > | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 ... 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 ... 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 A wiki artifact defines a single version of a single wiki page. Wiki artifacts accept the following card types: C change-comment D time-and-date-stamp L wiki-title N mimetype P parent-artifact-id+ U user-name W size \n text \n Z checksum ................................................................................ the usual checksum over the entire artifact and is required. The W card is used to specify the text of the wiki page. The argument to the W card is an integer which is the number of bytes of text in the wiki page. That text follows the newline character that terminates the W card. The wiki text is always followed by one extra newline. The C card on a wiki page is optional. The argument is a comment that explains why the changes was made. The ability to have a C card on a wiki page artifact was added on 2019-12-02 at the suggestion of user George Krivov and is not currently used or generated by the implementation. Older versions of Fossil will reject a wiki-page artifact that includes a C card. An example wiki artifact can be seen [/artifact?name=7b2f5fd0e0&txt=1 | here]. 2.5 Ticket Changes ................................................................................ Changes to www/fossil-v-git.wiki.  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 .. 71 72 73 74 75 76 77 78 79 80 81 82 83 84 ... 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 ... 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 ... 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 ... 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 ... 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 ... 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 ... 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 ... 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 ... 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 ... 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 2.0 Differences Between Fossil And Git Differences between Fossil and Git are summarized by the following table, with further description in the text that follows. GITFOSSIL File versioning only VCS, tickets, wiki, docs, notes, forum, UI, [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC] Sprawling, incoherent, and inefficient Self-contained and efficient Ad-hoc pile-of-files key/value database [https://sqlite.org/famous.html|The most popular database in the world] Portable to POSIX systems onlyRuns just about anywhere Bazaar-style developmentCathedral-style development Designed for Linux kernel development Designed for SQLite development Many contributors Select contributors Focus on individual branches Focus on the entire tree of changes One check-out per repository Many check-outs per repository Remembers what you should have done Remembers what you actually did Commit first Test first SHA-2 SHA-3 2.1 Featureful Git provides file versioning services only, whereas Fossil adds an integrated [./wikitheory.wiki | wiki], [./bugtheory.wiki | ticketing & bug tracking], ................................................................................ [/help?cmd=ui|UI], protected by [./caps/ | a fine-grained role-based access control system]. These additional capabilities are available for Git as 3rd-party add-ons, but with Fossil they are integrated into the design. One way to describe Fossil is that it is "[https://github.com/ | GitHub]-in-a-box." For developers who choose to self-host projects (rather than using a 3rd-party service such as GitHub) Fossil is much easier to set up, since the stand-alone Fossil executable together with a [./server/any/cgi.md|2-line CGI script] suffice to instantiate a full-featured developer website. To accomplish the same using Git requires locating, installing, configuring, integrating, and managing a wide assortment of separate tools. Standing up a developer ................................................................................ part of the job, which can be recombined (by experts) to perform powerful operations. Git has a lot of complexity and many dependencies, so that most people end up installing it via some kind of package manager, simply because the creation of complicated binary packages is best delegated to people skilled in their creation. Normal Git users are not expected to build Git from source and install it themselves. Fossil is a single self-contained stand-alone executable with hardly any dependencies. Fossil can be run inside a minimally configured [https://en.wikipedia.org/wiki/Chroot|chroot jail], from a Windows memory stick, off a Raspberry Pi with a tiny SD card, etc. To install Fossil, one merely puts the executable somewhere in the$PATH. Fossil is [https://fossil-scm.org/fossil/doc/trunk/www/build.wiki|straightforward to build and install], so that many Fossil users do in fact build and install "trunk" versions to get new features between formal releases. Some say that Git more closely adheres to the Unix philosophy, summarized as "many small tools, loosely joined," but we have many examples of other successful Unix software that violates that principle to good effect, from Apache to Python to ZFS. We can infer from that that this is not an absolute principle of good software design. Sometimes "many features, tightly-coupled" works better. What actually matters is effectiveness and efficiency. We believe Fossil achieves this. Git fails on efficiency once you add to it all of the third-party software needed to give it a Fossil-equivalent feature set. Consider [https://about.gitlab.com/|GitLab], a third-party extension to Git wrapping it in many features, making it roughly Fossil-equivalent, though [https://docs.gitlab.com/ee/install/requirements.html|much more resource hungry] and hence more costly to run than the equivalent Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating a local rack server or blade to it, since its minimum requirements are more or less a description of the smallest thing you could call a "server" these days, but when you go to host that in the cloud, you can expect to pay about 8⨉ as much to comfortably host GitLab as for Fossil.³ This difference is largely due to basic technology choices: Ruby and PostgreSQL vs C and SQLite. The Fossil project itself is [./selfhost.wiki|hosted on a very small VPS], and we've received many reports on the Fossil forum about people successfully hosting Fossil service on bare-bones $5/month VPS hosts, spare Raspberry Pi boards, and other small hosts. ................................................................................ by a set of relational lookup tables for quick indexing into that artifact store. (See "[./theory1.wiki|Thoughts On The Design Of The Fossil DVCS]" for more details.) Leaf check-ins in Git that lack a "ref" become "detached," making them difficult to locate and subject to garbage collection. This [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head state] problem has caused untold grief for countless Git users. With Fossil, detached heads are simply impossible because we can always find our way back into the block chain using one or more of the relational indices it automatically manages for you. This design difference shows up in several other places within each tool. It is why Fossil's [/help?cmd=timeline|timeline] is generally more detailed yet more clear than those available in Git front-ends. ................................................................................ Over half of the C code in Fossil is actually an embedded copy of the current version of SQLite. Much of what is Fossil-specific after you set SQLite itself aside is SQL code calling into SQLite. The number of lines of SQL code in Fossil isn't large by percentage, but since SQL is such an expressive, declarative language, it has an outsized contribution to Fossil's user-visible functionality. Fossil isn't entirely C and SQL code. Its web UI uses JavaScript where necessary.⁵ The server-side UI scripting uses a custom minimal [https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called [https://www.fossil-scm.org/xfer/doc/trunk/www/th1.md|TH1], which is embedded into Fossil itself. Fossil's build system and test suite are largely based on Tcl.⁶ All of this is quite portable. About half of Git's code is POSIX C, and about a third is POSIX shell code. This is largely why the so-called "Git for Windows" distributions (both [https://git-scm.com/download/win|first-party] and [https://gitforwindows.org/|third-party]) are actually an [http://mingw.org/wiki/msys|MSYS POSIX portability environment] bundled with all of the Git stuff, because it would be too painful to port Git natively to Windows. Git is a foreign citizen on Windows, speaking to it only through a translator.⁷ While Fossil does lean toward POSIX norms when given a choice — LF-only line endings are treated as first-class citizens over CR+LF, for example — the Windows build of Fossil is truly native. The third-party extensions to Git tend to follow this same pattern. [http://mingw.org/wiki/msys|GitLab isn't portable to Windows at all], ................................................................................ • No easy drive-by contributions: Git [https://www.git-scm.com/docs/git-request-pull|pull requests] offer a low-friction path to accepting [https://www.jonobacon.com/2012/07/25/building-strong-community-structural-integrity/|drive-by contributions]. Fossil's closest equivalent is its unique [/help?cmd=bundle|bundle] feature, which requires higher engagement than firing off a PR.⁸ This difference comes directly from the initial designed purpose for each tool: the SQLite project doesn't accept outside contributions from previously-unknown developers, but the Linux kernel does. • No rebasing: When your local repo clone syncs changes up to its parent, those changes are sent exactly as they were committed locally. [#history|There is no rebasing mechanism in ................................................................................ 2.5.4 Individual Branches vs. The Entire Change History Both Fossil and Git store history as a directed acyclic graph (DAG) of changes, but Git tends to focus more on individual branches of the DAG, whereas Fossil puts more emphasis on the entire DAG. For example, the default "sync" behavior in Git is to only sync a single branch, whereas with Fossil the only sync option it to sync the entire DAG. Git commands, GitHub, and GitLab tend to show only a single branch at a time, whereas Fossil usually shows all parallel branches at once. Git has commands like "rebase" that help keep all relevant changes on a single branch, whereas Fossil encourages a style of many concurrent branches constantly springing into existence, undergoing active development in parallel for a few days or weeks, then ................................................................................ changes on all branches all at once helps keep the whole team up-to-date with what everybody else is doing, resulting in a more tightly focused and cohesive implementation. 2.6 One vs. Many Check-outs per Repository The default mode of operation in Git is to have a single working directory with a single .git subdirectory holding the actual local repository contents. Fossil doesn't work that way. A Fossil repository is a SQLite database file which is normally stored outside the working directory. You can [/help?cmd=open | open] a Fossil repository any number of times into any number of working directories. A common usage pattern is to have one working directory per active working branch, so that switching branches is done with a cd command rather than by checking out the branches successively in a single working directory. You can use Git in the Fossil style, either by manually symlinking the .git directory from one working directory to another or by use of the [https://git-scm.com/docs/git-worktree|git-worktree] feature. Nevertheless, Git's default tie between working directory and repository means the standard method for working with a Git repo is to have one working directory only. Most Git tutorials teach this style, so it is how most people learn to use Git. Because relatively few people use Git with multiple working directories per repository, there are [https://duckduckgo.com/?q=git+worktree+problem | several known problems] in working that way, which don't happen in Fossil because of the clear separation between repository and working directory. Switching branches inside a single working directory loses local context on each switch. For instance, in any software project where the runnable program must be built from source files, you invalidate build objects on each switch, artificially increasing the time required to switch versions. This affects software written in statically-compiled programming languages such as C, Java, and Haskell, but it can even affect programs written in dynamic languages like JavaScript. A common [https://en.wikipedia.org/wiki/Single-page_application | SPA] build process involves a [http://browserify.org/ | Browserify] pass to convert [https://nodejs.org/ | Node] packages to run in a web browser, [https://sass-lang.com | SASS files] to CSS, [https://www.typescriptlang.org | Typescript] to JavaScript, etc., to say nothing of [https://github.com/mishoo/UglifyJS | uglification] and other passes. Once all that processing work is done for a given input file in a given working directory, why re-do that work just to switch versions? For another example, you might have an active long-running test grinding away in a working directory, then get a call from a customer requiring that you switch to a stable branch to answer questions in terms of the version that customer is running. You don't want to stop the test in order to switch your lone working directory to the stable branch. Disk space is cheap. Having several working directories, each with its own local state, makes switching versions cheap and fast. Plus, cd is faster to type than git checkout. 2.7 What you should have done vs. What you actually did Git puts a lot of emphasis on maintaining a "clean" check-in history. Extraneous and experimental branches by individual developers often never make it into the main repository. And ................................................................................ Fossil's implementation of the feature is also simpler to describe. The brief online help for [/help?cmd=merge | fossil merge] is currently 41 lines long, to which you want to add the 600 lines of [./branching.wiki | the branching document]. The equivalent documentation in Git is the aggregation of the man pages for the above three commands, which is over 1000 lines, much of it mutually redundant. (e.g. the --edit and --no-commit options get described three different times, each time differently.) Fossil's documentation is not only more concise, it gives a nice split of brief online help and full online documentation. 2.9 Hash Algorithm: SHA-3 vs SHA-2 vs SHA-1 Fossil started out using 160-bit SHA-1 hashes to identify check-ins, ................................................................................ [https://shattered.io/|SHAttered attack] broke, demonstrating that SHA-1 collisions were now practical to create. Two weeks later, the creator of Fossil delivered a new release allowing a clean migration to [https://en.wikipedia.org/wiki/SHA-3|256-bit SHA-3] with [./hashpolicy.wiki|full backwards compatibility] to old SHA-1 based repositories. Here in mid-2019, that feature is now in every OS and package repository known to include Fossil so that the next release (Fossil 2.10) will begin using SHA-3 hashes even on repos currently limited to SHA-1 for compatibility with Fossil 1.x, effectively upgrading them to require Fossil 2.1 or newer. This not only solves the SHAttered problem, it should prevent a reoccurrence for the foreseeable future. With the current release (Fossil 2.9) only repositories created before the transition to Fossil 2 are still using SHA-1, and then only if the repository's maintainer chose not to switch them into SHA-3 mode some time over the past 2 years. Meanwhile, the Git community took until August 2018 to announce [https://git-scm.com/docs/hash-function-transition/2.18.0|their plan] for solving the same problem by moving to SHA-256 (a variant of the [https://en.wikipedia.org/wiki/SHA-2|older SHA-2 algorithm]) and until February 2019 to release a version containing the change. It's looking like this will take years more to percolate through the community. ................................................................................ The practical impact of SHAttered on structured data stores like the one in Git and Fossil isn't clear, but you want to have your repositories moved over to a stronger hash algorithm before someone figures out how to make use of the weaknesses in the old one. Fossil's developers moved on this problem quickly and had a widely-deployed solution to it years ago. 3.0 Missing Features Although there is a large overlap in capability between Fossil and Git, there are many areas where one system has a feature that is simply missing in the other. We covered most of those above, but there are a few remaining feature differences we haven't gotten to yet. 3.1 Features found in Fossil but missing from Git * The [/help?cmd=all|fossil all] command Fossil keeps track of all repositories and check-outs and allows operations over all of them with a single command. For example, in Fossil is possible to request a pull of all repositories on a laptop from their respective servers, prior to taking the laptop off network. Or it is possible to do "fossil all changes" to see if there are any uncommitted changes that were overlooked prior to the end of the workday. * The [/help?cmd=undo|fossil undo] command Whenever Fossil is told to modify the local checkout in some destructive way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], [/help?cmd=revert|fossil revert], etc.) Fossil remembers the prior state and is able to return the local check-out directory to its prior state with a simple "fossil undo" command. You [#history|cannot undo a commit], since writes to the actual repository — as opposed to the local check-out directory — are more or less permanent, on purpose, but as long as the change is simply staged locally, Fossil makes undo [https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things|easier than in Git]. 3.2 Features found in Git but missing from Fossil * Rebase Because of its emphasis on recording history exactly as it happened, rather than as we would have liked it to happen, [./rebaseharm.md|Fossil deliberately omits the "rebase" command]. For those rare occasions where something like rebase is actually needed, the same topology can be achieved using cherrypick merges. * Push or pull a single branch The [/help?cmd=push|fossil push], [/help?cmd=pull|fossil pull], and [/help?cmd=sync|fossil sync] commands do not provide the capability to push or pull individual branches. Pushing and pulling in Fossil is all or nothing. This is in keeping with Fossil's emphasis on maintaining a complete record and on sharing everything between all developers. Asides and Digressions 1. [./mirrorlimitations.md|Many things are lost] in making a Git mirror of a Fossil repo due to ................................................................................ requirements among Digital Ocean's offerings currently costs$40/month.

2. This means you can give up waiting for Fossil to be ported to the PDP-11, but we remain hopeful that someone may eventually port it to [https://en.wikipedia.org/wiki/Z/OS|z/OS].

3. We try to keep use of Javascript to a minimum in the web UI, and we always try to provide sensible fall-backs for those that run their browsers with Javascript disabled. Some features of the web UI simply won't run without Javascript, but the UI behavior does degrade gracefully.

4. "Why is there all this Tcl in and around Fossil?" you may ask. It is because D. Richard Hipp is a long-time Tcl user and contributor. SQLite started out as an embedded database for Tcl specifically. ([https://sqlite.org/tclsqlite.html | [Reference]]) When he then created Fossil to manage the development of SQLite, it was natural for him to use Tcl-based tools for its scripting, build system, test system, etc. It came full circle in 2011 when | > | | > > > | | > > > | | > > > | > > > > > | > > > | | > > > | | > > > | | > > > | | > > > | | > > > | | > > > | | > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > | | | | < > > > > > > > > > > | > > > | | | > > | > | | | | | | > | < | | > > > > > > > > | | | | | | | | | | | > > > | > | | | | | | > > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < 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 ... 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 ... 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 ... 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 ... 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 ... 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 ... 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 ... 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 ... 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 ... 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 ... 844 845 846 847 848 849 850 851 852 853 854 855 856 857 ... 883 884 885 886 887 888 889 890 891 892 893 894 895 896

2.0 Differences Between Fossil And Git

Differences between Fossil and Git are summarized by the following table, with further description in the text that follows.
• GITFOSSILmore
File versioning only VCS, tickets, wiki, docs, notes, forum, UI, [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC] 2.1 ↓
Sprawling, incoherent, and inefficient Self-contained and efficient 2.2 ↓
Ad-hoc pile-of-files key/value database [https://sqlite.org/famous.html|The most popular database in the world] 2.3 ↓
Portable to POSIX systems only Runs just about anywhere 2.4 ↓
Bazaar-style development Cathedral-style development 2.5.1 ↓
Designed for Linux kernel development Designed for SQLite development 2.5.2 ↓
Many contributors Select contributors 2.5.3 ↓
Focus on individual branches Focus on the entire tree of changes 2.5.4 ↓
One check-out per repository Many check-outs per repository 2.6 ↓
Remembers what you should have done Remembers what you actually did 2.7 ↓
Commit first Test first 2.8 ↓
SHA-2 SHA-3 2.9 ↓

2.1 Featureful

Git provides file versioning services only, whereas Fossil adds an integrated [./wikitheory.wiki | wiki], [./bugtheory.wiki | ticketing & bug tracking], ................................................................................ [/help?cmd=ui|UI], protected by [./caps/ | a fine-grained role-based access control system]. These additional capabilities are available for Git as 3rd-party add-ons, but with Fossil they are integrated into the design. One way to describe Fossil is that it is "[https://github.com/ | GitHub]-in-a-box." Fossil can do operations over all local repo clones and check-out directories with a single command. For example, Fossil lets you say fossil all pull on a laptop prior to taking it off the network hosting those repos. You can sync up to all of the private repos on your company network plus those public Internet-hosted repos you use. Whether going out for a working lunch or on a transoceanic an airplane trip, one command gets you in sync. This works with several other Fossil sub-commands, such as fossil all changes to get a list of files that you forgot to commit prior to the end of your working day, across all repos. Whenever Fossil is told to modify the local checkout in some destructive way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], [/help?cmd=revert|fossil revert], etc.) Fossil remembers the prior state and is able to return the check-out directory to that state with a fossil undo command. You cannot undo a commit in Fossil ([#history | on purpose!]) but as long as the change remains confined to the local check-out directory only, Fossil makes undo [https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things|easier than in Git]. For developers who choose to self-host projects (rather than using a 3rd-party service such as GitHub) Fossil is much easier to set up, since the stand-alone Fossil executable together with a [./server/any/cgi.md|2-line CGI script] suffice to instantiate a full-featured developer website. To accomplish the same using Git requires locating, installing, configuring, integrating, and managing a wide assortment of separate tools. Standing up a developer ................................................................................ part of the job, which can be recombined (by experts) to perform powerful operations. Git has a lot of complexity and many dependencies, so that most people end up installing it via some kind of package manager, simply because the creation of complicated binary packages is best delegated to people skilled in their creation. Normal Git users are not expected to build Git from source and install it themselves. Fossil is a single self-contained stand-alone executable which by default depends only on common platform libraries. If your platform allows static linking — not all do these days! — you can even get it down to a single executable with no external dependencies at all. Most notably, we deliver the official Windows builds of Fossil this way: the Zip file contains only fossil.exe, a self-contained Fossil executable; it is not a setup.exe style installer, it is the whole enchilada. A typical Fossil executable is about 5 MiB, not counting system libraries it shares in common with Git such as OpenSSL and zlib, which we can factor out of the discussion. These properties allow Fossil to easily run inside a minimally configured [https://en.wikipedia.org/wiki/Chroot|chroot jail], from a Windows memory stick, off a Raspberry Pi with a tiny SD card, etc. To install Fossil, one merely puts the executable somewhere in the $PATH. Fossil is [https://fossil-scm.org/fossil/doc/trunk/www/build.wiki|straightforward to build and install], so that many Fossil users do in fact build and install "trunk" versions to get new features between formal releases. Contrast a basic installation of Git, which takes up about 15 MiB on Debian 10 across 230 files, not counting the contents of /usr/share/doc or /usr/share/locale. If you need to deploy to any platform where you cannot count facilities like the POSIX shell, Perl interpreter, and Tcl/Tk platform needed to fully use Git as part of the base platform, the full footprint of a Git installation extends to more like 45 MiB and thousands of files. This complicates several common scenarios: Git for Windows, chrooted Git servers, Docker images... Some say that Git more closely adheres to the Unix philosophy, summarized as "many small tools, loosely joined," but we have many examples of other successful Unix software that violates that principle to good effect, from Apache to Python to ZFS. We can infer from that that this is not an absolute principle of good software design. Sometimes "many features, tightly-coupled" works better. What actually matters is effectiveness and efficiency. We believe Fossil achieves this. The above size comparisons aren't apples-to-apples anyway. We've compared the size of Fossil with all of its [#features | many built-in features] to a fairly minimal Git installation. You must add a lot of third-party software to Git to give it a Fossil-equivalent feature set. Consider [https://about.gitlab.com/|GitLab], a third-party extension to Git wrapping it in many features, making it roughly Fossil-equivalent, though [https://docs.gitlab.com/ee/install/requirements.html|much more resource hungry] and hence more costly to run than the equivalent Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating a local rack server or blade to it, since its minimum requirements are more or less a description of the smallest thing you could call a "server" these days, but when you go to host that in the cloud, you can expect to pay about 8× as much to comfortably host GitLab as for Fossil.³ This difference is largely due to basic technology choices: Ruby and PostgreSQL vs C and SQLite. The Fossil project itself is [./selfhost.wiki|hosted on a very small VPS], and we've received many reports on the Fossil forum about people successfully hosting Fossil service on bare-bones$5/month VPS hosts, spare Raspberry Pi boards, and other small hosts. ................................................................................ by a set of relational lookup tables for quick indexing into that artifact store. (See "[./theory1.wiki|Thoughts On The Design Of The Fossil DVCS]" for more details.) Leaf check-ins in Git that lack a "ref" become "detached," making them difficult to locate and subject to garbage collection. This [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head state] problem has caused untold grief for [https://www.google.com/search?q=git+detached+head+state | a huge number of Git users]. With Fossil, detached heads are simply impossible because we can always find our way back into the block chain using one or more of the relational indices it automatically manages for you. This design difference shows up in several other places within each tool. It is why Fossil's [/help?cmd=timeline|timeline] is generally more detailed yet more clear than those available in Git front-ends. ................................................................................ Over half of the C code in Fossil is actually an embedded copy of the current version of SQLite. Much of what is Fossil-specific after you set SQLite itself aside is SQL code calling into SQLite. The number of lines of SQL code in Fossil isn't large by percentage, but since SQL is such an expressive, declarative language, it has an outsized contribution to Fossil's user-visible functionality. Fossil isn't entirely C and SQL code. Its web UI [./javascript.md | uses JavaScript where necessary]. The server-side UI scripting uses a custom minimal [https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called [https://www.fossil-scm.org/xfer/doc/trunk/www/th1.md|TH1], which is embedded into Fossil itself. Fossil's build system and test suite are largely based on Tcl.⁵ All of this is quite portable. About half of Git's code is POSIX C, and about a third is POSIX shell code. This is largely why the so-called "Git for Windows" distributions (both [https://git-scm.com/download/win|first-party] and [https://gitforwindows.org/|third-party]) are actually an [http://mingw.org/wiki/msys|MSYS POSIX portability environment] bundled with all of the Git stuff, because it would be too painful to port Git natively to Windows. Git is a foreign citizen on Windows, speaking to it only through a translator.⁶ While Fossil does lean toward POSIX norms when given a choice — LF-only line endings are treated as first-class citizens over CR+LF, for example — the Windows build of Fossil is truly native. The third-party extensions to Git tend to follow this same pattern. [http://mingw.org/wiki/msys|GitLab isn't portable to Windows at all], ................................................................................
• No easy drive-by contributions: Git [https://www.git-scm.com/docs/git-request-pull|pull requests] offer a low-friction path to accepting [https://www.jonobacon.com/2012/07/25/building-strong-community-structural-integrity/|drive-by contributions]. Fossil's closest equivalent is its unique [/help?cmd=bundle|bundle] feature, which requires higher engagement than firing off a PR.⁷ This difference comes directly from the initial designed purpose for each tool: the SQLite project doesn't accept outside contributions from previously-unknown developers, but the Linux kernel does.

• No rebasing: When your local repo clone syncs changes up to its parent, those changes are sent exactly as they were committed locally. [#history|There is no rebasing mechanism in ................................................................................

2.5.4 Individual Branches vs. The Entire Change History

Both Fossil and Git store history as a directed acyclic graph (DAG) of changes, but Git tends to focus more on individual branches of the DAG, whereas Fossil puts more emphasis on the entire DAG. For example, the default behavior in Git is to only synchronize a single branch, whereas with Fossil the only sync option is to sync the entire DAG. Git commands, GitHub, and GitLab tend to show only a single branch at a time, whereas Fossil usually shows all parallel branches at once. Git has commands like "rebase" that help keep all relevant changes on a single branch, whereas Fossil encourages a style of many concurrent branches constantly springing into existence, undergoing active development in parallel for a few days or weeks, then ................................................................................ changes on all branches all at once helps keep the whole team up-to-date with what everybody else is doing, resulting in a more tightly focused and cohesive implementation.

2.6 One vs. Many Check-outs per Repository

Because Git commingles the repository data with the initial checkout of that repository, the default mode of operation in Git is to stick to that single work/repo tree, even when that's a shortsighted way of working. Fossil doesn't work that way. A Fossil repository is a SQLite database file which is normally stored outside the working checkout directory. You can [/help?cmd=open | open] a Fossil repository any number of times into any number of working directories. A common usage pattern is to have one working directory per active working branch, so that switching branches is done with a cd command rather than by checking out the branches successively in a single working directory. Fossil does allow you to switch branches within a working checkout directory, and this is also often done. It is simply that there is no inherent penalty to either choice in Fossil as there is in Git. The standard advice is to use a switch-in-place workflow in Fossil when the disturbance from switching branches is small, and to use multiple checkouts when you have long-lived working branches that are different enough that switching in place is disruptive. You can use Git in the Fossil style, either by manually symlinking the .git directory from one working directory to another or by use of the [https://git-scm.com/docs/git-worktree|git-worktree] feature. Nevertheless, Git's default tie between working directory and repository means the standard method for working with a Git repo is to have one working directory only. Most Git tutorials teach this style, so it is how most people learn to use Git. Because relatively few people use Git with multiple working directories per repository, there are [https://duckduckgo.com/?q=git+worktree+problem | several known problems] with that way of working, problems which don't happen in Fossil because of the clear separation between repository and working directory. This distinction matters because switching branches inside a single working directory loses local context on each switch. For instance, in any software project where the runnable program must be built from source files, you invalidate build objects on each switch, artificially increasing the time required to switch versions. Most obviously, this affects software written in statically-compiled programming languages such as C, Java, and Haskell, but it can even affect programs written in dynamic languages like JavaScript. A typical [https://en.wikipedia.org/wiki/Single-page_application | SPA] build process involves several passes: [http://browserify.org/ | Browserify] to convert [https://nodejs.org/ | Node] packages so they'll run in a web browser, [https://sass-lang.com | SASS] to CSS translation, transpilation of [https://www.typescriptlang.org | Typescript] to JavaScript, [https://github.com/mishoo/UglifyJS | uglification], etc. Once all that processing work is done for a given input file in a given working directory, why re-do that work just to switch versions? If most of the files that differ between versions don't change very often, you can save substantial time by switching branches with cd rather than swapping versions in-place within a working checkout directory. For another example, you might have an active long-running test grinding away in a working directory, then get a call from a customer requiring that you switch to a stable branch to answer questions in terms of the version that customer is running. You don't want to stop the test in order to switch your lone working directory to the stable branch. Disk space is cheap. Having several working directories, each with its own local state, makes switching versions cheap and fast. Plus, cd is faster to type than git checkout or fossil update.

2.7 What you should have done vs. What you actually did

Git puts a lot of emphasis on maintaining a "clean" check-in history. Extraneous and experimental branches by individual developers often never make it into the main repository. And ................................................................................ Fossil's implementation of the feature is also simpler to describe. The brief online help for [/help?cmd=merge | fossil merge] is currently 41 lines long, to which you want to add the 600 lines of [./branching.wiki | the branching document]. The equivalent documentation in Git is the aggregation of the man pages for the above three commands, which is over 1000 lines, much of it mutually redundant. (e.g. the --edit and --no-commit options get described three times, each time differently.) Fossil's documentation is not only more concise, it gives a nice split of brief online help and full online documentation.

2.9 Hash Algorithm: SHA-3 vs SHA-2 vs SHA-1

Fossil started out using 160-bit SHA-1 hashes to identify check-ins, ................................................................................ [https://shattered.io/|SHAttered attack] broke, demonstrating that SHA-1 collisions were now practical to create. Two weeks later, the creator of Fossil delivered a new release allowing a clean migration to [https://en.wikipedia.org/wiki/SHA-3|256-bit SHA-3] with [./hashpolicy.wiki|full backwards compatibility] to old SHA-1 based repositories. By mid-2019, that feature arrived in every software package repository shipping Fossil, the last mover being Debian's stable package repo, which has a highly conservative policy on upgrading to new versions. With that hurdle run, we were able to change the default hash mode in Fossil 2.10 (released 2019-10-04) to require SHA-3 support both for new repositories and to create SHA-3 hashes in existing repos, effectively upgrading them if they were created with Fossil 1.x. This not only solves the SHAttered problem, it should prevent a reoccurrence of similar problems for the foreseeable future. Meanwhile, the Git community took until August 2018 to announce [https://git-scm.com/docs/hash-function-transition/2.18.0|their plan] for solving the same problem by moving to SHA-256 (a variant of the [https://en.wikipedia.org/wiki/SHA-2|older SHA-2 algorithm]) and until February 2019 to release a version containing the change. It's looking like this will take years more to percolate through the community. ................................................................................ The practical impact of SHAttered on structured data stores like the one in Git and Fossil isn't clear, but you want to have your repositories moved over to a stronger hash algorithm before someone figures out how to make use of the weaknesses in the old one. Fossil's developers moved on this problem quickly and had a widely-deployed solution to it years ago.

Asides and Digressions

1. [./mirrorlimitations.md|Many things are lost] in making a Git mirror of a Fossil repo due to ................................................................................ requirements among Digital Ocean's offerings currently costs $40/month. 2. This means you can give up waiting for Fossil to be ported to the PDP-11, but we remain hopeful that someone may eventually port it to [https://en.wikipedia.org/wiki/Z/OS|z/OS]. 3. "Why is there all this Tcl in and around Fossil?" you may ask. It is because D. Richard Hipp is a long-time Tcl user and contributor. SQLite started out as an embedded database for Tcl specifically. ([https://sqlite.org/tclsqlite.html | [Reference]]) When he then created Fossil to manage the development of SQLite, it was natural for him to use Tcl-based tools for its scripting, build system, test system, etc. It came full circle in 2011 when • Changes to www/javascript.md.  176 177 178 179 180 181 182 183 184 185 186 187 188 189 _Workaround:_ Edit the URL to give the “ln” query parameter per [the /file docs](/help?cmd=/file), or provide a patch to reload the page with this parameter included/excluded to implement the toggle via a server round-trip. [mainc]: https://fossil-scm.org/fossil/artifact?ln&name=87d67e745 ### Table Sorting On pages showing a data table, the column headers may be clickable to do a client-side sort of the data on that column. _Potential Workaround:_ This feature could be enhanced to do the sort on > > > > > > > > > > > > > > > 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 _Workaround:_ Edit the URL to give the “ln” query parameter per [the /file docs](/help?cmd=/file), or provide a patch to reload the page with this parameter included/excluded to implement the toggle via a server round-trip. [mainc]: https://fossil-scm.org/fossil/artifact?ln&name=87d67e745 ### Side-by-Side Diff Mode The default “diff” view is a side-by-side mode. If either of the boxes of output — the “from” and “to” versions of the repo contents for that check-in — requires a horizontal scroll bar given the box content, font size, browser window width, etc., both boxes will usually end up needing to scroll since they should contain roughly similar content. Fossil therefore scrolls both boxes when you drag the scroll bar on one because if you want to examine part of a line scrolled out of the HTML element in one box, you probably want to examine the same point on that line in the other box. _Graceful Fallback:_ Manually scroll both boxes to sync their views. ### Table Sorting On pages showing a data table, the column headers may be clickable to do a client-side sort of the data on that column. _Potential Workaround:_ This feature could be enhanced to do the sort on Added www/mdtest/test1.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 # Markdown Link-test This document exist solely as a test for some of the hyperlinking capabilities of Markdown as implemented by Fossil. ## Relative-Path Links * The index: [](../index.wiki) * Load management: [](../loadmgmt.md) * Site-map: [](../../../../sitemap) * Windows CGI: [](../server/windows/cgi.md) ## The Magic$ROOT Path Prefix In text of the form href="$ROOT/..." in the HTML that markdown generates, the$ROOT is replaced by the complete URI for the root of the document tree. Note that the $ROOT translation only occurs within the  element, not within the text of the hyperlink. So you should see the$ROOT text on this page, but if you mouse-over the hyperlink the $ROOT value should have been expanded to the actual document root. * Timeline: []($ROOT/timeline) * Site-map: []($ROOT/sitemap) The$ROOT prefix on markdown links is superfluous. The same link works without the $ROOT prefix. (Though: the$ROOT prefix is required for HTML documents.) * Timeline: [](/timeline) * Help: [](/help?cmd=help) * Site-map: [](/sitemap) ## The Magic $SELF Document Version Translation In URI text of the form .../doc/$SELF/... the $SELF value is converted to the version number of the document currently being displayed. This conversion happens after translation into HTML and only occurs on href='...' attributes so it does not occur for plain text. * Document index: [](/doc/$SELF/www/index.wiki) Both the $ROOT and the$SELF conversions can occur on the same link. * Document index: []($ROOT/doc/$SELF/www/index.wiki) The translations must be contained within HTML markup in order to work. They do not work for ordinary text that appears to be an href= attribute. * x href='$ROOT/timeline' * x action="$ROOT/whatever" * x href="https://some-other-site.com/doc/$SELF/tail" Changes to www/mkindex.tcl.  17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 blame.wiki {The Annotate/Blame Algorithm Of Fossil} blockchain.md {Fossil As Blockchain} branching.wiki {Branching, Forking, Merging, and Tagging} bugtheory.wiki {Bug Tracking In Fossil} build.wiki {Compiling and Installing Fossil} caps/ {Administering User Capabilities} caps/admin-v-setup.md {Differences Between Setup and Admin Users} caps/login-groups.md {Differences Between Setup and Admin Users} caps/ref.html {User Capability Reference} cgi.wiki {CGI Script Configuration Options} changes.wiki {Fossil Changelog} checkin_names.wiki {Check-in And Version Names} checkin.wiki {Check-in Checklist} childprojects.wiki {Child Projects} copyright-release.html {Contributor License Agreement} < 17 18 19 20 21 22 23 24 25 26 27 28 29 30 blame.wiki {The Annotate/Blame Algorithm Of Fossil} blockchain.md {Fossil As Blockchain} branching.wiki {Branching, Forking, Merging, and Tagging} bugtheory.wiki {Bug Tracking In Fossil} build.wiki {Compiling and Installing Fossil} caps/ {Administering User Capabilities} caps/admin-v-setup.md {Differences Between Setup and Admin Users} caps/ref.html {User Capability Reference} cgi.wiki {CGI Script Configuration Options} changes.wiki {Fossil Changelog} checkin_names.wiki {Check-in And Version Names} checkin.wiki {Check-in Checklist} childprojects.wiki {Child Projects} copyright-release.html {Contributor License Agreement} Changes to www/permutedindex.html.  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 .. 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 ... 171 172 173 174 175 176 177 178 179 180 181 182 183 184 ... 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 ... 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 Changes to www/rebaseharm.md.  236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 ... 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 ... 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 files in faultless finished form. A wish for collapsed, finalized check-ins is a wish for a counterfactual situation. The common counterargument is that collapsed check-ins represent a better world, the ideal we’re striving for. What that argument overlooks is that we must throw away valuable information to get there. ## 7.1 Individual check-ins support developer empathy Ideally, future developers of our software can understand every feature in it using only context available in the version of the code they start work with. Prior to widespread version control, developers had no choice but to work that way. Pre-existing codebases could only be understood as-is or not at all. Developers in that world had an incentive to develop software that was easy to understand retrospectively, even if ................................................................................ check-in it was a part of — and then to understand the surrounding check-ins as necessary — than it is to understand a 500-line check-in that collapses a whole branch’s worth of changes down to a single finished feature. [sdm]: ./fossil-v-git.wiki#durable ## 7.2 Bisecting works better on small check-ins Git lets a developer write a feature in ten check-ins but collapse it down to an eleventh check-in and then deliberately push only that final collapsed check-in to the parent repo. Someone else may then do a bisect that blames the merged check-in as the source of the problem they’re chasing down; they then have to manually work out which of the 10 steps the original developer took to create it to find the source of the ................................................................................ actual problem. Fossil pushes all 11 check-ins to the parent repository by default, so that someone doing that bisect sees the complete check-in history, so the bisect will point them at the single original check-in that caused the problem. ## 7.3 Multiple check-ins require multiple check-in comments The more comments you have from a given developer on a given body of code, the more concise documentation you have of that developer’s thought process. To resume the bisecting example, a developer trying to work out what the original developer was thinking with a given change will have more success given a check-in comment that explains what the one check-in out of ten blamed by the “bisect” command was trying to accomplish than if they must work that out from the eleventh check-in’s comment, which only explains the “clean” version of the collapsed feature. ## 7.4 Cherry-picks work better with small check-ins While working on a new feature in one branch, you may come across a bug in the pre-existing code that you need to fix in order for work on that feature to proceed. You could choose to switch briefly back to the parent branch, develop the fix there, check it in, then merge the parent back up to the feature branch in order to continue work, but that’s distracting. If the fix isn’t for a critical bug, fixing it on the ................................................................................ complete. If a support organization must manually disentangle a fix from a feature check-in, they are likely to introduce new bugs on the stable branch. Even if they manage to do their work without error, it takes them more time to do the cherry-pick that way. [rh]: https://en.wikipedia.org/wiki/Red_Hat ## 7.5 Back-outs also work better with small check-ins The inverse of the cherry-pick merge is the back-out merge. If you push only a collapsed version of a private working branch up to the parent repo, those working from that parent repo cannot automatically back out any of the individual check-ins that went into that private branch. Others must either manually disentangle the problematic part of your merge check-in or back out the entire feature. | | | | | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 ... 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 ... 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 files in faultless finished form. A wish for collapsed, finalized check-ins is a wish for a counterfactual situation. The common counterargument is that collapsed check-ins represent a better world, the ideal we’re striving for. What that argument overlooks is that we must throw away valuable information to get there. ### 7.1 Individual check-ins support developer empathy Ideally, future developers of our software can understand every feature in it using only context available in the version of the code they start work with. Prior to widespread version control, developers had no choice but to work that way. Pre-existing codebases could only be understood as-is or not at all. Developers in that world had an incentive to develop software that was easy to understand retrospectively, even if ................................................................................ check-in it was a part of — and then to understand the surrounding check-ins as necessary — than it is to understand a 500-line check-in that collapses a whole branch’s worth of changes down to a single finished feature. [sdm]: ./fossil-v-git.wiki#durable ### 7.2 Bisecting works better on small check-ins Git lets a developer write a feature in ten check-ins but collapse it down to an eleventh check-in and then deliberately push only that final collapsed check-in to the parent repo. Someone else may then do a bisect that blames the merged check-in as the source of the problem they’re chasing down; they then have to manually work out which of the 10 steps the original developer took to create it to find the source of the ................................................................................ actual problem. Fossil pushes all 11 check-ins to the parent repository by default, so that someone doing that bisect sees the complete check-in history, so the bisect will point them at the single original check-in that caused the problem. ### 7.3 Multiple check-ins require multiple check-in comments The more comments you have from a given developer on a given body of code, the more concise documentation you have of that developer’s thought process. To resume the bisecting example, a developer trying to work out what the original developer was thinking with a given change will have more success given a check-in comment that explains what the one check-in out of ten blamed by the “bisect” command was trying to accomplish than if they must work that out from the eleventh check-in’s comment, which only explains the “clean” version of the collapsed feature. ### 7.4 Cherry-picks work better with small check-ins While working on a new feature in one branch, you may come across a bug in the pre-existing code that you need to fix in order for work on that feature to proceed. You could choose to switch briefly back to the parent branch, develop the fix there, check it in, then merge the parent back up to the feature branch in order to continue work, but that’s distracting. If the fix isn’t for a critical bug, fixing it on the ................................................................................ complete. If a support organization must manually disentangle a fix from a feature check-in, they are likely to introduce new bugs on the stable branch. Even if they manage to do their work without error, it takes them more time to do the cherry-pick that way. [rh]: https://en.wikipedia.org/wiki/Red_Hat ### 7.5 Back-outs also work better with small check-ins The inverse of the cherry-pick merge is the back-out merge. If you push only a collapsed version of a private working branch up to the parent repo, those working from that parent repo cannot automatically back out any of the individual check-ins that went into that private branch. Others must either manually disentangle the problematic part of your merge check-in or back out the entire feature. Changes to www/server/windows/index.md.  1 2 3 4 5 6 # Using Windows as a Fossil Server - [Fossil as a Service](service.md) - [Using stunnel with Fossil on Windows](stunnel.md) *[Return to the top-level Fossil server article.](../)* > > | | 1 2 3 4 5 6 7 8 # Using Windows as a Fossil Server - [Fossil server command](./none.md) - [Fossil as CGI (IIS)](./iis.md) - [Fossil as a Service](./service.md) - [Using stunnel with Fossil on Windows](./stunnel.md) *[Return to the top-level Fossil server article.](../)* Changes to www/server/windows/service.md.  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 1. You have Administrative access to a Windows 2012r2 or above server. 2. You have PowerShell 5.1 or above installed. ## Place Fossil on Server However you obtained your copy of Fossil, it is recommended that you follow Windows conventions and place it within \Program Files (x86)\FossilSCM. Since Fossil is a 32bit binary, this is the proper location for the executable. This way Fossil is in an expected location and you will have minimal issues with Windows interfering in your ability to run Fossil as a service. You will need Administrative rights to place fossil at the recommended location. You do NOT need to add this location to the path, though you may do so if you wish. ## Make Fossil a Windows Service Luckily the hard work to use Fossil as a Windows Service has been done by the Fossil team. We simply have to install it with the proper command line options. As of Fossil 2.9 the built in fossil winsrv command is failing, so an alternative service install using PowerShell is documented here. The below should all be entered as a single line in an Administrative PowerShell console. PowerShell New-Service -Name fossil -DisplayName fossil -BinaryPathName '"C:\Program Files (x86)\FossilSCM\fossil.exe" server --port 8080 --repolist "D:/Path/to/Repos"' -StartupType Automatic  Please note the use of forward slashes in the paths passed to Fossil. Windows will accept either back slashes or forward slashes in path names, but Fossil has a preference for forward slashes. The use of --repolist will make this a multiple repository server. If you want to serve only a single repository, then leave off the --repolist parameter and provide the full path to the proper repository file. Other options are listed in the [fossil server](/help?cmd=server) documentation. The service will be installed by default to use the Local Service account. Since Fossil only needs access to local files, this is fine and causes no issues. The service will not be running once installed. You will need to start it to proceed (the -StartupType Automatic parameter to New-Service will result in the service auto-starting on boot). This can be done by entering | | | | > | < > < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > < | | | | | | | 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 1. You have Administrative access to a Windows 2012r2 or above server. 2. You have PowerShell 5.1 or above installed. ## Place Fossil on Server However you obtained your copy of Fossil, it is recommended that you follow Windows conventions and place it within \Program Files\FossilSCM. Since Fossil 2.10 is a 64bit binary, this is the proper location for the executable. This way Fossil is at an expected location and you will have minimal issues with Windows interfering in your ability to run Fossil as a service. You will need Administrative rights to place fossil at the recommended location. If you will only be running Fossil as a service, you do not need to add this location to the path, though you may do so if you wish. ## Installing Fossil as a Service Luckily the hard work to use Fossil as a Windows Service has been done by the Fossil team. We simply have to install it with the proper command line options. Fossil on Windows has a command fossil winsrv to allow installing Fossil as a service on Windows. This command is only documented on the windows executable of Fossil. You must also run the command as administrator for it to be successful. ### Fossil winsrv Example The simplest form of the command is:  fossil winsrv create --repository D:/Path/to/Repo.fossil  This will create a windows service named 'Fossil-DSCM' running under the local system account and accessible on port 8080 by default. fossil winsrv can also start, stop, and delete the service. For all available options, please execute fossil help winsrv on a windows install of Fossil. If you wish to server a directory of repositories, the fossil winsrv command requires a slightly different set of options vs. fossil server:  fossil winsrv create --repository D:/Path/to/Repos --repolist  ### Advanced service installation using PowerShell As great as fossil winsrv is, it does not have one to one reflection of all of the fossil server [options](/help?cmd=server). When you need to use some of the more advanced options, such as --https, --skin, or --extroot, you will need to use PowerShell to configure and install the Windows service. PowerShell provides the [New-Service](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-service?view=powershell-5.1) command, which we can use to install and configure Fossil as a service. The below should all be entered as a single line in an Administrative PowerShell console. PowerShell New-Service -Name fossil -DisplayName fossil -BinaryPathName '"C:\Program Files\FossilSCM\fossil.exe" server --port 8080 --repolist "D:/Path/to/Repos"' -StartupType Automatic  Please note the use of forward slashes in the repolist path passed to Fossil. Windows will accept either back slashes or forward slashes in path names, but Fossil has a preference for forward slashes. The use of --repolist will make this a multiple repository server. If you want to serve only a single repository, then leave off the --repolist parameter and provide the full path to the proper repository file. Other options are listed in the [fossil server](/help?cmd=server) documentation. The service will be installed by default to use the Local Service account. Since Fossil only needs access to local files, this is fine and causes no issues. The service will not be running once installed. You will need to start it to proceed (the -StartupType Automatic parameter to New-Service will result in the service auto-starting on boot). This can be done by entering Changes to www/server/windows/stunnel.md.  17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 versions may not function in a similar manner. There is a bug in Fossil 2.9 and earlier that prevents these versions of Fossil from properly constructing https URLs when used with stunnel as a proxy. Please make sure you are using Fossil 2.10 or later on Windows. ## Configure Fossil Service for https Following most of [Fossil as a Windows Service](./service.md), you will need to change the command to install the Fossil Service to configure it properly for use with stunnel as an https proxy. Run the following instead: PowerShell New-Service -Name fossil-secure -DisplayName fossil-secure -BinaryPathName '"C:\Program Files (x86)\FossilSCM\fossil.exe" server --localhost --port 9000 --https --repolist "D:/Path/to/Repos"' -StartupType Automatic  The use of --localhost means Fossil will only listen for traffic on the local host on the designated port - 9000 in this case - and will not respond to network traffic. Using --https will tell Fossil to generate HTTPS URLs rather than HTTP ones. | > | | | < < 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 versions may not function in a similar manner. There is a bug in Fossil 2.9 and earlier that prevents these versions of Fossil from properly constructing https URLs when used with stunnel as a proxy. Please make sure you are using Fossil 2.10 or later on Windows. ## Configure Fossil Service for https Due to the need for the --https option for successfully using Fossil with stunnel, we will use [Advanced service installation using PowerShell](./service.md#PowerShell). We will need to change the command to install the Fossil Service to configure it properly for use with stunnel as an https proxy. Run the following: PowerShell New-Service -Name fossil-secure -DisplayName fossil-secure -BinaryPathName '"C:\Program Files\FossilSCM\fossil.exe" server --localhost --port 9000 --https --repolist "D:/Path/to/Repos"' -StartupType Automatic  The use of --localhost means Fossil will only listen for traffic on the local host on the designated port - 9000 in this case - and will not respond to network traffic. Using --https` will tell Fossil to generate HTTPS URLs rather than HTTP ones. Changes to www/serverext.wiki.  32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 ... 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 [./server/any/cgi.md|CGI], then add a line to the [./cgi.wiki#extroot|CGI script file] that says: extroot: DIRECTORY Or, if the Fossil server is begin run as using the "[./server/any/none.md|fossil server]" or "[./server/any/none.md|fossil ui]" or "[./server/any/inetd.md|fossil http]" commands, then add an extra "--extroot DIRECTORY" option to that command. The DIRECTORY is the DOCUMENT_ROOT for the CGI. Files in the DOCUMENT_ROOT are accessed via URLs like this: ................................................................................ web browser. The FOSSIL_NONCE variable contains the value of that nonce. So, in other words, to get javascript to work, it must be enclosed in: Except, of course, the$FOSSIL_NONCE is replace by the value of the FOSSIL_NONCE environment variable. If the HTTP request includes content (for example if this is a POST request) then the CONTENT_LENGTH value will be positive and the data for the content will be readable on standard input.

4.0 CGI Outputs

| | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 ... 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 [./server/any/cgi.md|CGI], then add a line to the [./cgi.wiki#extroot|CGI script file] that says:
extroot: DIRECTORY
Or, if the Fossil server is being run using the "[./server/any/none.md|fossil server]" or "[./server/any/none.md|fossil ui]" or "[./server/any/inetd.md|fossil http]" commands, then add an extra "--extroot DIRECTORY" option to that command. The DIRECTORY is the DOCUMENT_ROOT for the CGI. Files in the DOCUMENT_ROOT are accessed via URLs like this: ................................................................................ web browser. The FOSSIL_NONCE variable contains the value of that nonce. So, in other words, to get javascript to work, it must be enclosed in:
Except, of course, the \$FOSSIL_NONCE is replaced by the value of the FOSSIL_NONCE environment variable. If the HTTP request includes content (for example if this is a POST request) then the CONTENT_LENGTH value will be positive and the data for the content will be readable on standard input.

4.0 CGI Outputs

Changes to www/th1.md.

 213 214 215 216 217 218 219 220 221 222 223 224 225 226 ... 731 732 733 734 735 736 737 738 739 740 741 742 743 744 * tclMakeSafe * tclReady * trace * unversioned content * unversioned list * utime * verifyCsrf * wiki Each of the commands above is documented by a block comment above their implementation in the th\_main.c or th\_tcl.c source files. All commands starting with "tcl", with the exception of "tclReady", require the Tcl integration subsystem be included at compile-time. ................................................................................ * verifyCsrf Before using the results of a form, first call this command to verify that this Anti-CSRF token is present and is valid. If the Anti-CSRF token is missing or is incorrect, that indicates a cross-site scripting attack. If the event of an attack is detected, an error message is generated and all further processing is aborted. TH1 wiki Command ----------------------------------- * wiki STRING Renders STRING as wiki content. > > > > > > > > > 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 ... 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 * tclMakeSafe * tclReady * trace * unversioned content * unversioned list * utime * verifyCsrf * verifyLogin * wiki Each of the commands above is documented by a block comment above their implementation in the th\_main.c or th\_tcl.c source files. All commands starting with "tcl", with the exception of "tclReady", require the Tcl integration subsystem be included at compile-time. ................................................................................ * verifyCsrf Before using the results of a form, first call this command to verify that this Anti-CSRF token is present and is valid. If the Anti-CSRF token is missing or is incorrect, that indicates a cross-site scripting attack. If the event of an attack is detected, an error message is generated and all further processing is aborted. TH1 verifyLogin Command ------------------------------------------------- * verifyLogin Returns non-zero if the specified user name and password represent a valid login for the repository. TH1 wiki Command ----------------------------------- * wiki STRING Renders STRING as wiki content.