Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merged in trunk. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | fileedit-ajaxify |
| Files: | files | file ages | folders |
| SHA3-256: |
559807ba86b02ec9129265a36ad9d046 |
| User & Date: | stephan 2020-05-26 06:43:44.667 |
Context
|
2020-05-26
| ||
| 07:42 | Removed a no-longer-true line from the fileedit help tab. check-in: 616333e5ba user: stephan tags: fileedit-ajaxify | |
| 06:43 | Merged in trunk. check-in: 559807ba86 user: stephan tags: fileedit-ajaxify | |
|
2020-05-25
| ||
| 23:40 | Update the changes log to include a date for 2.11 and to add a place-holder to begin recording 2.12 changes. check-in: 87e3ad3132 user: drh tags: trunk | |
|
2020-05-21
| ||
| 06:32 | Added a doc section about CSRF/HTTP Referrer. Other minor doc/message cleanups. check-in: 6de7e48021 user: stephan tags: fileedit-ajaxify | |
Changes
Changes to src/cgi.c.
| ︙ | ︙ | |||
442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
}
NORETURN void cgi_redirectf(const char *zFormat, ...){
va_list ap;
va_start(ap, zFormat);
cgi_redirect(vmprintf(zFormat, ap));
va_end(ap);
}
/*
** Return the URL for the caller. This is obtained from either the
** referer CGI parameter, if it exists, or the HTTP_REFERER HTTP parameter.
** If neither exist, return zDefault.
*/
const char *cgi_referer(const char *zDefault){
| > > > > > > > > > > > > > > > > > > > > > | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 |
}
NORETURN void cgi_redirectf(const char *zFormat, ...){
va_list ap;
va_start(ap, zFormat);
cgi_redirect(vmprintf(zFormat, ap));
va_end(ap);
}
/*
** Add a "Content-disposition: attachment; filename=%s" header to the reply.
*/
void cgi_content_disposition_filename(const char *zFilename){
char *z;
int i, n;
/* 0123456789 123456789 123456789 123456789 123456*/
z = mprintf("Content-Disposition: attachment; filename=\"%s\";\r\n",
file_tail(zFilename));
n = (int)strlen(z);
for(i=43; i<n-4; i++){
char c = z[i];
if( fossil_isalnum(c) ) continue;
if( c=='.' || c=='-' || c=='/' ) continue;
z[i] = '_';
}
cgi_append_header(z);
fossil_free(z);
}
/*
** Return the URL for the caller. This is obtained from either the
** referer CGI parameter, if it exists, or the HTTP_REFERER HTTP parameter.
** If neither exist, return zDefault.
*/
const char *cgi_referer(const char *zDefault){
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
2379 2380 2381 2382 2383 2384 2385 |
if( g.fSqlPrint ){
for(i=0; i<argc; i++){
char c = i==argc-1 ? '\n' : ' ';
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
}
}
}
| > > > > | > > > > > > > > | 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 |
if( g.fSqlPrint ){
for(i=0; i<argc; i++){
char c = i==argc-1 ? '\n' : ' ';
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
}
}
}
/*
** Callback for sqlite3_trace_v2();
*/
int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
sqlite3_stmt *pStmt = (sqlite3_stmt*)pP;
char *zSql;
int n;
const char *zArg = (const char*)pX;
char zEnd[40];
if( m & SQLITE_TRACE_CLOSE ){
/* If we are tracking closes, that means we want to clean up static
** prepared statements. */
while( db.pAllStmt ){
db_finalize(db.pAllStmt);
}
return 0;
}
if( zArg[0]=='-' ) return 0;
if( m & SQLITE_TRACE_PROFILE ){
sqlite3_int64 nNano = *(sqlite3_int64*)pX;
double rMillisec = 0.000001 * nNano;
sqlite3_snprintf(sizeof(zEnd),zEnd," /* %.3fms */\n", rMillisec);
}else{
zEnd[0] = '\n';
|
| ︙ | ︙ |
Changes to src/default_css.txt.
| ︙ | ︙ | |||
873 874 875 876 877 878 879 |
}
.hidden {
position: absolute;
opacity: 0;
pointer-events: none;
display: none;
}
| > > > > > > | 873 874 875 876 877 878 879 880 881 882 883 884 885 |
}
.hidden {
position: absolute;
opacity: 0;
pointer-events: none;
display: none;
}
input {
max-width: 95%;
}
textarea {
max-width: 95%;
}
|
Changes to src/doc.c.
| ︙ | ︙ | |||
822 823 824 825 826 827 828 | ** ** "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 | | > | 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 | ** ** "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. For /uv, FILE ** can also be the hash of the unversioned file. ** ** The "ckout" CHECKIN is intended for development - to provide a mechanism ** for looking at what a file will look like using the /doc webpage after ** it gets checked in. ** ** The file extension is used to decide how to render the file. ** |
| ︙ | ︙ | |||
929 930 931 932 933 934 935 |
}
}else{
goto doc_not_found;
}
}
if( isUV ){
if( db_table_exists("repository","unversioned") ){
| > > | | | | | | | | > > | | < > | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 |
}
}else{
goto doc_not_found;
}
}
if( isUV ){
if( db_table_exists("repository","unversioned") ){
rid = unversioned_content(zName, &filebody);
if( rid==1 ){
Stmt q;
db_prepare(&q, "SELECT hash, mtime FROM unversioned"
" WHERE name=%Q", zName);
if( db_step(&q)==SQLITE_ROW ){
etag_check(ETAG_HASH, db_column_text(&q,0));
etag_last_modified(db_column_int64(&q,1));
}
db_finalize(&q);
}else if( rid==2 ){
zName = db_text(zName,
"SELECT name FROM unversioned WHERE hash=%Q", zName);
g.isConst = 1;
}
zDfltTitle = zName;
}
}else if( fossil_strcmp(zCheckin,"ckout")==0 ){
/* Read from the local checkout */
char *zFullpath;
db_must_be_within_tree();
zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
if( file_isfile(zFullpath, RepoFILE)
|
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** of the server is held in global variables that are set by url_parse(). ** ** SSL support is abstracted out into this module because Fossil can ** be compiled without SSL support (which requires OpenSSL library) */ #include "config.h" #ifdef FOSSIL_ENABLE_SSL #include <openssl/bio.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/x509.h> | > < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | ** of the server is held in global variables that are set by url_parse(). ** ** SSL support is abstracted out into this module because Fossil can ** be compiled without SSL support (which requires OpenSSL library) */ #include "config.h" #include "http_ssl.h" #ifdef FOSSIL_ENABLE_SSL #include <openssl/bio.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/x509.h> #include <assert.h> #include <sys/types.h> /* ** There can only be a single OpenSSL IO connection open at a time. ** State information about that IO is stored in the following ** local variables: |
| ︙ | ︙ | |||
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
if ( cert==NULL ){
ssl_set_errmsg("No SSL certificate was presented by the peer");
ssl_close();
return 1;
}
if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
char *desc, *prompt;
Blob ans;
char cReply;
BIO *mem;
unsigned char md[32];
char zHash[32*2+1];
unsigned int mdLength = (int)sizeof(md);
memset(md, 0, sizeof(md));
zHash[0] = 0;
| > > > | > > > > | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
if ( cert==NULL ){
ssl_set_errmsg("No SSL certificate was presented by the peer");
ssl_close();
return 1;
}
if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
int x;
char *desc, *prompt;
Blob ans;
char cReply;
BIO *mem;
unsigned char md[32];
char zHash[32*2+1];
unsigned int mdLength = (int)sizeof(md);
memset(md, 0, sizeof(md));
zHash[0] = 0;
/* MMNNFFPPS */
#if OPENSSL_VERSION_NUMBER >= 0x010000000
x = X509_digest(cert, EVP_sha256(), md, &mdLength);
#else
x = X509_digest(cert, EVP_sha1(), md, &mdLength);
#endif
if( x ){
int j;
for(j=0; j<mdLength && j*2+1<sizeof(zHash); ++j){
zHash[j*2] = "0123456789abcdef"[md[j]>>4];
zHash[j*2+1] = "0123456789abcdef"[md[j]&0xf];
}
zHash[j*2] = 0;
}
|
| ︙ | ︙ | |||
516 517 518 519 520 521 522 |
**
** remove-exception DOMAIN... Remove TLS cert exceptions
** for the domains listed. Or if
** the --all option is specified,
** remove all TLS cert exceptions.
*/
void test_tlsconfig_info(void){
| < < < > > > | > | 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 |
**
** remove-exception DOMAIN... Remove TLS cert exceptions
** for the domains listed. Or if
** the --all option is specified,
** remove all TLS cert exceptions.
*/
void test_tlsconfig_info(void){
#if !defined(FOSSIL_ENABLE_SSL)
fossil_print("TLS disabled in this build\n");
#else
const char *zCmd;
size_t nCmd;
int nHit = 0;
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
db_open_config(1,0);
zCmd = g.argc>=3 ? g.argv[2] : "show";
nCmd = strlen(zCmd);
if( strncmp("show",zCmd,nCmd)==0 ){
const char *zName, *zValue;
size_t nName;
Stmt q;
fossil_print("OpenSSL-version: %s (0x%09x)\n",
SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
fossil_print("OpenSSL-cert-file: %s\n", X509_get_default_cert_file());
fossil_print("OpenSSL-cert-dir: %s\n", X509_get_default_cert_dir());
zName = X509_get_default_cert_file_env();
zValue = fossil_getenv(zName);
if( zValue==0 ) zValue = "";
nName = strlen(zName);
fossil_print("%s:%.*s%s\n", zName, 19-nName, "", zValue);
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
1755 1756 1757 1758 1759 1760 1761 | append_diff(zV1, zV2, diffFlags, pRe); append_diff_javascript(diffType); style_footer(); } /* ** WEBPAGE: raw | | > > > > > | 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 |
append_diff(zV1, zV2, diffFlags, pRe);
append_diff_javascript(diffType);
style_footer();
}
/*
** WEBPAGE: raw
** URL: /raw/ARTIFACTID
** URL: /raw?ci=BRANCH&filename=NAME
**
** Additional query parameters:
**
** m=MIMETYPE The mimetype is MIMETYPE
** at=FILENAME Content-disposition; attachment; filename=FILENAME;
**
** Return the uninterpreted content of an artifact. Used primarily
** to view artifacts that are images.
*/
void rawartifact_page(void){
int rid = 0;
char *zUuid;
|
| ︙ | ︙ | |||
1817 1818 1819 1820 1821 1822 1823 1824 |
** Generate a verbatim artifact as the result of an HTTP request.
** If zMime is not NULL, use it as the MIME-type. If zMime is
** NULL, guess at the MIME-type based on the filename
** associated with the artifact.
*/
void deliver_artifact(int rid, const char *zMime){
Blob content;
if( zMime==0 ){
| > > > | | | > | | | | > | > > | > > > > | 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 |
** Generate a verbatim artifact as the result of an HTTP request.
** If zMime is not NULL, use it as the MIME-type. If zMime is
** NULL, guess at the MIME-type based on the filename
** associated with the artifact.
*/
void deliver_artifact(int rid, const char *zMime){
Blob content;
const char *zAttachName = P("at");
if( zMime==0 ){
char *zFN = (char*)zAttachName;
if( zFN==0 ){
zFN = db_text(0, "SELECT filename.name FROM mlink, filename"
" WHERE mlink.fid=%d"
" AND filename.fnid=mlink.fnid", rid);
}
if( zFN==0 ){
/* Look also at the attachment table */
zFN = db_text(0, "SELECT attachment.filename FROM attachment, blob"
" WHERE blob.rid=%d"
" AND attachment.src=blob.uuid", rid);
}
if( zFN ){
zMime = mimetype_from_name(zFN);
}
if( zMime==0 ){
zMime = "application/x-fossil-artifact";
}
}
content_get(rid, &content);
fossil_free(style_csp(1));
cgi_set_content_type(zMime);
if( zAttachName ){
cgi_content_disposition_filename(zAttachName);
}
cgi_set_content(&content);
}
/*
** Render a hex dump of a file.
*/
static void hexdump(Blob *pBlob){
|
| ︙ | ︙ | |||
1930 1931 1932 1933 1934 1935 1936 |
@ (%d(rid)):</h2>
}else{
@ :</h2>
}
blob_zero(&downloadName);
if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
object_description(rid, objdescFlags, 0, &downloadName);
| | | | 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 |
@ (%d(rid)):</h2>
}else{
@ :</h2>
}
blob_zero(&downloadName);
if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
object_description(rid, objdescFlags, 0, &downloadName);
style_submenu_element("Download", "%R/raw/%s?at=%T",
zUuid, file_tail(blob_str(&downloadName)));
@ <hr />
content_get(rid, &content);
@ <blockquote><pre>
hexdump(&content);
@ </pre></blockquote>
style_footer();
}
|
| ︙ | ︙ | |||
2260 2261 2262 2263 2264 2265 2266 |
}
blob_zero(&downloadName);
if( asText ) objdescFlags &= ~OBJDESC_BASE;
objType = object_description(rid, objdescFlags,
(isFile?zName:0), &downloadName);
}
if( !descOnly && P("download")!=0 ){
| | | > | 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 |
}
blob_zero(&downloadName);
if( asText ) objdescFlags &= ~OBJDESC_BASE;
objType = object_description(rid, objdescFlags,
(isFile?zName:0), &downloadName);
}
if( !descOnly && P("download")!=0 ){
cgi_redirectf("%R/raw/%s?at=%T",
db_text("x", "SELECT uuid FROM blob WHERE rid=%d", rid),
file_tail(blob_str(&downloadName)));
/*NOTREACHED*/
}
if( g.perm.Admin ){
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
style_submenu_element("Unshun", "%s/shun?accept=%s&sub=1#accshun",
g.zTop, zUuid);
|
| ︙ | ︙ | |||
2306 2307 2308 2309 2310 2311 2312 |
const char *zUser = db_column_text(&q,0);
const char *zDate = db_column_text(&q,1);
const char *zIp = db_column_text(&q,2);
@ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
}
db_finalize(&q);
}
| | < | 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 |
const char *zUser = db_column_text(&q,0);
const char *zDate = db_column_text(&q,1);
const char *zIp = db_column_text(&q,2);
@ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
}
db_finalize(&q);
}
style_submenu_element("Download", "%R/raw/%s?at=%T", zUuid, file_tail(zName));
if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
}
zMime = mimetype_from_name(blob_str(&downloadName));
if( zMime ){
if( fossil_strcmp(zMime, "text/html")==0 ){
if( asText ){
|
| ︙ | ︙ | |||
2346 2347 2348 2349 2350 2351 2352 |
style_submenu_element("Content", "%R/artifact/%s", zUuid);
}else{
@ <hr />
content_get(rid, &content);
if( renderAsWiki ){
wiki_render_by_mimetype(&content, zMime);
}else if( renderAsHtml ){
| | | 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 |
style_submenu_element("Content", "%R/artifact/%s", zUuid);
}else{
@ <hr />
content_get(rid, &content);
if( renderAsWiki ){
wiki_render_by_mimetype(&content, zMime);
}else if( renderAsHtml ){
@ <iframe src="%R/raw/%s(zUuid)"
@ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
@ sandbox="allow-same-origin" id="ifm1">
@ </iframe>
@ <script nonce="%h(style_nonce())">
@ document.getElementById("ifm1").addEventListener("load",
@ function(){
@ this.height=this.contentDocument.documentElement.scrollHeight + 75;
|
| ︙ | ︙ |
Changes to src/shell.c.
| ︙ | ︙ | |||
6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 | ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful ** for working with sqlar archives and used by the shell tool's built-in ** sqlar support. */ /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #include <zlib.h> /* ** Implementation of the "sqlar_compress(X)" SQL function. ** ** If the type of X is SQLITE_BLOB, and compressing that blob using ** zlib utility function compress() yields a smaller blob, return the ** compressed blob. Otherwise, return a copy of X. | > | 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 | ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful ** for working with sqlar archives and used by the shell tool's built-in ** sqlar support. */ /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #include <zlib.h> #include <assert.h> /* ** Implementation of the "sqlar_compress(X)" SQL function. ** ** If the type of X is SQLITE_BLOB, and compressing that blob using ** zlib utility function compress() yields a smaller blob, return the ** compressed blob. Otherwise, return a copy of X. |
| ︙ | ︙ | |||
8004 8005 8006 8007 8008 8009 8010 |
int i;
if( !zDetail ) continue;
nDetail = STRLEN(zDetail);
for(i=0; i<nDetail; i++){
const char *zIdx = 0;
| | > | > | 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 |
int i;
if( !zDetail ) continue;
nDetail = STRLEN(zDetail);
for(i=0; i<nDetail; i++){
const char *zIdx = 0;
if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
zIdx = &zDetail[i+13];
}else if( i+22<nDetail
&& memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0
){
zIdx = &zDetail[i+22];
}
if( zIdx ){
const char *zSql;
int nIdx = 0;
while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
nIdx++;
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
** database connection to be more useful to the human operator.
*/
static int sqlcmd_autoinit(
sqlite3 *db,
const char **pzErrMsg,
const void *notUsed
){
add_content_sql_commands(db);
db_add_aux_functions(db);
re_add_sql_func(db);
search_sql_setup(db);
foci_register(db);
deltafunc_init(db);
g.repositoryOpen = 1;
| > | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
** database connection to be more useful to the human operator.
*/
static int sqlcmd_autoinit(
sqlite3 *db,
const char **pzErrMsg,
const void *notUsed
){
int mTrace = SQLITE_TRACE_CLOSE;
add_content_sql_commands(db);
db_add_aux_functions(db);
re_add_sql_func(db);
search_sql_setup(db);
foci_register(db);
deltafunc_init(db);
g.repositoryOpen = 1;
|
| ︙ | ︙ | |||
184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
}
if( g.zConfigDbName ){
char *zSql = sqlite3_mprintf("ATTACH %Q AS 'configdb' KEY ''",
g.zConfigDbName);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
return SQLITE_OK;
}
/*
** atexit() handler that cleans up global state modified by this module.
*/
static void sqlcmd_atexit(void) {
| > > > > | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
}
if( g.zConfigDbName ){
char *zSql = sqlite3_mprintf("ATTACH %Q AS 'configdb' KEY ''",
g.zConfigDbName);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
/* Arrange to trace close operations so that static prepared statements
** will get cleaned up when the shell closes the database connection */
if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
return SQLITE_OK;
}
/*
** atexit() handler that cleans up global state modified by this module.
*/
static void sqlcmd_atexit(void) {
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
1 2 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite | | | 1 2 3 4 5 6 7 8 9 10 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.32.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other |
| ︙ | ︙ | |||
1158 1159 1160 1161 1162 1163 1164 | ** 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()]. */ | | | | | 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 | ** 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.32.1" #define SQLITE_VERSION_NUMBER 3032001 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350" /* ** 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 |
| ︙ | ︙ | |||
17839 17840 17841 17842 17843 17844 17845 | }; /* ** An instance of this structure contains information needed to generate ** code for a SELECT that contains aggregate functions. ** ** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a | | | 17839 17840 17841 17842 17843 17844 17845 17846 17847 17848 17849 17850 17851 17852 17853 | }; /* ** An instance of this structure contains information needed to generate ** code for a SELECT that contains aggregate functions. ** ** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a ** pointer to this structure. The Expr.iAgg field is the index in ** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate ** code for that node. ** ** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the ** original Select structure that describes the SELECT statement. These ** fields do not need to be freed when deallocating the AggInfo structure. */ |
| ︙ | ︙ | |||
19078 19079 19080 19081 19082 19083 19084 19085 19086 19087 19088 19089 19090 19091 | SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*); SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); #endif /* ** Return code from the parse-tree walking primitives and their ** callbacks. | > > > | 19078 19079 19080 19081 19082 19083 19084 19085 19086 19087 19088 19089 19090 19091 19092 19093 19094 | SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*); SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*); SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); #endif /* ** Return code from the parse-tree walking primitives and their ** callbacks. |
| ︙ | ︙ | |||
28272 28273 28274 28275 28276 28277 28278 28279 28280 28281 28282 28283 28284 28285 | ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. */ #ifndef SQLITE_PRINT_BUF_SIZE # define SQLITE_PRINT_BUF_SIZE 70 #endif #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ /* ** Render a string given by "fmt" into the StrAccum object. */ SQLITE_API void sqlite3_str_vappendf( sqlite3_str *pAccum, /* Accumulate results here */ const char *fmt, /* Format string */ va_list ap /* arguments */ | > > > > > > > | 28275 28276 28277 28278 28279 28280 28281 28282 28283 28284 28285 28286 28287 28288 28289 28290 28291 28292 28293 28294 28295 | ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. */ #ifndef SQLITE_PRINT_BUF_SIZE # define SQLITE_PRINT_BUF_SIZE 70 #endif #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ /* ** Hard limit on the precision of floating-point conversions. */ #ifndef SQLITE_PRINTF_PRECISION_LIMIT # define SQLITE_FP_PRECISION_LIMIT 100000000 #endif /* ** Render a string given by "fmt" into the StrAccum object. */ SQLITE_API void sqlite3_str_vappendf( sqlite3_str *pAccum, /* Accumulate results here */ const char *fmt, /* Format string */ va_list ap /* arguments */ |
| ︙ | ︙ | |||
28472 28473 28474 28475 28476 28477 28478 28479 28480 28481 28482 28483 28484 28485 |
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
** is -1.
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
switch( xtype ){
case etPOINTER:
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
sizeof(char*)==sizeof(long int) ? 1 : 0;
/* Fall through into the next case */
case etORDINAL:
case etRADIX:
| > > | 28482 28483 28484 28485 28486 28487 28488 28489 28490 28491 28492 28493 28494 28495 28496 28497 |
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
** is -1.
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
assert( width>=0 );
assert( precision>=(-1) );
switch( xtype ){
case etPOINTER:
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
sizeof(char*)==sizeof(long int) ? 1 : 0;
/* Fall through into the next case */
case etORDINAL:
case etRADIX:
|
| ︙ | ︙ | |||
28593 28594 28595 28596 28597 28598 28599 28600 28601 28602 28603 28604 28605 28606 |
}else{
realvalue = va_arg(ap,double);
}
#ifdef SQLITE_OMIT_FLOATING_POINT
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
}else{
prefix = flag_prefix;
}
if( xtype==etGENERIC && precision>0 ) precision--;
| > > > > > | 28605 28606 28607 28608 28609 28610 28611 28612 28613 28614 28615 28616 28617 28618 28619 28620 28621 28622 28623 |
}else{
realvalue = va_arg(ap,double);
}
#ifdef SQLITE_OMIT_FLOATING_POINT
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
#ifdef SQLITE_FP_PRECISION_LIMIT
if( precision>SQLITE_FP_PRECISION_LIMIT ){
precision = SQLITE_FP_PRECISION_LIMIT;
}
#endif
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
}else{
prefix = flag_prefix;
}
if( xtype==etGENERIC && precision>0 ) precision--;
|
| ︙ | ︙ | |||
28875 28876 28877 28878 28879 28880 28881 |
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
| | | 28892 28893 28894 28895 28896 28897 28898 28899 28900 28901 28902 28903 28904 28905 28906 |
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
/* For %q, %Q, and %w, the precision is the number of bytes (or
** characters if the ! flags is present) to use from the input.
** Because of the extra quoting characters inserted, the number
** of output characters may be larger than the precision.
*/
k = precision;
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
if( ch==q ) n++;
|
| ︙ | ︙ | |||
29960 29961 29962 29963 29964 29965 29966 |
#ifndef SQLITE_OMIT_WINDOWFUNC
pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
#else
pWin = 0;
#endif
}
if( pExpr->op==TK_AGG_FUNCTION ){
| | | > | 29977 29978 29979 29980 29981 29982 29983 29984 29985 29986 29987 29988 29989 29990 29991 29992 29993 |
#ifndef SQLITE_OMIT_WINDOWFUNC
pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
#else
pWin = 0;
#endif
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s iAgg=%d agg=%p",
pExpr->op2, pExpr->u.zToken, zFlgs,
pExpr->iAgg, pExpr->pAggInfo);
}else if( pExpr->op2!=0 ){
const char *zOp2;
char zBuf[8];
sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
zOp2 = zBuf;
if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
|
| ︙ | ︙ | |||
30854 30855 30856 30857 30858 30859 30860 30861 30862 30863 30864 30865 30866 30867 30868 30869 30870 30871 30872 30873 30874 30875 30876 30877 30878 30879 30880 30881 30882 30883 30884 30885 30886 30887 30888 30889 30890 30891 30892 30893 30894 30895 30896 30897 30898 30899 30900 |
assert( desiredEnc==SQLITE_UTF8 );
if( pMem->enc==SQLITE_UTF16LE ){
/* UTF-16 Little-endian -> UTF-8 */
while( zIn<zTerm ){
c = *(zIn++);
c += (*(zIn++))<<8;
if( c>=0xd800 && c<0xe000 ){
if( c>=0xdc00 || zIn>=zTerm ){
c = 0xfffd;
}else{
int c2 = *(zIn++);
c2 += (*(zIn++))<<8;
if( c2<0xdc00 || c2>=0xe000 ){
zIn -= 2;
c = 0xfffd;
}else{
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
}
}
}
WRITE_UTF8(z, c);
}
}else{
/* UTF-16 Big-endian -> UTF-8 */
while( zIn<zTerm ){
c = (*(zIn++))<<8;
c += *(zIn++);
if( c>=0xd800 && c<0xe000 ){
if( c>=0xdc00 || zIn>=zTerm ){
c = 0xfffd;
}else{
int c2 = (*(zIn++))<<8;
c2 += *(zIn++);
if( c2<0xdc00 || c2>=0xe000 ){
zIn -= 2;
c = 0xfffd;
}else{
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
}
}
}
WRITE_UTF8(z, c);
}
}
pMem->n = (int)(z - zOut);
}
*z = 0;
| > > > > > > > > > > > > > > > > | 30872 30873 30874 30875 30876 30877 30878 30879 30880 30881 30882 30883 30884 30885 30886 30887 30888 30889 30890 30891 30892 30893 30894 30895 30896 30897 30898 30899 30900 30901 30902 30903 30904 30905 30906 30907 30908 30909 30910 30911 30912 30913 30914 30915 30916 30917 30918 30919 30920 30921 30922 30923 30924 30925 30926 30927 30928 30929 30930 30931 30932 30933 30934 |
assert( desiredEnc==SQLITE_UTF8 );
if( pMem->enc==SQLITE_UTF16LE ){
/* UTF-16 Little-endian -> UTF-8 */
while( zIn<zTerm ){
c = *(zIn++);
c += (*(zIn++))<<8;
if( c>=0xd800 && c<0xe000 ){
#ifdef SQLITE_REPLACE_INVALID_UTF
if( c>=0xdc00 || zIn>=zTerm ){
c = 0xfffd;
}else{
int c2 = *(zIn++);
c2 += (*(zIn++))<<8;
if( c2<0xdc00 || c2>=0xe000 ){
zIn -= 2;
c = 0xfffd;
}else{
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
}
}
#else
if( zIn<zTerm ){
int c2 = (*zIn++);
c2 += ((*zIn++)<<8);
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
}
#endif
}
WRITE_UTF8(z, c);
}
}else{
/* UTF-16 Big-endian -> UTF-8 */
while( zIn<zTerm ){
c = (*(zIn++))<<8;
c += *(zIn++);
if( c>=0xd800 && c<0xe000 ){
#ifdef SQLITE_REPLACE_INVALID_UTF
if( c>=0xdc00 || zIn>=zTerm ){
c = 0xfffd;
}else{
int c2 = (*(zIn++))<<8;
c2 += *(zIn++);
if( c2<0xdc00 || c2>=0xe000 ){
zIn -= 2;
c = 0xfffd;
}else{
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
}
}
#else
if( zIn<zTerm ){
int c2 = ((*zIn++)<<8);
c2 += (*zIn++);
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
}
#endif
}
WRITE_UTF8(z, c);
}
}
pMem->n = (int)(z - zOut);
}
*z = 0;
|
| ︙ | ︙ | |||
46819 46820 46821 46822 46823 46824 46825 |
sqlite3_free(zTmpname);
pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod;
pFile->pVfs = pVfs;
pFile->h = h;
if( isReadonly ){
pFile->ctrlFlags |= WINFILE_RDONLY;
}
| > | > | 46853 46854 46855 46856 46857 46858 46859 46860 46861 46862 46863 46864 46865 46866 46867 46868 46869 |
sqlite3_free(zTmpname);
pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod;
pFile->pVfs = pVfs;
pFile->h = h;
if( isReadonly ){
pFile->ctrlFlags |= WINFILE_RDONLY;
}
if( (flags & SQLITE_OPEN_MAIN_DB)
&& sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
){
pFile->ctrlFlags |= WINFILE_PSOW;
}
pFile->lastErrno = NO_ERROR;
pFile->zPath = zName;
#if SQLITE_MAX_MMAP_SIZE>0
pFile->hMap = NULL;
pFile->pMapRegion = 0;
|
| ︙ | ︙ | |||
48311 48312 48313 48314 48315 48316 48317 |
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
SQLITE_PRIVATE int sqlite3MemdbInit(void){
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
int sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
| < < | > > > | | 48347 48348 48349 48350 48351 48352 48353 48354 48355 48356 48357 48358 48359 48360 48361 48362 48363 48364 48365 |
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
SQLITE_PRIVATE int sqlite3MemdbInit(void){
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
int sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
/* The following conditional can only be true when compiled for
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
** it in, to be safe, but it is marked as NO_TEST since there
** is no way to reach it under most builds. */
if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
memdb_vfs.szOsFile = sz;
return sqlite3_vfs_register(&memdb_vfs, 0);
}
#endif /* SQLITE_ENABLE_DESERIALIZE */
/************** End of memdb.c ***********************************************/
/************** Begin file bitvec.c ******************************************/
|
| ︙ | ︙ | |||
59955 59956 59957 59958 59959 59960 59961 59962 59963 59964 59965 59966 59967 59968 59969 59970 59971 59972 |
}while( aData<aEnd );
}
aOut[0] = s1;
aOut[1] = s2;
}
static void walShmBarrier(Wal *pWal){
if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
sqlite3OsShmBarrier(pWal->pDbFd);
}
}
/*
** Write the header information in pWal->hdr into the wal-index.
**
** The checksum on pWal->hdr is updated before it is written.
*/
| > > > > > > > > > > > > > > > > > | > | 59992 59993 59994 59995 59996 59997 59998 59999 60000 60001 60002 60003 60004 60005 60006 60007 60008 60009 60010 60011 60012 60013 60014 60015 60016 60017 60018 60019 60020 60021 60022 60023 60024 60025 60026 60027 60028 60029 60030 60031 60032 60033 60034 60035 60036 60037 60038 60039 60040 60041 60042 |
}while( aData<aEnd );
}
aOut[0] = s1;
aOut[1] = s2;
}
/*
** If there is the possibility of concurrent access to the SHM file
** from multiple threads and/or processes, then do a memory barrier.
*/
static void walShmBarrier(Wal *pWal){
if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
sqlite3OsShmBarrier(pWal->pDbFd);
}
}
/*
** Add the SQLITE_NO_TSAN as part of the return-type of a function
** definition as a hint that the function contains constructs that
** might give false-positive TSAN warnings.
**
** See tag-20200519-1.
*/
#if defined(__clang__) && !defined(SQLITE_NO_TSAN)
# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
#else
# define SQLITE_NO_TSAN
#endif
/*
** Write the header information in pWal->hdr into the wal-index.
**
** The checksum on pWal->hdr is updated before it is written.
*/
static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
const int nCksum = offsetof(WalIndexHdr, aCksum);
assert( pWal->writeLock );
pWal->hdr.isInit = 1;
pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
/* Possible TSAN false-positive. See tag-20200519-1 */
memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
walShmBarrier(pWal);
memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
}
/*
** This function encodes a single frame header and writes it to a buffer
|
| ︙ | ︙ | |||
61163 61164 61165 61166 61167 61168 61169 |
** safe to write into the database. Frames beyond mxSafeFrame might
** overwrite database pages that are in use by active readers and thus
** cannot be backfilled from the WAL.
*/
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
for(i=1; i<WAL_NREADER; i++){
| < < < < < < < < < < < < < < < < < < < < | | > | | 61218 61219 61220 61221 61222 61223 61224 61225 61226 61227 61228 61229 61230 61231 61232 61233 61234 61235 61236 61237 61238 61239 61240 61241 61242 61243 61244 61245 61246 61247 61248 61249 61250 61251 61252 61253 61254 61255 61256 |
** safe to write into the database. Frames beyond mxSafeFrame might
** overwrite database pages that are in use by active readers and thus
** cannot be backfilled from the WAL.
*/
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
for(i=1; i<WAL_NREADER; i++){
u32 y = AtomicLoad(pInfo->aReadMark+i);
if( mxSafeFrame>y ){
assert( y<=pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
AtomicStore(pInfo->aReadMark+i, iMark);
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
}else if( rc==SQLITE_BUSY ){
mxSafeFrame = y;
xBusy = 0;
}else{
goto walcheckpoint_out;
}
}
}
/* Allocate the iterator */
if( pInfo->nBackfill<mxSafeFrame ){
rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter);
assert( rc==SQLITE_OK || pIter==0 );
}
if( pIter
&& (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
){
u32 nBackfill = pInfo->nBackfill;
pInfo->nBackfillAttempted = mxSafeFrame;
/* Sync the WAL to disk */
rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
|
| ︙ | ︙ | |||
61421 61422 61423 61424 61425 61426 61427 | ** If and only if the read is consistent and the header is different from ** pWal->hdr, then pWal->hdr is updated to the content of the new header ** and *pChanged is set to 1. ** ** If the checksum cannot be verified return non-zero. If the header ** is read successfully and the checksum verified, return zero. */ | | > | > > > > > | | 61457 61458 61459 61460 61461 61462 61463 61464 61465 61466 61467 61468 61469 61470 61471 61472 61473 61474 61475 61476 61477 61478 61479 61480 61481 61482 61483 61484 61485 61486 61487 61488 61489 61490 61491 61492 61493 61494 61495 61496 |
** If and only if the read is consistent and the header is different from
** pWal->hdr, then pWal->hdr is updated to the content of the new header
** and *pChanged is set to 1.
**
** If the checksum cannot be verified return non-zero. If the header
** is read successfully and the checksum verified, return zero.
*/
static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
u32 aCksum[2]; /* Checksum on the header content */
WalIndexHdr h1, h2; /* Two copies of the header content */
WalIndexHdr volatile *aHdr; /* Header in shared memory */
/* The first page of the wal-index must be mapped at this point. */
assert( pWal->nWiData>0 && pWal->apWiData[0] );
/* Read the header. This might happen concurrently with a write to the
** same area of shared memory on a different CPU in a SMP,
** meaning it is possible that an inconsistent snapshot is read
** from the file. If this happens, return non-zero.
**
** tag-20200519-1:
** There are two copies of the header at the beginning of the wal-index.
** When reading, read [0] first then [1]. Writes are in the reverse order.
** Memory barriers are used to prevent the compiler or the hardware from
** reordering the reads and writes. TSAN and similar tools can sometimes
** give false-positive warnings about these accesses because the tools do not
** account for the double-read and the memory barrier. The use of mutexes
** here would be problematic as the memory being accessed is potentially
** shared among multiple processes and not all mutex implementions work
** reliably in that environment.
*/
aHdr = walIndexHdr(pWal);
memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
walShmBarrier(pWal);
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
return 1; /* Dirty read */
}
if( h1.isInit==0 ){
|
| ︙ | ︙ | |||
62107 62108 62109 62110 62111 62112 62113 62114 62115 62116 62117 |
** transaction, then *pChanged is set to 1 before returning. The
** Pager layer will use this to know that its cache is stale and
** needs to be flushed.
*/
SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
assert( pWal->ckptLock==0 );
#ifdef SQLITE_ENABLE_SNAPSHOT
| > > > > < < | 62149 62150 62151 62152 62153 62154 62155 62156 62157 62158 62159 62160 62161 62162 62163 62164 62165 62166 62167 62168 62169 62170 |
** transaction, then *pChanged is set to 1 before returning. The
** Pager layer will use this to know that its cache is stale and
** needs to be flushed.
*/
SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
int rc; /* Return code */
int cnt = 0; /* Number of TryBeginRead attempts */
#ifdef SQLITE_ENABLE_SNAPSHOT
int bChanged = 0;
WalIndexHdr *pSnapshot = pWal->pSnapshot;
#endif
assert( pWal->ckptLock==0 );
#ifdef SQLITE_ENABLE_SNAPSHOT
if( pSnapshot ){
if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
bChanged = 1;
}
/* It is possible that there is a checkpointer thread running
** concurrent with this code. If this is the case, it may be that the
|
| ︙ | ︙ | |||
62281 62282 62283 62284 62285 62286 62287 62288 62289 62290 62291 62292 62293 |
*/
iMinHash = walFramePage(pWal->minFrame);
for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
WalHashLoc sLoc; /* Hash table location */
int iKey; /* Hash slot index */
int nCollide; /* Number of hash collisions remaining */
int rc; /* Error code */
rc = walHashGet(pWal, iHash, &sLoc);
if( rc!=SQLITE_OK ){
return rc;
}
nCollide = HASHTABLE_NSLOT;
| > | | > | 62325 62326 62327 62328 62329 62330 62331 62332 62333 62334 62335 62336 62337 62338 62339 62340 62341 62342 62343 62344 62345 62346 62347 62348 62349 62350 62351 62352 62353 62354 62355 62356 |
*/
iMinHash = walFramePage(pWal->minFrame);
for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
WalHashLoc sLoc; /* Hash table location */
int iKey; /* Hash slot index */
int nCollide; /* Number of hash collisions remaining */
int rc; /* Error code */
u32 iH;
rc = walHashGet(pWal, iHash, &sLoc);
if( rc!=SQLITE_OK ){
return rc;
}
nCollide = HASHTABLE_NSLOT;
iKey = walHash(pgno);
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
u32 iFrame = iH + sLoc.iZero;
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame;
}
if( (nCollide--)==0 ){
return SQLITE_CORRUPT_BKPT;
}
iKey = walNextHash(iKey);
}
if( iRead ) break;
}
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* If expensive assert() statements are available, do a linear search
** of the wal-index file content. Make sure the results agree with the
|
| ︙ | ︙ | |||
97434 97435 97436 97437 97438 97439 97440 97441 97442 97443 97444 97445 97446 97447 |
if( pWalker->xSelectCallback2 ){
pWalker->xSelectCallback2(pWalker, p);
}
p = p->pPrior;
}while( p!=0 );
return WRC_Continue;
}
/************** End of walker.c **********************************************/
/************** Begin file resolve.c *****************************************/
/*
** 2008 August 18
**
** The author disclaims copyright to this source code. In place of
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 97480 97481 97482 97483 97484 97485 97486 97487 97488 97489 97490 97491 97492 97493 97494 97495 97496 97497 97498 97499 97500 97501 97502 97503 97504 97505 97506 97507 97508 97509 97510 97511 97512 97513 97514 97515 97516 97517 97518 97519 97520 97521 97522 97523 97524 97525 97526 97527 97528 97529 97530 |
if( pWalker->xSelectCallback2 ){
pWalker->xSelectCallback2(pWalker, p);
}
p = p->pPrior;
}while( p!=0 );
return WRC_Continue;
}
/* Increase the walkerDepth when entering a subquery, and
** descrease when leaving the subquery.
*/
SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){
UNUSED_PARAMETER(pSelect);
pWalker->walkerDepth++;
return WRC_Continue;
}
SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){
UNUSED_PARAMETER(pSelect);
pWalker->walkerDepth--;
}
/*
** No-op routine for the parse-tree walker.
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node. Presumably,
** when this routine is used for Walker.xExprCallback then
** Walker.xSelectCallback is set to do something useful for every
** subquery in the parser tree.
*/
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return WRC_Continue;
}
/*
** No-op routine for the parse-tree walker for SELECT statements.
** subquery in the parser tree.
*/
SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return WRC_Continue;
}
/************** End of walker.c **********************************************/
/************** Begin file resolve.c *****************************************/
/*
** 2008 August 18
**
** The author disclaims copyright to this source code. In place of
|
| ︙ | ︙ | |||
97463 97464 97465 97466 97467 97468 97469 97470 97471 97472 97473 97474 97475 97476 |
** Walk the expression tree pExpr and increase the aggregate function
** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
** This needs to occur when copying a TK_AGG_FUNCTION node from an
** outer query into an inner subquery.
**
** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
** is a helper function - a callback for the tree walker.
*/
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
return WRC_Continue;
}
static void incrAggFunctionDepth(Expr *pExpr, int N){
if( N>0 ){
| > > | 97546 97547 97548 97549 97550 97551 97552 97553 97554 97555 97556 97557 97558 97559 97560 97561 |
** Walk the expression tree pExpr and increase the aggregate function
** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
** This needs to occur when copying a TK_AGG_FUNCTION node from an
** outer query into an inner subquery.
**
** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
** is a helper function - a callback for the tree walker.
**
** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c
*/
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
return WRC_Continue;
}
static void incrAggFunctionDepth(Expr *pExpr, int N){
if( N>0 ){
|
| ︙ | ︙ | |||
103204 103205 103206 103207 103208 103209 103210 |
}else{
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
op = pExpr->op;
}
switch( op ){
case TK_AGG_COLUMN: {
AggInfo *pAggInfo = pExpr->pAggInfo;
| | > > > | 103289 103290 103291 103292 103293 103294 103295 103296 103297 103298 103299 103300 103301 103302 103303 103304 103305 103306 |
}else{
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
op = pExpr->op;
}
switch( op ){
case TK_AGG_COLUMN: {
AggInfo *pAggInfo = pExpr->pAggInfo;
struct AggInfo_col *pCol;
assert( pAggInfo!=0 );
assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
pCol = &pAggInfo->aCol[pExpr->iAgg];
if( !pAggInfo->directMode ){
assert( pCol->iMem>0 );
return pCol->iMem;
}else if( pAggInfo->useSortingIdx ){
Table *pTab = pCol->pTab;
sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
pCol->iSorterColumn, target);
|
| ︙ | ︙ | |||
103504 103505 103506 103507 103508 103509 103510 |
VdbeCoverageIf(v, op==TK_NOTNULL);
sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
sqlite3VdbeJumpHere(v, addr);
break;
}
case TK_AGG_FUNCTION: {
AggInfo *pInfo = pExpr->pAggInfo;
| | > > > | 103592 103593 103594 103595 103596 103597 103598 103599 103600 103601 103602 103603 103604 103605 103606 103607 103608 103609 |
VdbeCoverageIf(v, op==TK_NOTNULL);
sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
sqlite3VdbeJumpHere(v, addr);
break;
}
case TK_AGG_FUNCTION: {
AggInfo *pInfo = pExpr->pAggInfo;
if( pInfo==0
|| NEVER(pExpr->iAgg<0)
|| NEVER(pExpr->iAgg>=pInfo->nFunc)
){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
}else{
return pInfo->aFunc[pExpr->iAgg].iMem;
}
break;
}
|
| ︙ | ︙ | |||
105260 105261 105262 105263 105264 105265 105266 |
}else{
return WRC_Continue;
}
}
}
return WRC_Continue;
}
| < < < < < < < < < | | | 105351 105352 105353 105354 105355 105356 105357 105358 105359 105360 105361 105362 105363 105364 105365 105366 105367 105368 105369 105370 105371 105372 105373 105374 105375 105376 105377 105378 105379 |
}else{
return WRC_Continue;
}
}
}
return WRC_Continue;
}
/*
** Analyze the pExpr expression looking for aggregate functions and
** for variables that need to be added to AggInfo object that pNC->pAggInfo
** points to. Additional entries are made on the AggInfo object as
** necessary.
**
** This routine should only be called after the expression has been
** analyzed by sqlite3ResolveExprNames().
*/
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
Walker w;
w.xExprCallback = analyzeAggregate;
w.xSelectCallback = sqlite3WalkerDepthIncrease;
w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
w.walkerDepth = 0;
w.u.pNC = pNC;
w.pParse = 0;
assert( pNC->pSrcList!=0 );
sqlite3WalkExpr(&w, pExpr);
}
|
| ︙ | ︙ | |||
122005 122006 122007 122008 122009 122010 122011 |
}else{
addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
}
if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
| | | 122087 122088 122089 122090 122091 122092 122093 122094 122095 122096 122097 122098 122099 122100 122101 |
}else{
addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
}
if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
VdbeNoopComment((v, "prep index %s", pIdx->zName));
iThisCur = iIdxCur+ix;
/* Skip partial indices for which the WHERE clause is not true */
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
pParse->iSelfTab = -(regNewData+1);
|
| ︙ | ︙ | |||
133977 133978 133979 133980 133981 133982 133983 |
if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){
p->selFlags |= SF_ComplexResult;
}
}
return WRC_Continue;
}
| < < < < < < < < < < < < < < < < < < < < < < < | 134059 134060 134061 134062 134063 134064 134065 134066 134067 134068 134069 134070 134071 134072 |
if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){
p->selFlags |= SF_ComplexResult;
}
}
return WRC_Continue;
}
#if SQLITE_DEBUG
/*
** Always assert. This xSelectCallback2 implementation proves that the
** xSelectCallback2 is never invoked.
*/
SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker *NotUsed, Select *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
| ︙ | ︙ | |||
135170 135171 135172 135173 135174 135175 135176 |
sNC.ncFlags &= ~NC_InAggFunc;
}
sAggInfo.mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
int ii;
| | | 135229 135230 135231 135232 135233 135234 135235 135236 135237 135238 135239 135240 135241 135242 135243 |
sNC.ncFlags &= ~NC_InAggFunc;
}
sAggInfo.mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", &sAggInfo));
sqlite3TreeViewSelect(0, p, 0);
for(ii=0; ii<sAggInfo.nColumn; ii++){
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
ii, sAggInfo.aCol[ii].iMem);
sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
}
for(ii=0; ii<sAggInfo.nFunc; ii++){
|
| ︙ | ︙ | |||
151213 151214 151215 151216 151217 151218 151219 151220 151221 151222 151223 151224 151225 151226 |
}
pList = sqlite3ExprListAppend(pParse, pList, pDup);
if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
}
}
return pList;
}
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.
| > > > > > > > > > > > > > > > > > | 151272 151273 151274 151275 151276 151277 151278 151279 151280 151281 151282 151283 151284 151285 151286 151287 151288 151289 151290 151291 151292 151293 151294 151295 151296 151297 151298 151299 151300 151301 151302 |
}
pList = sqlite3ExprListAppend(pParse, pList, pDup);
if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
}
}
return pList;
}
/*
** When rewriting a query, if the new subquery in the FROM clause
** contains TK_AGG_FUNCTION nodes that refer to an outer query,
** then we have to increase the Expr->op2 values of those nodes
** due to the extra subquery layer that was added.
**
** See also the incrAggDepth() routine in resolve.c
*/
static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION
&& pExpr->op2>=pWalker->walkerDepth
){
pExpr->op2++;
}
return WRC_Continue;
}
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.
|
| ︙ | ︙ | |||
151323 151324 151325 151326 151327 151328 151329 151330 151331 151332 151333 151334 151335 151336 151337 151338 151339 151340 151341 151342 151343 151344 151345 151346 151347 151348 151349 151350 151351 |
pSub = sqlite3SelectNew(
pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
);
p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( p->pSrc ){
Table *pTab2;
p->pSrc->a[0].pSelect = pSub;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
pSub->selFlags |= SF_Expanded;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
pSub->selFlags |= (selFlags & SF_Aggregate);
if( pTab2==0 ){
/* Might actually be some other kind of error, but in that case
** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
** the correct error message regardless. */
rc = SQLITE_NOMEM;
}else{
memcpy(pTab, pTab2, sizeof(Table));
pTab->tabFlags |= TF_Ephemeral;
p->pSrc->a[0].pTab = pTab;
pTab = pTab2;
}
}else{
sqlite3SelectDelete(db, pSub);
}
if( db->mallocFailed ) rc = SQLITE_NOMEM;
sqlite3DbFree(db, pTab);
}
| > > > > > > | 151399 151400 151401 151402 151403 151404 151405 151406 151407 151408 151409 151410 151411 151412 151413 151414 151415 151416 151417 151418 151419 151420 151421 151422 151423 151424 151425 151426 151427 151428 151429 151430 151431 151432 151433 |
pSub = sqlite3SelectNew(
pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
);
p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( p->pSrc ){
Table *pTab2;
Walker w;
p->pSrc->a[0].pSelect = pSub;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
pSub->selFlags |= SF_Expanded;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
pSub->selFlags |= (selFlags & SF_Aggregate);
if( pTab2==0 ){
/* Might actually be some other kind of error, but in that case
** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
** the correct error message regardless. */
rc = SQLITE_NOMEM;
}else{
memcpy(pTab, pTab2, sizeof(Table));
pTab->tabFlags |= TF_Ephemeral;
p->pSrc->a[0].pTab = pTab;
pTab = pTab2;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
w.xSelectCallback = sqlite3WalkerDepthIncrease;
w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
sqlite3WalkSelect(&w, pSub);
}
}else{
sqlite3SelectDelete(db, pSub);
}
if( db->mallocFailed ) rc = SQLITE_NOMEM;
sqlite3DbFree(db, pTab);
}
|
| ︙ | ︙ | |||
224736 224737 224738 224739 224740 224741 224742 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
| | | 224818 224819 224820 224821 224822 224823 224824 224825 224826 224827 224828 224829 224830 224831 224832 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350", -1, SQLITE_TRANSIENT);
}
/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
|
| ︙ | ︙ | |||
229519 229520 229521 229522 229523 229524 229525 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ | | | | 229601 229602 229603 229604 229605 229606 229607 229608 229609 229610 229611 229612 229613 229614 |
#endif
return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
#if __LINE__!=229608
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba8alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/
|
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
119 120 121 122 123 124 125 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** 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.32.1" #define SQLITE_VERSION_NUMBER 3032001 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350" /* ** 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 |
| ︙ | ︙ |
Changes to src/th_main.c.
| ︙ | ︙ | |||
1498 1499 1500 1501 1502 1503 1504 |
int *argl
){
if( argc!=3 ){
return Th_WrongNumArgs(interp, "unversioned content FILENAME");
}
if( Th_IsRepositoryOpen() ){
Blob content;
| | | 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 |
int *argl
){
if( argc!=3 ){
return Th_WrongNumArgs(interp, "unversioned content FILENAME");
}
if( Th_IsRepositoryOpen() ){
Blob content;
if( unversioned_content(argv[2], &content)!=0 ){
Th_SetResult(interp, blob_str(&content), blob_size(&content));
blob_reset(&content);
return TH_OK;
}else{
return TH_ERROR;
}
}else{
|
| ︙ | ︙ |
Changes to src/unversioned.c.
| ︙ | ︙ | |||
83 84 85 86 87 88 89 | } return zHash; } /* ** Initialize pContent to be the content of an unversioned file zName. ** | | > > | | > | > > > > > > > > > > > > | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
}
return zHash;
}
/*
** Initialize pContent to be the content of an unversioned file zName.
**
** Return 0 on failures.
** Return 1 if the file is found by name.
** Return 2 if the file is found by hash.
*/
int unversioned_content(const char *zName, Blob *pContent){
Stmt q;
int rc = 0;
blob_init(pContent, 0, 0);
db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE name=%Q",
zName);
if( db_step(&q)==SQLITE_ROW ){
db_column_blob(&q, 1, pContent);
if( db_column_int(&q, 0)==1 ){
blob_uncompress(pContent, pContent);
}
rc = 1;
}
db_finalize(&q);
if( rc==0 && validate16(zName,-1) ){
db_prepare(&q, "SELECT encoding, content FROM unversioned WHERE hash=%Q",
zName);
if( db_step(&q)==SQLITE_ROW ){
db_column_blob(&q, 1, pContent);
if( db_column_int(&q, 0)==1 ){
blob_uncompress(pContent, pContent);
}
rc = 2;
}
db_finalize(&q);
}
return rc;
}
/*
** Write unversioned content into the database.
*/
static void unversioned_write(
|
| ︙ | ︙ | |||
326 327 328 329 330 331 332 |
db_end_transaction(0);
}else if( memcmp(zCmd, "cat", nCmd)==0 ){
int i;
verify_all_options();
db_begin_transaction();
for(i=3; i<g.argc; i++){
Blob content;
| | | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
db_end_transaction(0);
}else if( memcmp(zCmd, "cat", nCmd)==0 ){
int i;
verify_all_options();
db_begin_transaction();
for(i=3; i<g.argc; i++){
Blob content;
if( unversioned_content(g.argv[i], &content)!=0 ){
blob_write_to_file(&content, "-");
}
blob_reset(&content);
}
db_end_transaction(0);
}else if( memcmp(zCmd, "edit", nCmd)==0 ){
const char *zEditor; /* Name of the text-editor command */
|
| ︙ | ︙ | |||
350 351 352 353 354 355 356 |
if( zEditor==0 ){
fossil_fatal("no text editor - set the VISUAL env variable");
}
zTFile = fossil_temp_filename();
if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
db_begin_transaction();
content_rcvid_init("#!fossil unversioned edit");
| | | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
if( zEditor==0 ){
fossil_fatal("no text editor - set the VISUAL env variable");
}
zTFile = fossil_temp_filename();
if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
db_begin_transaction();
content_rcvid_init("#!fossil unversioned edit");
if( unversioned_content(zUVFile, &content)==0 ){
fossil_fatal("no such uv-file: %Q", zUVFile);
}
if( looks_like_binary(&content) ){
fossil_fatal("cannot edit binary content");
}
#if defined(_WIN32) || defined(__CYGWIN__)
blob_add_cr(&content);
|
| ︙ | ︙ | |||
379 380 381 382 383 384 385 |
unversioned_write(zUVFile, &content, mtime);
db_end_transaction(0);
blob_reset(&content);
}else if( memcmp(zCmd, "export", nCmd)==0 ){
Blob content;
verify_all_options();
if( g.argc!=5 ) usage("export UVFILE OUTPUT");
| | | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
unversioned_write(zUVFile, &content, mtime);
db_end_transaction(0);
blob_reset(&content);
}else if( memcmp(zCmd, "export", nCmd)==0 ){
Blob content;
verify_all_options();
if( g.argc!=5 ) usage("export UVFILE OUTPUT");
if( unversioned_content(g.argv[3], &content)==0 ){
fossil_fatal("no such uv-file: %Q", g.argv[3]);
}
blob_write_to_file(&content, g.argv[4]);
blob_reset(&content);
}else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */
/* Show the hash value used during uv sync */
int debugFlag = find_option("debug",0,0)!=0;
|
| ︙ | ︙ |
Changes to www/changes.wiki.
1 2 3 | <title>Change Log</title> <a name='v2_11'></a> | > > > > > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<title>Change Log</title>
<a name='v2_12'></a>
<h2>Changes for Version 2.12 (pending)</h2>
* <i>(no changes yet...)</i>
<a name='v2_11'></a>
<h2>Changes for Version 2.11 (2020-05-25)</h2>
* Support [/md_rules|Markdown] in the default ticket configuration.
* Timestamp strings in [./checkin_names.wiki|object names]
can now omit punctation. So, for example, "202004181942" and
"2020-04-18 19:42" mean the same thing.
* Enhance backlink processing so that it works with Markdown-formatted
tickets and so that it works for wiki pages.
|
| ︙ | ︙ |