Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | merge trunk |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | svn-import |
| Files: | files | file ages | folders |
| SHA1: |
154abe4d478d6ed78147b031da2fd07c |
| User & Date: | baruch 2014-10-21 09:27:06.322 |
Context
|
2014-10-21
| ||
| 12:18 | fix manifest creation bugs check-in: ffd61eedf5 user: baruch tags: svn-import | |
| 09:27 | merge trunk check-in: 154abe4d47 user: baruch tags: svn-import | |
| 09:22 | Very very basic svn-dump import. Can not handle anything realistic yet check-in: 287cd78e27 user: baruch tags: svn-import | |
| 03:23 | Fix build break when the TH1 docs feature is enabled. check-in: 6d4e5d801e user: mistachkin tags: trunk | |
Changes
Changes to auto.def.
| ︙ | ︙ | |||
276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
if {[string match *mingw* [get-define host]]} {
define-append LIBS -lwsock32
}
}
cc-check-function-in-lib iconv iconv
cc-check-functions utime
cc-check-functions usleep
# Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE
if {![cc-check-functions getloadavg]} {
define FOSSIL_OMIT_LOAD_AVERAGE 1
msg-result "Load average support unavailable"
}
| > | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
if {[string match *mingw* [get-define host]]} {
define-append LIBS -lwsock32
}
}
cc-check-function-in-lib iconv iconv
cc-check-functions utime
cc-check-functions usleep
cc-check-functions strchrnul
# Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE
if {![cc-check-functions getloadavg]} {
define FOSSIL_OMIT_LOAD_AVERAGE 1
msg-result "Load average support unavailable"
}
|
| ︙ | ︙ |
Changes to src/allrepo.c.
| ︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 105 106 107 108 109 | ** caution should be exercised with this command because its ** effects cannot be undone. Use of the --dry-run option to ** carefully review the local checkouts to be operated upon ** and the --whatif option to carefully review the files to ** be deleted beforehand is highly recommended. The command ** line options supported by the clean command itself, if any ** are present, are passed along verbatim. ** ** extras Shows "extra" files from all local checkouts. The command ** line options supported by the extra command itself, if any ** are present, are passed along verbatim. ** ** ignore Arguments are repositories that should be ignored by ** subsequent clean, extras, list, pull, push, rebuild, and | > > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | ** caution should be exercised with this command because its ** effects cannot be undone. Use of the --dry-run option to ** carefully review the local checkouts to be operated upon ** and the --whatif option to carefully review the files to ** be deleted beforehand is highly recommended. The command ** line options supported by the clean command itself, if any ** are present, are passed along verbatim. ** ** dbstat Run the "dbstat" command on all repositories. ** ** extras Shows "extra" files from all local checkouts. The command ** line options supported by the extra command itself, if any ** are present, are passed along verbatim. ** ** ignore Arguments are repositories that should be ignored by ** subsequent clean, extras, list, pull, push, rebuild, and |
| ︙ | ︙ | |||
127 128 129 130 131 132 133 | ** --randomize options are not supported. ** ** sync Run a "sync" on all repositories. Only the --verbose ** option is supported. ** ** setting Run the "setting", "set", or "unset" commands on all ** set repositories. These command are particularly useful in | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | ** --randomize options are not supported. ** ** sync Run a "sync" on all repositories. Only the --verbose ** option is supported. ** ** setting Run the "setting", "set", or "unset" commands on all ** set repositories. These command are particularly useful in ** unset conjunction with the "max-loadavg" setting which cannot ** otherwise be set globally. ** ** Repositories are automatically added to the set of known repositories ** when one of the following commands are run against the repository: ** clone, info, pull, push, or sync. Even previously ignored repositories ** are added back to the list of repositories by these commands. ** |
| ︙ | ︙ | |||
188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
collect_argument(&extra, "force","f");
collect_argument_value(&extra, "ignore");
collect_argument_value(&extra, "keep");
collect_argument(&extra, "temp",0);
collect_argument(&extra, "verbose","v");
collect_argument(&extra, "whatif",0);
useCheckouts = 1;
}else if( strncmp(zCmd, "extras", n)==0 ){
if( showFile ){
zCmd = "extras --chdir";
}else{
zCmd = "extras --header --chdir";
}
collect_argument(&extra, "abs-paths",0);
| > > > > > > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
collect_argument(&extra, "force","f");
collect_argument_value(&extra, "ignore");
collect_argument_value(&extra, "keep");
collect_argument(&extra, "temp",0);
collect_argument(&extra, "verbose","v");
collect_argument(&extra, "whatif",0);
useCheckouts = 1;
}else if( strncmp(zCmd, "dbstat", n)==0 ){
zCmd = "dbstat --omit-version-info -R";
showLabel = 1;
quiet = 1;
collect_argument(&extra, "brief", "b");
collect_argument(&extra, "db-check", 0);
}else if( strncmp(zCmd, "extras", n)==0 ){
if( showFile ){
zCmd = "extras --chdir";
}else{
zCmd = "extras --header --chdir";
}
collect_argument(&extra, "abs-paths",0);
|
| ︙ | ︙ | |||
247 248 249 250 251 252 253 |
quiet = 1;
}else if( strncmp(zCmd, "ignore", n)==0 ){
int j;
useCheckouts = find_option("ckout","c",0)!=0;
verify_all_options();
db_begin_transaction();
for(j=3; j<g.argc; j++){
| | > > | | > | | | | 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 |
quiet = 1;
}else if( strncmp(zCmd, "ignore", n)==0 ){
int j;
useCheckouts = find_option("ckout","c",0)!=0;
verify_all_options();
db_begin_transaction();
for(j=3; j<g.argc; j++){
Blob sql;
blob_zero(&sql);
blob_append_sql(&sql,
"DELETE FROM global_config WHERE name GLOB '%s:%q'",
useCheckouts?"ckout":"repo", g.argv[j]
);
if( dryRunFlag ){
fossil_print("%s\n", blob_sql_text(&sql));
}else{
db_multi_exec("%s", blob_sql_text(&sql));
}
blob_reset(&sql);
}
db_end_transaction(0);
return;
}else if( strncmp(zCmd, "info", n)==0 ){
zCmd = "info";
showLabel = 1;
quiet = 1;
|
| ︙ | ︙ | |||
336 337 338 339 340 341 342 |
** be found, remove those names from the ~/.fossil file.
*/
if( nToDel>0 ){
const char *zSql = "DELETE FROM global_config WHERE name IN toDel";
if( dryRunFlag ){
fossil_print("%s\n", zSql);
}else{
| | | 347 348 349 350 351 352 353 354 355 356 357 |
** be found, remove those names from the ~/.fossil file.
*/
if( nToDel>0 ){
const char *zSql = "DELETE FROM global_config WHERE name IN toDel";
if( dryRunFlag ){
fossil_print("%s\n", zSql);
}else{
db_multi_exec("%s", zSql /*safe-for-%s*/ );
}
}
}
|
Changes to src/attach.c.
| ︙ | ︙ | |||
38 39 40 41 42 43 44 |
const char *zTkt = P("tkt");
Blob sql;
Stmt q;
if( zPage && zTkt ) zTkt = 0;
login_check_credentials();
blob_zero(&sql);
| | | | | | | 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 |
const char *zTkt = P("tkt");
Blob sql;
Stmt q;
if( zPage && zTkt ) zTkt = 0;
login_check_credentials();
blob_zero(&sql);
blob_append_sql(&sql,
"SELECT datetime(mtime%s), src, target, filename,"
" comment, user,"
" (SELECT uuid FROM blob WHERE rid=attachid), attachid"
" FROM attachment",
timeline_utc()
);
if( zPage ){
if( g.perm.RdWiki==0 ) login_needed();
style_header("Attachments To %h", zPage);
blob_append_sql(&sql, " WHERE target=%Q", zPage);
}else if( zTkt ){
if( g.perm.RdTkt==0 ) login_needed();
style_header("Attachments To Ticket %S", zTkt);
blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
}else{
if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ) login_needed();
style_header("All Attachments");
}
blob_append_sql(&sql, " ORDER BY mtime DESC");
db_prepare(&q, "%s", blob_sql_text(&sql));
@ <ol>
while( db_step(&q)==SQLITE_ROW ){
const char *zDate = db_column_text(&q, 0);
const char *zSrc = db_column_text(&q, 1);
const char *zTarget = db_column_text(&q, 2);
const char *zFilename = db_column_text(&q, 3);
const char *zComment = db_column_text(&q, 4);
|
| ︙ | ︙ | |||
375 376 377 378 379 380 381 |
rid = name_to_rid_www("name");
if( rid==0 ){ fossil_redirect_home(); }
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
#if 0
/* Shunning here needs to get both the attachment control artifact and
** the object that is attached. */
if( g.perm.Admin ){
| | | | | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
rid = name_to_rid_www("name");
if( rid==0 ){ fossil_redirect_home(); }
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
#if 0
/* Shunning here needs to get both the attachment control artifact and
** the object that is attached. */
if( g.perm.Admin ){
if( db_exists("SELECT 1 FROM shun WHERE uuid='%q'", zUuid) ){
style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
g.zTop, zUuid);
}else{
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
g.zTop, zUuid);
}
}
#endif
pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0);
if( pAttach==0 ) fossil_redirect_home();
zTarget = pAttach->zAttachTarget;
zSrc = pAttach->zAttachSrc;
ridSrc = db_int(0,"SELECT rid FROM blob WHERE uuid='%q'", zSrc);
zName = pAttach->zAttachName;
zDesc = pAttach->zComment;
zMime = mimetype_from_name(zName);
fShowContent = zMime ? strncmp(zMime,"text/", 5)==0 : 0;
if( validate16(zTarget, strlen(zTarget))
&& db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget)
){
zTktUuid = zTarget;
if( !g.perm.RdTkt ){ login_needed(); return; }
if( g.perm.WrTkt ){
style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
}
}else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){
|
| ︙ | ︙ |
Changes to src/blob.c.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
** A Blob can hold a string or a binary object of arbitrary size. The
** size changes as necessary.
*/
struct Blob {
unsigned int nUsed; /* Number of bytes used in aData[] */
unsigned int nAlloc; /* Number of bytes allocated for aData[] */
unsigned int iCursor; /* Next character of input to parse */
char *aData; /* Where the information is stored */
void (*xRealloc)(Blob*, unsigned int); /* Function to reallocate the buffer */
};
/*
** The current size of a Blob
*/
#define blob_size(X) ((X)->nUsed)
/*
** The buffer holding the blob data
| > > > > > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
** A Blob can hold a string or a binary object of arbitrary size. The
** size changes as necessary.
*/
struct Blob {
unsigned int nUsed; /* Number of bytes used in aData[] */
unsigned int nAlloc; /* Number of bytes allocated for aData[] */
unsigned int iCursor; /* Next character of input to parse */
unsigned int blobFlags; /* One or more BLOBFLAG_* bits */
char *aData; /* Where the information is stored */
void (*xRealloc)(Blob*, unsigned int); /* Function to reallocate the buffer */
};
/*
** Allowed values for Blob.blobFlags
*/
#define BLOBFLAG_NotSQL 0x0001 /* Non-SQL text */
/*
** The current size of a Blob
*/
#define blob_size(X) ((X)->nUsed)
/*
** The buffer holding the blob data
|
| ︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
void blobReallocMalloc(Blob *pBlob, unsigned int newSize){
if( newSize==0 ){
free(pBlob->aData);
pBlob->aData = 0;
pBlob->nAlloc = 0;
pBlob->nUsed = 0;
pBlob->iCursor = 0;
}else if( newSize>pBlob->nAlloc || newSize<pBlob->nAlloc-4000 ){
char *pNew = fossil_realloc(pBlob->aData, newSize);
pBlob->aData = pNew;
pBlob->nAlloc = newSize;
if( pBlob->nUsed>pBlob->nAlloc ){
pBlob->nUsed = pBlob->nAlloc;
}
}
}
/*
** An initializer for Blobs
*/
#if INTERFACE
| > | | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
void blobReallocMalloc(Blob *pBlob, unsigned int newSize){
if( newSize==0 ){
free(pBlob->aData);
pBlob->aData = 0;
pBlob->nAlloc = 0;
pBlob->nUsed = 0;
pBlob->iCursor = 0;
pBlob->blobFlags = 0;
}else if( newSize>pBlob->nAlloc || newSize<pBlob->nAlloc-4000 ){
char *pNew = fossil_realloc(pBlob->aData, newSize);
pBlob->aData = pNew;
pBlob->nAlloc = newSize;
if( pBlob->nUsed>pBlob->nAlloc ){
pBlob->nUsed = pBlob->nAlloc;
}
}
}
/*
** An initializer for Blobs
*/
#if INTERFACE
#define BLOB_INITIALIZER {0,0,0,0,0,blobReallocMalloc}
#endif
const Blob empty_blob = BLOB_INITIALIZER;
/*
** A reallocation function for when the initial string is in unmanaged
** space. Copy the string to memory obtained from malloc().
*/
|
| ︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
if( zData==0 ){
*pBlob = empty_blob;
}else{
if( size<=0 ) size = strlen(zData);
pBlob->nUsed = pBlob->nAlloc = size;
pBlob->aData = (char*)zData;
pBlob->iCursor = 0;
pBlob->xRealloc = blobReallocStatic;
}
}
/*
** Initialize a blob to a nul-terminated string.
** Any prior data in the blob is discarded.
| > | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
if( zData==0 ){
*pBlob = empty_blob;
}else{
if( size<=0 ) size = strlen(zData);
pBlob->nUsed = pBlob->nAlloc = size;
pBlob->aData = (char*)zData;
pBlob->iCursor = 0;
pBlob->blobFlags = 0;
pBlob->xRealloc = blobReallocStatic;
}
}
/*
** Initialize a blob to a nul-terminated string.
** Any prior data in the blob is discarded.
|
| ︙ | ︙ | |||
246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
void blob_zero(Blob *pBlob){
static const char zEmpty[] = "";
assert_blob_is_reset(pBlob);
pBlob->nUsed = 0;
pBlob->nAlloc = 1;
pBlob->aData = (char*)zEmpty;
pBlob->iCursor = 0;
pBlob->xRealloc = blobReallocStatic;
}
/*
** Append text or data to the end of a blob.
*/
void blob_append(Blob *pBlob, const char *aData, int nData){
| > | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
void blob_zero(Blob *pBlob){
static const char zEmpty[] = "";
assert_blob_is_reset(pBlob);
pBlob->nUsed = 0;
pBlob->nAlloc = 1;
pBlob->aData = (char*)zEmpty;
pBlob->iCursor = 0;
pBlob->blobFlags = 0;
pBlob->xRealloc = blobReallocStatic;
}
/*
** Append text or data to the end of a blob.
*/
void blob_append(Blob *pBlob, const char *aData, int nData){
|
| ︙ | ︙ | |||
290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
p->nUsed = 0;
}
if( p->aData[p->nUsed]!=0 ){
blob_materialize(p);
}
return p->aData;
}
/*
** Return a pointer to a null-terminated string for a blob.
**
** WARNING: If the blob is ephemeral, it might cause a '\000'
** character to be inserted into the middle of the parent blob.
** Example: Suppose p is a token extracted from some larger
| > > > > > > > > > > > > > > | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
p->nUsed = 0;
}
if( p->aData[p->nUsed]!=0 ){
blob_materialize(p);
}
return p->aData;
}
/*
** Return a pointer to a null-terminated string for a blob that has
** been created using blob_append_sql() and not blob_appendf(). If
** text was ever added using blob_appendf() then throw an error.
*/
char *blob_sql_text(Blob *p){
blob_is_init(p);
if( (p->blobFlags & BLOBFLAG_NotSQL) ){
fossil_fatal("Internal error: Use of blob_appendf() to construct SQL text");
}
return blob_str(p);
}
/*
** Return a pointer to a null-terminated string for a blob.
**
** WARNING: If the blob is ephemeral, it might cause a '\000'
** character to be inserted into the middle of the parent blob.
** Example: Suppose p is a token extracted from some larger
|
| ︙ | ︙ | |||
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 |
int i;
for(i=0; i<nToken && blob_token(pIn, &aToken[i]); i++){}
return i;
}
/*
** Do printf-style string rendering and append the results to a blob.
*/
void blob_appendf(Blob *pBlob, const char *zFormat, ...){
if( pBlob ){
va_list ap;
va_start(ap, zFormat);
vxprintf(pBlob, zFormat, ap);
va_end(ap);
}
}
void blob_vappendf(Blob *pBlob, const char *zFormat, va_list ap){
| > > > > > > > > > > > > | 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
int i;
for(i=0; i<nToken && blob_token(pIn, &aToken[i]); i++){}
return i;
}
/*
** Do printf-style string rendering and append the results to a blob.
**
** The blob_appendf() version sets the BLOBFLAG_NotSQL bit in Blob.blobFlags
** whereas blob_append_sql() does not.
*/
void blob_appendf(Blob *pBlob, const char *zFormat, ...){
if( pBlob ){
va_list ap;
va_start(ap, zFormat);
vxprintf(pBlob, zFormat, ap);
va_end(ap);
pBlob->blobFlags |= BLOBFLAG_NotSQL;
}
}
void blob_append_sql(Blob *pBlob, const char *zFormat, ...){
if( pBlob ){
va_list ap;
va_start(ap, zFormat);
vxprintf(pBlob, zFormat, ap);
va_end(ap);
}
}
void blob_vappendf(Blob *pBlob, const char *zFormat, va_list ap){
|
| ︙ | ︙ |
Changes to src/branch.c.
| ︙ | ︙ | |||
298 299 300 301 302 303 304 |
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
if( colorTest ){
showClosed = 0;
showAll = 1;
}
| | | | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
if( colorTest ){
showClosed = 0;
showAll = 1;
}
style_header("%s", showClosed ? "Closed Branches" :
showAll ? "All Branches" : "Open Branches");
style_submenu_element("Timeline", "Timeline", "brtimeline");
if( showClosed ){
style_submenu_element("All", "All", "brlist?all");
style_submenu_element("Open","Open","brlist");
}else if( showAll ){
style_submenu_element("Closed", "Closed", "brlist?closed");
style_submenu_element("Open","Open","brlist");
|
| ︙ | ︙ |
Changes to src/browse.c.
| ︙ | ︙ | |||
757 758 759 760 761 762 763 |
if( pManifest==0 ) return 1;
manifest_file_rewind(pManifest);
db_prepare(&ins,
"INSERT INTO temp.fileage(fid, pathname)"
" SELECT rid, :path FROM blob WHERE uuid=:uuid"
);
while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
| | | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
if( pManifest==0 ) return 1;
manifest_file_rewind(pManifest);
db_prepare(&ins,
"INSERT INTO temp.fileage(fid, pathname)"
" SELECT rid, :path FROM blob WHERE uuid=:uuid"
);
while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue;
db_bind_text(&ins, ":uuid", pFile->zUuid);
db_bind_text(&ins, ":path", pFile->zName);
db_step(&ins);
db_reset(&ins);
nFile++;
}
db_finalize(&ins);
|
| ︙ | ︙ | |||
826 827 828 829 830 831 832 |
zName = P("name");
if( zName==0 ) zName = "tip";
rid = symbolic_name_to_rid(zName, "ci");
if( rid==0 ){
fossil_fatal("not a valid check-in: %s", zName);
}
style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName);
| | | 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 |
zName = P("name");
if( zName==0 ) zName = "tip";
rid = symbolic_name_to_rid(zName, "ci");
if( rid==0 ){
fossil_fatal("not a valid check-in: %s", zName);
}
style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName);
style_header("File Ages");
zGlob = P("glob");
compute_fileage(rid,zGlob);
baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc());
@ <h2>File Ages For Check-in
@ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
@
|
| ︙ | ︙ |
Changes to src/cache.c.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
}
rc = sqlite3_open(zDbName, &db);
fossil_free(zDbName);
if( rc ){
sqlite3_close(db);
return 0;
}
| | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
}
rc = sqlite3_open(zDbName, &db);
fossil_free(zDbName);
if( rc ){
sqlite3_close(db);
return 0;
}
rc = sqlite3_exec(db,
"PRAGMA page_size=8192;"
"CREATE TABLE IF NOT EXISTS blob(id INTEGER PRIMARY KEY, data BLOB);"
"CREATE TABLE IF NOT EXISTS cache("
"key TEXT PRIMARY KEY," /* Key used to access the cache */
"id INT REFERENCES blob," /* The cache content */
"sz INT," /* Size of content in bytes */
"tm INT," /* Last access time (unix timestampe) */
|
| ︙ | ︙ | |||
92 93 94 95 96 97 98 |
int rc;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ){
sqlite3_finalize(pStmt);
pStmt = 0;
}
| | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
int rc;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ){
sqlite3_finalize(pStmt);
pStmt = 0;
}
return pStmt;
}
/*
** This routine implements an SQL function that renders a large integer
** compactly: ex: 12.3MB
*/
static void cache_sizename(
|
| ︙ | ︙ | |||
151 152 153 154 155 156 157 |
sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0);
pStmt = cacheStmt(db, "INSERT INTO blob(data) VALUES(?1)");
if( pStmt==0 ) goto cache_write_end;
sqlite3_bind_blob(pStmt, 1, blob_buffer(pContent), blob_size(pContent),
SQLITE_STATIC);
if( sqlite3_step(pStmt)!=SQLITE_DONE ) goto cache_write_end;
sqlite3_finalize(pStmt);
| | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0);
pStmt = cacheStmt(db, "INSERT INTO blob(data) VALUES(?1)");
if( pStmt==0 ) goto cache_write_end;
sqlite3_bind_blob(pStmt, 1, blob_buffer(pContent), blob_size(pContent),
SQLITE_STATIC);
if( sqlite3_step(pStmt)!=SQLITE_DONE ) goto cache_write_end;
sqlite3_finalize(pStmt);
pStmt = cacheStmt(db,
"INSERT OR IGNORE INTO cache(key,sz,tm,nref,id)"
"VALUES(?1,?2,strftime('%s','now'),1,?3)"
);
if( pStmt==0 ) goto cache_write_end;
sqlite3_bind_text(pStmt, 1, zKey, -1, SQLITE_STATIC);
sqlite3_bind_int(pStmt, 2, blob_size(pContent));
sqlite3_bind_int(pStmt, 3, sqlite3_last_insert_rowid(db));
|
| ︙ | ︙ | |||
200 201 202 203 204 205 206 | sqlite3_stmt *pStmt; int rc = 0; db = cacheOpen(0); if( db==0 ) return 0; sqlite3_busy_timeout(db, 10000); sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0); | | | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
sqlite3_stmt *pStmt;
int rc = 0;
db = cacheOpen(0);
if( db==0 ) return 0;
sqlite3_busy_timeout(db, 10000);
sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, 0);
pStmt = cacheStmt(db,
"SELECT blob.data FROM cache, blob"
" WHERE cache.key=?1 AND cache.id=blob.id");
if( pStmt==0 ) goto cache_read_done;
sqlite3_bind_text(pStmt, 1, zKey, -1, SQLITE_STATIC);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
blob_append(pContent, sqlite3_column_blob(pStmt, 0),
sqlite3_column_bytes(pStmt, 0));
rc = 1;
sqlite3_reset(pStmt);
pStmt = cacheStmt(db,
"UPDATE cache SET nref=nref+1, tm=strftime('%s','now')"
" WHERE key=?1");
if( pStmt ){
sqlite3_bind_text(pStmt, 1, zKey, -1, SQLITE_STATIC);
sqlite3_step(pStmt);
}
}
sqlite3_finalize(pStmt);
cache_read_done:
sqlite3_exec(db, "COMMIT", 0, 0, 0);
sqlite3_close(db);
return rc;
}
|
| ︙ | ︙ | |||
254 255 256 257 258 259 260 | int nCmd; sqlite3 *db; sqlite3_stmt *pStmt; db_find_and_open_repository(0,0); zCmd = g.argc>=3 ? g.argv[2] : ""; nCmd = (int)strlen(zCmd); | | | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
int nCmd;
sqlite3 *db;
sqlite3_stmt *pStmt;
db_find_and_open_repository(0,0);
zCmd = g.argc>=3 ? g.argv[2] : "";
nCmd = (int)strlen(zCmd);
if( nCmd<=1 ){
fossil_fatal("Usage: %s cache SUBCOMMAND", g.argv[0]);
}
if( strncmp(zCmd, "init", nCmd)==0 ){
db = cacheOpen(0);
sqlite3_close(db);
if( db ){
fossil_print("cache already exists in file %z\n", cacheName());
|
| ︙ | ︙ | |||
288 289 290 291 292 293 294 |
db = cacheOpen(0);
if( db==0 ){
fossil_print("cache does not exist\n");
}else{
int nEntry = 0;
char *zDbName = cacheName();
cache_register_sizename(db);
| | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
db = cacheOpen(0);
if( db==0 ){
fossil_print("cache does not exist\n");
}else{
int nEntry = 0;
char *zDbName = cacheName();
cache_register_sizename(db);
pStmt = cacheStmt(db,
"SELECT key, sizename(sz), nRef, datetime(tm,'unixepoch')"
" FROM cache"
" ORDER BY tm DESC"
);
if( pStmt ){
while( sqlite3_step(pStmt)==SQLITE_ROW ){
fossil_print("%s %4d %8s %s\n",
|
| ︙ | ︙ | |||
336 337 338 339 340 341 342 |
style_header("Web Cache Status");
db = cacheOpen(0);
if( db==0 ){
@ The web-page cache is disabled for this repository
}else{
char *zDbName = cacheName();
cache_register_sizename(db);
| | | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
style_header("Web Cache Status");
db = cacheOpen(0);
if( db==0 ){
@ The web-page cache is disabled for this repository
}else{
char *zDbName = cacheName();
cache_register_sizename(db);
pStmt = cacheStmt(db,
"SELECT key, sizename(sz), nRef, datetime(tm,'unixepoch')"
" FROM cache"
" ORDER BY tm DESC"
);
if( pStmt ){
@ <ol>
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
| ︙ | ︙ |
Changes to src/cgi.c.
| ︙ | ︙ | |||
275 276 277 278 279 280 281 |
/*
** Return true if the response should be sent with Content-Encoding: gzip.
*/
static int is_gzippable(void){
if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
return strncmp(zContentType, "text/", 5)==0
| | | | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
/*
** Return true if the response should be sent with Content-Encoding: gzip.
*/
static int is_gzippable(void){
if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
return strncmp(zContentType, "text/", 5)==0
|| sqlite3_strglob("application/*xml", zContentType)==0
|| sqlite3_strglob("application/*javascript", zContentType)==0;
}
/*
** Do a normal HTTP reply
*/
void cgi_reply(void){
int total_size;
|
| ︙ | ︙ | |||
1710 1711 1712 1713 1714 1715 1716 |
}
if( iPort>mxPort ) return 1;
listen(listener,10);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
fflush(stdout);
if( zBrowser ){
| > | | 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 |
}
if( iPort>mxPort ) return 1;
listen(listener,10);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
fflush(stdout);
if( zBrowser ){
assert( strstr(zBrowser,"%d")!=0 );
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
#if defined(__CYGWIN__)
/* On Cygwin, we can do better than "echo" */
if( strncmp(zBrowser, "echo ", 5)==0 ){
wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
if( (size_t)ShellExecuteW(0, L"open", wUrl, 0, 0, 1)<33 ){
fossil_warning("cannot start browser\n");
|
| ︙ | ︙ |
Changes to src/checkin.c.
| ︙ | ︙ | |||
50 51 52 53 54 55 56 |
Blob fname;
file_tree_name(g.argv[i], &fname, 1);
zName = blob_str(&fname);
if( fossil_strcmp(zName, ".")==0 ) {
blob_reset(&where);
break;
}
| > | | | | | > | | 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 |
Blob fname;
file_tree_name(g.argv[i], &fname, 1);
zName = blob_str(&fname);
if( fossil_strcmp(zName, ".")==0 ) {
blob_reset(&where);
break;
}
blob_append_sql(&where,
" %s (pathname=%Q %s) "
"OR (pathname>'%q/' %s AND pathname<'%q0' %s)",
(blob_size(&where)>0) ? "OR" : "AND", zName,
filename_collation(), zName, filename_collation(),
zName, filename_collation()
);
}
db_prepare(&q,
"SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
" FROM vfile "
" WHERE is_selected(id) %s"
" AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1",
blob_sql_text(&where)
);
blob_zero(&rewrittenPathname);
while( db_step(&q)==SQLITE_ROW ){
const char *zPathname = db_column_text(&q,0);
const char *zDisplayName = zPathname;
int isDeleted = db_column_int(&q, 1);
int isChnged = db_column_int(&q,2);
|
| ︙ | ︙ | |||
311 312 313 314 315 316 317 |
Blob fname;
file_tree_name(g.argv[i], &fname, 1);
zName = blob_str(&fname);
if( fossil_strcmp(zName, ".")==0 ) {
blob_reset(&where);
break;
}
| > | | | | | > | > | | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
Blob fname;
file_tree_name(g.argv[i], &fname, 1);
zName = blob_str(&fname);
if( fossil_strcmp(zName, ".")==0 ) {
blob_reset(&where);
break;
}
blob_append_sql(&where,
" %s (pathname=%Q %s) "
"OR (pathname>'%q/' %s AND pathname<'%q0' %s)",
(blob_size(&where)>0) ? "OR" : "WHERE", zName,
filename_collation(), zName, filename_collation(),
zName, filename_collation()
);
}
vfile_check_signature(vid, 0);
if( showAge ){
db_prepare(&q,
"SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0),"
" datetime(checkin_mtime(%d,rid),'unixepoch'%s)"
" FROM vfile %s"
" ORDER BY %s",
vid, timeline_utc(), blob_sql_text(&where), zOrderBy /*safe-for-%s*/
);
}else{
db_prepare(&q,
"SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
" FROM vfile %s"
" ORDER BY %s", blob_sql_text(&where), zOrderBy /*safe-for-%s*/
);
}
blob_reset(&where);
while( db_step(&q)==SQLITE_ROW ){
const char *zPathname = db_column_text(&q,0);
int isDeleted = db_column_int(&q, 1);
int isNew = db_column_int(&q,2)==0;
|
| ︙ | ︙ | |||
906 907 908 909 910 911 912 |
int select_commit_files(void){
int result = 0;
assert( g.aCommitFile==0 );
if( g.argc>2 ){
int ii, jj=0;
Blob fname;
Stmt q;
| < < | | | 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 |
int select_commit_files(void){
int result = 0;
assert( g.aCommitFile==0 );
if( g.argc>2 ){
int ii, jj=0;
Blob fname;
Stmt q;
Bag toCommit;
blob_zero(&fname);
bag_init(&toCommit);
for(ii=2; ii<g.argc; ii++){
int cnt = 0;
file_tree_name(g.argv[ii], &fname, 1);
if( fossil_strcmp(blob_str(&fname),".")==0 ){
bag_clear(&toCommit);
return result;
}
db_prepare(&q,
"SELECT id FROM vfile WHERE pathname=%Q %s"
" OR (pathname>'%q/' %s AND pathname<'%q0' %s)",
blob_str(&fname), filename_collation(), blob_str(&fname),
filename_collation(), blob_str(&fname), filename_collation());
while( db_step(&q)==SQLITE_ROW ){
cnt++;
bag_insert(&toCommit, db_column_int(&q, 0));
}
db_finalize(&q);
if( cnt==0 ){
fossil_warning("fossil knows nothing about: %s", g.argv[ii]);
|
| ︙ | ︙ |
Changes to src/checkout.c.
| ︙ | ︙ | |||
58 59 60 61 62 63 64 |
*/
int load_vfile(const char *zName, int forceMissingFlag){
Blob uuid;
int vid;
blob_init(&uuid, zName, -1);
if( name_to_uuid(&uuid, 1, "ci") ){
| | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
*/
int load_vfile(const char *zName, int forceMissingFlag){
Blob uuid;
int vid;
blob_init(&uuid, zName, -1);
if( name_to_uuid(&uuid, 1, "ci") ){
fossil_fatal("%s", g.zErrMsg);
}
vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
if( vid==0 ){
fossil_fatal("no such check-in: %s", g.argv[2]);
}
if( !is_a_version(vid) ){
fossil_fatal("object [%S] is not a check-in", blob_str(&uuid));
|
| ︙ | ︙ |
Added src/codecheck1.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
/*
** Copyright (c) 2014 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This program reads Fossil source code files and tries to verify that
** printf-style format strings are correct.
**
** This program implements a compile-time validation step on the Fossil
** source code. Running this program is entirely optional. Its role is
** similar to the -Wall compiler switch on gcc, or the scan-build utility
** of clang, or other static analyzers. The purpose is to try to identify
** problems in the source code at compile-time. The difference is that this
** static checker is specifically designed for the particular printf formatter
** implementation used by Fossil.
**
** Checks include:
**
** * Verify that vararg formatting routines like blob_printf() or
** db_multi_exec() have the correct number of arguments for their
** format string.
**
** * For routines designed to generate SQL, warn about the use of %s
** which might allow SQL injection.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
/*
** Malloc, aborting if it fails.
*/
void *safe_malloc(int nByte){
void *x = malloc(nByte);
if( x==0 ){
fprintf(stderr, "failed to allocate %d bytes\n", nByte);
exit(1);
}
return x;
}
void *safe_realloc(void *pOld, int nByte){
void *x = realloc(pOld, nByte);
if( x==0 ){
fprintf(stderr, "failed to allocate %d bytes\n", nByte);
exit(1);
}
return x;
}
/*
** Read the entire content of the file named zFilename into memory obtained
** from malloc(). Add a zero-terminator to the end.
** Return a pointer to that memory.
*/
static char *read_file(const char *zFilename){
FILE *in;
char *z;
int nByte;
int got;
in = fopen(zFilename, "rb");
if( in==0 ){
return 0;
}
fseek(in, 0, SEEK_END);
nByte = ftell(in);
fseek(in, 0, SEEK_SET);
z = safe_malloc( nByte+1 );
got = fread(z, 1, nByte, in);
z[got] = 0;
fclose(in);
return z;
}
/*
** When parsing the input file, the following token types are recognized.
*/
#define TK_SPACE 1 /* Whitespace or comments */
#define TK_ID 2 /* An identifier */
#define TK_STR 3 /* A string literal in double-quotes */
#define TK_OTHER 4 /* Any other token */
#define TK_EOF 99 /* End of file */
/*
** Determine the length and type of the token beginning at z[0]
*/
static int token_length(const char *z, int *pType, int *pLN){
int i;
if( z[0]==0 ){
*pType = TK_EOF;
return 0;
}
if( z[0]=='"' || z[0]=='\'' ){
for(i=1; z[i] && z[i]!=z[0]; i++){
if( z[i]=='\\' && z[i+1]!=0 ){
if( z[i+1]=='\n' ) (*pLN)++;
i++;
}
}
if( z[i]!=0 ) i++;
*pType = z[0]=='"' ? TK_STR : TK_OTHER;
return i;
}
if( isalnum(z[0]) || z[0]=='_' ){
for(i=1; isalnum(z[i]) || z[i]=='_'; i++){}
*pType = isalpha(z[0]) || z[0]=='_' ? TK_ID : TK_OTHER;
return i;
}
if( isspace(z[0]) ){
if( z[0]=='\n' ) (*pLN)++;
for(i=1; isspace(z[i]); i++){
if( z[i]=='\n' ) (*pLN)++;
}
*pType = TK_SPACE;
return i;
}
if( z[0]=='/' && z[1]=='*' ){
for(i=2; z[i] && (z[i]!='*' || z[i+1]!='/'); i++){
if( z[i]=='\n' ) (*pLN)++;
}
if( z[i] ) i += 2;
*pType = TK_SPACE;
return i;
}
if( z[0]=='/' && z[1]=='/' ){
for(i=2; z[i] && z[i]!='\n'; i++){}
if( z[i] ){
(*pLN)++;
i++;
}
*pType = TK_SPACE;
return i;
}
*pType = TK_OTHER;
return 1;
}
/*
** Return the next non-whitespace token
*/
const char *next_non_whitespace(const char *z, int *pLen, int *pType){
int len;
int eType;
int ln = 0;
while( (len = token_length(z, &eType, &ln))>0 && eType==TK_SPACE ){
z += len;
}
*pLen = len;
*pType = eType;
return z;
}
/*
** Return index into z[] for the first balanced TK_OTHER token with
** value cValue.
*/
static int distance_to(const char *z, char cVal){
int len;
int dist = 0;
int eType;
int nNest = 0;
int ln = 0;
while( z[0] && (len = token_length(z, &eType, &ln))>0 ){
if( eType==TK_OTHER ){
if( z[0]==cVal && nNest==0 ){
break;
}else if( z[0]=='(' ){
nNest++;
}else if( z[0]==')' ){
nNest--;
}
}
dist += len;
z += len;
}
return dist;
}
/*
** Return the first non-whitespace characters in z[]
*/
static const char *skip_space(const char *z){
while( isspace(z[0]) ){ z++; }
return z;
}
/*
** Return true if the input is a string literal.
*/
static int is_string_lit(const char *z){
int nu1, nu2;
z = next_non_whitespace(z, &nu1, &nu2);
return z[0]=='"';
}
/*
** Return true if the input is an expression of string literals:
**
** EXPR ? "..." : "..."
*/
static int is_string_expr(const char *z){
int len = 0, eType;
const char *zOrig = z;
len = distance_to(z, '?');
if( z[len]==0 && skip_space(z)[0]=='(' ){
z = skip_space(z) + 1;
len = distance_to(z, '?');
}
z += len;
if( z[0]=='?' ){
z++;
z = next_non_whitespace(z, &len, &eType);
if( eType==TK_STR ){
z += len;
z = next_non_whitespace(z, &len, &eType);
if( eType==TK_OTHER && z[0]==':' ){
z += len;
z = next_non_whitespace(z, &len, &eType);
if( eType==TK_STR ){
z += len;
z = next_non_whitespace(z, &len, &eType);
if( eType==TK_EOF ) return 1;
if( eType==TK_OTHER && z[0]==')' && skip_space(zOrig)[0]=='(' ){
z += len;
z = next_non_whitespace(z, &len, &eType);
if( eType==TK_EOF ) return 1;
}
}
}
}
}
return 0;
}
/*
** A list of functions that return strings that are safe to insert into
** SQL using %s.
*/
static const char *azSafeFunc[] = {
"filename_collation",
"db_name",
"timeline_utc",
"leaf_is_closed_sql",
"timeline_query_for_www",
"timeline_query_for_tty",
"blob_sql_text",
"glob_expr",
"fossil_all_reserved_names",
"configure_inop_rhs",
"db_setting_inop_rhs",
};
/*
** Return true if the input is an argument that is safe to use with %s
** while building an SQL statement.
*/
static int is_s_safe(const char *z){
int len, eType;
int i;
/* A string literal is safe for use with %s */
if( is_string_lit(z) ) return 1;
/* Certain functions are guaranteed to return a string that is safe
** for use with %s */
z = next_non_whitespace(z, &len, &eType);
for(i=0; i<sizeof(azSafeFunc)/sizeof(azSafeFunc[0]); i++){
if( eType==TK_ID
&& strncmp(z, azSafeFunc[i], len)==0
&& strlen(azSafeFunc[i])==len
){
return 1;
}
}
/* Expressions of the form: EXPR ? "..." : "...." can count as
** a string literal. */
if( is_string_expr(z) ) return 1;
/* If the "safe-for-%s" comment appears in the argument, then
** let it through */
if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1;
return 0;
}
/*
** Processing flags
*/
#define FMT_NO_S 0x00001 /* Do not allow %s substitutions */
/*
** A list of internal Fossil interfaces that take a printf-style format
** string.
*/
struct {
const char *zFName; /* Name of the function */
int iFmtArg; /* Index of format argument. Leftmost is 1. */
unsigned fmtFlags; /* Processing flags */
} aFmtFunc[] = {
{ "blob_append_sql", 2, FMT_NO_S },
{ "blob_appendf", 2, 0 },
{ "cgi_panic", 1, 0 },
{ "cgi_redirectf", 1, 0 },
{ "db_blob", 2, FMT_NO_S },
{ "db_double", 2, FMT_NO_S },
{ "db_err", 1, 0 },
{ "db_exists", 1, FMT_NO_S },
{ "db_int", 2, FMT_NO_S },
{ "db_int64", 2, FMT_NO_S },
{ "db_multi_exec", 1, FMT_NO_S },
{ "db_optional_sql", 2, FMT_NO_S },
{ "db_prepare", 2, FMT_NO_S },
{ "db_prepare_ignore_error", 2, FMT_NO_S },
{ "db_static_prepare", 2, FMT_NO_S },
{ "db_text", 2, FMT_NO_S },
{ "form_begin", 2, 0 },
{ "fossil_error", 2, 0 },
{ "fossil_errorlog", 1, 0 },
{ "fossil_fatal", 1, 0 },
{ "fossil_fatal_recursive", 1, 0 },
{ "fossil_panic", 1, 0 },
{ "fossil_print", 1, 0 },
{ "fossil_trace", 1, 0 },
{ "fossil_warning", 1, 0 },
{ "href", 1, 0 },
{ "json_new_string_f", 1, 0 },
{ "mprintf", 1, 0 },
{ "socket_set_errmsg", 1, 0 },
{ "ssl_set_errmsg", 1, 0 },
{ "style_header", 1, 0 },
{ "style_set_current_page", 1, 0 },
{ "webpage_error", 1, 0 },
{ "xhref", 2, 0 },
};
/*
** Determine if the indentifier zIdent of length nIndent is a Fossil
** internal interface that uses a printf-style argument. Return zero if not.
** Return the index of the format string if true with the left-most
** argument having an index of 1.
*/
static int isFormatFunc(const char *zIdent, int nIdent, unsigned *pFlags){
int upr, lwr;
lwr = 0;
upr = sizeof(aFmtFunc)/sizeof(aFmtFunc[0]) - 1;
while( lwr<=upr ){
unsigned x = (lwr + upr)/2;
int c = strncmp(zIdent, aFmtFunc[x].zFName, nIdent);
if( c==0 ){
if( aFmtFunc[x].zFName[nIdent]==0 ){
*pFlags = aFmtFunc[x].fmtFlags;
return aFmtFunc[x].iFmtArg;
}
c = -1;
}
if( c<0 ){
upr = x - 1;
}else{
lwr = x + 1;
}
}
*pFlags = 0;
return 0;
}
/*
** Return the expected number of arguments for the format string.
** Return -1 if the value cannot be computed.
**
** For each argument less than nType, store the conversion character
** for that argument in cType[i].
*/
static int formatArgCount(const char *z, int nType, char *cType){
int nArg = 0;
int i, k;
int len;
int eType;
int ln = 0;
while( z[0] ){
len = token_length(z, &eType, &ln);
if( eType==TK_STR ){
for(i=1; i<len-1; i++){
if( z[i]!='%' ) continue;
if( z[i+1]=='%' ){ i++; continue; }
for(k=i+1; k<len && !isalpha(z[k]); k++){
if( z[k]=='*' || z[k]=='#' ){
if( nArg<nType ) cType[nArg] = z[k];
nArg++;
}
}
if( z[k]!='R' ){
if( nArg<nType ) cType[nArg] = z[k];
nArg++;
}
}
}
z += len;
}
return nArg;
}
/*
** The function call that begins at zFCall[0] (which is on line lnFCall of the
** original file) is a function that uses a printf-style format string
** on argument number fmtArg. It has processings flags fmtFlags. Do
** compile-time checking on this function, output any errors, and return
** the number of errors.
*/
static int checkFormatFunc(
const char *zFilename, /* Name of the file being processed */
const char *zFCall, /* Pointer to start of function call */
int lnFCall, /* Line number that holds z[0] */
int fmtArg, /* Format string should be this argument */
int fmtFlags /* Extra processing flags */
){
int szFName;
int eToken;
int ln = lnFCall;
int len;
const char *zStart;
char *z;
char *zCopy;
int nArg = 0;
char const **azArg = 0;
int i, k;
int nErr = 0;
char *acType;
szFName = token_length(zFCall, &eToken, &ln);
zStart = next_non_whitespace(zFCall+szFName, &len, &eToken);
assert( zStart[0]=='(' && len==1 );
len = distance_to(zStart+1, ')');
zCopy = safe_malloc( len + 1 );
memcpy(zCopy, zStart+1, len);
zCopy[len] = 0;
azArg = 0;
nArg = 0;
z = zCopy;
while( z[0] ){
len = distance_to(z, ',');
azArg = safe_realloc(azArg, (sizeof(azArg[0])+1)*(nArg+1));
azArg[nArg++] = skip_space(z);
if( z[len]==0 ) break;
z[len] = 0;
for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; }
z += len + 1;
}
acType = (char*)&azArg[nArg];
if( fmtArg>nArg ){
printf("%s:%d: too few arguments to %.*s()\n",
zFilename, lnFCall, szFName, zFCall);
nErr++;
}else{
const char *zFmt = azArg[fmtArg-1];
const char *zOverride = strstr(zFmt, "/*works-like:");
if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1;
if( !is_string_lit(zFmt) ){
printf("%s:%d: %.*s() has non-constant format string\n",
zFilename, lnFCall, szFName, zFCall);
nErr++;
}else if( (k = formatArgCount(zFmt, nArg, acType))>=0
&& nArg!=fmtArg+k ){
printf("%s:%d: too %s arguments to %.*s() "
"- got %d and expected %d\n",
zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"),
szFName, zFCall, nArg, fmtArg+k);
nErr++;
}else if( fmtFlags & FMT_NO_S ){
for(i=0; i<nArg && i<k; i++){
if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b')
&& !is_s_safe(azArg[fmtArg+i])
){
printf("%s:%d: Argument %d to %.*s() not safe for SQL\n",
zFilename, lnFCall, i+fmtArg, szFName, zFCall);
nErr++;
}
}
}
}
if( nErr ){
for(i=0; i<nArg; i++){
printf(" arg[%d]: %s\n", i, azArg[i]);
}
}
free(azArg);
free(zCopy);
return nErr;
}
/*
** Do a design-rule check of format strings for the file named zName
** with content zContent. Write errors on standard output. Return
** the number of errors.
*/
static int scan_file(const char *zName, const char *zContent){
const char *z;
int ln = 0;
int szToken;
int eToken;
const char *zPrev;
int ePrev;
int szPrev;
int lnPrev;
int nCurly = 0;
int x;
unsigned fmtFlags = 0;
int nErr = 0;
if( zContent==0 ){
printf("cannot read file: %s\n", zName);
return 1;
}
for(z=zContent; z[0]; z += szToken){
szToken = token_length(z, &eToken, &ln);
if( eToken==TK_SPACE ) continue;
if( eToken==TK_OTHER ){
if( z[0]=='{' ){
nCurly++;
}else if( z[0]=='}' ){
nCurly--;
}else if( nCurly>0 && z[0]=='(' && ePrev==TK_ID
&& (x = isFormatFunc(zPrev,szPrev,&fmtFlags))>0 ){
nErr += checkFormatFunc(zName, zPrev, lnPrev, x, fmtFlags);
}
}
zPrev = z;
ePrev = eToken;
szPrev = szToken;
lnPrev = ln;
}
return nErr;
}
/*
** Check for format-string design rule violations on all files listed
** on the command-line.
*/
int main(int argc, char **argv){
int i;
int nErr = 0;
for(i=1; i<argc; i++){
char *zFile = read_file(argv[i]);
nErr += scan_file(argv[i], zFile);
free(zFile);
}
return nErr;
}
|
Changes to src/comformat.c.
| ︙ | ︙ | |||
495 496 497 498 499 500 501 |
if( zOrigText ){
blob_read_from_file(&fileData, zOrigText);
zOrigText = mprintf("%s", blob_str(&fileData));
blob_reset(&fileData);
}
}
if( decode ){
| | | | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 |
if( zOrigText ){
blob_read_from_file(&fileData, zOrigText);
zOrigText = mprintf("%s", blob_str(&fileData));
blob_reset(&fileData);
}
}
if( decode ){
zText = mprintf(fromFile?"%z":"%s" /*works-like:"%s"*/, zText);
defossilize(zText);
if( zOrigText ){
zOrigText = mprintf(fromFile?"%z":"%s" /*works-like:"%s"*/, zOrigText);
defossilize(zOrigText);
}
}
if( indent<0 ){
indent = strlen(zPrefix);
}
if( zPrefix && *zPrefix ){
|
| ︙ | ︙ |
Changes to src/configure.c.
| ︙ | ︙ | |||
192 193 194 195 196 197 198 |
*/
const char *configure_inop_rhs(int iMask){
Blob x;
int i;
const char *zSep = "";
blob_zero(&x);
| | | | | | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
*/
const char *configure_inop_rhs(int iMask){
Blob x;
int i;
const char *zSep = "";
blob_zero(&x);
blob_append_sql(&x, "(");
for(i=0; i<count(aConfig); i++){
if( (aConfig[i].groupMask & iMask)==0 ) continue;
if( aConfig[i].zName[0]=='@' ) continue;
blob_append_sql(&x, "%s'%q'", zSep/*safe-for-%s*/, aConfig[i].zName);
zSep = ",";
}
blob_append_sql(&x, ")");
return blob_sql_text(&x);
}
/*
** Return the mask for the named configuration parameter if it can be
** safely exported. Return 0 if the parameter is not safe to export.
**
** "Safe" in the previous paragraph means the permission is created to
|
| ︙ | ︙ | |||
359 360 361 362 363 364 365 |
@ photo BLOB -- JPEG image of this user
@ );
@ INSERT INTO _xfer_reportfmt
@ SELECT rn,owner,title,cols,sqlcode FROM reportfmt;
@ INSERT INTO _xfer_user
@ SELECT uid,login,pw,cap,cookie,ipaddr,cexpire,info,photo FROM user;
;
| > | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
@ photo BLOB -- JPEG image of this user
@ );
@ INSERT INTO _xfer_reportfmt
@ SELECT rn,owner,title,cols,sqlcode FROM reportfmt;
@ INSERT INTO _xfer_user
@ SELECT uid,login,pw,cap,cookie,ipaddr,cexpire,info,photo FROM user;
;
assert( strchr(zSQL1,'%')==0 );
db_multi_exec(zSQL1 /*works-like:""*/);
/* When the replace flag is set, add triggers that run the first time
** that new data is seen. The triggers run only once and delete all the
** existing data.
*/
if( replaceFlag ){
static const char zSQL2[] =
|
| ︙ | ︙ | |||
388 389 390 391 392 393 394 |
@ END;
;
sqlite3_create_function(g.db, "config_is_reset", 1, SQLITE_UTF8, 0,
config_is_reset_function, 0, 0);
sqlite3_create_function(g.db, "config_reset", 1, SQLITE_UTF8, 0,
config_reset_function, 0, 0);
configHasBeenReset = 0;
| > | > | | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 |
@ END;
;
sqlite3_create_function(g.db, "config_is_reset", 1, SQLITE_UTF8, 0,
config_is_reset_function, 0, 0);
sqlite3_create_function(g.db, "config_reset", 1, SQLITE_UTF8, 0,
config_reset_function, 0, 0);
configHasBeenReset = 0;
assert( strchr(zSQL2,'%')==0 );
db_multi_exec(zSQL2 /*works-like:""*/);
}
}
/*
** After receiving configuration data, call this routine to transfer
** the results into the main database.
*/
void configure_finalize_receive(void){
static const char zSQL[] =
@ DELETE FROM user;
@ INSERT INTO user SELECT * FROM _xfer_user;
@ DELETE FROM reportfmt;
@ INSERT INTO reportfmt SELECT * FROM _xfer_reportfmt;
@ DROP TABLE _xfer_user;
@ DROP TABLE _xfer_reportfmt;
;
assert( strchr(zSQL,'%')==0 );
db_multi_exec(zSQL /*works-like:""*/);
}
/*
** Mask of modified configuration sets
*/
static int rebuildMask = 0;
|
| ︙ | ︙ | |||
561 562 563 564 565 566 567 |
thisMask = configure_is_exportable(aType[ii].zName);
}
if( (thisMask & groupMask)==0 ) return;
blob_zero(&sql);
if( groupMask & CONFIGSET_OVERWRITE ){
if( (thisMask & configHasBeenReset)==0 && aType[ii].zName[0]!='/' ){
| | | | | | | > | | > | > | | | > | | 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
thisMask = configure_is_exportable(aType[ii].zName);
}
if( (thisMask & groupMask)==0 ) return;
blob_zero(&sql);
if( groupMask & CONFIGSET_OVERWRITE ){
if( (thisMask & configHasBeenReset)==0 && aType[ii].zName[0]!='/' ){
db_multi_exec("DELETE FROM \"%w\"", &aType[ii].zName[1]);
configHasBeenReset |= thisMask;
}
blob_append_sql(&sql, "REPLACE INTO ");
}else{
blob_append_sql(&sql, "INSERT OR IGNORE INTO ");
}
blob_append_sql(&sql, "\"%w\"(\"%w\", mtime", &zName[1], aType[ii].zPrimKey);
for(jj=2; jj<nToken; jj+=2){
blob_append_sql(&sql, ",\"%w\"", azToken[jj]);
}
blob_append_sql(&sql,") VALUES(%s,%s",
azToken[1] /*safe-for-%s*/, azToken[0] /*safe-for-%s*/);
for(jj=2; jj<nToken; jj+=2){
blob_append_sql(&sql, ",%s", azToken[jj+1] /*safe-for-%s*/);
}
db_multi_exec("%s)", blob_sql_text(&sql));
if( db_changes()==0 ){
blob_reset(&sql);
blob_append_sql(&sql, "UPDATE \"%w\" SET mtime=%s",
&zName[1], azToken[0]/*safe-for-%s*/);
for(jj=2; jj<nToken; jj+=2){
blob_append_sql(&sql, ", \"%w\"=%s",
azToken[jj], azToken[jj+1]/*safe-for-%s*/);
}
blob_append_sql(&sql, " WHERE \"%w\"=%s AND mtime<%s",
aType[ii].zPrimKey, azToken[1]/*safe-for-%s*/,
azToken[0]/*safe-for-%s*/);
db_multi_exec("%s", blob_sql_text(&sql));
}
blob_reset(&sql);
rebuildMask |= thisMask;
}else{
/* Otherwise, the old format */
if( (configure_is_exportable(zName) & groupMask)==0 ) return;
if( fossil_strcmp(zName, "logo-image")==0 ){
|
| ︙ | ︙ | |||
607 608 609 610 611 612 613 |
db_finalize(&ins);
}else if( zName[0]=='@' ){
/* Notice that we are evaluating arbitrary SQL received from the
** client. But this can only happen if the client has authenticated
** as an administrator, so presumably we trust the client at this
** point.
*/
| | | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
db_finalize(&ins);
}else if( zName[0]=='@' ){
/* Notice that we are evaluating arbitrary SQL received from the
** client. But this can only happen if the client has authenticated
** as an administrator, so presumably we trust the client at this
** point.
*/
db_multi_exec("%s", blob_str(pContent) /*safe-for-%s*/);
}else{
db_multi_exec(
"REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
zName, blob_str(pContent)
);
}
}
|
| ︙ | ︙ | |||
964 965 966 967 968 969 970 |
db_create_default_users(0, 0);
}else if( fossil_strcmp(zName,"@concealed")==0 ){
db_multi_exec("DELETE FROM concealed");
}else if( fossil_strcmp(zName,"@shun")==0 ){
db_multi_exec("DELETE FROM shun");
}else if( fossil_strcmp(zName,"@reportfmt")==0 ){
db_multi_exec("DELETE FROM reportfmt");
| > | | 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 |
db_create_default_users(0, 0);
}else if( fossil_strcmp(zName,"@concealed")==0 ){
db_multi_exec("DELETE FROM concealed");
}else if( fossil_strcmp(zName,"@shun")==0 ){
db_multi_exec("DELETE FROM shun");
}else if( fossil_strcmp(zName,"@reportfmt")==0 ){
db_multi_exec("DELETE FROM reportfmt");
assert( strchr(zRepositorySchemaDefaultReports,'%')==0 );
db_multi_exec(zRepositorySchemaDefaultReports /*works-like:""*/);
}
}
db_end_transaction(0);
fossil_print("Configuration reset to factory defaults.\n");
fossil_print("To recover, use: %s %s import %s\n",
g.argv[0], g.argv[1], zBackup);
rebuildMask |= mask;
|
| ︙ | ︙ |
Changes to src/content.c.
| ︙ | ︙ | |||
556 557 558 559 560 561 562 |
isDephantomize = 1;
content_mark_available(rid);
}
}else{
/* We are creating a new entry */
db_prepare(&s1,
"INSERT INTO blob(rcvid,size,uuid,content)"
| | | | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
isDephantomize = 1;
content_mark_available(rid);
}
}else{
/* We are creating a new entry */
db_prepare(&s1,
"INSERT INTO blob(rcvid,size,uuid,content)"
"VALUES(%d,%d,'%q',:data)",
g.rcvid, size, blob_str(&hash)
);
db_bind_blob(&s1, ":data", &cmpr);
db_exec(&s1);
rid = db_last_insert_rowid();
if( !pBlob ){
db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid);
}
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
175 176 177 178 179 180 181 |
}
for(i=0; db.doRollback==0 && i<db.nCommitHook; i++){
db.doRollback |= db.aHook[i].xHook();
}
while( db.pAllStmt ){
db_finalize(db.pAllStmt);
}
| | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
}
for(i=0; db.doRollback==0 && i<db.nCommitHook; i++){
db.doRollback |= db.aHook[i].xHook();
}
while( db.pAllStmt ){
db_finalize(db.pAllStmt);
}
db_multi_exec("%s", db.doRollback ? "ROLLBACK" : "COMMIT");
db.doRollback = 0;
}
}
/*
** Force a rollback and shutdown the database
*/
|
| ︙ | ︙ | |||
662 663 664 665 666 667 668 |
const char *zSql;
va_list ap;
db = db_open(zFileName);
sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
rc = sqlite3_exec(db, zSchema, 0, 0, 0);
if( rc!=SQLITE_OK ){
| | | | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 |
const char *zSql;
va_list ap;
db = db_open(zFileName);
sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
rc = sqlite3_exec(db, zSchema, 0, 0, 0);
if( rc!=SQLITE_OK ){
db_err("%s", sqlite3_errmsg(db));
}
va_start(ap, zSchema);
while( (zSql = va_arg(ap, const char*))!=0 ){
rc = sqlite3_exec(db, zSql, 0, 0, 0);
if( rc!=SQLITE_OK ){
db_err("%s", sqlite3_errmsg(db));
}
}
va_end(ap);
sqlite3_exec(db, "COMMIT", 0, 0, 0);
sqlite3_close(db);
}
|
| ︙ | ︙ | |||
748 749 750 751 752 753 754 |
}
/*
** Detaches the zLabel database.
*/
void db_detach(const char *zLabel){
| | | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 |
}
/*
** Detaches the zLabel database.
*/
void db_detach(const char *zLabel){
db_multi_exec("DETACH DATABASE %Q", zLabel);
}
/*
** zDbName is the name of a database file. Attach zDbName using
** the name zLabel.
*/
void db_attach(const char *zDbName, const char *zLabel){
db_multi_exec("ATTACH DATABASE %Q AS %Q", zDbName, zLabel);
}
/*
** zDbName is the name of a database file. If no other database
** file is open, then open this one. If another database file is
** already open, then attach zDbName using the name zLabel.
*/
|
| ︙ | ︙ | |||
885 886 887 888 889 890 891 |
** zColumn
*/
static int db_local_table_exists_but_lacks_column(
const char *zTable,
const char *zColumn
){
char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
| | | | 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 |
** zColumn
*/
static int db_local_table_exists_but_lacks_column(
const char *zTable,
const char *zColumn
){
char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
" WHERE name==%Q /*scan*/",
db_name("localdb"), zTable);
int rc = 0;
if( zDef ){
char *zPattern = mprintf("* %s *", zColumn);
rc = sqlite3_strglob(zPattern, zDef)!=0;
fossil_free(zPattern);
fossil_free(zDef);
}
return rc;
}
/*
|
| ︙ | ︙ | |||
917 918 919 920 921 922 923 |
" WHERE name=='vfile'", db_name("localdb"));
if( zVFileDef==0 ) return 0;
/* If the "isexe" column is missing from the vfile table, then
** add it now. This code added on 2010-03-06. After all users have
** upgraded, this code can be safely deleted.
*/
| | | | 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 |
" WHERE name=='vfile'", db_name("localdb"));
if( zVFileDef==0 ) return 0;
/* If the "isexe" column is missing from the vfile table, then
** add it now. This code added on 2010-03-06. After all users have
** upgraded, this code can be safely deleted.
*/
if( sqlite3_strglob("* isexe *", zVFileDef)!=0 ){
db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
}
/* If "islink"/"isLink" columns are missing from tables, then
** add them now. This code added on 2011-01-17 and 2011-08-27.
** After all users have upgraded, this code can be safely deleted.
*/
if( sqlite3_strglob("* islink *", zVFileDef)!=0 ){
db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
}
if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
}
|
| ︙ | ︙ | |||
1117 1118 1119 1120 1121 1122 1123 |
/*
** Return TRUE if the schema is out-of-date
*/
int db_schema_is_outofdate(void){
return db_exists("SELECT 1 FROM config"
" WHERE name='aux-schema'"
| | | 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 |
/*
** Return TRUE if the schema is out-of-date
*/
int db_schema_is_outofdate(void){
return db_exists("SELECT 1 FROM config"
" WHERE name='aux-schema'"
" AND value<>%Q", AUX_SCHEMA);
}
/*
** Return true if the database is writeable
*/
int db_is_writeable(const char *zName){
return g.db!=0 && !sqlite3_db_readonly(g.db, db_name(zName));
|
| ︙ | ︙ | |||
1328 1329 1330 1331 1332 1333 1334 |
"INSERT INTO config(name,value,mtime)"
" VALUES('server-code', lower(hex(randomblob(20))),now());"
"INSERT INTO config(name,value,mtime)"
" VALUES('project-code', lower(hex(randomblob(20))),now());"
);
}else{
if( db_get("server-code", 0)==0 ) {
| | | | | | | | 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 |
"INSERT INTO config(name,value,mtime)"
" VALUES('server-code', lower(hex(randomblob(20))),now());"
"INSERT INTO config(name,value,mtime)"
" VALUES('project-code', lower(hex(randomblob(20))),now());"
);
}else{
if( db_get("server-code", 0)==0 ) {
db_multi_exec(
"INSERT INTO config(name,value,mtime)"
" VALUES('server-code', lower(hex(randomblob(20))),now());"
);
}
if( db_get("project-code", 0)==0 ) {
db_multi_exec(
"INSERT INTO config(name,value,mtime)"
" VALUES('project-code', lower(hex(randomblob(20))),now());"
);
}
}
}
/*
** Return a pointer to a string that contains the RHS of an IN operator
** that will select CONFIG table names that are in the list of control
** settings.
*/
const char *db_setting_inop_rhs(){
Blob x;
int i;
const char *zSep = "";
blob_zero(&x);
blob_append_sql(&x, "(");
for(i=0; ctrlSettings[i].name; i++){
blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, ctrlSettings[i].name);
zSep = ",";
}
blob_append_sql(&x, ")");
return blob_sql_text(&x);
}
/*
** Fill an empty repository database with the basic information for a
** repository. This function is shared between 'create_repository_cmd'
** ('new') and 'reconstruct_cmd' ('reconstruct'), both of which create
** new repositories.
|
| ︙ | ︙ | |||
2001 2002 2003 2004 2005 2006 2007 |
** as follows:
**
** ckout:%s
**
** Where %s is the checkout root. The value is the repository file.
*/
void db_record_repository_filename(const char *zName){
| < | | | | | | | | | | | 2001 2002 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 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 |
** as follows:
**
** ckout:%s
**
** Where %s is the checkout root. The value is the repository file.
*/
void db_record_repository_filename(const char *zName){
char *zRepoSetting;
char *zCkoutSetting;
Blob full;
if( zName==0 ){
if( !g.localOpen ) return;
zName = db_repository_filename();
}
file_canonical_name(zName, &full, 0);
(void)filename_collation(); /* Initialize before connection swap */
db_swap_connections();
zRepoSetting = mprintf("repo:%q", blob_str(&full));
db_multi_exec(
"DELETE FROM global_config WHERE name %s = %Q;",
filename_collation(), zRepoSetting
);
db_multi_exec(
"INSERT OR IGNORE INTO global_config(name,value)"
"VALUES(%Q,1);",
zRepoSetting
);
fossil_free(zRepoSetting);
if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
Blob localRoot;
file_canonical_name(g.zLocalRoot, &localRoot, 1);
zCkoutSetting = mprintf("ckout:%q", blob_str(&localRoot));
db_multi_exec(
"DELETE FROM global_config WHERE name %s = %Q;",
filename_collation(), zCkoutSetting
);
db_multi_exec(
"REPLACE INTO global_config(name, value)"
"VALUES(%Q,%Q);",
zCkoutSetting, blob_str(&full)
);
db_swap_connections();
db_optional_sql("repository",
"DELETE FROM config WHERE name %s = %Q;",
filename_collation(), zCkoutSetting
);
db_optional_sql("repository",
"REPLACE INTO config(name,value,mtime)"
"VALUES(%Q,1,now());",
zCkoutSetting
);
fossil_free(zCkoutSetting);
blob_reset(&localRoot);
}else{
db_swap_connections();
}
|
| ︙ | ︙ | |||
2652 2653 2654 2655 2656 2657 2658 |
blob_append(&newSql, zOrigSql, j);
blob_append(&newSql, "PRIMARY KEY", -1);
zOrigSql += j+6;
j = -1;
}
}
blob_append(&newSql, zOrigSql, -1);
| | | | | | | | | | 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 |
blob_append(&newSql, zOrigSql, j);
blob_append(&newSql, "PRIMARY KEY", -1);
zOrigSql += j+6;
j = -1;
}
}
blob_append(&newSql, zOrigSql, -1);
blob_append_sql(&allSql,
"ALTER TABLE \"%w\" RENAME TO \"x_%w\";\n"
"%s WITHOUT ROWID;\n"
"INSERT INTO \"%w\" SELECT * FROM \"x_%w\";\n"
"DROP TABLE \"x_%w\";\n",
zTName, zTName, blob_sql_text(&newSql), zTName, zTName, zTName
);
fossil_print("Converting table %s of %s to WITHOUT ROWID.\n", zTName, g.argv[i]);
blob_reset(&newSql);
}
blob_append_sql(&allSql, "COMMIT;\n");
db_finalize(&q);
if( dryRun ){
fossil_print("SQL that would have been evaluated:\n");
fossil_print("-------------------------------------------------------------\n");
fossil_print("%s", blob_sql_text(&allSql));
}else{
db_multi_exec("%s", blob_sql_text(&allSql));
}
blob_reset(&allSql);
db_close(1);
}
}
|
Changes to src/delta.c.
| ︙ | ︙ | |||
63 64 65 66 67 68 69 | #if INTERFACE /* ** The "u32" type must be an unsigned 32-bit integer. Adjust this */ typedef unsigned int u32; /* | | | | 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 | #if INTERFACE /* ** The "u32" type must be an unsigned 32-bit integer. Adjust this */ typedef unsigned int u32; /* ** Must be a 16-bit value */ typedef short int s16; typedef unsigned short int u16; #endif /* INTERFACE */ /* ** The width of a hash window in bytes. The algorithm only works if this ** is a power of 2. */ #define NHASH 16 /* ** The current state of the rolling hash. ** ** z[] holds the values that have been hashed. z[] is a circular buffer. ** z[i] is the first entry and z[(i+NHASH-1)%NHASH] is the last entry of ** the window. ** ** Hash.a is the sum of all elements of hash.z[]. Hash.b is a weighted ** sum. Hash.b is z[i]*NHASH + z[i+1]*(NHASH-1) + ... + z[i+NHASH-1]*1. ** (Each index for z[] should be module NHASH, of course. The %NHASH operator ** is omitted in the prior expression for brevity.) */ |
| ︙ | ︙ | |||
133 134 135 136 137 138 139 |
return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
}
/*
** Write an base-64 integer into the given buffer.
*/
static void putInt(unsigned int v, char **pz){
| | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
return (pHash->a & 0xffff) | (((u32)(pHash->b & 0xffff))<<16);
}
/*
** Write an base-64 integer into the given buffer.
*/
static void putInt(unsigned int v, char **pz){
static const char zDigits[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~";
/* 123456789 123456789 123456789 123456789 123456789 123456789 123 */
int i, j;
char zBuf[20];
if( v==0 ){
*(*pz)++ = '0';
return;
|
| ︙ | ︙ | |||
227 228 229 230 231 232 233 | } return sum3; } /* ** Create a new delta. ** | | | | 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 | } return sum3; } /* ** Create a new delta. ** ** The delta is written into a preallocated buffer, zDelta, which ** should be at least 60 bytes longer than the target file, zOut. ** The delta string will be NUL-terminated, but it might also contain ** embedded NUL characters if either the zSrc or zOut files are ** binary. This function returns the length of the delta string ** in bytes, excluding the final NUL terminator character. ** ** Output Format: ** ** The delta begins with a base64 number followed by a newline. This ** number is the number of bytes in the TARGET file. Thus, given a ** delta file z, a program can compute the size of the output file ** simply by reading the first line and decoding the base-64 number ** found there. The delta_output_size() routine does exactly this. ** ** After the initial size number, the delta consists of a series of ** literal text segments and commands to copy from the SOURCE file. ** A copy command looks like this: ** ** NNN@MMM, ** ** where NNN is the number of bytes to be copied and MMM is the offset ** into the source file of the first byte (both base-64). If NNN is 0 ** it means copy the rest of the input file. Literal text is like this: |
| ︙ | ︙ | |||
281 282 283 284 285 286 287 | ** Next we begin scanning the target file using a sliding 16-byte ** window. The hash of the 16-byte window in the target is used to ** search for a matching section in the source file. When a match ** is found, a copy command is added to the delta. An effort is ** made to extend the matching section to regions that come before ** and after the 16-byte hash window. A copy command is only issued ** if the result would use less space that just quoting the text | | | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | ** Next we begin scanning the target file using a sliding 16-byte ** window. The hash of the 16-byte window in the target is used to ** search for a matching section in the source file. When a match ** is found, a copy command is added to the delta. An effort is ** made to extend the matching section to regions that come before ** and after the 16-byte hash window. A copy command is only issued ** if the result would use less space that just quoting the text ** literally. Literal text is added to the delta for sections that ** do not match or which can not be encoded efficiently using copy ** commands. */ int delta_create( const char *zSrc, /* The source or pattern file */ unsigned int lenSrc, /* Length of the source file */ const char *zOut, /* The target file */ |
| ︙ | ︙ | |||
354 355 356 357 358 359 360 |
int limit = 250;
hv = hash_32bit(&h) % nHash;
DEBUG2( printf("LOOKING: %4d [%s]\n", base+i, print16(&zOut[base+i])); )
iBlock = landmark[hv];
while( iBlock>=0 && (limit--)>0 ){
/*
| | | | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
int limit = 250;
hv = hash_32bit(&h) % nHash;
DEBUG2( printf("LOOKING: %4d [%s]\n", base+i, print16(&zOut[base+i])); )
iBlock = landmark[hv];
while( iBlock>=0 && (limit--)>0 ){
/*
** The hash window has identified a potential match against
** landmark block iBlock. But we need to investigate further.
**
** Look for a region in zOut that matches zSrc. Anchor the search
** at zSrc[iSrc] and zOut[base+i]. Do not include anything prior to
** zOut[base] or after zOut[outLen] nor anything after zSrc[srcLen].
**
** Set cnt equal to the length of the match and set ofst so that
** zSrc[ofst] is the first element of the match. litsz is the number
** of characters between zOut[base] and the beginning of the match.
|
| ︙ | ︙ | |||
466 467 468 469 470 471 472 |
memcpy(zDelta, &zOut[base], lenOut-base);
zDelta += lenOut-base;
}
/* Output the final checksum record. */
putInt(checksum(zOut, lenOut), &zDelta);
*(zDelta++) = ';';
fossil_free(collide);
| | | | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
memcpy(zDelta, &zOut[base], lenOut-base);
zDelta += lenOut-base;
}
/* Output the final checksum record. */
putInt(checksum(zOut, lenOut), &zDelta);
*(zDelta++) = ';';
fossil_free(collide);
return zDelta - zOrigDelta;
}
/*
** Return the size (in bytes) of the output from applying
** a delta.
**
** This routine is provided so that an procedure that is able
** to call delta_apply() can learn how much space is required
** for the output and hence allocate nor more space that is really
** needed.
*/
int delta_output_size(const char *zDelta, int lenDelta){
|
| ︙ | ︙ |
Changes to src/descendants.c.
| ︙ | ︙ | |||
387 388 389 390 391 392 393 | /* We should be done with options.. */ verify_all_options(); if( recomputeFlag ) leaf_rebuild(); blob_zero(&sql); blob_append(&sql, timeline_query_for_tty(), -1); | | | | | | | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 |
/* We should be done with options.. */
verify_all_options();
if( recomputeFlag ) leaf_rebuild();
blob_zero(&sql);
blob_append(&sql, timeline_query_for_tty(), -1);
blob_append_sql(&sql, " AND blob.rid IN leaf");
if( showClosed ){
blob_append_sql(&sql," AND %z", leaf_is_closed_sql("blob.rid"));
}else if( !showAll ){
blob_append_sql(&sql," AND NOT %z", leaf_is_closed_sql("blob.rid"));
}
if( byBranch ){
db_prepare(&q, "%s ORDER BY nullif(branch,'trunk') COLLATE nocase,"
" event.mtime DESC",
blob_sql_text(&sql));
}else{
db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_sql_text(&sql));
}
blob_reset(&sql);
n = 0;
while( db_step(&q)==SQLITE_ROW ){
const char *zId = db_column_text(&q, 1);
const char *zDate = db_column_text(&q, 2);
const char *zCom = db_column_text(&q, 3);
|
| ︙ | ︙ | |||
472 473 474 475 476 477 478 |
}else if( showClosed ){
@ <h1>Closed leaves:</h1>
}else{
@ <h1>Open leaves:</h1>
}
blob_zero(&sql);
blob_append(&sql, timeline_query_for_www(), -1);
| | | | | | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
}else if( showClosed ){
@ <h1>Closed leaves:</h1>
}else{
@ <h1>Open leaves:</h1>
}
blob_zero(&sql);
blob_append(&sql, timeline_query_for_www(), -1);
blob_append_sql(&sql, " AND blob.rid IN leaf");
if( showClosed ){
blob_append_sql(&sql," AND %z", leaf_is_closed_sql("blob.rid"));
}else if( !showAll ){
blob_append_sql(&sql," AND NOT %z", leaf_is_closed_sql("blob.rid"));
}
db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_sql_text(&sql));
blob_reset(&sql);
www_print_timeline(&q, TIMELINE_LEAFONLY, 0, 0, 0);
db_finalize(&q);
@ <br />
style_footer();
}
|
| ︙ | ︙ | |||
506 507 508 509 510 511 512 | Bag pending; Stmt ins; Stmt q; int rid; bag_init(&seen); bag_init(&pending); | | | 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
Bag pending;
Stmt ins;
Stmt q;
int rid;
bag_init(&seen);
bag_init(&pending);
db_prepare(&ins, "INSERT OR IGNORE INTO \"%w\" VALUES(:rid)", zTab);
db_prepare(&q, "SELECT mid FROM mlink WHERE fid=%d", fid);
while( db_step(&q)==SQLITE_ROW ){
int mid = db_column_int(&q, 0);
bag_insert(&pending, mid);
bag_insert(&seen, mid);
db_bind_int(&ins, ":rid", mid);
db_step(&ins);
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
140 141 142 143 144 145 146 |
int cnt = 0;
Blob nameFile1; /* Name of temporary file to old pFile1 content */
Blob cmd; /* Text of command to run */
if( !fIncludeBinary ){
Blob file2;
if( isBin1 ){
| | | | | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
int cnt = 0;
Blob nameFile1; /* Name of temporary file to old pFile1 content */
Blob cmd; /* Text of command to run */
if( !fIncludeBinary ){
Blob file2;
if( isBin1 ){
fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
return;
}
if( zBinGlob ){
Glob *pBinary = glob_create(zBinGlob);
if( glob_match(pBinary, zName) ){
fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
glob_free(pBinary);
return;
}
glob_free(pBinary);
}
blob_zero(&file2);
if( file_wd_size(zFile2)>=0 ){
if( file_wd_islink(zFile2) ){
blob_read_link(&file2, zFile2);
}else{
blob_read_from_file(&file2, zFile2);
}
}
if( looks_like_binary(&file2) ){
fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
blob_reset(&file2);
return;
}
blob_reset(&file2);
}
/* Construct a temporary file to hold pFile1 based on the name of
|
| ︙ | ︙ | |||
236 237 238 239 240 241 242 |
}else{
Blob cmd;
char zTemp1[300];
char zTemp2[300];
if( !fIncludeBinary ){
if( isBin1 || isBin2 ){
| | | | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
}else{
Blob cmd;
char zTemp1[300];
char zTemp2[300];
if( !fIncludeBinary ){
if( isBin1 || isBin2 ){
fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
return;
}
if( zBinGlob ){
Glob *pBinary = glob_create(zBinGlob);
if( glob_match(pBinary, zName) ){
fossil_print("%s",DIFF_CANNOT_COMPUTE_BINARY);
glob_free(pBinary);
return;
}
glob_free(pBinary);
}
}
|
| ︙ | ︙ | |||
300 301 302 303 304 305 306 |
Blob content;
int isLink;
int isBin;
file_tree_name(zFileTreeName, &fname, 1);
historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0,
fIncludeBinary ? 0 : &isBin, 0);
if( !isLink != !file_wd_islink(zFrom) ){
| | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
Blob content;
int isLink;
int isBin;
file_tree_name(zFileTreeName, &fname, 1);
historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0,
fIncludeBinary ? 0 : &isBin, 0);
if( !isLink != !file_wd_islink(zFrom) ){
fossil_print("%s",DIFF_CANNOT_COMPUTE_SYMLINK);
}else{
diff_file(&content, isBin, zFileTreeName, zFileTreeName,
zDiffCmd, zBinGlob, fIncludeBinary, diffFlags);
}
blob_reset(&content);
blob_reset(&fname);
}
|
| ︙ | ︙ | |||
344 345 346 347 348 349 350 |
db_begin_transaction();
if( zFrom ){
int rid = name_to_typed_rid(zFrom, "ci");
if( !is_a_version(rid) ){
fossil_fatal("no such check-in: %s", zFrom);
}
load_vfile_from_rid(rid);
| | | | | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
db_begin_transaction();
if( zFrom ){
int rid = name_to_typed_rid(zFrom, "ci");
if( !is_a_version(rid) ){
fossil_fatal("no such check-in: %s", zFrom);
}
load_vfile_from_rid(rid);
blob_append_sql(&sql,
"SELECT v2.pathname, v2.deleted, v2.chnged, v2.rid==0, v1.rid, v1.islink"
" FROM vfile v1, vfile v2 "
" WHERE v1.pathname=v2.pathname AND v1.vid=%d AND v2.vid=%d"
" AND (v2.deleted OR v2.chnged OR v1.mrid!=v2.rid)"
"UNION "
"SELECT pathname, 1, 0, 0, 0, islink"
" FROM vfile v1"
" WHERE v1.vid=%d"
" AND NOT EXISTS(SELECT 1 FROM vfile v2"
" WHERE v2.vid=%d AND v2.pathname=v1.pathname)"
"UNION "
"SELECT pathname, 0, 0, 1, 0, islink"
" FROM vfile v2"
" WHERE v2.vid=%d"
" AND NOT EXISTS(SELECT 1 FROM vfile v1"
" WHERE v1.vid=%d AND v1.pathname=v2.pathname)"
" ORDER BY 1",
rid, vid, rid, vid, vid, rid
);
}else{
blob_append_sql(&sql,
"SELECT pathname, deleted, chnged , rid==0, rid, islink"
" FROM vfile"
" WHERE vid=%d"
" AND (deleted OR chnged OR rid==0)"
" ORDER BY pathname",
vid
);
}
db_prepare(&q, "%s", blob_sql_text(&sql));
while( db_step(&q)==SQLITE_ROW ){
const char *zPathname = db_column_text(&q,0);
int isDeleted = db_column_int(&q, 1);
int isChnged = db_column_int(&q,2);
int isNew = db_column_int(&q,3);
int srcid = db_column_int(&q, 4);
int isLink = db_column_int(&q, 5);
|
| ︙ | ︙ | |||
406 407 408 409 410 411 412 |
}
if( showDiff ){
Blob content;
int isBin;
if( !isLink != !file_wd_islink(zFullName) ){
diff_print_index(zPathname, diffFlags);
diff_print_filenames(zPathname, zPathname, diffFlags);
| | | 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
}
if( showDiff ){
Blob content;
int isBin;
if( !isLink != !file_wd_islink(zFullName) ){
diff_print_index(zPathname, diffFlags);
diff_print_filenames(zPathname, zPathname, diffFlags);
fossil_print("%s",DIFF_CANNOT_COMPUTE_SYMLINK);
continue;
}
if( srcid>0 ){
content_get(srcid, &content);
}else{
blob_zero(&content);
}
|
| ︙ | ︙ | |||
460 461 462 463 464 465 466 |
zName = blob_str(&fname);
historical_version_of_file(zFrom, zName, &v1, &isLink1, 0,
fIncludeBinary ? 0 : &isBin1, 0);
historical_version_of_file(zTo, zName, &v2, &isLink2, 0,
fIncludeBinary ? 0 : &isBin2, 0);
if( isLink1 != isLink2 ){
diff_print_filenames(zName, zName, diffFlags);
| | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
zName = blob_str(&fname);
historical_version_of_file(zFrom, zName, &v1, &isLink1, 0,
fIncludeBinary ? 0 : &isBin1, 0);
historical_version_of_file(zTo, zName, &v2, &isLink2, 0,
fIncludeBinary ? 0 : &isBin2, 0);
if( isLink1 != isLink2 ){
diff_print_filenames(zName, zName, diffFlags);
fossil_print("%s",DIFF_CANNOT_COMPUTE_SYMLINK);
}else{
diff_file_mem(&v1, &v2, isBin1, isBin2, zName, zDiffCmd,
zBinGlob, fIncludeBinary, diffFlags);
}
blob_reset(&v1);
blob_reset(&v2);
blob_reset(&fname);
|
| ︙ | ︙ |
Changes to src/doc.c.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 | /* ** Try to guess the mimetype from content. ** ** If the content is pure text, return NULL. ** ** For image types, attempt to return an appropriate mimetype | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/*
** Try to guess the mimetype from content.
**
** If the content is pure text, return NULL.
**
** For image types, attempt to return an appropriate mimetype
** name like "image/gif" or "image/jpeg".
**
** For any other binary type, return "unknown/unknown".
*/
const char *mimetype_from_content(Blob *pBlob){
int i;
int n;
const unsigned char *x;
|
| ︙ | ︙ | |||
81 82 83 84 85 86 87 |
const char *mimetype_from_name(const char *zName){
const char *z;
int i;
int first, last;
int len;
char zSuffix[20];
| | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
const char *mimetype_from_name(const char *zName){
const char *z;
int i;
int first, last;
int len;
char zSuffix[20];
/* A table of mimetypes based on file suffixes.
** Suffixes must be in sorted order so that we can do a binary
** search to find the mime-type
*/
static const struct {
const char *zSuffix; /* The file suffix */
int size; /* Length of the suffix */
const char *zMimetype; /* The corresponding mimetype */
|
| ︙ | ︙ | |||
485 486 487 488 489 490 491 |
goto doc_not_found;
}
db_end_transaction(0);
}
blob_to_utf8_no_bom(&filebody, 0);
/* The file is now contained in the filebody blob. Deliver the
| | | | < | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 |
goto doc_not_found;
}
db_end_transaction(0);
}
blob_to_utf8_no_bom(&filebody, 0);
/* The file is now contained in the filebody blob. Deliver the
** file to the user
*/
zMime = P("mimetype");
if( zMime==0 ){
zMime = mimetype_from_name(zName);
}
Th_Store("doc_name", zName);
Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
" FROM blob WHERE rid=%d", vid));
Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
" WHERE objid=%d AND type='ci'", vid));
if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){
Blob title, tail;
if( wiki_find_title(&filebody, &title, &tail) ){
style_header("%s", blob_str(&title));
wiki_convert(&tail, 0, WIKI_BUTTONS);
}else{
style_header("Documentation");
wiki_convert(&filebody, 0, WIKI_BUTTONS);
}
style_footer();
}else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){
Blob title = BLOB_INITIALIZER;
Blob tail = BLOB_INITIALIZER;
markdown_to_html(&filebody, &title, &tail);
if( blob_size(&title)>0 ){
style_header("%s", blob_str(&title));
}else{
style_header("Documentation");
}
blob_append(cgi_output_blob(), blob_buffer(&tail), blob_size(&tail));
style_footer();
}else if( fossil_strcmp(zMime, "text/plain")==0 ){
style_header("Documentation");
@ <blockquote><pre>
@ %h(blob_str(&filebody))
@ </pre></blockquote>
style_footer();
#ifdef FOSSIL_ENABLE_TH1_DOCS
}else if( db_get_boolean("th1-docs", 0) &&
fossil_strcmp(zMime, "application/x-th1")==0 ){
style_header("%h", zName);
Th_Render(blob_str(&filebody));
style_footer();
#endif
}else{
cgi_set_content_type(zMime);
cgi_set_content(&filebody);
}
return;
doc_not_found:
/* Jump here when unable to locate the document */
db_end_transaction(0);
style_header("Document Not Found");
@ <p>No such document: %h(zName)</p>
style_footer();
return;
}
/*
** The default logo.
*/
static const unsigned char aLogo[] = {
71, 73, 70, 56, 55, 97, 62, 0, 71, 0, 244, 0, 0, 85,
129, 149, 95, 136, 155, 99, 139, 157, 106, 144, 162, 113, 150, 166,
116, 152, 168, 127, 160, 175, 138, 168, 182, 148, 176, 188, 159, 184,
195, 170, 192, 202, 180, 199, 208, 184, 202, 210, 191, 207, 215, 201,
215, 221, 212, 223, 228, 223, 231, 235, 226, 227, 226, 226, 234, 237,
233, 239, 241, 240, 244, 246, 244, 247, 248, 255, 255, 255, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0,
0, 0, 62, 0, 71, 0, 0, 5, 255, 96, 100, 141, 100, 105,
158, 168, 37, 41, 132, 192, 164, 112, 44, 207, 102, 99, 0, 56,
16, 84, 116, 239, 199, 141, 65, 110, 232, 248, 25, 141, 193, 161,
82, 113, 108, 202, 32, 55, 229, 210, 73, 61, 41, 164, 88, 102,
181, 10, 41, 96, 179, 91, 106, 35, 240, 5, 135, 143, 137, 242,
87, 123, 246, 33, 190, 81, 108, 163, 237, 198, 14, 30, 113, 233,
131, 78, 115, 72, 11, 115, 87, 101, 19, 124, 51, 66, 74, 8,
19, 16, 67, 100, 74, 133, 50, 15, 101, 135, 56, 11, 74, 6,
143, 49, 126, 106, 56, 8, 145, 67, 9, 152, 48, 139, 155, 5,
22, 13, 74, 115, 161, 41, 147, 101, 13, 130, 57, 132, 170, 40,
167, 155, 0, 94, 57, 3, 178, 48, 183, 181, 57, 160, 186, 40,
19, 141, 189, 0, 69, 192, 40, 16, 195, 155, 185, 199, 41, 201,
189, 191, 205, 193, 188, 131, 210, 49, 175, 88, 209, 214, 38, 19,
3, 11, 19, 111, 127, 60, 219, 39, 55, 204, 19, 11, 6, 100,
5, 10, 227, 228, 37, 163, 0, 239, 117, 56, 238, 243, 49, 195,
177, 247, 48, 158, 56, 251, 50, 216, 254, 197, 56, 128, 107, 158,
2, 125, 171, 114, 92, 218, 246, 96, 66, 3, 4, 50, 134, 176,
145, 6, 97, 64, 144, 24, 19, 136, 108, 91, 177, 160, 0, 194,
19, 253, 0, 216, 107, 214, 224, 192, 129, 5, 16, 83, 255, 244,
43, 213, 195, 24, 159, 27, 169, 64, 230, 88, 208, 227, 129, 182,
54, 4, 89, 158, 24, 181, 163, 199, 1, 155, 52, 233, 8, 130,
176, 83, 24, 128, 137, 50, 18, 32, 48, 48, 114, 11, 173, 137,
19, 110, 4, 64, 105, 1, 194, 30, 140, 68, 15, 24, 24, 224,
50, 76, 70, 0, 11, 171, 54, 26, 160, 181, 194, 149, 148, 40,
174, 148, 122, 64, 180, 208, 161, 17, 207, 112, 164, 1, 128, 96,
148, 78, 18, 21, 194, 33, 229, 51, 247, 65, 133, 97, 5, 250,
69, 229, 100, 34, 220, 128, 166, 116, 190, 62, 8, 167, 195, 170,
47, 163, 0, 130, 90, 152, 11, 160, 173, 170, 27, 154, 26, 91,
232, 151, 171, 18, 14, 162, 253, 98, 170, 18, 70, 171, 64, 219,
10, 67, 136, 134, 187, 116, 75, 180, 46, 179, 174, 135, 4, 189,
229, 231, 78, 40, 10, 62, 226, 164, 172, 64, 240, 167, 170, 10,
18, 124, 188, 10, 107, 65, 193, 94, 11, 93, 171, 28, 248, 17,
239, 46, 140, 78, 97, 34, 25, 153, 36, 99, 65, 130, 7, 203,
183, 168, 51, 34, 136, 25, 140, 10, 6, 16, 28, 255, 145, 241,
230, 140, 10, 66, 178, 167, 112, 48, 192, 128, 129, 9, 31, 141,
84, 138, 63, 163, 162, 2, 203, 206, 240, 56, 55, 98, 192, 188,
15, 185, 50, 160, 6, 0, 125, 62, 33, 214, 195, 33, 5, 24,
184, 25, 231, 14, 201, 245, 144, 23, 126, 104, 228, 0, 145, 2,
13, 140, 244, 212, 17, 21, 20, 176, 159, 17, 95, 225, 160, 128,
16, 1, 32, 224, 142, 32, 227, 125, 87, 64, 0, 16, 54, 129,
205, 2, 141, 76, 53, 130, 103, 37, 166, 64, 144, 107, 78, 196,
5, 192, 0, 54, 50, 229, 9, 141, 49, 84, 194, 35, 12, 196,
153, 48, 192, 137, 57, 84, 24, 7, 87, 159, 249, 240, 215, 143,
105, 241, 118, 149, 9, 139, 4, 64, 203, 141, 35, 140, 129, 131,
16, 222, 125, 231, 128, 2, 238, 17, 152, 66, 3, 5, 56, 224,
159, 103, 16, 76, 25, 75, 5, 11, 164, 215, 96, 9, 14, 16,
36, 225, 15, 11, 40, 144, 192, 156, 41, 10, 178, 199, 3, 66,
64, 80, 193, 3, 124, 90, 48, 129, 129, 102, 177, 18, 192, 154,
49, 84, 240, 208, 92, 22, 149, 96, 39, 9, 31, 74, 17, 94,
3, 8, 177, 199, 72, 59, 85, 76, 25, 216, 8, 139, 194, 197,
138, 163, 69, 96, 115, 0, 147, 72, 72, 84, 28, 14, 79, 86,
233, 230, 23, 113, 26, 160, 128, 3, 10, 58, 129, 103, 14, 159,
214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13,
27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59,
};
/*
** WEBPAGE: logo
**
** Return the logo image. This image is available to anybody who can see
** the login page. It is designed for use in the upper left-hand corner
|
| ︙ | ︙ |
Changes to src/encode.c.
| ︙ | ︙ | |||
45 46 47 48 49 50 51 |
}
i++;
}
i = 0;
zOut = fossil_malloc( count+1 );
while( n-->0 && (c = *zIn)!=0 ){
switch( c ){
| | | | | | 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 |
}
i++;
}
i = 0;
zOut = fossil_malloc( count+1 );
while( n-->0 && (c = *zIn)!=0 ){
switch( c ){
case '<':
zOut[i++] = '&';
zOut[i++] = 'l';
zOut[i++] = 't';
zOut[i++] = ';';
break;
case '>':
zOut[i++] = '&';
zOut[i++] = 'g';
zOut[i++] = 't';
zOut[i++] = ';';
break;
case '&':
zOut[i++] = '&';
zOut[i++] = 'a';
zOut[i++] = 'm';
zOut[i++] = 'p';
zOut[i++] = ';';
break;
case '"':
zOut[i++] = '&';
zOut[i++] = 'q';
zOut[i++] = 'u';
zOut[i++] = 'o';
zOut[i++] = 't';
zOut[i++] = ';';
break;
|
| ︙ | ︙ | |||
179 180 181 182 183 184 185 | } /* ** Convert the input string into a form that is suitable for use as ** a token in the HTTP protocol. Spaces are encoded as '+' and special ** characters are encoded as "%HH" where HH is a two-digit hexidecimal ** representation of the character. The "/" character is not encoded | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
}
/*
** Convert the input string into a form that is suitable for use as
** a token in the HTTP protocol. Spaces are encoded as '+' and special
** characters are encoded as "%HH" where HH is a two-digit hexidecimal
** representation of the character. The "/" character is not encoded
** by this routine.
*/
char *urlize(const char *z, int n){
return EncodeHttp(z, n, 0);
}
/*
** Convert a single HEX digit to an integer
|
| ︙ | ︙ | |||
325 326 327 328 329 330 331 | if( z[j] ) z[j] = 0; } /* ** The characters used for HTTP base64 encoding. */ | | | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | if( z[j] ) z[j] = 0; } /* ** The characters used for HTTP base64 encoding. */ static unsigned char zBase[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* ** Encode a string using a base-64 encoding. ** The encoding can be reversed using the <b>decode64</b> function. ** ** Space to hold the result comes from malloc(). |
| ︙ | ︙ | |||
364 365 366 367 368 369 370 |
z64[n++] = '=';
}
z64[n] = 0;
return z64;
}
/*
| | | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 |
z64[n++] = '=';
}
z64[n] = 0;
return z64;
}
/*
** COMMAND: test-encode64
** Usage: %fossil test-encode64 STRING
*/
void test_encode64_cmd(void){
char *z;
int i;
for(i=2; i<g.argc; i++){
z = encode64(g.argv[i], -1);
|
| ︙ | ︙ | |||
429 430 431 432 433 434 435 | } zData[j] = 0; *pnByte = j; return zData; } /* | | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
}
zData[j] = 0;
*pnByte = j;
return zData;
}
/*
** COMMAND: test-decode64
** Usage: %fossil test-decode64 STRING
*/
void test_decode64_cmd(void){
char *z;
int i, n;
for(i=2; i<g.argc; i++){
z = decode64(g.argv[i], &n);
|
| ︙ | ︙ | |||
452 453 454 455 456 457 458 | ** 0123456789abcdef ** */ /* ** The array used for encoding */ /* 123456789 12345 */ | | | | | | | | | | | | | | | | | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 |
** 0123456789abcdef
**
*/
/*
** The array used for encoding
*/ /* 123456789 12345 */
static const char zEncode[] = "0123456789abcdef";
/*
** Encode a N-digit base-256 in base-16. Return zero on success
** and non-zero if there is an error.
*/
int encode16(const unsigned char *pIn, unsigned char *zOut, int N){
int i;
for(i=0; i<N; i++){
*(zOut++) = zEncode[pIn[i]>>4];
*(zOut++) = zEncode[pIn[i]&0xf];
}
*zOut = 0;
return 0;
}
/*
** An array for translating single base-16 characters into a value.
** Disallowed input characters have a value of 64. Upper and lower
** case is the same.
*/
static const char zDecode[] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 64, 64, 64, 64, 64, 64,
64, 10, 11, 12, 13, 14, 15, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 10, 11, 12, 13, 14, 15, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
};
/*
** Decode a N-character base-16 number into base-256. N must be a
** multiple of 2. The output buffer must be at least N/2 characters
** in length
*/
int decode16(const unsigned char *zIn, unsigned char *pOut, int N){
int i, j;
if( (N&1)!=0 ) return 1;
for(i=j=0; i<N; i += 2, j++){
|
| ︙ | ︙ | |||
543 544 545 546 547 548 549 |
}
/* Randomness used for XOR-ing by the obscure() and unobscure() routines */
static const unsigned char aObscurer[16] = {
0xa7, 0x21, 0x31, 0xe3, 0x2a, 0x50, 0x2c, 0x86,
0x4c, 0xa4, 0x52, 0x25, 0xff, 0x49, 0x35, 0x85
};
| | | | | | 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 |
}
/* Randomness used for XOR-ing by the obscure() and unobscure() routines */
static const unsigned char aObscurer[16] = {
0xa7, 0x21, 0x31, 0xe3, 0x2a, 0x50, 0x2c, 0x86,
0x4c, 0xa4, 0x52, 0x25, 0xff, 0x49, 0x35, 0x85
};
/*
** Obscure plain text so that it is not easily readable.
**
** This is used for storing sensitive information (such as passwords) in a
** way that prevents their exposure through idle browsing. This is not
** encryption. Anybody who really wants the password can still get it.
**
** The text is XOR-ed with a repeating pattern then converted to hex.
** Space to hold the returned string is obtained from malloc and should
** be freed by the caller.
*/
char *obscure(const char *zIn){
int n, i;
unsigned char salt;
char *zOut;
if( zIn==0 ) return 0;
n = strlen(zIn);
zOut = fossil_malloc( n*2+3 );
sqlite3_randomness(1, &salt);
zOut[n+1] = (char)salt;
for(i=0; i<n; i++) zOut[i+n+2] = zIn[i]^aObscurer[i&0x0f]^salt;
encode16((unsigned char*)&zOut[n+1], (unsigned char*)zOut, n+1);
return zOut;
}
/*
** Undo the obscuring of text performed by obscure(). Or, if the input is
** not hexadecimal (meaning the input is not the output of obscure()) then
** do the equivalent of strdup().
**
** The result is memory obtained from malloc that should be freed by the caller.
*/
char *unobscure(const char *zIn){
int n, i;
unsigned char salt;
char *zOut;
if( zIn==0 ) return 0;
n = strlen(zIn);
zOut = fossil_malloc( n + 1 );
if( n<2
|| decode16((unsigned char*)zIn, &salt, 2)
|| decode16((unsigned char*)&zIn[2], (unsigned char*)zOut, n-2)
){
|
| ︙ | ︙ |
Changes to src/event.c.
| ︙ | ︙ | |||
117 118 119 120 121 122 123 |
*/
pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
if( pEvent==0 ){
fossil_fatal("Object #%d is not an event", rid);
}
blob_init(&fullbody, pEvent->zWiki, -1);
if( wiki_find_title(&fullbody, &title, &tail) ){
| | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
*/
pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
if( pEvent==0 ){
fossil_fatal("Object #%d is not an event", rid);
}
blob_init(&fullbody, pEvent->zWiki, -1);
if( wiki_find_title(&fullbody, &title, &tail) ){
style_header("%s", blob_str(&title));
}else{
style_header("Event %S", zEventId);
tail = fullbody;
}
if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
g.zTop, zEventId);
|
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
** Edit an event. If name is omitted, create a new event.
*/
void eventedit_page(void){
char *zTag;
int rid = 0;
Blob event;
const char *zEventId;
| < | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
** Edit an event. If name is omitted, create a new event.
*/
void eventedit_page(void){
char *zTag;
int rid = 0;
Blob event;
const char *zEventId;
int n;
const char *z;
char *zBody = (char*)P("w");
char *zETime = (char*)P("t");
const char *zComment = P("c");
const char *zTags = P("g");
const char *zClr;
|
| ︙ | ︙ | |||
362 363 364 365 366 367 368 |
if( P("cancel")!=0 ){
cgi_redirectf("event?name=%T", zEventId);
return;
}
if( zBody==0 ){
zBody = mprintf("<i>Event Text</i>");
}
| | < | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
if( P("cancel")!=0 ){
cgi_redirectf("event?name=%T", zEventId);
return;
}
if( zBody==0 ){
zBody = mprintf("<i>Event Text</i>");
}
style_header("Edit Event %S", zEventId);
if( P("preview")!=0 ){
Blob title, tail, com;
@ <p><b>Timeline comment preview:</b></p>
@ <blockquote>
@ <table border="0">
if( zClr && zClr[0] ){
@ <tr><td style="background-color: %h(zClr);">
|
| ︙ | ︙ |
Changes to src/export.c.
| ︙ | ︙ | |||
230 231 232 233 234 235 236 | db_finalize(&q); db_finalize(&q2); db_finalize(&q3); /* Output the commit records. */ db_prepare(&q, | | | | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
db_finalize(&q);
db_finalize(&q2);
db_finalize(&q3);
/* Output the commit records.
*/
db_prepare(&q,
"SELECT strftime('%%s',mtime), objid, coalesce(ecomment,comment),"
" coalesce(euser,user),"
" (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)"
" FROM event"
" WHERE type='ci' AND NOT EXISTS (SELECT 1 FROM oldcommit WHERE objid=rid)"
" ORDER BY mtime ASC",
TAG_BRANCH
);
db_prepare(&q2, "INSERT INTO oldcommit VALUES (:rid)");
|
| ︙ | ︙ |
Changes to src/finfo.c.
| ︙ | ︙ | |||
317 318 319 320 321 322 323 |
if( baseCheckin ) firstChngOnly = 1;
if( !firstChngOnly ) url_add_parameter(&url, "fco", "0");
zPrevDate[0] = 0;
zFilename = PD("name","");
url_add_parameter(&url, "name", zFilename);
blob_zero(&sql);
| | | | | | | | | | | | | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
if( baseCheckin ) firstChngOnly = 1;
if( !firstChngOnly ) url_add_parameter(&url, "fco", "0");
zPrevDate[0] = 0;
zFilename = PD("name","");
url_add_parameter(&url, "name", zFilename);
blob_zero(&sql);
blob_append_sql(&sql,
"SELECT"
" datetime(event.mtime%s)," /* Date of change */
" coalesce(event.ecomment, event.comment)," /* Check-in comment */
" coalesce(event.euser, event.user)," /* User who made chng */
" mlink.pid," /* Parent file rid */
" mlink.fid," /* File rid */
" (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
" (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */
" (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */
" event.bgcolor," /* Background color */
" (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
" AND tagxref.rid=mlink.mid)," /* Tags */
" mlink.mid," /* check-in ID */
" mlink.pfnid", /* Previous filename */
timeline_utc(), TAG_BRANCH
);
if( firstChngOnly ){
#if 0
blob_append_sql(&sql, ", min(event.mtime)");
#else
blob_append_sql(&sql,
", min(CASE (SELECT value FROM tagxref"
" WHERE tagtype>0 AND tagid=%d"
" AND tagxref.rid=mlink.mid)"
" WHEN 'trunk' THEN event.mtime-10000 ELSE event.mtime END)",
TAG_BRANCH);
#endif
}
blob_append_sql(&sql,
" FROM mlink, event"
" WHERE mlink.fnid IN (SELECT fnid FROM filename WHERE name=%Q)"
" AND event.objid=mlink.mid",
zFilename
);
if( baseCheckin ){
compute_direct_ancestors(baseCheckin, 10000000);
blob_append_sql(&sql," AND mlink.mid IN (SELECT rid FROM ancestor)");
}
if( (zA = P("a"))!=0 ){
blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zA);
url_add_parameter(&url, "a", zA);
}
if( (zB = P("b"))!=0 ){
blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zB);
url_add_parameter(&url, "b", zB);
}
if( firstChngOnly ){
blob_append_sql(&sql, " GROUP BY mlink.fid");
}
blob_append_sql(&sql," ORDER BY event.mtime DESC /*sort*/");
if( (n = atoi(PD("n","0")))>0 ){
blob_append_sql(&sql, " LIMIT %d", n);
url_add_parameter(&url, "n", P("n"));
}
if( baseCheckin==0 ){
if( firstChngOnly ){
style_submenu_element("Full", "Show all changes","%s",
url_render(&url, "fco", "0", 0, 0));
}else{
style_submenu_element("Simplified",
"Show only first use of a change","%s",
url_render(&url, "fco", 0, 0, 0));
}
}
db_prepare(&q, "%s", blob_sql_text(&sql));
if( P("showsql")!=0 ){
@ <p>SQL: %h(blob_str(&sql))</p>
}
blob_reset(&sql);
blob_zero(&title);
if( baseCheckin ){
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
|
| ︙ | ︙ | |||
471 472 473 474 475 476 477 |
@ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a> by check-in
fossil_free(zNewName);
}else{
@ <b>Deleted</b> by check-in
}
}
hyperlink_to_uuid(zCkin);
| | | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
@ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a> by check-in
fossil_free(zNewName);
}else{
@ <b>Deleted</b> by check-in
}
}
hyperlink_to_uuid(zCkin);
@ %W(zCom) (user:
hyperlink_to_user(zUser, zDate, "");
@ branch: %h(zBr))
if( g.perm.Hyperlink && zUuid ){
const char *z = zFilename;
@ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
@ [annotate]</a>
@ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
|
| ︙ | ︙ |
Changes to src/http.c.
| ︙ | ︙ | |||
165 166 167 168 169 170 171 |
char *zUser;
char *zPw;
char *zPrompt;
char *zHttpAuth = 0;
if( !isatty(fileno(stdin)) ) return 0;
zPrompt = mprintf("\n%s authorization required by\n%s\n",
g.url.isHttps==1 ? "Encrypted HTTPS" : "Unencrypted HTTP", g.url.canonical);
| | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
char *zUser;
char *zPw;
char *zPrompt;
char *zHttpAuth = 0;
if( !isatty(fileno(stdin)) ) return 0;
zPrompt = mprintf("\n%s authorization required by\n%s\n",
g.url.isHttps==1 ? "Encrypted HTTPS" : "Unencrypted HTTP", g.url.canonical);
fossil_print("%s", zPrompt);
free(zPrompt);
if ( g.url.user && g.url.passwd && use_fossil_creds_for_httpauth_prompt() ){
zHttpAuth = mprintf("%s:%s", g.url.user, g.url.passwd);
}else{
prompt_user("Basic Authorization user: ", &x);
zUser = mprintf("%b", &x);
zPrompt = mprintf("HTTP password for %b: ", &x);
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 |
int iHttpVersion; /* Which version of HTTP protocol server uses */
char *zLine; /* A single line of the reply header */
int i; /* Loop counter */
int isError = 0; /* True if the reply is an error message */
int isCompressed = 1; /* True if the reply is compressed */
if( transport_open(&g.url) ){
| | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
int iHttpVersion; /* Which version of HTTP protocol server uses */
char *zLine; /* A single line of the reply header */
int i; /* Loop counter */
int isError = 0; /* True if the reply is an error message */
int isCompressed = 1; /* True if the reply is compressed */
if( transport_open(&g.url) ){
fossil_warning("%s", transport_errmsg(&g.url));
return 1;
}
/* Construct the login card and prepare the complete payload */
blob_zero(&login);
if( useLogin ) http_build_login_card(pSend, &login);
if( g.fHttpTrace ){
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
533 534 535 536 537 538 539 |
" WHERE blob.rid=%d"
" AND event.objid=%d",
timeline_utc(), timeline_utc(), rid, rid
);
sideBySide = !is_false(PD("sbs","1"));
if( db_step(&q1)==SQLITE_ROW ){
const char *zUuid = db_column_text(&q1, 0);
| < | < | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
" WHERE blob.rid=%d"
" AND event.objid=%d",
timeline_utc(), timeline_utc(), rid, rid
);
sideBySide = !is_false(PD("sbs","1"));
if( db_step(&q1)==SQLITE_ROW ){
const char *zUuid = db_column_text(&q1, 0);
char *zEUser, *zEComment;
const char *zUser;
const char *zComment;
const char *zDate;
const char *zOrigDate;
style_header("Check-in [%S]", zUuid);
login_anonymous_available();
zEUser = db_text(0,
"SELECT value FROM tagxref"
" WHERE tagid=%d AND rid=%d AND tagtype>0",
TAG_USER, rid);
zEComment = db_text(0,
"SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
TAG_COMMENT, rid);
|
| ︙ | ︙ | |||
1580 1581 1582 1583 1584 1585 1586 |
rid = name_to_rid_www("name");
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
if( rid==0 ) fossil_redirect_home();
if( g.perm.Admin ){
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
| | | 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 |
rid = name_to_rid_www("name");
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
if( rid==0 ) fossil_redirect_home();
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","Unshun", "%s/shun?accept=%s&sub=1#delshun",
g.zTop, zUuid);
}else{
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
g.zTop, zUuid);
}
}
|
| ︙ | ︙ | |||
1766 1767 1768 1769 1770 1771 1772 |
}
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
if( rid==0 ) fossil_redirect_home();
if( g.perm.Admin ){
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
| | | | 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 |
}
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
if( rid==0 ) fossil_redirect_home();
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","Unshun", "%s/shun?accept=%s&sub=1#accshun",
g.zTop, zUuid);
}else{
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
g.zTop, zUuid);
}
}
if( descOnly || P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
style_header("%s", descOnly ? "Artifact Description" : "Artifact Content");
zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
if( g.perm.Setup ){
@ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
}else{
@ <h2>Artifact %s(zUuid):</h2>
}
blob_zero(&downloadName);
|
| ︙ | ︙ | |||
1882 1883 1884 1885 1886 1887 1888 |
char *zTktTitle;
login_check_credentials();
if( !g.perm.RdTkt ){ login_needed(); return; }
rid = name_to_rid_www("name");
if( rid==0 ){ fossil_redirect_home(); }
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
if( g.perm.Admin ){
| | | 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 |
char *zTktTitle;
login_check_credentials();
if( !g.perm.RdTkt ){ login_needed(); return; }
rid = name_to_rid_www("name");
if( rid==0 ){ fossil_redirect_home(); }
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
if( g.perm.Admin ){
if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){
style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun",
g.zTop, zUuid);
}else{
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
g.zTop, zUuid);
}
}
|
| ︙ | ︙ | |||
2027 2028 2029 2030 2031 2032 2033 |
return;
}else if( rc==2 ){
cgi_set_parameter("src","info");
ambiguous_page();
return;
}
zName = blob_str(&uuid);
| | | 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 |
return;
}else if( rc==2 ){
cgi_set_parameter("src","info");
ambiguous_page();
return;
}
zName = blob_str(&uuid);
rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
if( rid==0 ){
style_header("Broken Link");
@ <p>No such object: %h(zName)</p>
style_footer();
return;
}
if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
|
| ︙ | ︙ |
Changes to src/json.c.
| ︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 |
** to simplify the trivial use-cases (which don't need a Blob).
*/
cson_value * json_sql_to_array_of_obj(Blob * pSql, cson_array * pTgt,
char resetBlob){
Stmt q = empty_Stmt;
cson_value * pay = NULL;
assert( blob_size(pSql) > 0 );
| | | 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 |
** to simplify the trivial use-cases (which don't need a Blob).
*/
cson_value * json_sql_to_array_of_obj(Blob * pSql, cson_array * pTgt,
char resetBlob){
Stmt q = empty_Stmt;
cson_value * pay = NULL;
assert( blob_size(pSql) > 0 );
db_prepare(&q, "%s", blob_str(pSql) /*safe-for-%s*/);
if(resetBlob){
blob_reset(pSql);
}
pay = json_stmt_to_array_of_obj(&q, pTgt);
db_finalize(&q);
return pay;
|
| ︙ | ︙ | |||
1981 1982 1983 1984 1985 1986 1987 |
jv2 = cson_value_new_object();
jo2 = cson_value_get_object(jv2);
cson_object_set(jo, "sqlite", jv2);
sqlite3_snprintf(BufLen, zBuf, "%.19s [%.10s] (%s)",
sqlite3_sourceid(), &sqlite3_sourceid()[20], sqlite3_libversion());
SETBUF(jo2, "version");
zDb = db_name("repository");
| | | | | | | 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 |
jv2 = cson_value_new_object();
jo2 = cson_value_get_object(jv2);
cson_object_set(jo, "sqlite", jv2);
sqlite3_snprintf(BufLen, zBuf, "%.19s [%.10s] (%s)",
sqlite3_sourceid(), &sqlite3_sourceid()[20], sqlite3_libversion());
SETBUF(jo2, "version");
zDb = db_name("repository");
cson_object_set(jo2, "pageCount", cson_value_new_integer((cson_int_t)db_int(0, "PRAGMA \"%w\".page_count", zDb)));
cson_object_set(jo2, "pageSize", cson_value_new_integer((cson_int_t)db_int(0, "PRAGMA \"%w\".page_size", zDb)));
cson_object_set(jo2, "freeList", cson_value_new_integer((cson_int_t)db_int(0, "PRAGMA \"%w\".freelist_count", zDb)));
sqlite3_snprintf(BufLen, zBuf, "%s", db_text(0, "PRAGMA \"%w\".encoding", zDb));
SETBUF(jo2, "encoding");
sqlite3_snprintf(BufLen, zBuf, "%s", db_text(0, "PRAGMA \"%w\".journal_mode", zDb));
cson_object_set(jo2, "journalMode", *zBuf ? cson_value_new_string(zBuf, strlen(zBuf)) : cson_value_null());
return jv;
#undef SETBUF
}
|
| ︙ | ︙ | |||
2014 2015 2016 2017 2018 2019 2020 |
Blob * pOut, int filterByMode){
int i = 0;
for( ; zPages->name; ++zPages, ++i ){
if(filterByMode){
if(g.isHTTP && zPages->runMode < 0) continue;
else if(zPages->runMode > 0) continue;
}
| | | 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 |
Blob * pOut, int filterByMode){
int i = 0;
for( ; zPages->name; ++zPages, ++i ){
if(filterByMode){
if(g.isHTTP && zPages->runMode < 0) continue;
else if(zPages->runMode > 0) continue;
}
blob_append(pOut, zPages->name, -1);
if((zPages+1)->name){
blob_append(pOut, ", ",2);
}
}
return i;
}
|
| ︙ | ︙ |
Changes to src/json_config.c.
| ︙ | ︙ | |||
143 144 145 146 147 148 149 |
const struct JsonConfigProperty * prop = &JsonConfigProperties[0];
blob_append(&sql," OR name IN (",-1);
for( i = 0; prop->name; ++prop ){
if(prop->groupMask & confMask){
if( i++ ){
blob_append(&sql,",",1);
}
| | | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
const struct JsonConfigProperty * prop = &JsonConfigProperties[0];
blob_append(&sql," OR name IN (",-1);
for( i = 0; prop->name; ++prop ){
if(prop->groupMask & confMask){
if( i++ ){
blob_append(&sql,",",1);
}
blob_append_sql(&sql, "%Q", prop->name);
}
}
blob_append(&sql,") ", -1);
}
if( optSkinBackups ){
blob_append(&sql, " OR name GLOB 'skin:*'", -1);
}
blob_append(&sql," ORDER BY name", -1);
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
pay = cson_new_object();
while( (SQLITE_ROW==db_step(&q)) ){
cson_object_set(pay,
db_column_text(&q,0),
json_new_string(db_column_text(&q,1)));
}
|
| ︙ | ︙ |
Changes to src/json_finfo.c.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 |
}
zBefore = json_find_option_cstr("before",NULL,"b");
zAfter = json_find_option_cstr("after",NULL,"a");
limit = json_find_option_int("limit",NULL,"n", -1);
zCheckin = json_find_option_cstr("checkin",NULL,"ci");
| | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
}
zBefore = json_find_option_cstr("before",NULL,"b");
zAfter = json_find_option_cstr("after",NULL,"a");
limit = json_find_option_int("limit",NULL,"n", -1);
zCheckin = json_find_option_cstr("checkin",NULL,"ci");
blob_append_sql(&sql,
/*0*/ "SELECT b.uuid,"
/*1*/ " ci.uuid,"
/*2*/ " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */
/*3*/ " cast(strftime('%%s',event.mtime) AS INTEGER),"
/*4*/ " coalesce(event.euser, event.user),"
/*5*/ " coalesce(event.ecomment, event.comment),"
/*6*/ " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
|
| ︙ | ︙ | |||
91 92 93 94 95 96 97 |
/*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/
if(rc<=0){
json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND,
"Checkin UUID %s.", (rc<0) ? "is ambiguous" : "not found");
blob_reset(&sql);
return NULL;
}
| | | | | | < | 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 |
/*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/
if(rc<=0){
json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND,
"Checkin UUID %s.", (rc<0) ? "is ambiguous" : "not found");
blob_reset(&sql);
return NULL;
}
blob_append_sql(&sql, " AND ci.uuid='%q'", zU);
free(zU);
}else{
if( zAfter && *zAfter ){
blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zAfter);
sort = 1;
}else if( zBefore && *zBefore ){
blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zBefore);
}
}
blob_append_sql(&sql," ORDER BY event.mtime %s /*sort*/", (sort>0?"ASC":"DESC"));
/*printf("SQL=\n%s\n",blob_str(&sql));*/
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
pay = cson_new_object();
cson_object_set(pay, "name", json_new_string(zFilename));
if( limit > 0 ){
cson_object_set(pay, "limit", json_new_int(limit));
}
|
| ︙ | ︙ |
Changes to src/json_query.c.
| ︙ | ︙ | |||
62 63 64 65 66 67 68 |
json_set_err(FSL_JSON_E_MISSING_ARGS,
"'sql' (-s) argument is missing.");
return NULL;
}
zFmt = json_find_option_cstr2("format",NULL,"f",3);
if(!zFmt) zFmt = "o";
| | | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
json_set_err(FSL_JSON_E_MISSING_ARGS,
"'sql' (-s) argument is missing.");
return NULL;
}
zFmt = json_find_option_cstr2("format",NULL,"f",3);
if(!zFmt) zFmt = "o";
db_prepare(&q,"%s", zSql/*safe-for-%s*/);
if( 0 == sqlite3_column_count( q.pStmt ) ){
json_set_err(FSL_JSON_E_USAGE,
"Input query has no result columns. "
"Only SELECT-like queries are supported.");
db_finalize(&q);
return NULL;
}
|
| ︙ | ︙ |
Changes to src/json_report.c.
| ︙ | ︙ | |||
202 203 204 205 206 207 208 |
limit = json_find_option_int("limit",NULL,"n",-1);
/* Copy over report's SQL...*/
blob_append(&sql, db_column_text(&q,0), -1);
zTitle = mprintf("%s", db_column_text(&q,1));
db_finalize(&q);
| | | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
limit = json_find_option_int("limit",NULL,"n",-1);
/* Copy over report's SQL...*/
blob_append(&sql, db_column_text(&q,0), -1);
zTitle = mprintf("%s", db_column_text(&q,1));
db_finalize(&q);
db_prepare(&q, "%s", blob_sql_text(&sql));
/** Build the response... */
pay = cson_new_object();
cson_object_set(pay, "report", json_new_int(nReport));
cson_object_set(pay, "title", json_new_string(zTitle));
if(limit>0){
|
| ︙ | ︙ |
Changes to src/json_tag.c.
| ︙ | ︙ | |||
299 300 301 302 303 304 305 |
" AND event.type GLOB '%q'"
" AND blob.rid IN ("
" SELECT rid FROM tagxref"
" WHERE tagtype>0 AND tagid=%d"
" )"
" ORDER BY event.mtime DESC"
"%s LIMIT %d",
| | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
" AND event.type GLOB '%q'"
" AND blob.rid IN ("
" SELECT rid FROM tagxref"
" WHERE tagtype>0 AND tagid=%d"
" )"
" ORDER BY event.mtime DESC"
"%s LIMIT %d",
zSqlBase /*safe-for-%s*/, zType, tagid,
(limit>0)?"":"--", limit
);
listV = json_stmt_to_array_of_obj(&q, NULL);
db_finalize(&q);
}
if(!listV) {
|
| ︙ | ︙ | |||
440 441 442 443 444 445 446 |
-1
);
if(!fTicket){
blob_append(&sql, " AND tagname NOT GLOB('tkt-*') ", -1);
}
blob_append(&sql,
" ORDER BY tagname", -1);
| | | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
-1
);
if(!fTicket){
blob_append(&sql, " AND tagname NOT GLOB('tkt-*') ", -1);
}
blob_append(&sql,
" ORDER BY tagname", -1);
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
cson_object_set(pay, "includeTickets", cson_value_new_bool(fTicket) );
while( SQLITE_ROW == db_step(&q) ){
const char *zName = db_column_text(&q, 0);
if(NULL==arV){
arV = cson_value_new_array();
ar = cson_value_get_array(arV);
|
| ︙ | ︙ |
Changes to src/json_timeline.c.
| ︙ | ︙ | |||
81 82 83 84 85 86 87 |
@ bgColor TEXT,
@ eventType TEXT,
@ tags TEXT,
@ tagId INTEGER,
@ brief TEXT
@ )
;
| | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
@ bgColor TEXT,
@ eventType TEXT,
@ tags TEXT,
@ tagId INTEGER,
@ brief TEXT
@ )
;
db_multi_exec("%s", zSql /*safe-for-%s*/);
}
/*
** Return a pointer to a constant string that forms the basis
** for a timeline query for the JSON interface.
*/
char const * json_timeline_query(void){
|
| ︙ | ︙ | |||
382 383 384 385 386 387 388 |
" coalesce(euser, user) as user,"
" blob.rid IN leaf as isLeaf,"
" bgcolor as bgColor"
" FROM event JOIN blob"
" WHERE blob.rid=event.objid",
-1);
| | | | | 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 |
" coalesce(euser, user) as user,"
" blob.rid IN leaf as isLeaf,"
" bgcolor as bgColor"
" FROM event JOIN blob"
" WHERE blob.rid=event.objid",
-1);
blob_append_sql(&sql,
" AND event.type='ci'"
" AND blob.rid IN (SELECT rid FROM tagxref"
" WHERE tagtype>0 AND tagid=%d AND srcid!=0)"
" ORDER BY event.mtime DESC",
TAG_BRANCH);
limit = json_timeline_limit(20);
if(limit>0){
blob_append_sql(&sql," LIMIT %d ",limit);
}
db_prepare(&q,"%s", blob_sql_text(&sql));
blob_reset(&sql);
pay = json_stmt_to_array_of_obj(&q, NULL);
db_finalize(&q);
assert(NULL != pay);
if(pay){
/* get the array-form tags of each record. */
cson_string * tags = cson_new_string("tags",4);
|
| ︙ | ︙ | |||
480 481 482 483 484 485 486 |
} (void)0
#if 0
/* only for testing! */
tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
SET("timelineSql");
#endif
| | | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
} (void)0
#if 0
/* only for testing! */
tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
SET("timelineSql");
#endif
db_multi_exec("%s", blob_buffer(&sql)/*safe-for-%s*/);
blob_reset(&sql);
db_prepare(&q, "SELECT "
" rid AS rid"
" FROM json_timeline"
" ORDER BY rowid");
listV = cson_value_new_array();
list = cson_value_get_array(listV);
|
| ︙ | ︙ | |||
545 546 547 548 549 550 551 |
}
#if 0
/* only for testing! */
tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
SET("timelineSql");
#endif
| | | < | 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 |
}
#if 0
/* only for testing! */
tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)));
SET("timelineSql");
#endif
db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
blob_reset(&sql);
db_prepare(&q, "SELECT"
" uuid AS uuid,"
" mtime AS timestamp,"
#if 0
" timestampString AS timestampString,"
#endif
" comment AS comment, "
" user AS user,"
" eventType AS eventType"
#if 0
/* can wiki pages have tags? */
" tags AS tags," /*FIXME: split this into
a JSON array*/
" tagId AS tagId,"
#endif
" FROM json_timeline"
" ORDER BY rowid");
list = cson_new_array();
json_stmt_to_array_of_obj(&q, list);
cson_object_set(pay, "timeline", cson_array_value(list));
goto ok;
error:
assert( 0 != g.json.resultCode );
cson_value_free(payV);
|
| ︙ | ︙ | |||
605 606 607 608 609 610 611 |
pay = cson_value_get_object(payV);
check = json_timeline_setup_sql( "t", &sql, pay );
if(check){
json_set_err(check, "Query initialization failed.");
goto error;
}
| | | 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 |
pay = cson_value_get_object(payV);
check = json_timeline_setup_sql( "t", &sql, pay );
if(check){
json_set_err(check, "Query initialization failed.");
goto error;
}
db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
#define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \
json_set_err((cson_rc.AllocError==check) \
? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN, \
"Object property insertion failed."); \
goto error;\
} (void)0
|
| ︙ | ︙ | |||
636 637 638 639 640 641 642 |
" timestampString AS timestampString,"
#endif
" user AS user,"
" eventType AS eventType,"
" comment AS comment,"
" brief AS briefComment"
" FROM json_timeline"
| | < | 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
" timestampString AS timestampString,"
#endif
" user AS user,"
" eventType AS eventType,"
" comment AS comment,"
" brief AS briefComment"
" FROM json_timeline"
" ORDER BY rowid");
listV = cson_value_new_array();
list = cson_value_get_array(listV);
tmp = listV;
SET("timeline");
while( (SQLITE_ROW == db_step(&q) )){
/* convert each row into a JSON object...*/
int rc;
|
| ︙ | ︙ |
Changes to src/json_user.c.
| ︙ | ︙ | |||
284 285 286 287 288 289 290 |
}
forceLogout = cson_value_true()
/* reminders: 1) does not allocate.
2) we do this because changing a name
invalidates any login token because the old name
is part of the token hash.
*/;
| | | | | | | | | | | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
}
forceLogout = cson_value_true()
/* reminders: 1) does not allocate.
2) we do this because changing a name
invalidates any login token because the old name
is part of the token hash.
*/;
blob_append_sql(&sql, ", login=%Q", zNameNew);
++gotFields;
}
}
if( zCap && *zCap ){
if(!g.perm.Admin || !g.perm.Setup){
/* we "could" arguably silently ignore cap in this case. */
json_set_err(FSL_JSON_E_DENIED,
"Changing capabilities requires 'a' or 's' privileges.");
goto error;
}
blob_append_sql(&sql, ", cap=%Q", zCap);
++gotFields;
}
if( zPW && *zPW ){
if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
json_set_err( FSL_JSON_E_DENIED,
"Password change requires 'a', 's', "
"or 'p' permissions.");
goto error;
}else{
#define TRY_LOGIN_GROUP 0 /* login group support is not yet implemented. */
#if !TRY_LOGIN_GROUP
char * zPWHash = NULL;
++gotFields;
zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
blob_append_sql(&sql, ", pw=%Q", zPWHash);
free(zPWHash);
#else
++gotFields;
blob_append_sql(&sql, ", pw=coalesce(shared_secret(%Q,%Q,"
"(SELECT value FROM config WHERE name='project-code')))",
zPW, zNameNew ? zNameNew : zName);
/* shared_secret() func is undefined? */
#endif
}
}
if( zInfo ){
blob_append_sql(&sql, ", info=%Q", zInfo);
++gotFields;
}
if((g.perm.Admin || g.perm.Setup)
&& forceLogout && cson_value_get_bool(forceLogout)){
blob_append(&sql, ", cookie=NULL, cexpire=NULL", -1);
++gotFields;
}
if(!gotFields){
json_set_err( FSL_JSON_E_MISSING_ARGS,
"Required user data are missing.");
goto error;
}
assert(uid>0);
#if !TRY_LOGIN_GROUP
blob_append_sql(&sql, " WHERE uid=%d", uid);
#else /* need name for login group support :/ */
blob_append_sql(&sql, " WHERE login=%Q", zName);
#endif
#if 0
puts(blob_str(&sql));
cson_output_FILE( cson_object_value(pUser), stdout, NULL );
#endif
db_prepare(&q, "%s", blob_sql_text(&sql));
db_exec(&q);
db_finalize(&q);
#if TRY_LOGIN_GROUP
if( zPW || cson_value_get_bool(forceLogout) ){
Blob groupSql = empty_blob;
char * zErr = NULL;
blob_append_sql(&groupSql,
"INSERT INTO user(login)"
" SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
zName, zName
);
blob_append(&groupSql, blob_str(&sql), blob_size(&sql));
login_group_sql(blob_str(&groupSql), NULL, NULL, &zErr);
blob_reset(&groupSql);
|
| ︙ | ︙ |
Changes to src/json_wiki.c.
| ︙ | ︙ | |||
442 443 444 445 446 447 448 |
}
blob_append(&sql,"SELECT"
" substr(tagname,6) as name"
" FROM tag WHERE tagname GLOB 'wiki-*'",
-1);
zGlob = json_find_option_cstr("glob",NULL,"g");
if(zGlob && *zGlob){
| | | | | < | | 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 |
}
blob_append(&sql,"SELECT"
" substr(tagname,6) as name"
" FROM tag WHERE tagname GLOB 'wiki-*'",
-1);
zGlob = json_find_option_cstr("glob",NULL,"g");
if(zGlob && *zGlob){
blob_append_sql(&sql," AND name %s GLOB %Q",
fInvert ? "NOT" : "", zGlob);
}else{
zGlob = json_find_option_cstr("like",NULL,"l");
if(zGlob && *zGlob){
blob_append_sql(&sql," AND name %s LIKE %Q",
fInvert ? "NOT" : "", zGlob);
}
}
blob_append(&sql," ORDER BY lower(name)", -1);
db_prepare(&q,"%s", blob_sql_text(&sql));
blob_reset(&sql);
listV = cson_value_new_array();
list = cson_value_get_array(listV);
while( SQLITE_ROW == db_step(&q) ){
cson_value * v;
if( verbose ){
char const * name = db_column_text(&q,0);
|
| ︙ | ︙ |
Changes to src/leaf.c.
| ︙ | ︙ | |||
37 38 39 40 41 42 43 |
@ SELECT 1 FROM plink
@ WHERE pid=%d
@ AND coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.pid), 'trunk')
@ =coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.cid), 'trunk')
;
| > | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
@ SELECT 1 FROM plink
@ WHERE pid=%d
@ AND coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.pid), 'trunk')
@ =coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.cid), 'trunk')
;
rc = db_int(0, zSql /*works-like:"%d,%d,%d"*/,
rid, TAG_BRANCH, TAG_BRANCH);
return rc==0;
}
/*
** Count the number of primary non-branch children for the given check-in.
**
** A primary child is one where the parent is the primary parent, not
|
| ︙ | ︙ | |||
61 62 63 64 65 66 67 |
@ SELECT count(*) FROM plink
@ WHERE pid=:pid AND isprim
@ AND coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.pid), 'trunk')
@ =coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.cid), 'trunk')
;
| | | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
@ SELECT count(*) FROM plink
@ WHERE pid=:pid AND isprim
@ AND coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.pid), 'trunk')
@ =coalesce((SELECT value FROM tagxref
@ WHERE tagid=%d AND rid=plink.cid), 'trunk')
;
db_static_prepare(&q, zSql /*works-like: "%d,%d"*/, TAG_BRANCH, TAG_BRANCH);
db_bind_int(&q, ":pid", pid);
if( db_step(&q)==SQLITE_ROW ){
nNonBranch = db_column_int(&q, 0);
}
db_reset(&q);
return nNonBranch;
}
|
| ︙ | ︙ |
Changes to src/loadctrl.c.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 |
/*
** Return the load average for the host processor
*/
double load_average(void){
#if !defined(_WIN32) && !defined(FOSSIL_OMIT_LOAD_AVERAGE)
double a[3];
if( getloadavg(a, 3)>0 ){
| | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/*
** Return the load average for the host processor
*/
double load_average(void){
#if !defined(_WIN32) && !defined(FOSSIL_OMIT_LOAD_AVERAGE)
double a[3];
if( getloadavg(a, 3)>0 ){
return a[0]>=0.000001 ? a[0] : 0.000001;
}
#endif
return 0.0;
}
/*
** COMMAND: test-loadavg
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
393 394 395 396 397 398 399 |
if( prefix_match("spider", zAgent+i) ) return 0;
if( prefix_match("crawl", zAgent+i) ) return 0;
/* If a URI appears in the User-Agent, it is probably a bot */
if( strncmp("http", zAgent+i,4)==0 ) return 0;
}
if( strncmp(zAgent, "Mozilla/", 8)==0 ){
if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
| | | | | | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
if( prefix_match("spider", zAgent+i) ) return 0;
if( prefix_match("crawl", zAgent+i) ) return 0;
/* If a URI appears in the User-Agent, it is probably a bot */
if( strncmp("http", zAgent+i,4)==0 ) return 0;
}
if( strncmp(zAgent, "Mozilla/", 8)==0 ){
if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ) return 1; /* IE11+ */
if( sqlite3_strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent)==0 ) return 1;
return 0;
}
if( strncmp(zAgent, "Opera/", 6)==0 ) return 1;
if( strncmp(zAgent, "Safari/", 7)==0 ) return 1;
if( strncmp(zAgent, "Lynx/", 5)==0 ) return 1;
if( strncmp(zAgent, "NetSurf/", 8)==0 ) return 1;
return 0;
|
| ︙ | ︙ | |||
1292 1293 1294 1295 1296 1297 1298 |
@ %s(zUsername) already exists.
@ </span></p>
}else{
char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
int uid;
db_multi_exec(
"INSERT INTO user(login,pw,cap,info,mtime)"
| | | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 |
@ %s(zUsername) already exists.
@ </span></p>
}else{
char *zPw = sha1_shared_secret(blob_str(&passwd), blob_str(&login), 0);
int uid;
db_multi_exec(
"INSERT INTO user(login,pw,cap,info,mtime)"
"VALUES(%B,%Q,%B,%B,strftime('%%s','now'))",
&login, zPw, &caps, &contact
);
free(zPw);
/* The user is registered, now just log him in. */
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUsername);
login_set_user_cookie( zUsername, uid, NULL );
|
| ︙ | ︙ | |||
1467 1468 1469 1470 1471 1472 1473 |
const char *zSelf; /* The ATTACH name of our repository */
*pzErrMsg = 0; /* Default to no errors */
zSelf = db_name("repository");
/* Get the full pathname of the other repository */
file_canonical_name(zRepo, &fullName, 0);
| | | | 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 |
const char *zSelf; /* The ATTACH name of our repository */
*pzErrMsg = 0; /* Default to no errors */
zSelf = db_name("repository");
/* Get the full pathname of the other repository */
file_canonical_name(zRepo, &fullName, 0);
zRepo = fossil_strdup(blob_str(&fullName));
blob_reset(&fullName);
/* Get the full pathname for our repository. Also the project code
** and project name for ourself. */
file_canonical_name(g.zRepositoryName, &fullName, 0);
zSelfRepo = fossil_strdup(blob_str(&fullName));
blob_reset(&fullName);
zSelfProjCode = db_get("project-code", "unknown");
zSelfLabel = db_get("project-name", 0);
if( zSelfLabel==0 ){
zSelfLabel = zSelfProjCode;
}
|
| ︙ | ︙ | |||
1498 1499 1500 1501 1502 1503 1504 |
}
rc = sqlite3_open_v2(
zRepo, &pOther,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
g.zVfsName
);
if( rc!=SQLITE_OK ){
| | | 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 |
}
rc = sqlite3_open_v2(
zRepo, &pOther,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
g.zVfsName
);
if( rc!=SQLITE_OK ){
*pzErrMsg = fossil_strdup(sqlite3_errmsg(pOther));
}else{
rc = sqlite3_exec(pOther, "SELECT count(*) FROM user", 0, 0, pzErrMsg);
}
sqlite3_close(pOther);
if( rc ) return;
/* Attach the other repository. Make sure the username/password is
|
| ︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 | /* Create all the necessary CONFIG table entries on both the ** other repository and on our own repository. */ zSelfProjCode = abbreviated_project_code(zSelfProjCode); zOtherProjCode = abbreviated_project_code(zOtherProjCode); db_begin_transaction(); db_multi_exec( | | | | | | 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 |
/* Create all the necessary CONFIG table entries on both the
** other repository and on our own repository.
*/
zSelfProjCode = abbreviated_project_code(zSelfProjCode);
zOtherProjCode = abbreviated_project_code(zOtherProjCode);
db_begin_transaction();
db_multi_exec(
"DELETE FROM \"%w\".config WHERE name GLOB 'peer-*';"
"INSERT INTO \"%w\".config(name,value) VALUES('peer-repo-%q',%Q);"
"INSERT INTO \"%w\".config(name,value) "
" SELECT 'peer-name-%q', value FROM other.config"
" WHERE name='project-name';",
zSelf,
zSelf, zOtherProjCode, zRepo,
zSelf, zOtherProjCode
);
db_multi_exec(
"INSERT OR IGNORE INTO other.config(name,value)"
" VALUES('login-group-name',%Q);"
"INSERT OR IGNORE INTO other.config(name,value)"
" VALUES('login-group-code',lower(hex(randomblob(8))));",
zNewName
);
db_multi_exec(
"REPLACE INTO \"%w\".config(name,value)"
" SELECT name, value FROM other.config"
" WHERE name GLOB 'peer-*' OR name GLOB 'login-group-*'",
zSelf
);
db_end_transaction(0);
db_multi_exec("DETACH other");
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
167 168 169 170 171 172 173 | FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ int *aCommitFile; /* Array of files to be committed */ int markPrivate; /* All new artifacts are private if true */ int clockSkewSeen; /* True if clocks on client and server out of sync */ | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
FILE *httpIn; /* Accept HTTP input from here */
FILE *httpOut; /* Send HTTP output here */
int xlinkClusterOnly; /* Set when cloning. Only process clusters */
int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
int *aCommitFile; /* Array of files to be committed */
int markPrivate; /* All new artifacts are private if true */
int clockSkewSeen; /* True if clocks on client and server out of sync */
int wikiFlags; /* Wiki conversion flags applied to %W */
char isHTTP; /* True if server/CGI modes, else assume CLI. */
char javascriptHyperlink; /* If true, set href= using script, not HTML */
Blob httpHeader; /* Complete text of the HTTP request header */
UrlData url; /* Information about current URL */
const char *zLogin; /* Login name. NULL or "" if not logged in. */
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
** SSL client identity */
|
| ︙ | ︙ | |||
1719 1720 1721 1722 1723 1724 1725 |
if( zName && validate16(zName, strlen(zName)) ){
for(i=0; i<nRedirect; i++){
if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
zNotFound = azRedirect[i*2+1];
continue;
}
db_open_repository(azRedirect[i*2]);
| | | | | 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 |
if( zName && validate16(zName, strlen(zName)) ){
for(i=0; i<nRedirect; i++){
if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
zNotFound = azRedirect[i*2+1];
continue;
}
db_open_repository(azRedirect[i*2]);
if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%q*'", zName) ){
cgi_redirectf(azRedirect[i*2+1] /*works-like:"%s"*/, zName);
return;
}
db_close(1);
}
}
if( zNotFound ){
cgi_redirectf(zNotFound /*works-like:"%s"*/, zName);
}else{
@ <html>
@ <head><title>No Such Object</title></head>
@ <body>
@ <p>No such object: <b>%h(zName)</b></p>
@ </body>
cgi_reply();
|
| ︙ | ︙ | |||
1925 1926 1927 1928 1929 1930 1931 |
** --files GLOB comma-separate glob patterns for static file to serve
** --baseurl URL base URL (useful with reverse proxies)
** --scgi Interpret input as SCGI rather than HTTP
**
** See also: cgi, server, winsrv
*/
void cmd_http(void){
| | | 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 |
** --files GLOB comma-separate glob patterns for static file to serve
** --baseurl URL base URL (useful with reverse proxies)
** --scgi Interpret input as SCGI rather than HTTP
**
** See also: cgi, server, winsrv
*/
void cmd_http(void){
const char *zIpAddr = 0;
const char *zNotFound;
const char *zHost;
const char *zAltBase;
const char *zFileGlob;
int useSCGI;
/* The winhttp module passes the --files option as --files-urlenc with
|
| ︙ | ︙ | |||
1950 1951 1952 1953 1954 1955 1956 |
}
zNotFound = find_option("notfound", 0, 1);
g.useLocalauth = find_option("localauth", 0, 0)!=0;
g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
useSCGI = find_option("scgi", 0, 0)!=0;
zAltBase = find_option("baseurl", 0, 1);
if( zAltBase ) set_base_url(zAltBase);
| | > > > < | 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 |
}
zNotFound = find_option("notfound", 0, 1);
g.useLocalauth = find_option("localauth", 0, 0)!=0;
g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
useSCGI = find_option("scgi", 0, 0)!=0;
zAltBase = find_option("baseurl", 0, 1);
if( zAltBase ) set_base_url(zAltBase);
if( find_option("https",0,0)!=0 ){
zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
cgi_replace_parameter("HTTPS","on");
}
zHost = find_option("host", 0, 1);
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
g.cgiOutput = 1;
/* We should be done with options.. */
verify_all_options();
if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
fossil_fatal("no repository specified");
}
g.fullHttpReply = 1;
if( g.argc>=5 ){
g.httpIn = fossil_fopen(g.argv[2], "rb");
g.httpOut = fossil_fopen(g.argv[3], "wb");
zIpAddr = g.argv[4];
find_server_repository(0, 5);
}else{
g.httpIn = stdin;
g.httpOut = stdout;
find_server_repository(0, 2);
}
if( zIpAddr==0 ){
zIpAddr = cgi_ssh_remote_addr(0);
if( zIpAddr && zIpAddr[0] ){
g.fSshClient |= CGI_SSH_CLIENT;
}
|
| ︙ | ︙ |
Changes to src/main.mk.
| ︙ | ︙ | |||
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 | all: $(OBJDIR) $(APPNAME) install: $(APPNAME) mkdir -p $(INSTALLDIR) mv $(APPNAME) $(INSTALLDIR) $(OBJDIR): -mkdir $(OBJDIR) $(OBJDIR)/translate: $(SRCDIR)/translate.c $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion | > > > > > > | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | all: $(OBJDIR) $(APPNAME) install: $(APPNAME) mkdir -p $(INSTALLDIR) mv $(APPNAME) $(INSTALLDIR) codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1 $(OBJDIR)/codecheck1 $(TRANS_SRC) $(OBJDIR): -mkdir $(OBJDIR) $(OBJDIR)/translate: $(SRCDIR)/translate.c $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion |
| ︙ | ︙ | |||
428 429 430 431 432 433 434 | $(OBJDIR)/shell.o \ $(OBJDIR)/th.o \ $(OBJDIR)/th_lang.o \ $(OBJDIR)/th_tcl.o \ $(OBJDIR)/cson_amalgamation.o | | > | 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | $(OBJDIR)/shell.o \ $(OBJDIR)/th.o \ $(OBJDIR)/th_lang.o \ $(OBJDIR)/th_tcl.o \ $(OBJDIR)/cson_amalgamation.o $(APPNAME): $(OBJDIR)/headers $(OBJDIR)/codecheck1 $(OBJ) $(EXTRAOBJ) $(OBJDIR)/codecheck1 $(TRANS_SRC) $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
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 |
<<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
all: $(OBJDIR) $(APPNAME)
install: $(APPNAME)
mkdir -p $(INSTALLDIR)
mv $(APPNAME) $(INSTALLDIR)
$(OBJDIR):
-mkdir $(OBJDIR)
$(OBJDIR)/translate: $(SRCDIR)/translate.c
$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
$(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
$(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test: $(OBJDIR) $(APPNAME)
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
| > > > > > > | 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 |
<<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n "]] {
all: $(OBJDIR) $(APPNAME)
install: $(APPNAME)
mkdir -p $(INSTALLDIR)
mv $(APPNAME) $(INSTALLDIR)
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
$(OBJDIR)/codecheck1 $(TRANS_SRC)
$(OBJDIR):
-mkdir $(OBJDIR)
$(OBJDIR)/translate: $(SRCDIR)/translate.c
$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
$(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c
$(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
$(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
$(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
$(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c
$(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c
# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test: $(OBJDIR) $(APPNAME)
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
|
| ︙ | ︙ | |||
302 303 304 305 306 307 308 |
$(OBJDIR)/th.o <<<NEXT_LINE>>>
$(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
$(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
$(OBJDIR)/cson_amalgamation.o
}]
writeln {
| | > | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
$(OBJDIR)/th.o <<<NEXT_LINE>>>
$(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
$(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
$(OBJDIR)/cson_amalgamation.o
}]
writeln {
$(APPNAME): $(OBJDIR)/headers $(OBJDIR)/codecheck1 $(OBJ) $(EXTRAOBJ)
$(OBJDIR)/codecheck1 $(TRANS_SRC)
$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)
# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
$(SRCDIR)/../manifest:
# noop
|
| ︙ | ︙ | |||
503 504 505 506 507 508 509 | ZLIBDIR = $(SRCDIR)/../compat/zlib #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # | | | | 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | ZLIBDIR = $(SRCDIR)/../compat/zlib #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1j/include OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1j #### Either the directory where the Tcl library is installed or the Tcl # source code directory resides (depending on the value of the macro # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, # this directory must have "include" and "lib" sub-directories. If # this points to the Tcl source code directory, this directory must # have "generic" and "win" sub-directories. The recommended usage |
| ︙ | ︙ | |||
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 | # recognized internally by make. # ifdef USE_WINDOWS TRANSLATE = $(subst /,\,$(OBJDIR)/translate.exe) MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe) MKINDEX = $(subst /,\,$(OBJDIR)/mkindex.exe) VERSION = $(subst /,\,$(OBJDIR)/version.exe) CAT = type CP = copy GREP = find MV = copy RM = del /Q MKDIR = -mkdir RMDIR = rmdir /S /Q else TRANSLATE = $(OBJDIR)/translate.exe MAKEHEADERS = $(OBJDIR)/makeheaders.exe MKINDEX = $(OBJDIR)/mkindex.exe VERSION = $(OBJDIR)/version.exe CAT = cat CP = cp GREP = grep MV = mv RM = rm -f MKDIR = -mkdir -p RMDIR = rm -rf | > > | 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 | # recognized internally by make. # ifdef USE_WINDOWS TRANSLATE = $(subst /,\,$(OBJDIR)/translate.exe) MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe) MKINDEX = $(subst /,\,$(OBJDIR)/mkindex.exe) VERSION = $(subst /,\,$(OBJDIR)/version.exe) CODECHECK1 = $(subst /,\,$(OBJDIR)/codecheck1.exe) CAT = type CP = copy GREP = find MV = copy RM = del /Q MKDIR = -mkdir RMDIR = rmdir /S /Q else TRANSLATE = $(OBJDIR)/translate.exe MAKEHEADERS = $(OBJDIR)/makeheaders.exe MKINDEX = $(OBJDIR)/mkindex.exe VERSION = $(OBJDIR)/version.exe CODECHECK1 = $(OBJDIR)/codecheck1.exe CAT = cat CP = cp GREP = grep MV = mv RM = rm -f MKDIR = -mkdir -p RMDIR = rm -rf |
| ︙ | ︙ | |||
817 818 819 820 821 822 823 824 825 826 827 828 829 830 | $(MKINDEX): $(SRCDIR)/mkindex.c $(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c $(VERSION): $(SRCDIR)/mkversion.c $(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION) | > > > | 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 | $(MKINDEX): $(SRCDIR)/mkindex.c $(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c $(VERSION): $(SRCDIR)/mkversion.c $(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c $(CODECHECK1): $(SRCDIR)/codecheck1.c $(BCC) -o $(CODECHECK1) $(SRCDIR)/codecheck1.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION) |
| ︙ | ︙ | |||
884 885 886 887 888 889 890 | APPTARGETS += $(LIBTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif | | > | 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | APPTARGETS += $(LIBTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif $(APPNAME): $(OBJDIR)/headers $(OBJ) $(CODECHECK1) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(APPTARGETS) $(CODECHECK1) $(TRANS_SRC) $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop |
| ︙ | ︙ | |||
1035 1036 1037 1038 1039 1040 1041 | RC=$(DMDIR)\bin\rcc RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ APPNAME = $(OBJDIR)\fossil$(E) all: $(APPNAME) | | > | 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | RC=$(DMDIR)\bin\rcc RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ APPNAME = $(OBJDIR)\fossil$(E) all: $(APPNAME) $(APPNAME) : translate$E mkindex$E codecheck1$E headers $(OBJ) $(OBJDIR)\link cd $(OBJDIR) codecheck1$E $(SRC) $(DMDIR)\bin\link @link $(OBJDIR)\fossil.res: $B\win\fossil.rc $(RC) $(RCFLAGS) -o$@ $** $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res} writeln -nonewline "\t+echo " |
| ︙ | ︙ | |||
1064 1065 1066 1067 1068 1069 1070 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) -o$@ $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) -o$@ $** | | > > > | | | 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) -o$@ $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) -o$@ $** mkversion$E: $(SRCDIR)\mkversion.c $(BCC) -o$@ $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) -o$@ $** $(OBJDIR)\shell$O : $(SRCDIR)\shell.c $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $** $(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c $(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $** $(OBJDIR)\th$O : $(SRCDIR)\th.c $(TCC) -o$@ -c $** $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c $(TCC) -o$@ -c $** $(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h cp $@ $@ VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION +$** > $@ page_index.h: mkindex$E $(SRC) +$** > $@ clean: -del $(OBJDIR)\*.obj -del *.obj *_.c *.h *.map realclean: -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E codecheck1$E $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h |
| ︙ | ︙ | |||
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 |
set output_file [open ../win/Makefile.msc w]
fconfigure $output_file -translation binary
writeln {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B = ..
SRCDIR = $B\src
| > > > > > > > > | 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 |
set output_file [open ../win/Makefile.msc w]
fconfigure $output_file -translation binary
writeln {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################
#
# This Makefile will only function correctly if used from a sub-directory
# that is a direct child of the top-level directory for this project.
#
!if !exist("..\.fossil-settings")
!error "Please change the current directory to the one containing this file."
!endif
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B = ..
SRCDIR = $B\src
|
| ︙ | ︙ | |||
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 | # be built from source code. The PERLDIR variable should point to # the directory containing the main Perl binary (i.e. "perl.exe"). PERLDIR = C:\Perl\bin PERL = perl.exe # Uncomment to enable debug symbols # DEBUG = 1 # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable miniz usage # FOSSIL_ENABLE_MINIZ = 1 | > > > | 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 | # be built from source code. The PERLDIR variable should point to # the directory containing the main Perl binary (i.e. "perl.exe"). PERLDIR = C:\Perl\bin PERL = perl.exe # Uncomment to enable debug symbols # DEBUG = 1 # Uncomment to support Windows XP with Visual Studio 201x # FOSSIL_ENABLE_WINXP = 1 # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable miniz usage # FOSSIL_ENABLE_MINIZ = 1 |
| ︙ | ︙ | |||
1187 1188 1189 1190 1191 1192 1193 | # Uncomment to enable TH1 hooks # FOSSIL_ENABLE_TH1_HOOKS = 1 # Uncomment to enable Tcl support # FOSSIL_ENABLE_TCL = 1 !ifdef FOSSIL_ENABLE_SSL | | > | 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 | # Uncomment to enable TH1 hooks # FOSSIL_ENABLE_TH1_HOOKS = 1 # Uncomment to enable Tcl support # FOSSIL_ENABLE_TCL = 1 !ifdef FOSSIL_ENABLE_SSL SSLDIR = $(B)\compat\openssl-1.0.1j SSLINCDIR = $(SSLDIR)\inc32 SSLLIBDIR = $(SSLDIR)\out32 SSLLFLAGS = /nologo /opt:ref /debug SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" !message Using 'x64' platform for OpenSSL... SSLCONFIG = VC-WIN64A no-asm SSLSETUP = ms\do_win64a.bat SSLNMAKE = ms\nt.mak all !elseif "$(PLATFORM)"=="ia64" |
| ︙ | ︙ | |||
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 | !ifdef FOSSIL_ENABLE_TCL INCL = $(INCL) /I$(TCLINCDIR) !endif CFLAGS = /nologo LDFLAGS = /NODEFAULTLIB:msvcrt /MANIFEST:NO !ifdef DEBUG CFLAGS = $(CFLAGS) /Zi /MTd /Od LDFLAGS = $(LDFLAGS) /DEBUG !else CFLAGS = $(CFLAGS) /MT /O2 !endif | > > > > > > > > > > > | 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | !ifdef FOSSIL_ENABLE_TCL INCL = $(INCL) /I$(TCLINCDIR) !endif CFLAGS = /nologo LDFLAGS = /NODEFAULTLIB:msvcrt /MANIFEST:NO !ifdef FOSSIL_ENABLE_WINXP XPCFLAGS = $(XPCFLAGS) /D_USING_V110_SDK71_=1 CFLAGS = $(CFLAGS) $(XPCFLAGS) !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" XPLDFLAGS = $(XPLDFLAGS) /SUBSYSTEM:CONSOLE,5.02 !else XPLDFLAGS = $(XPLDFLAGS) /SUBSYSTEM:CONSOLE,5.01 !endif LDFLAGS = $(LDFLAGS) $(XPLDFLAGS) !endif !ifdef DEBUG CFLAGS = $(CFLAGS) /Zi /MTd /Od LDFLAGS = $(LDFLAGS) /DEBUG !else CFLAGS = $(CFLAGS) /MT /O2 !endif |
| ︙ | ︙ | |||
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 | PDBNAME = $(OX)\fossil$(P) APPTARGETS = all: $(OX) $(APPNAME) zlib: @echo Building zlib from "$(ZLIBDIR)"... @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) && popd !ifdef FOSSIL_ENABLE_SSL openssl: @echo Building OpenSSL from "$(SSLDIR)"... !if "$(PERLDIR)" != "" @set PATH=$(PERLDIR);$(PATH) !endif @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd !endif !ifndef FOSSIL_ENABLE_MINIZ APPTARGETS = $(APPTARGETS) zlib !endif !ifdef FOSSIL_ENABLE_SSL !ifdef FOSSIL_BUILD_SSL APPTARGETS = $(APPTARGETS) openssl !endif !endif | > > > > > > > > | > | 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 |
PDBNAME = $(OX)\fossil$(P)
APPTARGETS =
all: $(OX) $(APPNAME)
zlib:
@echo Building zlib from "$(ZLIBDIR)"...
!ifdef FOSSIL_ENABLE_WINXP
@pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) "CC=cl $(XPCFLAGS)" "LD=link $(XPLDFLAGS)" && popd
!else
@pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) && popd
!endif
!ifdef FOSSIL_ENABLE_SSL
openssl:
@echo Building OpenSSL from "$(SSLDIR)"...
!if "$(PERLDIR)" != ""
@set PATH=$(PERLDIR);$(PATH)
!endif
@pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd
@pushd "$(SSLDIR)" && call $(SSLSETUP) && popd
!ifdef FOSSIL_ENABLE_WINXP
@pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd
!else
@pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd
!endif
!endif
!ifndef FOSSIL_ENABLE_MINIZ
APPTARGETS = $(APPTARGETS) zlib
!endif
!ifdef FOSSIL_ENABLE_SSL
!ifdef FOSSIL_BUILD_SSL
APPTARGETS = $(APPTARGETS) openssl
!endif
!endif
$(APPNAME) : $(APPTARGETS) translate$E mkindex$E codecheck1$E headers $(OBJ) $(OX)\linkopts
cd $(OX)
codecheck1$E $(SRC)
link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts
$(OX)\linkopts: $B\win\Makefile.msc}
set redir {>}
foreach s [lsort [concat $src $AdditionalObj]] {
writeln "\techo \$(OX)\\$s.obj $redir \$@"
set redir {>>}
|
| ︙ | ︙ | |||
1393 1394 1395 1396 1397 1398 1399 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) $** | | > > > | 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) $** mkversion$E: $(SRCDIR)\mkversion.c $(BCC) $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) $** $(OX)\shell$O : $(SRCDIR)\shell.c $B\win\Makefile.msc $(TCC) /Fo$@ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)\shell.c $(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c $B\win\Makefile.msc $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SRCDIR)\sqlite3.c |
| ︙ | ︙ | |||
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 | -del translate$P -del mkindex$E -del mkindex$P -del makeheaders$E -del makeheaders$P -del mkversion$E -del mkversion$P $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h | > > | 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 | -del translate$P -del mkindex$E -del mkindex$P -del makeheaders$E -del makeheaders$P -del mkversion$E -del mkversion$P -del codecheck1$E -del codecheck1$P $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h |
| ︙ | ︙ |
Changes to src/manifest.c.
| ︙ | ︙ | |||
376 377 378 379 380 381 382 | /* Every control 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); n = blob_size(pContent); | | | | 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
/* Every control 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);
n = blob_size(pContent);
if( pErr && (n<=0 || z[n-1]!='\n') ){
blob_reset(pContent);
blob_append(pErr, n ? "not terminated with \\n" : "zero-length", -1);
return 0;
}
/* Strip off the PGP signature if there is one.
*/
remove_pgp_signature(&z, &n);
|
| ︙ | ︙ | |||
1587 1588 1589 1590 1591 1592 1593 |
blob_zero(&brief);
if( once ){
once = 0;
zTitleExpr = db_get("ticket-title-expr", "title");
zStatusColumn = db_get("ticket-status-column", "status");
}
zTitle = db_text("unknown",
| | | | 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 |
blob_zero(&brief);
if( once ){
once = 0;
zTitleExpr = db_get("ticket-title-expr", "title");
zStatusColumn = db_get("ticket-status-column", "status");
}
zTitle = db_text("unknown",
"SELECT \"%w\" FROM ticket WHERE tkt_uuid=%Q",
zTitleExpr, pManifest->zTicketUuid
);
if( !isNew ){
for(i=0; i<pManifest->nField; i++){
if( fossil_strcmp(pManifest->aField[i].zName, zStatusColumn)==0 ){
zNewStatus = pManifest->aField[i].zValue;
}
}
if( zNewStatus ){
blob_appendf(&comment, "%h ticket [%s|%S]: <i>%h</i>",
zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle
);
if( pManifest->nField>1 ){
blob_appendf(&comment, " plus %d other change%s",
pManifest->nField-1, pManifest->nField==2 ? "" : "s");
}
blob_appendf(&brief, "%h ticket [%s|%S].",
zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid);
}else{
zNewStatus = db_text("unknown",
"SELECT \"%w\" FROM ticket WHERE tkt_uuid=%Q",
zStatusColumn, pManifest->zTicketUuid
);
blob_appendf(&comment, "Ticket [%s|%S] <i>%h</i> status still %h with "
"%d other change%s",
pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle, zNewStatus,
pManifest->nField, pManifest->nField==1 ? "" : "s"
);
|
| ︙ | ︙ | |||
1892 1893 1894 1895 1896 1897 1898 |
" bgcolor,euser,ecomment)"
"VALUES('w',%.17g,%d,%Q,%Q,"
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>1),"
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
p->rDate, rid, p->zUser, zComment,
TAG_BGCOLOR, rid,
| < | 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 |
" bgcolor,euser,ecomment)"
"VALUES('w',%.17g,%d,%Q,%Q,"
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>1),"
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
p->rDate, rid, p->zUser, zComment,
TAG_BGCOLOR, rid,
TAG_USER, rid,
TAG_COMMENT, rid
);
fossil_free(zComment);
}
if( p->type==CFTYPE_EVENT ){
char *zTag = mprintf("event-%s", p->zEventId);
|
| ︙ | ︙ | |||
2024 2025 2026 2027 2028 2029 2030 |
if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
blob_appendf(&comment,
" Edit [%s|%S]:",
zTagUuid, zTagUuid);
branchMove = 0;
if( permitHooks && db_exists("SELECT 1 FROM event, blob"
" WHERE event.type='ci' AND event.objid=blob.rid"
| | | 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 |
if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
blob_appendf(&comment,
" Edit [%s|%S]:",
zTagUuid, zTagUuid);
branchMove = 0;
if( permitHooks && db_exists("SELECT 1 FROM event, blob"
" WHERE event.type='ci' AND event.objid=blob.rid"
" AND blob.uuid=%Q", zTagUuid) ){
zScript = xfer_commit_code();
zUuid = zTagUuid;
}
}
zName = p->aTag[i].zName;
zValue = p->aTag[i].zValue;
if( strcmp(zName, "*branch")==0 ){
|
| ︙ | ︙ |
Changes to src/merge3.c.
| ︙ | ︙ | |||
266 267 268 269 270 271 272 |
*/
int sz = 1; /* Size of the conflict in lines */
nConflict++;
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
sz++;
}
DEBUG( printf("CONFLICT %d\n", sz); )
| | | | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
*/
int sz = 1; /* Size of the conflict in lines */
nConflict++;
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
sz++;
}
DEBUG( printf("CONFLICT %d\n", sz); )
blob_append(pOut, mergeMarker[0], -1);
i1 = output_one_side(pOut, pV1, aC1, i1, sz);
blob_append(pOut, mergeMarker[1], -1);
blob_copy_lines(pOut, pPivot, sz);
blob_append(pOut, mergeMarker[2], -1);
i2 = output_one_side(pOut, pV2, aC2, i2, sz);
blob_append(pOut, mergeMarker[3], -1);
}
/* If we are finished with an edit triple, advance to the next
** triple.
*/
if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3;
if( i2<limit2 && aC2[i2]==0 && aC2[i2+1]==0 && aC2[i2+2]==0 ) i2+=3;
|
| ︙ | ︙ |
Changes to src/moderate.c.
| ︙ | ︙ | |||
71 72 73 74 75 76 77 |
"mlink", "mid",
"mlink", "fid",
"tagxref", "srcid",
"tagxref", "rid",
};
int i;
for(i=0; i<sizeof(aTabField)/sizeof(aTabField[0]); i+=2){
| | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
"mlink", "mid",
"mlink", "fid",
"tagxref", "srcid",
"tagxref", "rid",
};
int i;
for(i=0; i<sizeof(aTabField)/sizeof(aTabField[0]); i+=2){
if( db_exists("SELECT 1 FROM \"%w\" WHERE \"%w\"=%d",
aTabField[i], aTabField[i+1], rid) ) return 1;
}
return 0;
}
/*
** Delete a moderation item given by objid
|
| ︙ | ︙ | |||
150 151 152 153 154 155 156 |
login_check_credentials();
if( !g.perm.RdWiki && !g.perm.RdTkt ){ login_needed(); return; }
style_header("Pending Moderation Requests");
@ <h2>All Pending Moderation Requests</h2>
if( moderation_table_exists() ){
blob_init(&sql, timeline_query_for_www(), -1);
| | | | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
login_check_credentials();
if( !g.perm.RdWiki && !g.perm.RdTkt ){ login_needed(); return; }
style_header("Pending Moderation Requests");
@ <h2>All Pending Moderation Requests</h2>
if( moderation_table_exists() ){
blob_init(&sql, timeline_query_for_www(), -1);
blob_append_sql(&sql,
" AND event.objid IN (SELECT objid FROM modreq)"
" ORDER BY event.mtime DESC"
);
db_prepare(&q, "%s", blob_sql_text(&sql));
www_print_timeline(&q, 0, 0, 0, 0);
db_finalize(&q);
}
style_footer();
}
|
Changes to src/name.c.
| ︙ | ︙ | |||
214 215 216 217 218 219 220 |
if( nTag>=4 && nTag<=UUID_SIZE && validate16(zTag, nTag) ){
Stmt q;
char zUuid[UUID_SIZE+1];
memcpy(zUuid, zTag, nTag+1);
canonical16(zUuid, nTag);
rid = 0;
if( zType[0]=='*' ){
| | | | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
if( nTag>=4 && nTag<=UUID_SIZE && validate16(zTag, nTag) ){
Stmt q;
char zUuid[UUID_SIZE+1];
memcpy(zUuid, zTag, nTag+1);
canonical16(zUuid, nTag);
rid = 0;
if( zType[0]=='*' ){
db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUuid);
}else{
db_prepare(&q,
"SELECT blob.rid"
" FROM blob, event"
" WHERE blob.uuid GLOB '%q*'"
" AND event.objid=blob.rid"
" AND event.type GLOB '%q'",
zUuid, zType
);
}
if( db_step(&q)==SQLITE_ROW ){
rid = db_column_int(&q, 0);
|
| ︙ | ︙ | |||
257 258 259 260 261 262 263 |
if( strcmp(zType,"*")==0 ){
rid = atoi(zTag);
}else{
rid = db_int(0,
"SELECT event.objid"
" FROM event"
" WHERE event.objid=%s"
| | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
if( strcmp(zType,"*")==0 ){
rid = atoi(zTag);
}else{
rid = db_int(0,
"SELECT event.objid"
" FROM event"
" WHERE event.objid=%s"
" AND event.type GLOB '%q'", zTag /*safe-for-%s*/, zType);
}
}
}
return rid;
}
/*
|
| ︙ | ︙ | |||
552 553 554 555 556 557 558 |
/* Report any HIDDEN, PRIVATE, CLUSTER, or CLOSED tags on this artifact */
db_prepare(&q,
"SELECT tagname"
" FROM tag JOIN tagxref ON tag.tagid=tagxref.tagid"
" WHERE tagxref.rid=%d"
" AND tag.tagid IN (5,6,7,9)"
" ORDER BY 1",
| | | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
/* Report any HIDDEN, PRIVATE, CLUSTER, or CLOSED tags on this artifact */
db_prepare(&q,
"SELECT tagname"
" FROM tag JOIN tagxref ON tag.tagid=tagxref.tagid"
" WHERE tagxref.rid=%d"
" AND tag.tagid IN (5,6,7,9)"
" ORDER BY 1",
rid
);
cnt = 0;
while( db_step(&q)==SQLITE_ROW ){
const char *zPrefix = cnt++ ? ", " : "raw-tags: ";
fossil_print("%s%s", zPrefix, db_column_text(&q,0));
}
if( cnt ) fossil_print("\n");
|
| ︙ | ︙ |
Changes to src/path.c.
| ︙ | ︙ | |||
110 111 112 113 114 115 116 | /* ** Compute the shortest path from iFrom to iTo ** ** If directOnly is true, then use only the "primary" links from parent to ** child. In other words, ignore merges. ** | | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | /* ** Compute the shortest path from iFrom to iTo ** ** If directOnly is true, then use only the "primary" links from parent to ** child. In other words, ignore merges. ** ** Return a pointer to the beginning of the path (the iFrom node). ** Elements of the path can be traversed by following the PathNode.u.pTo ** pointer chain. ** ** Return NULL if no path is found. */ PathNode *path_shortest( int iFrom, /* Path starts here */ |
| ︙ | ︙ | |||
133 134 135 136 137 138 139 |
path_reset();
path.pStart = path_new_node(iFrom, 0, 0);
if( iTo==iFrom ){
path.pEnd = path.pStart;
return path.pStart;
}
if( oneWayOnly && directOnly ){
| | | | | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
path_reset();
path.pStart = path_new_node(iFrom, 0, 0);
if( iTo==iFrom ){
path.pEnd = path.pStart;
return path.pStart;
}
if( oneWayOnly && directOnly ){
db_prepare(&s,
"SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim"
);
}else if( oneWayOnly ){
db_prepare(&s,
"SELECT cid, 1 FROM plink WHERE pid=:pid "
);
}else if( directOnly ){
db_prepare(&s,
"SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
"UNION ALL "
"SELECT pid, 0 FROM plink WHERE cid=:pid AND isprim"
);
}else{
db_prepare(&s,
"SELECT cid, 1 FROM plink WHERE pid=:pid "
"UNION ALL "
"SELECT pid, 0 FROM plink WHERE cid=:pid"
);
}
while( path.pCurrent ){
path.nStep++;
|
| ︙ | ︙ | |||
228 229 230 231 232 233 234 |
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
" FROM blob, event"
" WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
p->rid, p->rid);
fossil_print("%4d: %5d %s", n, p->rid, z);
fossil_free(z);
if( p->u.pTo ){
| | | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
"SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
" FROM blob, event"
" WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
p->rid, p->rid);
fossil_print("%4d: %5d %s", n, p->rid, z);
fossil_free(z);
if( p->u.pTo ){
fossil_print(" is a %s of\n",
p->u.pTo->fromIsParent ? "parent" : "child");
}else{
fossil_print("\n");
}
}
}
|
| ︙ | ︙ | |||
351 352 353 354 355 356 357 | }; /* ** Compute all file name changes that occur going from checkin iFrom ** to checkin iTo. ** ** The number of name changes is written into *pnChng. For each name | | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | }; /* ** Compute all file name changes that occur going from checkin iFrom ** to checkin iTo. ** ** The number of name changes is written into *pnChng. For each name ** change, two integers are allocated for *piChng. The first is the ** filename.fnid for the original name as seen in check-in iFrom and ** the second is for new name as it is used in check-in iTo. ** ** Space to hold *piChng is obtained from fossil_malloc() and should ** be released by the caller. ** ** This routine really has nothing to do with path. It is located |
| ︙ | ︙ | |||
514 515 516 517 518 519 520 |
fossil_free(aChng);
g.argv += 2;
g.argc -= 2;
}
}
/* Query to extract all rename operations */
| | | | | 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 |
fossil_free(aChng);
g.argv += 2;
g.argc -= 2;
}
}
/* Query to extract all rename operations */
static const char zRenameQuery[] =
@ SELECT
@ datetime(event.mtime),
@ F.name AS old_name,
@ T.name AS new_name,
@ blob.uuid
@ FROM mlink, filename F, filename T, event, blob
@ WHERE coalesce(mlink.pfnid,0)!=0 AND mlink.pfnid!=mlink.fnid
@ AND F.fnid=mlink.pfnid
@ AND T.fnid=mlink.fnid
@ AND event.objid=mlink.mid
@ AND event.type='ci'
@ AND blob.rid=mlink.mid
@ ORDER BY 1 DESC, 2;
;
/*
** WEBPAGE: test-rename-list
**
** Print a list of all file rename operations throughout history.
** This page is intended for for testing purposes only and may change
** or be discontinued without notice.
*/
void test_rename_list_page(void){
Stmt q;
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
style_header("List Of File Name Changes");
@ <h3>NB: Experimental Page</h3>
@ <table border="1" width="100%%">
@ <tr><th>Date & Time</th>
@ <th>Old Name</th>
@ <th>New Name</th>
@ <th>Check-in</th></tr>
db_prepare(&q, "%s", zRenameQuery/*safe-for-%s*/);
while( db_step(&q)==SQLITE_ROW ){
const char *zDate = db_column_text(&q, 0);
const char *zOld = db_column_text(&q, 1);
const char *zNew = db_column_text(&q, 2);
const char *zUuid = db_column_text(&q, 3);
@ <tr>
@ <td>%z(href("%R/timeline?c=%t",zDate))%s(zDate)</a></td>
|
| ︙ | ︙ |
Changes to src/printf.c.
| ︙ | ︙ | |||
42 43 44 45 46 47 48 |
#define etERROR 10 /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
#define etBLOB 11 /* Blob objects. %b */
#define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
#define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
| > | | | | | | | | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#define etERROR 10 /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
#define etBLOB 11 /* Blob objects. %b */
#define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
#define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etSQLESCAPE3 15 /* Double '"' characters within an indentifier. %w */
#define etPOINTER 16 /* The %p conversion */
#define etHTMLIZE 17 /* Make text safe for HTML */
#define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
#define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
#define etFOSSILIZE 20 /* The fossil header encoding format. */
#define etPATH 21 /* Path type */
#define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */
#define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
#define etROOT 24 /* String value of g.zTop: %R */
/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;
|
| ︙ | ︙ | |||
94 95 96 97 98 99 100 |
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
{ 'b', 0, 2, etBLOB, 0, 0 },
{ 'B', 0, 2, etBLOBSQL, 0, 0 },
| | > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
{ 'b', 0, 2, etBLOB, 0, 0 },
{ 'B', 0, 2, etBLOBSQL, 0, 0 },
{ 'W', 0, 2, etWIKISTR, 0, 0 },
{ 'h', 0, 4, etHTMLIZE, 0, 0 },
{ 'R', 0, 0, etROOT, 0, 0 },
{ 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */
{ 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 },
{ 'F', 0, 4, etFOSSILIZE, 0, 0 },
{ 'S', 0, 4, etSTRINGID, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etRADIX, 0, 0 },
{ 'x', 16, 0, etRADIX, 16, 1 },
{ 'X', 16, 0, etRADIX, 0, 4 },
|
| ︙ | ︙ | |||
659 660 661 662 663 664 665 |
}
bufpt[j++] = '\'';
length = j;
assert( length==n+cnt+2 );
break;
}
case etSQLESCAPE:
| > | > | | | | | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
}
bufpt[j++] = '\'';
length = j;
assert( length==n+cnt+2 );
break;
}
case etSQLESCAPE:
case etSQLESCAPE2:
case etSQLESCAPE3: {
int i, j, n, ch, isnull;
int needQuote;
int limit = flag_alternateform ? va_arg(ap,int) : -1;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote characters */
char *escarg = va_arg(ap,char*);
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
if( limit<0 ) limit = strlen(escarg);
for(i=n=0; i<limit; i++){
if( escarg[i]==q ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = fossil_malloc( n );
}else{
bufpt = buf;
}
j = 0;
if( needQuote ) bufpt[j++] = q;
for(i=0; i<limit; i++){
bufpt[j++] = ch = escarg[i];
if( ch==q ) bufpt[j++] = ch;
}
if( needQuote ) bufpt[j++] = q;
bufpt[j] = 0;
length = j;
if( precision>=0 && precision<length ) length = precision;
break;
}
case etHTMLIZE: {
int limit = flag_alternateform ? va_arg(ap,int) : -1;
|
| ︙ | ︙ |
Changes to src/rebuild.c.
| ︙ | ︙ | |||
79 80 81 82 83 84 85 |
@ cols TEXT, -- A color-key specification
@ sqlcode TEXT -- An SQL SELECT statement for this report
@ );
;
static void rebuild_update_schema(void){
int rc;
| | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
@ cols TEXT, -- A color-key specification
@ sqlcode TEXT -- An SQL SELECT statement for this report
@ );
;
static void rebuild_update_schema(void){
int rc;
db_multi_exec("%s", zSchemaUpdates1 /*safe-for-%s*/);
db_multi_exec("%s", zSchemaUpdates2 /*safe-for-%s*/);
rc = db_exists("SELECT 1 FROM sqlite_master"
" WHERE name='user' AND sql GLOB '* mtime *'");
if( rc==0 ){
db_multi_exec(
"CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
"DROP TABLE user;"
|
| ︙ | ︙ | |||
133 134 135 136 137 138 139 |
rc = db_exists("SELECT 1 FROM sqlite_master"
" WHERE name='reportfmt' AND sql GLOB '* mtime *'");
if( rc==0 ){
db_multi_exec(
"CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
"DROP TABLE reportfmt;"
);
| | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
rc = db_exists("SELECT 1 FROM sqlite_master"
" WHERE name='reportfmt' AND sql GLOB '* mtime *'");
if( rc==0 ){
db_multi_exec(
"CREATE TEMP TABLE old_fmt AS SELECT * FROM reportfmt;"
"DROP TABLE reportfmt;"
);
db_multi_exec("%s", zSchemaUpdates2/*safe-for-%s*/);
db_multi_exec(
"INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
" SELECT rn, owner, title, cols, sqlcode, now() FROM old_fmt;"
"INSERT OR IGNORE INTO reportfmt(rn,owner,title,cols,sqlcode,mtime)"
" SELECT rn, owner, title || ' (' || rn || ')', cols, sqlcode, now()"
" FROM old_fmt;"
);
|
| ︙ | ︙ | |||
252 253 254 255 256 257 258 |
}
if( zFNameFormat==0 ){
/* We are doing "fossil rebuild" */
manifest_crosslink(rid, pUse, MC_NONE);
}else{
/* We are doing "fossil deconstruct" */
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
| | > | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
}
if( zFNameFormat==0 ){
/* We are doing "fossil rebuild" */
manifest_crosslink(rid, pUse, MC_NONE);
}else{
/* We are doing "fossil deconstruct" */
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
char *zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/,
zUuid, zUuid+prefixLength);
blob_write_to_file(pUse,zFile);
free(zFile);
free(zUuid);
blob_reset(pUse);
}
assert( blob_is_reset(pUse) );
rebuild_step_done(rid);
|
| ︙ | ︙ | |||
353 354 355 356 357 358 359 |
" AND name NOT GLOB 'sqlite_*'"
" AND name NOT GLOB 'fx_*'"
);
if( zTable==0 ) break;
db_multi_exec("DROP TABLE %Q", zTable);
free(zTable);
}
| | | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
" AND name NOT GLOB 'sqlite_*'"
" AND name NOT GLOB 'fx_*'"
);
if( zTable==0 ) break;
db_multi_exec("DROP TABLE %Q", zTable);
free(zTable);
}
db_multi_exec("%s", zRepositorySchema2/*safe-for-%s*/);
ticket_create_table(0);
shun_artifacts();
db_multi_exec(
"INSERT INTO unclustered"
" SELECT rid FROM blob EXCEPT SELECT rid FROM private"
);
|
| ︙ | ︙ | |||
585 586 587 588 589 590 591 | verify_all_options(); db_begin_transaction(); ttyOutput = 1; errCnt = rebuild_db(randomizeFlag, 1, doClustering); reconstruct_private_table(); db_multi_exec( | | | | | 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
verify_all_options();
db_begin_transaction();
ttyOutput = 1;
errCnt = rebuild_db(randomizeFlag, 1, doClustering);
reconstruct_private_table();
db_multi_exec(
"REPLACE INTO config(name,value,mtime) VALUES('content-schema',%Q,now());"
"REPLACE INTO config(name,value,mtime) VALUES('aux-schema',%Q,now());"
"REPLACE INTO config(name,value,mtime) VALUES('rebuilt',%Q,now());",
CONTENT_SCHEMA, AUX_SCHEMA, get_version()
);
if( errCnt && !forceFlag ){
fossil_print(
"%d errors. Rolling back changes. Use --force to force a commit.\n",
errCnt
);
|
| ︙ | ︙ |
Changes to src/report.c.
| ︙ | ︙ | |||
434 435 436 437 438 439 440 |
}
}
if( zOwner==0 ) zOwner = g.zLogin;
style_submenu_element("Cancel", "Cancel", "reportlist");
if( rn>0 ){
style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn);
}
| | | 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
}
}
if( zOwner==0 ) zOwner = g.zLogin;
style_submenu_element("Cancel", "Cancel", "reportlist");
if( rn>0 ){
style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn);
}
style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format");
if( zErr ){
@ <blockquote class="reportError">%h(zErr)</blockquote>
}
@ <form action="rptedit" method="post"><div>
@ <input type="hidden" name="rn" value="%d(rn)" />
@ <p>Report Title:<br />
@ <input type="text" name="t" value="%h(zTitle)" size="60" /></p>
|
| ︙ | ︙ | |||
1068 1069 1070 1071 1072 1073 1074 |
if( g.perm.TktFmt ){
style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
}
if( g.perm.NewTkt ){
style_submenu_element("New Ticket", "Create a new ticket",
"%s/tktnew", g.zTop);
}
| | | 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 |
if( g.perm.TktFmt ){
style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
}
if( g.perm.NewTkt ){
style_submenu_element("New Ticket", "Create a new ticket",
"%s/tktnew", g.zTop);
}
style_header("%s", zTitle);
output_color_key(zClrKey, 1,
"border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
@ <table border="1" cellpadding="2" cellspacing="0" class="report"
@ id="reportTable">
sState.rn = rn;
sState.nCount = 0;
report_restrict_sql(&zErr1);
|
| ︙ | ︙ | |||
1110 1111 1112 1113 1114 1115 1116 |
/*
** show all reports, which can be used for ticket show.
** Output is written to stdout as tab delimited table
*/
void rpt_list_reports(void){
Stmt q;
| < < | | | | 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 |
/*
** show all reports, which can be used for ticket show.
** Output is written to stdout as tab delimited table
*/
void rpt_list_reports(void){
Stmt q;
fossil_print("Available reports:\n");
fossil_print("%s\t%s\n","report number","report title");
fossil_print("%s\t%s\n",zFullTicketRptRn,zFullTicketRptTitle);
db_prepare(&q,"SELECT rn,title FROM reportfmt ORDER BY rn");
while( db_step(&q)==SQLITE_ROW ){
const char *zRn = db_column_text(&q, 0);
const char *zTitle = db_column_text(&q, 1);
fossil_print("%s\t%s\n",zRn,zTitle);
}
db_finalize(&q);
}
/*
** user defined separator used by ticket show command
*/
|
| ︙ | ︙ |
Changes to src/rss.c.
| ︙ | ︙ | |||
74 75 76 77 78 79 80 |
blob_zero(&bSQL);
blob_append( &bSQL, zSQL1, -1 );
if( zType[0]!='a' ){
if( zType[0]=='c' && !g.perm.Read ) zType = "x";
if( zType[0]=='w' && !g.perm.RdWiki ) zType = "x";
if( zType[0]=='t' && !g.perm.RdTkt ) zType = "x";
| | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
blob_zero(&bSQL);
blob_append( &bSQL, zSQL1, -1 );
if( zType[0]!='a' ){
if( zType[0]=='c' && !g.perm.Read ) zType = "x";
if( zType[0]=='w' && !g.perm.RdWiki ) zType = "x";
if( zType[0]=='t' && !g.perm.RdTkt ) zType = "x";
blob_append_sql(&bSQL, " AND event.type=%Q", zType);
}else{
if( !g.perm.Read ){
if( g.perm.RdTkt && g.perm.RdWiki ){
blob_append(&bSQL, " AND event.type!='ci'", -1);
}else if( g.perm.RdTkt ){
blob_append(&bSQL, " AND event.type=='t'", -1);
|
| ︙ | ︙ | |||
120 121 122 123 124 125 126 |
nTagId = -1;
}
}else{
nTagId = 0;
}
if( nTagId==-1 ){
| | | | | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
nTagId = -1;
}
}else{
nTagId = 0;
}
if( nTagId==-1 ){
blob_append_sql(&bSQL, " AND 0");
}else if( nTagId!=0 ){
blob_append_sql(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
}
if( zFilename ){
blob_append_sql(&bSQL,
" AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)",
zFilename, filename_collation()
);
}
blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
|
| ︙ | ︙ | |||
158 159 160 161 162 163 164 | @ <channel> @ <title>%h(zProjectName)</title> @ <link>%s(g.zBaseURL)</link> @ <description>%h(zProjectDescr)</description> @ <pubDate>%s(zPubDate)</pubDate> @ <generator>Fossil version %s(MANIFEST_VERSION) %s(MANIFEST_DATE)</generator> free(zPubDate); | | | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
@ <channel>
@ <title>%h(zProjectName)</title>
@ <link>%s(g.zBaseURL)</link>
@ <description>%h(zProjectDescr)</description>
@ <pubDate>%s(zPubDate)</pubDate>
@ <generator>Fossil version %s(MANIFEST_VERSION) %s(MANIFEST_DATE)</generator>
free(zPubDate);
db_prepare(&q, "%s", blob_sql_text(&bSQL));
blob_reset( &bSQL );
while( db_step(&q)==SQLITE_ROW && nLine<nLimit ){
const char *zId = db_column_text(&q, 1);
const char *zCom = db_column_text(&q, 3);
const char *zAuthor = db_column_text(&q, 4);
char *zPrefix = "";
char *zDate;
|
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
/* We should be done with options.. */
verify_all_options();
blob_zero(&bSQL);
blob_append( &bSQL, zSQL1, -1 );
if( zType[0]!='a' ){
| | | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
/* We should be done with options.. */
verify_all_options();
blob_zero(&bSQL);
blob_append( &bSQL, zSQL1, -1 );
if( zType[0]!='a' ){
blob_append_sql(&bSQL, " AND event.type=%Q", zType);
}
if( zTicketUuid ){
nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
zTicketUuid);
if ( nTagId==0 ){
nTagId = -1;
|
| ︙ | ︙ | |||
304 305 306 307 308 309 310 |
nTagId = -1;
}
}else{
nTagId = 0;
}
if( nTagId==-1 ){
| | | | | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
nTagId = -1;
}
}else{
nTagId = 0;
}
if( nTagId==-1 ){
blob_append_sql(&bSQL, " AND 0");
}else if( nTagId!=0 ){
blob_append_sql(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
}
if( zFilename ){
blob_append_sql(&bSQL,
" AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)",
zFilename, filename_collation()
);
}
blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
|
| ︙ | ︙ | |||
341 342 343 344 345 346 347 |
fossil_print("<title>%h</title>\n", zProjectName);
fossil_print("<link>%s</link>\n", zBaseURL);
fossil_print("<description>%h</description>\n", zProjectDescr);
fossil_print("<pubDate>%s</pubDate>\n", zPubDate);
fossil_print("<generator>Fossil version %s %s</generator>\n",
MANIFEST_VERSION, MANIFEST_DATE);
free(zPubDate);
| | | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
fossil_print("<title>%h</title>\n", zProjectName);
fossil_print("<link>%s</link>\n", zBaseURL);
fossil_print("<description>%h</description>\n", zProjectDescr);
fossil_print("<pubDate>%s</pubDate>\n", zPubDate);
fossil_print("<generator>Fossil version %s %s</generator>\n",
MANIFEST_VERSION, MANIFEST_DATE);
free(zPubDate);
db_prepare(&q, "%s", blob_sql_text(&bSQL));
blob_reset( &bSQL );
while( db_step(&q)==SQLITE_ROW && nLine<nLimit ){
const char *zId = db_column_text(&q, 1);
const char *zCom = db_column_text(&q, 3);
const char *zAuthor = db_column_text(&q, 4);
char *zPrefix = "";
char *zDate;
|
| ︙ | ︙ |
Changes to src/search.c.
| ︙ | ︙ | |||
229 230 231 232 233 234 235 |
timeline_utc()
);
iBest = db_int(0, "SELECT max(x) FROM srch");
blob_append(&sql,
"SELECT rid, uuid, date, comment, 0, 0 FROM srch "
"WHERE 1 ", -1);
if(!fAll){
| | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
timeline_utc()
);
iBest = db_int(0, "SELECT max(x) FROM srch");
blob_append(&sql,
"SELECT rid, uuid, date, comment, 0, 0 FROM srch "
"WHERE 1 ", -1);
if(!fAll){
blob_append_sql(&sql,"AND x>%d ", iBest/3);
}
blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
print_timeline(&q, nLimit, width, 0);
db_finalize(&q);
}
|
Changes to src/setup.c.
| ︙ | ︙ | |||
305 306 307 308 309 310 311 |
const char *zOldLogin;
int doWrite;
int uid, i;
int higherUser = 0; /* True if user being edited is SETUP and the */
/* user doing the editing is ADMIN. Disallow editing */
char *inherit[128];
int a[128];
| | | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
const char *zOldLogin;
int doWrite;
int uid, i;
int higherUser = 0; /* True if user being edited is SETUP and the */
/* user doing the editing is ADMIN. Disallow editing */
char *inherit[128];
int a[128];
const char *oa[128];
/* Must have ADMIN privileges to access this page
*/
login_check_credentials();
if( !g.perm.Admin ){ login_needed(); return; }
/* Check to see if an ADMIN user is trying to edit a SETUP account.
|
| ︙ | ︙ | |||
373 374 375 376 377 378 379 |
@ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
style_footer();
return;
}
login_verify_csrf_secret();
db_multi_exec(
"REPLACE INTO user(uid,login,info,pw,cap,mtime) "
| | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
@ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
style_footer();
return;
}
login_verify_csrf_secret();
db_multi_exec(
"REPLACE INTO user(uid,login,info,pw,cap,mtime) "
"VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
uid, P("login"), P("info"), zPw, zCap
);
if( atoi(PD("all","0"))>0 ){
Blob sql;
char *zErr = 0;
blob_zero(&sql);
if( zOldLogin==0 ){
|
| ︙ | ︙ | |||
439 440 441 442 443 444 445 |
/* figure out inherited permissions */
memset(inherit, 0, sizeof(inherit));
if( fossil_strcmp(zLogin, "developer") ){
char *z1, *z2;
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
while( z1 && *z1 ){
inherit[0x7f & *(z1++)] =
| | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 |
/* figure out inherited permissions */
memset(inherit, 0, sizeof(inherit));
if( fossil_strcmp(zLogin, "developer") ){
char *z1, *z2;
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
while( z1 && *z1 ){
inherit[0x7f & *(z1++)] =
"<span class=\"ueditInheritDeveloper\"><sub>[D]</sub></span>";
}
free(z2);
}
if( fossil_strcmp(zLogin, "reader") ){
char *z1, *z2;
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'");
while( z1 && *z1 ){
inherit[0x7f & *(z1++)] =
"<span class=\"ueditInheritReader\"><sub>[R]</sub></span>";
}
free(z2);
}
if( fossil_strcmp(zLogin, "anonymous") ){
char *z1, *z2;
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'");
while( z1 && *z1 ){
inherit[0x7f & *(z1++)] =
"<span class=\"ueditInheritAnonymous\"><sub>[A]</sub></span>";
}
free(z2);
}
if( fossil_strcmp(zLogin, "nobody") ){
char *z1, *z2;
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'");
while( z1 && *z1 ){
inherit[0x7f & *(z1++)] =
"<span class=\"ueditInheritNobody\"><sub>[N]</sub></span>";
}
free(z2);
}
/* Begin generating the page
*/
style_submenu_element("Cancel", "Cancel", "setup_ulist");
if( uid ){
style_header("Edit User %h", zLogin);
}else{
style_header("Add A New User");
}
@ <div class="ueditCapBox">
@ <form action="%s(g.zPath)" method="post"><div>
login_insert_csrf_secret();
if( login_is_special(zLogin) ){
@ <input type="hidden" name="login" value="%s(zLogin)">
@ <input type="hidden" name="info" value="">
@ <input type="hidden" name="pw" value="*">
}
@ <script type='text/javascript'>
@ function updateCapabilityString(){
@ /*
@ ** This function updates the "#usetupEditCapability" span content
@ ** with the capabilities selected by the interactive user, based
@ ** upon the state of the capability checkboxes.
@ */
@ try {
@ var inputs = document.getElementsByTagName('input');
@ if( inputs && inputs.length ){
@ var output = document.getElementById('usetupEditCapability');
@ if( output ){
@ var permsIds = [], x = 0;
@ for(var i = 0; i < inputs.length; i++){
@ var e = inputs[i];
@ if( !e.name || !e.type ) continue;
@ if( e.type.toLowerCase()!=='checkbox' ) continue;
@ if( e.name.length===2 && e.name[0]==='a' ){
@ // looks like a capability checkbox
@ if( e.checked ){
@ // grab the second character of the element
@ // name, which is the textual flag for this
@ // capability, and then add it to the result
@ // array.
@ permsIds[x++] = e.name[1];
@ }
@ }
@ }
@ permsIds.sort();
@ output.innerHTML = permsIds.join('');
@ }
@ }
@ } catch (e) {
@ /* ignore errors */
@ }
@ }
@ </script>
@ <table>
@ <tr>
@ <td class="usetupEditLabel">User ID:</td>
if( uid ){
@ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td>
}else{
@ <td>(new user)<input type="hidden" name="id" value="0" /></td>
|
| ︙ | ︙ | |||
514 515 516 517 518 519 520 |
@ </tr>
@ <tr>
@ <td class="usetupEditLabel">Capabilities:</td>
@ <td>
#define B(x) inherit[x]
@ <table border=0><tr><td valign="top">
if( g.perm.Setup ){
| | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > | > > > > > > > | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 |
@ </tr>
@ <tr>
@ <td class="usetupEditLabel">Capabilities:</td>
@ <td>
#define B(x) inherit[x]
@ <table border=0><tr><td valign="top">
if( g.perm.Setup ){
@ <label><input type="checkbox" name="as"%s(oa['s'])
@ onchange="updateCapabilityString()"/>
@ Setup%s(B('s'))</label><br />
}
@ <label><input type="checkbox" name="aa"%s(oa['a'])
@ onchange="updateCapabilityString()" />
@ Admin%s(B('a'))</label><br />
@ <label><input type="checkbox" name="ad"%s(oa['d'])
@ onchange="updateCapabilityString()" />
@ Delete%s(B('d'))</label><br />
@ <label><input type="checkbox" name="ae"%s(oa['e'])
@ onchange="updateCapabilityString()" />
@ Email%s(B('e'))</label><br />
@ <label><input type="checkbox" name="ap"%s(oa['p'])
@ onchange="updateCapabilityString()" />
@ Password%s(B('p'))</label><br />
@ <label><input type="checkbox" name="ai"%s(oa['i'])
@ onchange="updateCapabilityString()" />
@ Check-In%s(B('i'))</label><br />
@ <label><input type="checkbox" name="ao"%s(oa['o'])
@ onchange="updateCapabilityString()" />
@ Check-Out%s(B('o'))</label><br />
@ <label><input type="checkbox" name="ah"%s(oa['h'])
@ onchange="updateCapabilityString()" />
@ Hyperlinks%s(B('h'))</label><br />
@ <label><input type="checkbox" name="ab"%s(oa['b'])
@ onchange="updateCapabilityString()" />
@ Attachments%s(B('b'))</label><br />
@ </td><td><td width="40"></td><td valign="top">
@ <label><input type="checkbox" name="au"%s(oa['u'])
@ onchange="updateCapabilityString()" />
@ Reader%s(B('u'))</label><br />
@ <label><input type="checkbox" name="av"%s(oa['v'])
@ onchange="updateCapabilityString()" />
@ Developer%s(B('v'))</label><br />
@ <label><input type="checkbox" name="ag"%s(oa['g'])
@ onchange="updateCapabilityString()" />
@ Clone%s(B('g'))</label><br />
@ <label><input type="checkbox" name="aj"%s(oa['j'])
@ onchange="updateCapabilityString()" />
@ Read Wiki%s(B('j'))</label><br />
@ <label><input type="checkbox" name="af"%s(oa['f'])
@ onchange="updateCapabilityString()" />
@ New Wiki%s(B('f'))</label><br />
@ <label><input type="checkbox" name="am"%s(oa['m'])
@ onchange="updateCapabilityString()" />
@ Append Wiki%s(B('m'))</label><br />
@ <label><input type="checkbox" name="ak"%s(oa['k'])
@ onchange="updateCapabilityString()" />
@ Write Wiki%s(B('k'))</label><br />
@ <label><input type="checkbox" name="al"%s(oa['l'])
@ onchange="updateCapabilityString()" />
@ Moderate Wiki%s(B('l'))</label><br />
@ </td><td><td width="40"></td><td valign="top">
@ <label><input type="checkbox" name="ar"%s(oa['r'])
@ onchange="updateCapabilityString()" />
@ Read Ticket%s(B('r'))</label><br />
@ <label><input type="checkbox" name="an"%s(oa['n'])
@ onchange="updateCapabilityString()" />
@ New Tickets%s(B('n'))</label><br />
@ <label><input type="checkbox" name="ac"%s(oa['c'])
@ onchange="updateCapabilityString()" />
@ Append To Ticket%s(B('c'))</label><br />
@ <label><input type="checkbox" name="aw"%s(oa['w'])
@ onchange="updateCapabilityString()" />
@ Write Tickets%s(B('w'))</label><br />
@ <label><input type="checkbox" name="aq"%s(oa['q'])
@ onchange="updateCapabilityString()" />
@ Moderate Tickets%s(B('q'))</label><br />
@ <label><input type="checkbox" name="at"%s(oa['t'])
@ onchange="updateCapabilityString()" />
@ Ticket Report%s(B('t'))</label><br />
@ <label><input type="checkbox" name="ax"%s(oa['x'])
@ onchange="updateCapabilityString()" />
@ Private%s(B('x'))</label><br />
@ <label><input type="checkbox" name="az"%s(oa['z'])
@ onchange="updateCapabilityString()" />
@ Download Zip%s(B('z'))</label>
@ </td></tr>
@ </table>
@ </td>
@ </tr>
@ <tr>
@ <td class="usetupEditLabel">Selected Cap.:</td>
@ <td>
@ <span id="usetupEditCapability">(missing JS?)</span>
@ </td>
@ </tr>
if( !login_is_special(zLogin) ){
@ <tr>
@ <td align="right">Password:</td>
if( zPw[0] ){
/* Obscure the password for all users */
|
| ︙ | ︙ | |||
602 603 604 605 606 607 608 609 610 611 612 613 614 615 |
@ <td> </td>
@ <td><input type="submit" name="submit" value="Apply Changes" /></td>
@ </tr>
}
@ </table>
@ </div></form>
@ </div>
@ <h2>Privileges And Capabilities:</h2>
@ <ul>
if( higherUser ){
@ <li><p class="missingPriv">
@ User %h(zLogin) has Setup privileges and you only have Admin privileges
@ so you are not permitted to make changes to %h(zLogin).
@ </p></li>
| > | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 |
@ <td> </td>
@ <td><input type="submit" name="submit" value="Apply Changes" /></td>
@ </tr>
}
@ </table>
@ </div></form>
@ </div>
@ <script type='text/javascript'>updateCapabilityString();</script>
@ <h2>Privileges And Capabilities:</h2>
@ <ul>
if( higherUser ){
@ <li><p class="missingPriv">
@ User %h(zLogin) has Setup privileges and you only have Admin privileges
@ so you are not permitted to make changes to %h(zLogin).
@ </p></li>
|
| ︙ | ︙ | |||
1085 1086 1087 1088 1089 1090 1091 |
const char *zNewName = PD("newname", "New Login Group");
login_check_credentials();
if( !g.perm.Setup ){
login_needed();
}
file_canonical_name(g.zRepositoryName, &fullName, 0);
| | | 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 |
const char *zNewName = PD("newname", "New Login Group");
login_check_credentials();
if( !g.perm.Setup ){
login_needed();
}
file_canonical_name(g.zRepositoryName, &fullName, 0);
zSelfRepo = fossil_strdup(blob_str(&fullName));
blob_reset(&fullName);
if( P("join")!=0 ){
login_group_join(zRepo, zLogin, zPw, zNewName, &zErrMsg);
}else if( P("leave") ){
login_group_leave(&zErrMsg);
}
style_header("Login Group Configuration");
|
| ︙ | ︙ | |||
1259 1260 1261 1262 1263 1264 1265 |
login_check_credentials();
if( !g.perm.Setup ){
login_needed();
}
(void) aCmdHelp; /* NOTE: Silence compiler warning. */
style_header("Settings");
| > > > | > | 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 |
login_check_credentials();
if( !g.perm.Setup ){
login_needed();
}
(void) aCmdHelp; /* NOTE: Silence compiler warning. */
style_header("Settings");
if(!g.repositoryOpen){
/* Provide read-only access to versioned settings,
but only if no repo file was explicitly provided. */
db_open_local(0);
}
db_begin_transaction();
@ <p>This page provides a simple interface to the "fossil setting" command.
@ See the "fossil help setting" output below for further information on
@ the meaning of each setting.</p><hr />
@ <form action="%s(g.zTop)/setup_settings" method="post"><div>
@ <table border="0"><tr><td valign="top">
login_insert_csrf_secret();
|
| ︙ | ︙ |
Changes to src/shell.c.
| ︙ | ︙ | |||
878 879 880 881 882 883 884 |
#endif
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
}
fprintf(p->out,"%s",p->newline);
}
| | | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 |
#endif
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
}
fprintf(p->out,"%s",p->newline);
}
if( nArg>0 ){
for(i=0; i<nArg; i++){
output_csv(p, azArg[i], i<nArg-1);
}
fprintf(p->out,"%s",p->newline);
}
#if defined(WIN32) || defined(_WIN32)
fflush(p->out);
|
| ︙ | ︙ | |||
1349 1350 1351 1352 1353 1354 1355 1356 |
fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
}
}
sqlite3_finalize(pExplain);
sqlite3_free(zEQP);
}
/* Output TESTCTRL_EXPLAIN text of requested */
| > | > | 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 |
fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
}
}
sqlite3_finalize(pExplain);
sqlite3_free(zEQP);
}
#if USE_SYSTEM_SQLITE+0==1
/* Output TESTCTRL_EXPLAIN text of requested */
if( pArg && pArg->mode==MODE_Explain && sqlite3_libversion_number()<3008007 ){
const char *zExplain = 0;
sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
if( zExplain && zExplain[0] ){
fprintf(pArg->out, "%s", zExplain);
}
}
#endif
/* If the shell is currently in ".explain" mode, gather the extra
** data required to add indents to the output.*/
if( pArg && pArg->mode==MODE_Explain ){
explain_data_prepare(pArg, pStmt);
}
|
| ︙ | ︙ | |||
3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 |
}else if( rc != SQLITE_OK ){
fprintf(stderr,"Error: querying schema information\n");
rc = 1;
}else{
rc = 0;
}
}else
#ifdef SQLITE_DEBUG
/* Undocumented commands for internal testing. Subject to change
** without notice. */
if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
int i, v;
| > > > > > > > > > | 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 |
}else if( rc != SQLITE_OK ){
fprintf(stderr,"Error: querying schema information\n");
rc = 1;
}else{
rc = 0;
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
extern int sqlite3SelectTrace;
sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
}else
#endif
#ifdef SQLITE_DEBUG
/* Undocumented commands for internal testing. Subject to change
** without notice. */
if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
int i, v;
|
| ︙ | ︙ | |||
3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 |
if( p->echoOn ) printf("%s\n", zSql);
nSql = 0;
}
}
if( nSql ){
if( !_all_whitespace(zSql) ){
fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
}
free(zSql);
}
free(zLine);
return errCnt>0;
}
| > | 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 |
if( p->echoOn ) printf("%s\n", zSql);
nSql = 0;
}
}
if( nSql ){
if( !_all_whitespace(zSql) ){
fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
errCnt++;
}
free(zSql);
}
free(zLine);
return errCnt>0;
}
|
| ︙ | ︙ |
Changes to src/shun.c.
| ︙ | ︙ | |||
41 42 43 44 45 46 47 |
void shun_page(void){
Stmt q;
int cnt = 0;
const char *zUuid = P("uuid");
const char *zShun = P("shun");
const char *zAccept = P("accept");
const char *zRcvid = P("rcvid");
| | < | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
void shun_page(void){
Stmt q;
int cnt = 0;
const char *zUuid = P("uuid");
const char *zShun = P("shun");
const char *zAccept = P("accept");
const char *zRcvid = P("rcvid");
int nRcvid = 0;
int numRows = 3;
char *zCanonical = 0;
login_check_credentials();
if( !g.perm.Admin ){
login_needed();
}
|
| ︙ | ︙ | |||
77 78 79 80 81 82 83 |
j++;
}
i++;
}
zCanonical[j+1] = zCanonical[j] = 0;
p = zCanonical;
while( *p ){
| | | | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
j++;
}
i++;
}
zCanonical[j+1] = zCanonical[j] = 0;
p = zCanonical;
while( *p ){
int nUuid = strlen(p);
if( nUuid!=UUID_SIZE || !validate16(p, nUuid) ){
@ <p class="generalError">Error: Bad artifact IDs.</p>
fossil_free(zCanonical);
zCanonical = 0;
break;
}else{
canonical16(p, UUID_SIZE);
p += UUID_SIZE+1;
}
}
zUuid = zCanonical;
}
style_header("Shunned Artifacts");
if( zUuid && P("sub") ){
const char *p = zUuid;
int allExist = 1;
login_verify_csrf_secret();
while( *p ){
db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p);
if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){
allExist = 0;
}
p += UUID_SIZE+1;
}
if( allExist ){
@ <p class="noMoreShun">Artifact(s)<br />
for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
|
| ︙ | ︙ | |||
126 127 128 129 130 131 132 |
if( zUuid && P("add") ){
const char *p = zUuid;
int rid, tagid;
login_verify_csrf_secret();
while( *p ){
db_multi_exec(
"INSERT OR IGNORE INTO shun(uuid,mtime)"
| | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
if( zUuid && P("add") ){
const char *p = zUuid;
int rid, tagid;
login_verify_csrf_secret();
while( *p ){
db_multi_exec(
"INSERT OR IGNORE INTO shun(uuid,mtime)"
" VALUES(%Q, now())", p);
db_multi_exec("DELETE FROM attachment WHERE src=%Q", p);
rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", p);
if( rid ){
db_multi_exec("DELETE FROM event WHERE objid=%d", rid);
}
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='tkt-%q'", p);
if( tagid ){
|
| ︙ | ︙ | |||
150 151 152 153 154 155 156 |
}
@ have been shunned. They will no longer be pushed.
@ They will be removed from the repository the next time the repository
@ is rebuilt using the <b>fossil rebuild</b> command-line</p>
}
if( zRcvid ){
nRcvid = atoi(zRcvid);
| | > | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
}
@ have been shunned. They will no longer be pushed.
@ They will be removed from the repository the next time the repository
@ is rebuilt using the <b>fossil rebuild</b> command-line</p>
}
if( zRcvid ){
nRcvid = atoi(zRcvid);
numRows = db_int(0, "SELECT min(count(), 10) FROM blob WHERE rcvid=%d",
nRcvid);
}
@ <p>A shunned artifact will not be pushed nor accepted in a pull and the
@ artifact content will be purged from the repository the next time the
@ repository is rebuilt. A list of shunned artifacts can be seen at the
@ bottom of this page.</p>
@
@ <a name="addshun"></a>
|
| ︙ | ︙ | |||
181 182 183 184 185 186 187 |
@ <blockquote>
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
login_insert_csrf_secret();
@ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
if( zShun ){
if( strlen(zShun) ){
@ %h(zShun)
| | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
@ <blockquote>
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
login_insert_csrf_secret();
@ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
if( zShun ){
if( strlen(zShun) ){
@ %h(zShun)
}else if( nRcvid ){
db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
while( db_step(&q)==SQLITE_ROW ){
@ %s(db_column_text(&q, 0))
}
db_finalize(&q);
}
}
|
| ︙ | ︙ | |||
208 209 210 211 212 213 214 |
@ <blockquote>
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
login_insert_csrf_secret();
@ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
if( zAccept ){
if( strlen(zAccept) ){
@ %h(zAccept)
| | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
@ <blockquote>
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
login_insert_csrf_secret();
@ <textarea class="fullsize-text" cols="50" rows="%d(numRows)" name="uuid">
if( zAccept ){
if( strlen(zAccept) ){
@ %h(zAccept)
}else if( nRcvid ){
db_prepare(&q, "SELECT uuid FROM blob WHERE rcvid=%d", nRcvid);
while( db_step(&q)==SQLITE_ROW ){
@ %s(db_column_text(&q, 0))
}
db_finalize(&q);
}
}
|
| ︙ | ︙ |
Changes to src/skins.c.
| ︙ | ︙ | |||
1390 1391 1392 1393 1394 1395 1396 |
);
}
seen = 0;
for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
if( fossil_strcmp(aBuiltinSkin[i].zName, z)==0 ){
seen = 1;
zCurrent = aBuiltinSkin[i].zValue;
| | | | 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 |
);
}
seen = 0;
for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
if( fossil_strcmp(aBuiltinSkin[i].zName, z)==0 ){
seen = 1;
zCurrent = aBuiltinSkin[i].zValue;
db_multi_exec("%s", zCurrent/*safe-for-%s*/);
break;
}
}
if( !seen ){
zName = skinVarName(z,0);
zCurrent = db_get(zName, 0);
db_multi_exec("%s", zCurrent/*safe-for-%s*/);
}
}
style_header("Skins");
if( zErr ){
@ <p><font color="red">%h(zErr)</font></p>
}
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
*/
void cmd_sqlite3(void){
extern int sqlite3_shell(int, char**);
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
db_close(1);
sqlite3_shutdown();
sqlite3_shell(g.argc-1, g.argv+1);
g.db = 0;
}
/*
** This routine is called by the patched sqlite3 command-line shell in order
** to load the name and database connection for the open Fossil database.
*/
void fossil_open(const char **pzRepoName){
| > > > > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
*/
void cmd_sqlite3(void){
extern int sqlite3_shell(int, char**);
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
db_close(1);
sqlite3_shutdown();
sqlite3_shell(g.argc-1, g.argv+1);
sqlite3_cancel_auto_extension((void(*)(void))sqlcmd_autoinit);
g.db = 0;
g.zMainDbType = 0;
g.repositoryOpen = 0;
g.localOpen = 0;
}
/*
** This routine is called by the patched sqlite3 command-line shell in order
** to load the name and database connection for the open Fossil database.
*/
void fossil_open(const char **pzRepoName){
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
| ︙ | ︙ | |||
229 230 231 232 233 234 235 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.7" #define SQLITE_VERSION_NUMBER 3008007 | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.7" #define SQLITE_VERSION_NUMBER 3008007 #define SQLITE_SOURCE_ID "2014-10-17 11:24:17 e4ab094f8afce0817f4074e823fabe59fc29ebb4" /* ** 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 |
| ︙ | ︙ | |||
2789 2790 2791 2792 2793 2794 2795 | ** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] ** object.)^ ^(If the database is opened (and/or created) successfully, then ** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The ** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain ** an English language description of the error following a failure of any ** of the sqlite3_open() routines. ** | | | | | 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 | ** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] ** object.)^ ^(If the database is opened (and/or created) successfully, then ** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The ** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain ** an English language description of the error following a failure of any ** of the sqlite3_open() routines. ** ** ^The default encoding will be UTF-8 for databases created using ** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases ** created using sqlite3_open16() will be UTF-16 in the native byte order. ** ** 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 |
| ︙ | ︙ | |||
2879 2880 2881 2882 2883 2884 2885 | ** present, is ignored. ** ** ^SQLite uses the path component of the URI as the name of the disk file ** which contains the database. ^If the path begins with a '/' character, ** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) ** then the path is interpreted as a relative path. | | | > | | 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 | ** present, is ignored. ** ** ^SQLite uses the path component of the URI as the name of the disk file ** which contains the database. ^If the path begins with a '/' character, ** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) ** then the path is interpreted as a relative path. ** ^(On windows, the first component of an absolute path ** is a drive specification (e.g. "C:").)^ ** ** [[core URI query parameters]] ** The query component of a URI may contain parameters that are interpreted ** either by SQLite itself, or by a [VFS | custom VFS implementation]. ** SQLite and its built-in [VFSes] interpret the ** following query parameters: ** ** <ul> ** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of ** a VFS object that provides the operating system interface that should ** be used to access the database file on disk. ^If this option is set to ** an empty string the default VFS object is used. ^Specifying an unknown ** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is |
| ︙ | ︙ | |||
2920 2921 2922 2923 2924 2925 2926 | ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** | | < | < | 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 | ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** ** <li> <b>psow</b>: ^The psow parameter indicates whether or not the ** [powersafe overwrite] property does or does not apply to the ** storage media on which the database file resides. ** ** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter ** which if set disables file locking in rollback journal modes. This ** is useful for accessing a database on a filesystem that does not ** support locking. Caution: Database corruption might result if two ** or more processes write to the same database and any one of those ** processes uses nolock=1. |
| ︙ | ︙ | |||
3519 3520 3521 3522 3523 3524 3525 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occur at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** | | | | < | | 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occur at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces ** is a destructor used to dispose of the BLOB or ** string after SQLite has finished with it. ^The destructor is called ** to dispose of the BLOB or string even if the call to bind API fails. ** ^If the fifth argument is ** the special value [SQLITE_STATIC], then SQLite assumes that the ** information is in static, unmanaged space and does not need to be freed. ** ^If the fifth argument has the value [SQLITE_TRANSIENT], then ** SQLite makes its own private copy of the data immediately, before ** the sqlite3_bind_*() routine returns. ** ** ^The sixth argument to sqlite3_bind_text64() must be one of ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] ** to specify the encoding of the text in the third parameter. If ** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior ** is undefined. ** ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that ** is filled with zeroes. ^A zeroblob uses a fixed amount of memory ** (just an integer to hold its size) while it is being processed. |
| ︙ | ︙ | |||
4570 4571 4572 4573 4574 4575 4576 | ** of the application-defined function to be the 64-bit signed integer ** value given in the 2nd argument. ** ** ^The sqlite3_result_null() interface sets the return value ** of the application-defined function to be NULL. ** ** ^The sqlite3_result_text(), sqlite3_result_text16(), | | | 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 | ** of the application-defined function to be the 64-bit signed integer ** value given in the 2nd argument. ** ** ^The sqlite3_result_null() interface sets the return value ** of the application-defined function to be NULL. ** ** ^The sqlite3_result_text(), sqlite3_result_text16(), ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. ** ^The sqlite3_result_text64() interface sets the return value of an ** application-defined function to be a text string in an encoding ** specified by the fifth (and last) parameter, which must be one ** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. |
| ︙ | ︙ | |||
6330 6331 6332 6333 6334 6335 6336 | #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 | | | 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 | #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_LAST 24 |
| ︙ | ︙ | |||
7944 7945 7946 7947 7948 7949 7950 | /* ** A macro to hint to the compiler that a function should not be ** inlined. */ #if defined(__GNUC__) # define SQLITE_NOINLINE __attribute__((noinline)) | | | 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 | /* ** A macro to hint to the compiler that a function should not be ** inlined. */ #if defined(__GNUC__) # define SQLITE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) && _MSC_VER>=1310 # define SQLITE_NOINLINE __declspec(noinline) #else # define SQLITE_NOINLINE #endif /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. |
| ︙ | ︙ | |||
8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 | /* ** Macros to compute minimum and maximum of two numbers. */ #define MIN(A,B) ((A)<(B)?(A):(B)) #define MAX(A,B) ((A)>(B)?(A):(B)) /* ** Check to see if this machine uses EBCDIC. (Yes, believe it or ** not, there are still machines out there that use EBCDIC.) */ #if 'A' == '\301' # define SQLITE_EBCDIC 1 #else | > > > > > | 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 |
/*
** Macros to compute minimum and maximum of two numbers.
*/
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAX(A,B) ((A)>(B)?(A):(B))
/*
** Swap two objects of type TYPE.
*/
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
/*
** Check to see if this machine uses EBCDIC. (Yes, believe it or
** not, there are still machines out there that use EBCDIC.)
*/
#if 'A' == '\301'
# define SQLITE_EBCDIC 1
#else
|
| ︙ | ︙ | |||
8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 | # define SQLITE_ENABLE_STAT3_OR_STAT4 1 #elif SQLITE_ENABLE_STAT3 # define SQLITE_ENABLE_STAT3_OR_STAT4 1 #elif SQLITE_ENABLE_STAT3_OR_STAT4 # undef SQLITE_ENABLE_STAT3_OR_STAT4 #endif /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** ** The sqlite.busyHandler member of the sqlite struct contains the busy ** callback for the database handle. Each pager opened via the sqlite ** handle is passed a pointer to sqlite.busyHandler. The busy-handler | > > > > > > > > > > | 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 | # define SQLITE_ENABLE_STAT3_OR_STAT4 1 #elif SQLITE_ENABLE_STAT3 # define SQLITE_ENABLE_STAT3_OR_STAT4 1 #elif SQLITE_ENABLE_STAT3_OR_STAT4 # undef SQLITE_ENABLE_STAT3_OR_STAT4 #endif /* ** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not ** the Select query generator tracing logic is turned on. */ #if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE) # define SELECTTRACE_ENABLED 1 #else # define SELECTTRACE_ENABLED 0 #endif /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** ** The sqlite.busyHandler member of the sqlite struct contains the busy ** callback for the database handle. Each pager opened via the sqlite ** handle is passed a pointer to sqlite.busyHandler. The busy-handler |
| ︙ | ︙ | |||
8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 | typedef struct SQLiteThread SQLiteThread; typedef struct SelectDest SelectDest; typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; | > | 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 | typedef struct SQLiteThread SQLiteThread; typedef struct SelectDest SelectDest; typedef struct SrcList SrcList; typedef struct StrAccum StrAccum; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TreeView TreeView; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; |
| ︙ | ︙ | |||
11306 11307 11308 11309 11310 11311 11312 11313 11314 11315 11316 11317 11318 11319 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ unsigned isCovering:1; /* True if this is a covering index */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; /* ** Allowed values for Index.idxType */ #define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */ | > | 11320 11321 11322 11323 11324 11325 11326 11327 11328 11329 11330 11331 11332 11333 11334 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ unsigned isCovering:1; /* True if this is a covering index */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this table */ #endif }; /* ** Allowed values for Index.idxType */ #define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */ |
| ︙ | ︙ | |||
11736 11737 11738 11739 11740 11741 11742 | #define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ #define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ #define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ | | | 11751 11752 11753 11754 11755 11756 11757 11758 11759 11760 11761 11762 11763 11764 11765 |
#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
/* 0x0080 // not currently used */
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
/* Allowed return values from sqlite3WhereIsDistinct()
|
| ︙ | ︙ | |||
11821 11822 11823 11824 11825 11826 11827 11828 11829 11830 11831 11832 11833 11834 |
** sequences for the ORDER BY clause.
*/
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
u16 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
u64 nSelectRow; /* Estimated number of result rows */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
Expr *pHaving; /* The HAVING clause */
ExprList *pOrderBy; /* The ORDER BY clause */
| > > > | 11836 11837 11838 11839 11840 11841 11842 11843 11844 11845 11846 11847 11848 11849 11850 11851 11852 |
** sequences for the ORDER BY clause.
*/
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
u16 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
#if SELECTTRACE_ENABLED
char zSelName[12]; /* Symbolic name of this SELECT use for debugging */
#endif
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
u64 nSelectRow; /* Estimated number of result rows */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
Expr *pHaving; /* The HAVING clause */
ExprList *pOrderBy; /* The ORDER BY clause */
|
| ︙ | ︙ | |||
12079 12080 12081 12082 12083 12084 12085 12086 12087 12088 12089 12090 12091 12092 | Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ /* Information used while coding trigger programs. */ | > > > > | 12097 12098 12099 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 | Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ int nMaxArg; /* Max args passed to user function by sub-program */ #if SELECTTRACE_ENABLED int nSelect; /* Number of SELECT statements seen */ int nSelectIndent; /* How far to indent SELECTTRACE() output */ #endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ /* Information used while coding trigger programs. */ |
| ︙ | ︙ | |||
12158 12159 12160 12161 12162 12163 12164 12165 12166 12167 12168 | Parse *pParse; /* The Parse structure */ }; /* ** Bitfield flags for P5 value in various opcodes. */ #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ | > < | 12180 12181 12182 12183 12184 12185 12186 12187 12188 12189 12190 12191 12192 12193 12194 12195 12196 12197 12198 | Parse *pParse; /* The Parse structure */ }; /* ** Bitfield flags for P5 value in various opcodes. */ #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ /* |
| ︙ | ︙ | |||
12426 12427 12428 12429 12430 12431 12432 12433 12434 12435 12436 12437 12438 12439 |
char *zName; /* Name of this CTE */
ExprList *pCols; /* List of explicit column names, or NULL */
Select *pSelect; /* The definition of this CTE */
const char *zErr; /* Error message for circular references */
} a[1];
};
/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
| > > > > > > > > > > > | 12448 12449 12450 12451 12452 12453 12454 12455 12456 12457 12458 12459 12460 12461 12462 12463 12464 12465 12466 12467 12468 12469 12470 12471 12472 |
char *zName; /* Name of this CTE */
ExprList *pCols; /* List of explicit column names, or NULL */
Select *pSelect; /* The definition of this CTE */
const char *zErr; /* Error message for circular references */
} a[1];
};
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
** data structures on sqlite3DebugPrintf() using a tree-like view.
*/
struct TreeView {
int iLevel; /* Which level of the tree we are on */
u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */
};
#endif /* SQLITE_DEBUG */
/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
|
| ︙ | ︙ | |||
12491 12492 12493 12494 12495 12496 12497 12498 12499 12500 12501 12502 12503 12504 | # define sqlite3Isspace(x) isspace((unsigned char)(x)) # define sqlite3Isalnum(x) isalnum((unsigned char)(x)) # define sqlite3Isalpha(x) isalpha((unsigned char)(x)) # define sqlite3Isdigit(x) isdigit((unsigned char)(x)) # define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) # define sqlite3Tolower(x) tolower((unsigned char)(x)) #endif /* ** Internal function prototypes */ #define sqlite3StrICmp sqlite3_stricmp SQLITE_PRIVATE int sqlite3Strlen30(const char*); #define sqlite3StrNICmp sqlite3_strnicmp | > | 12524 12525 12526 12527 12528 12529 12530 12531 12532 12533 12534 12535 12536 12537 12538 | # define sqlite3Isspace(x) isspace((unsigned char)(x)) # define sqlite3Isalnum(x) isalnum((unsigned char)(x)) # define sqlite3Isalpha(x) isalpha((unsigned char)(x)) # define sqlite3Isdigit(x) isdigit((unsigned char)(x)) # define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) # define sqlite3Tolower(x) tolower((unsigned char)(x)) #endif SQLITE_PRIVATE int sqlite3IsIdChar(u8); /* ** Internal function prototypes */ #define sqlite3StrICmp sqlite3_stricmp SQLITE_PRIVATE int sqlite3Strlen30(const char*); #define sqlite3StrNICmp sqlite3_strnicmp |
| ︙ | ︙ | |||
12589 12590 12591 12592 12593 12594 12595 | #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif | < | | | | | | | < | < < < < < < < < < | 12623 12624 12625 12626 12627 12628 12629 12630 12631 12632 12633 12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644 | #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif #if defined(SQLITE_DEBUG) SQLITE_PRIVATE TreeView *sqlite3TreeViewPush(TreeView*,u8); SQLITE_PRIVATE void sqlite3TreeViewPop(TreeView*); SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char*, ...); SQLITE_PRIVATE void sqlite3TreeViewItem(TreeView*, const char*, u8); SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); #endif SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*, ...); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); SQLITE_PRIVATE int sqlite3Dequote(char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| ︙ | ︙ | |||
12789 12790 12791 12792 12793 12794 12795 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*); SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*); SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); | | | 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825 12826 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*); SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*); SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8); SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*); SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); |
| ︙ | ︙ | |||
12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825 12826 | SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*); SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*); SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); | > > > > > | 12836 12837 12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 | SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*); SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*); SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); #if SELECTTRACE_ENABLED SQLITE_PRIVATE void sqlite3SelectSetName(Select*,const char*); #else # define sqlite3SelectSetName(A,B) #endif SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); |
| ︙ | ︙ | |||
13290 13291 13292 13293 13294 13295 13296 | SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8); #else # define sqlite3MemdebugSetType(X,Y) /* no-op */ # define sqlite3MemdebugHasType(X,Y) 1 # define sqlite3MemdebugNoType(X,Y) 1 #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ | | < | 13318 13319 13320 13321 13322 13323 13324 13325 13326 13327 13328 13329 13330 13331 13332 13333 13334 | SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8); #else # define sqlite3MemdebugSetType(X,Y) /* no-op */ # define sqlite3MemdebugHasType(X,Y) 1 # define sqlite3MemdebugNoType(X,Y) 1 #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ #define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ #define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ #define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ /* ** Threading interface */ #if SQLITE_MAX_WORKER_THREADS>0 SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*); SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); |
| ︙ | ︙ | |||
13437 13438 13439 13440 13441 13442 13443 13444 13445 13446 13447 13448 13449 13450 | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */ }; #endif #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 0 #endif #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 #endif | > > > > > > > | 13464 13465 13466 13467 13468 13469 13470 13471 13472 13473 13474 13475 13476 13477 13478 13479 13480 13481 13482 13483 13484 | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */ }; #endif /* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards ** compatibility for legacy applications, the URI filename capability is ** disabled by default. ** ** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled ** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options. */ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 0 #endif #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 #endif |
| ︙ | ︙ | |||
13943 13944 13945 13946 13947 13948 13949 |
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
n = sqlite3Strlen30(zOptName);
/* Since ArraySize(azCompileOpt) is normally in single digits, a
** linear search is adequate. No need for a binary search. */
for(i=0; i<ArraySize(azCompileOpt); i++){
if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
| | | 13977 13978 13979 13980 13981 13982 13983 13984 13985 13986 13987 13988 13989 13990 13991 |
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
n = sqlite3Strlen30(zOptName);
/* Since ArraySize(azCompileOpt) is normally in single digits, a
** linear search is adequate. No need for a binary search. */
for(i=0; i<ArraySize(azCompileOpt); i++){
if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
&& sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0
){
return 1;
}
}
return 0;
}
|
| ︙ | ︙ | |||
14058 14059 14060 14061 14062 14063 14064 | i16 nField; /* Number of fields in the header */ u16 nHdrParsed; /* Number of header fields parsed so far */ #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ #endif i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ u8 nullRow; /* True if pointing to a row with no data */ | < < > | 14092 14093 14094 14095 14096 14097 14098 14099 14100 14101 14102 14103 14104 14105 14106 14107 14108 14109 14110 14111 14112 14113 14114 14115 14116 14117 14118 14119 14120 14121 14122 14123 14124 14125 14126 14127 14128 14129 14130 14131 | i16 nField; /* Number of fields in the header */ u16 nHdrParsed; /* Number of header fields parsed so far */ #ifdef SQLITE_DEBUG u8 seekOp; /* Most recent seek operation on this cursor */ #endif i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ u8 nullRow; /* True if pointing to a row with no data */ u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ Bool isTable:1; /* True if a table requiring integer keys */ Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ Pgno pgnoRoot; /* Root page of the open btree cursor */ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ /* Cached information about the header for the data record that the ** cursor is currently pointing to. Only valid if cacheStatus matches ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that ** the cache is out of date. ** ** aRow might point to (ephemeral) data for the current row, or it might ** be NULL. */ u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ u32 payloadSize; /* Total number of bytes in the record */ u32 szRow; /* Byte available in aRow */ u32 iHdrOffset; /* Offset to next unparsed byte of the header */ const u8 *aRow; /* Data for the current row, if all on one page */ u32 *aOffset; /* Pointer to aType[nField] */ u32 aType[1]; /* Type values for all entries in the record */ /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for ** aType[] and nField+1 array slots for aOffset[] */ }; typedef struct VdbeCursor VdbeCursor; |
| ︙ | ︙ | |||
14161 14162 14163 14164 14165 14166 14167 | u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ int n; /* Number of characters in string value, excluding '\0' */ char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ int szMalloc; /* Size of the zMalloc allocation */ | | | 14194 14195 14196 14197 14198 14199 14200 14201 14202 14203 14204 14205 14206 14207 14208 | u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ int n; /* Number of characters in string value, excluding '\0' */ char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ int szMalloc; /* Size of the zMalloc allocation */ u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ sqlite3 *db; /* The associated database connection */ void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ #endif }; |
| ︙ | ︙ | |||
14257 14258 14259 14260 14261 14262 14263 |
** This structure is defined inside of vdbeInt.h because it uses substructures
** (Mem) which are only defined there.
*/
struct sqlite3_context {
Mem *pOut; /* The return value is stored here */
FuncDef *pFunc; /* Pointer to function information */
Mem *pMem; /* Memory cell used to store aggregate context */
| < | 14290 14291 14292 14293 14294 14295 14296 14297 14298 14299 14300 14301 14302 14303 |
** This structure is defined inside of vdbeInt.h because it uses substructures
** (Mem) which are only defined there.
*/
struct sqlite3_context {
Mem *pOut; /* The return value is stored here */
FuncDef *pFunc; /* Pointer to function information */
Mem *pMem; /* Memory cell used to store aggregate context */
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 skipFlag; /* Skip accumulator loading if true */
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
};
|
| ︙ | ︙ | |||
14346 14347 14348 14349 14350 14351 14352 |
#endif
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
| < < < < | 14378 14379 14380 14381 14382 14383 14384 14385 14386 14387 14388 14389 14390 14391 |
#endif
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
int nFrame; /* Number of frames in pFrame list */
u32 expmask; /* Binding to these vars invalidates VM */
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
int nOnceFlag; /* Size of array aOnceFlag[] */
u8 *aOnceFlag; /* Flags for OP_Once */
|
| ︙ | ︙ | |||
14374 14375 14376 14377 14378 14379 14380 14381 14382 14383 14384 14385 14386 14387 | /* ** Function prototypes */ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); #endif SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int); SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); | > | 14402 14403 14404 14405 14406 14407 14408 14409 14410 14411 14412 14413 14414 14415 14416 | /* ** Function prototypes */ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); #endif SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int); SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); |
| ︙ | ︙ | |||
14673 14674 14675 14676 14677 14678 14679 |
db->pnBytesFreed = &nByte;
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
sqlite3VdbeClearObject(db, pVdbe);
sqlite3DbFree(db, pVdbe);
}
db->pnBytesFreed = 0;
| | | 14702 14703 14704 14705 14706 14707 14708 14709 14710 14711 14712 14713 14714 14715 14716 |
db->pnBytesFreed = &nByte;
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
sqlite3VdbeClearObject(db, pVdbe);
sqlite3DbFree(db, pVdbe);
}
db->pnBytesFreed = 0;
*pHighwater = 0; /* IMP: R-64479-57858 */
*pCurrent = nByte;
break;
}
/*
** Set *pCurrent to the total cache hits or misses encountered by all
|
| ︙ | ︙ | |||
14698 14699 14700 14701 14702 14703 14704 |
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt ){
Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
}
}
| | > > | | 14727 14728 14729 14730 14731 14732 14733 14734 14735 14736 14737 14738 14739 14740 14741 14742 14743 14744 14745 14746 14747 14748 14749 14750 14751 14752 14753 |
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt ){
Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
}
}
*pHighwater = 0; /* IMP: R-42420-56072 */
/* IMP: R-54100-20147 */
/* IMP: R-29431-39229 */
*pCurrent = nRet;
break;
}
/* Set *pCurrent to non-zero if there are unresolved deferred foreign
** key constraints. Set *pCurrent to zero if all foreign key constraints
** have been satisfied. The *pHighwater is always set to zero.
*/
case SQLITE_DBSTATUS_DEFERRED_FKS: {
*pHighwater = 0; /* IMP: R-11967-56545 */
*pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
break;
}
default: {
rc = SQLITE_ERROR;
}
|
| ︙ | ︙ | |||
17096 17097 17098 17099 17100 17101 17102 | /* ** Return TRUE if the mask of type in eType matches the type of the ** allocation p. Also return true if p==NULL. ** ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** | | | 17127 17128 17129 17130 17131 17132 17133 17134 17135 17136 17137 17138 17139 17140 17141 |
/*
** Return TRUE if the mask of type in eType matches the type of the
** allocation p. Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation. For example:
**
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
*/
SQLITE_PRIVATE int sqlite3MemdebugHasType(void *p, u8 eType){
int rc = 1;
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
|
| ︙ | ︙ | |||
17118 17119 17120 17121 17122 17123 17124 | /* ** Return TRUE if the mask of type in eType matches no bits of the type of the ** allocation p. Also return true if p==NULL. ** ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** | | | 17149 17150 17151 17152 17153 17154 17155 17156 17157 17158 17159 17160 17161 17162 17163 |
/*
** Return TRUE if the mask of type in eType matches no bits of the type of the
** allocation p. Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation. For example:
**
** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
*/
SQLITE_PRIVATE int sqlite3MemdebugNoType(void *p, u8 eType){
int rc = 1;
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
|
| ︙ | ︙ | |||
20193 20194 20195 20196 20197 20198 20199 |
}else if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
mallocWithAlarm((int)n, &p);
sqlite3_mutex_leave(mem0.mutex);
}else{
p = sqlite3GlobalConfig.m.xMalloc((int)n);
}
| | | 20224 20225 20226 20227 20228 20229 20230 20231 20232 20233 20234 20235 20236 20237 20238 |
}else if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
mallocWithAlarm((int)n, &p);
sqlite3_mutex_leave(mem0.mutex);
}else{
p = sqlite3GlobalConfig.m.xMalloc((int)n);
}
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */
return p;
}
/*
** This version of the memory allocation is for use by the application.
** First make sure the memory subsystem is initialized, then do the
** allocation.
|
| ︙ | ︙ | |||
20330 20331 20332 20333 20334 20335 20336 |
/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
| < > > | | < > > < > | 20361 20362 20363 20364 20365 20366 20367 20368 20369 20370 20371 20372 20373 20374 20375 20376 20377 20378 20379 20380 20381 20382 20383 20384 20385 20386 20387 20388 20389 20390 20391 20392 20393 20394 20395 20396 20397 20398 20399 20400 20401 20402 20403 20404 20405 |
/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
if( db==0 ){
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3MallocSize(p);
}else{
assert( sqlite3_mutex_held(db->mutex) );
if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
return sqlite3GlobalConfig.m.xSize(p);
}
}
}
SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
}
/*
** Free memory previously obtained from sqlite3Malloc().
*/
SQLITE_API void sqlite3_free(void *p){
if( p==0 ) return; /* IMP: R-49053-54554 */
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
|
| ︙ | ︙ | |||
20402 20403 20404 20405 20406 20407 20408 |
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
db->lookaside.nOut--;
return;
}
}
| | | > > | | | 20435 20436 20437 20438 20439 20440 20441 20442 20443 20444 20445 20446 20447 20448 20449 20450 20451 20452 20453 20454 20455 20456 20457 20458 20459 20460 20461 20462 20463 20464 20465 20466 20467 20468 |
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
db->lookaside.nOut--;
return;
}
}
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
}
/*
** Change the size of an existing memory allocation
*/
SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
int nOld, nNew, nDiff;
void *pNew;
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
if( pOld==0 ){
return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
}
if( nBytes==0 ){
sqlite3_free(pOld); /* IMP: R-26507-47431 */
return 0;
}
if( nBytes>=0x7fffff00 ){
/* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
return 0;
}
nOld = sqlite3MallocSize(pOld);
|
| ︙ | ︙ | |||
20441 20442 20443 20444 20445 20446 20447 |
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
| < < | | | 20476 20477 20478 20479 20480 20481 20482 20483 20484 20485 20486 20487 20488 20489 20490 20491 20492 20493 20494 20495 20496 20497 20498 20499 20500 20501 20502 20503 20504 20505 20506 20507 20508 20509 20510 20511 20512 20513 20514 20515 |
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm((int)nBytes);
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
if( pNew ){
nNew = sqlite3MallocSize(pNew);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
}
sqlite3_mutex_leave(mem0.mutex);
}else{
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */
return pNew;
}
/*
** The public interface to sqlite3Realloc. Make sure that the memory
** subsystem is initialized prior to invoking sqliteRealloc.
*/
SQLITE_API void *sqlite3_realloc(void *pOld, int n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
if( n<0 ) n = 0; /* IMP: R-26507-47431 */
return sqlite3Realloc(pOld, n);
}
SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return sqlite3Realloc(pOld, n);
|
| ︙ | ︙ | |||
20555 20556 20557 20558 20559 20560 20561 |
return 0;
}
#endif
p = sqlite3Malloc(n);
if( !p && db ){
db->mallocFailed = 1;
}
| | | | 20588 20589 20590 20591 20592 20593 20594 20595 20596 20597 20598 20599 20600 20601 20602 20603 |
return 0;
}
#endif
p = sqlite3Malloc(n);
if( !p && db ){
db->mallocFailed = 1;
}
sqlite3MemdebugSetType(p,
(db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
return p;
}
/*
** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
|
| ︙ | ︙ | |||
20582 20583 20584 20585 20586 20587 20588 |
}
pNew = sqlite3DbMallocRaw(db, n);
if( pNew ){
memcpy(pNew, p, db->lookaside.sz);
sqlite3DbFree(db, p);
}
}else{
| | | < | | 20615 20616 20617 20618 20619 20620 20621 20622 20623 20624 20625 20626 20627 20628 20629 20630 20631 20632 20633 20634 20635 20636 |
}
pNew = sqlite3DbMallocRaw(db, n);
if( pNew ){
memcpy(pNew, p, db->lookaside.sz);
sqlite3DbFree(db, p);
}
}else{
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
pNew = sqlite3_realloc64(p, n);
if( !pNew ){
db->mallocFailed = 1;
}
sqlite3MemdebugSetType(pNew,
(db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
}
}
return pNew;
}
/*
|
| ︙ | ︙ | |||
21755 21756 21757 21758 21759 21760 21761 21762 21763 21764 21765 21766 21767 21768 |
va_end(ap);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
#endif
/*
** variable-argument wrapper around sqlite3VXPrintf().
*/
SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){
va_list ap;
va_start(ap,zFormat);
sqlite3VXPrintf(p, bFlags, zFormat, ap);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 21787 21788 21789 21790 21791 21792 21793 21794 21795 21796 21797 21798 21799 21800 21801 21802 21803 21804 21805 21806 21807 21808 21809 21810 21811 21812 21813 21814 21815 21816 21817 21818 21819 21820 21821 21822 21823 21824 21825 21826 21827 21828 21829 21830 21831 21832 21833 21834 21835 21836 21837 21838 21839 21840 21841 21842 21843 21844 21845 21846 21847 21848 21849 21850 21851 21852 21853 21854 21855 21856 21857 21858 21859 21860 21861 21862 21863 |
va_end(ap);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
#endif
#ifdef SQLITE_DEBUG
/*************************************************************************
** Routines for implementing the "TreeView" display of hierarchical
** data structures for debugging.
**
** The main entry points (coded elsewhere) are:
** sqlite3TreeViewExpr(0, pExpr, 0);
** sqlite3TreeViewExprList(0, pList, 0, 0);
** sqlite3TreeViewSelect(0, pSelect, 0);
** Insert calls to those routines while debugging in order to display
** a diagram of Expr, ExprList, and Select objects.
**
*/
/* Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree. */
SQLITE_PRIVATE TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
return p;
}
/* Finished with one layer of the tree */
SQLITE_PRIVATE void sqlite3TreeViewPop(TreeView *p){
if( p==0 ) return;
p->iLevel--;
if( p->iLevel<0 ) sqlite3_free(p);
}
/* Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines */
SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
acc.useMalloc = 0;
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
/* Shorthand for starting a new tree item that consists of a single label */
SQLITE_PRIVATE void sqlite3TreeViewItem(TreeView *p, const char *zLabel, u8 moreToFollow){
p = sqlite3TreeViewPush(p, moreToFollow);
sqlite3TreeViewLine(p, "%s", zLabel);
}
#endif /* SQLITE_DEBUG */
/*
** variable-argument wrapper around sqlite3VXPrintf().
*/
SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){
va_list ap;
va_start(ap,zFormat);
sqlite3VXPrintf(p, bFlags, zFormat, ap);
|
| ︙ | ︙ | |||
21994 21995 21996 21997 21998 21999 22000 | } #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */ /******************************** End Unix Pthreads *************************/ /********************************* Win32 Threads ****************************/ | | | | 22089 22090 22091 22092 22093 22094 22095 22096 22097 22098 22099 22100 22101 22102 22103 22104 22105 22106 22107 22108 22109 22110 |
}
#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
/******************************** End Unix Pthreads *************************/
/********************************* Win32 Threads ****************************/
#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
#include <process.h>
/* A running thread */
struct SQLiteThread {
void *tid; /* The thread handle */
unsigned id; /* The thread identifier */
void *(*xTask)(void*); /* The routine to run as a thread */
void *pIn; /* Argument to xTask */
void *pResult; /* Result of xTask */
};
/* Thread procedure Win32 compatibility shim */
|
| ︙ | ︙ | |||
22049 22050 22051 22052 22053 22054 22055 |
p = sqlite3Malloc(sizeof(*p));
if( p==0 ) return SQLITE_NOMEM;
if( sqlite3GlobalConfig.bCoreMutex==0 ){
memset(p, 0, sizeof(*p));
}else{
p->xTask = xTask;
p->pIn = pIn;
| | | 22144 22145 22146 22147 22148 22149 22150 22151 22152 22153 22154 22155 22156 22157 22158 |
p = sqlite3Malloc(sizeof(*p));
if( p==0 ) return SQLITE_NOMEM;
if( sqlite3GlobalConfig.bCoreMutex==0 ){
memset(p, 0, sizeof(*p));
}else{
p->xTask = xTask;
p->pIn = pIn;
p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
if( p->tid==0 ){
memset(p, 0, sizeof(*p));
}
}
if( p->xTask==0 ){
p->id = GetCurrentThreadId();
p->pResult = xTask(pIn);
|
| ︙ | ︙ | |||
22087 22088 22089 22090 22091 22092 22093 |
assert( bRc );
}
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
sqlite3_free(p);
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
}
| | | 22182 22183 22184 22185 22186 22187 22188 22189 22190 22191 22192 22193 22194 22195 22196 |
assert( bRc );
}
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
sqlite3_free(p);
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
}
#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */
/******************************** End Win32 Threads *************************/
/********************************* Single-Threaded **************************/
#ifndef SQLITE_THREADS_IMPLEMENTED
/*
** This implementation does not actually create a new thread. It does the
|
| ︙ | ︙ | |||
29657 29658 29659 29660 29661 29662 29663 | ** ** * A constant sqlite3_io_methods object call METHOD that has locking ** methods CLOSE, LOCK, UNLOCK, CKRESLOCK. ** ** * An I/O method finder function called FINDER that returns a pointer ** to the METHOD object in the previous bullet. */ | | | | 29752 29753 29754 29755 29756 29757 29758 29759 29760 29761 29762 29763 29764 29765 29766 29767 29768 29769 29770 29771 29772 29773 29774 29775 29776 29777 29778 29779 29780 29781 |
**
** * A constant sqlite3_io_methods object call METHOD that has locking
** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
**
** * An I/O method finder function called FINDER that returns a pointer
** to the METHOD object in the previous bullet.
*/
#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK, SHMMAP) \
static const sqlite3_io_methods METHOD = { \
VERSION, /* iVersion */ \
CLOSE, /* xClose */ \
unixRead, /* xRead */ \
unixWrite, /* xWrite */ \
unixTruncate, /* xTruncate */ \
unixSync, /* xSync */ \
unixFileSize, /* xFileSize */ \
LOCK, /* xLock */ \
UNLOCK, /* xUnlock */ \
CKLOCK, /* xCheckReservedLock */ \
unixFileControl, /* xFileControl */ \
unixSectorSize, /* xSectorSize */ \
unixDeviceCharacteristics, /* xDeviceCapabilities */ \
SHMMAP, /* xShmMap */ \
unixShmLock, /* xShmLock */ \
unixShmBarrier, /* xShmBarrier */ \
unixShmUnmap, /* xShmUnmap */ \
unixFetch, /* xFetch */ \
unixUnfetch, /* xUnfetch */ \
}; \
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
|
| ︙ | ︙ | |||
29698 29699 29700 29701 29702 29703 29704 | IOMETHODS( posixIoFinder, /* Finder function name */ posixIoMethods, /* sqlite3_io_methods object name */ 3, /* shared memory and mmap are enabled */ unixClose, /* xClose method */ unixLock, /* xLock method */ unixUnlock, /* xUnlock method */ | | > | > | > | > | > | > | 29793 29794 29795 29796 29797 29798 29799 29800 29801 29802 29803 29804 29805 29806 29807 29808 29809 29810 29811 29812 29813 29814 29815 29816 29817 29818 29819 29820 29821 29822 29823 29824 29825 29826 29827 29828 29829 29830 29831 29832 29833 29834 29835 29836 29837 29838 29839 29840 29841 29842 29843 29844 29845 29846 29847 29848 29849 29850 29851 29852 29853 29854 29855 29856 29857 29858 29859 29860 29861 29862 29863 29864 29865 29866 | IOMETHODS( posixIoFinder, /* Finder function name */ posixIoMethods, /* sqlite3_io_methods object name */ 3, /* shared memory and mmap are enabled */ unixClose, /* xClose method */ unixLock, /* xLock method */ unixUnlock, /* xUnlock method */ unixCheckReservedLock, /* xCheckReservedLock method */ unixShmMap /* xShmMap method */ ) IOMETHODS( nolockIoFinder, /* Finder function name */ nolockIoMethods, /* sqlite3_io_methods object name */ 3, /* shared memory is disabled */ nolockClose, /* xClose method */ nolockLock, /* xLock method */ nolockUnlock, /* xUnlock method */ nolockCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) IOMETHODS( dotlockIoFinder, /* Finder function name */ dotlockIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ dotlockClose, /* xClose method */ dotlockLock, /* xLock method */ dotlockUnlock, /* xUnlock method */ dotlockCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS IOMETHODS( flockIoFinder, /* Finder function name */ flockIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ flockClose, /* xClose method */ flockLock, /* xLock method */ flockUnlock, /* xUnlock method */ flockCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif #if OS_VXWORKS IOMETHODS( semIoFinder, /* Finder function name */ semIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ semClose, /* xClose method */ semLock, /* xLock method */ semUnlock, /* xUnlock method */ semCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE IOMETHODS( afpIoFinder, /* Finder function name */ afpIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ afpClose, /* xClose method */ afpLock, /* xLock method */ afpUnlock, /* xUnlock method */ afpCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif /* ** The proxy locking method is a "super-method" in the sense that it ** opens secondary file descriptors for the conch and lock files and ** it uses proxy, dot-file, AFP, and flock() locking methods on those |
| ︙ | ︙ | |||
29776 29777 29778 29779 29780 29781 29782 | IOMETHODS( proxyIoFinder, /* Finder function name */ proxyIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ proxyClose, /* xClose method */ proxyLock, /* xLock method */ proxyUnlock, /* xUnlock method */ | | > | > | 29877 29878 29879 29880 29881 29882 29883 29884 29885 29886 29887 29888 29889 29890 29891 29892 29893 29894 29895 29896 29897 29898 29899 29900 29901 29902 29903 29904 29905 29906 | IOMETHODS( proxyIoFinder, /* Finder function name */ proxyIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ proxyClose, /* xClose method */ proxyLock, /* xLock method */ proxyUnlock, /* xUnlock method */ proxyCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif /* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */ #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE IOMETHODS( nfsIoFinder, /* Finder function name */ nfsIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ unixClose, /* xClose method */ unixLock, /* xLock method */ nfsUnlock, /* xUnlock method */ unixCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE /* ** This "finder" function attempts to determine the best locking strategy ** for the database file "filePath". It then returns the sqlite3_io_methods |
| ︙ | ︙ | |||
33382 33383 33384 33385 33386 33387 33388 33389 33390 33391 33392 33393 33394 33395 33396 |
#else
{ "WaitForSingleObject", (SYSCALL)0, 0 },
#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
DWORD))aSyscall[63].pCurrent)
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
BOOL))aSyscall[64].pCurrent)
#if SQLITE_OS_WINRT
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
#else
| > > > > | 33485 33486 33487 33488 33489 33490 33491 33492 33493 33494 33495 33496 33497 33498 33499 33500 33501 33502 33503 |
#else
{ "WaitForSingleObject", (SYSCALL)0, 0 },
#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
DWORD))aSyscall[63].pCurrent)
#if !SQLITE_OS_WINCE
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
#else
{ "WaitForSingleObjectEx", (SYSCALL)0, 0 },
#endif
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
BOOL))aSyscall[64].pCurrent)
#if SQLITE_OS_WINRT
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
#else
|
| ︙ | ︙ | |||
33725 33726 33727 33728 33729 33730 33731 | assert( sleepObj!=NULL ); osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE); #else osSleep(milliseconds); #endif } | | > | 33832 33833 33834 33835 33836 33837 33838 33839 33840 33841 33842 33843 33844 33845 33846 33847 |
assert( sleepObj!=NULL );
osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
#else
osSleep(milliseconds);
#endif
}
#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
SQLITE_THREADSAFE>0
SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
DWORD rc;
while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
TRUE))==WAIT_IO_COMPLETION ){}
return rc;
}
#endif
|
| ︙ | ︙ | |||
39750 39751 39752 39753 39754 39755 39756 |
assert( pCache->nPage >= pCache->nRecyclable );
nPinned = pCache->nPage - pCache->nRecyclable;
assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
assert( pCache->n90pct == pCache->nMax*9/10 );
if( createFlag==1 && (
nPinned>=pGroup->mxPinned
|| nPinned>=pCache->n90pct
| | | 39858 39859 39860 39861 39862 39863 39864 39865 39866 39867 39868 39869 39870 39871 39872 |
assert( pCache->nPage >= pCache->nRecyclable );
nPinned = pCache->nPage - pCache->nRecyclable;
assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
assert( pCache->n90pct == pCache->nMax*9/10 );
if( createFlag==1 && (
nPinned>=pGroup->mxPinned
|| nPinned>=pCache->n90pct
|| (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned)
)){
return 0;
}
if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache);
assert( pCache->nHash>0 && pCache->apHash );
|
| ︙ | ︙ | |||
44371 44372 44373 44374 44375 44376 44377 |
if( rc==SQLITE_OK ){
pNew = (char *)sqlite3PageMalloc(pageSize);
if( !pNew ) rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
pager_reset(pPager);
| < < > > > > | 44479 44480 44481 44482 44483 44484 44485 44486 44487 44488 44489 44490 44491 44492 44493 44494 44495 44496 44497 44498 44499 44500 44501 |
if( rc==SQLITE_OK ){
pNew = (char *)sqlite3PageMalloc(pageSize);
if( !pNew ) rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
pager_reset(pPager);
rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
}
if( rc==SQLITE_OK ){
sqlite3PageFree(pPager->pTmpSpace);
pPager->pTmpSpace = pNew;
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
pPager->pageSize = pageSize;
}else{
sqlite3PageFree(pNew);
}
}
*pPageSize = pPager->pageSize;
if( rc==SQLITE_OK ){
if( nReserve<0 ) nReserve = pPager->nReserve;
assert( nReserve>=0 && nReserve<1000 );
|
| ︙ | ︙ | |||
51381 51382 51383 51384 51385 51386 51387 |
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
| | > > | < | 51491 51492 51493 51494 51495 51496 51497 51498 51499 51500 51501 51502 51503 51504 51505 51506 51507 51508 |
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
u8 intKey; /* True if table b-trees. False for index b-trees */
u8 intKeyLeaf; /* True if the leaf of an intKey table */
u8 noPayload; /* True if internal intKey page (thus w/o data) */
u8 leaf; /* True if a leaf page */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u8 max1bytePayload; /* min(maxLocal,127) */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
u16 nFree; /* Number of free bytes on the page */
|
| ︙ | ︙ | |||
51543 51544 51545 51546 51547 51548 51549 | Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */ #ifndef SQLITE_OMIT_SHARED_CACHE int nRef; /* Number of references to this structure */ BtShared *pNext; /* Next on a list of sharable BtShared structs */ BtLock *pLock; /* List of locks held on this shared-btree struct */ Btree *pWriter; /* Btree with currently open write transaction */ #endif | | | | < | < | | 51654 51655 51656 51657 51658 51659 51660 51661 51662 51663 51664 51665 51666 51667 51668 51669 51670 51671 51672 51673 51674 51675 51676 51677 51678 51679 51680 51681 51682 51683 51684 51685 51686 51687 51688 51689 51690 51691 51692 |
Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nRef; /* Number of references to this structure */
BtShared *pNext; /* Next on a list of sharable BtShared structs */
BtLock *pLock; /* List of locks held on this shared-btree struct */
Btree *pWriter; /* Btree with currently open write transaction */
#endif
u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
};
/*
** Allowed values for BtShared.btsFlags
*/
#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */
#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */
#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */
#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */
/*
** An instance of the following structure is used to hold information
** about a cell. The parseCellPtr() function fills in this structure
** based on information extract from the raw disk page.
*/
typedef struct CellInfo CellInfo;
struct CellInfo {
i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
u8 *pPayload; /* Pointer to the start of payload */
u32 nPayload; /* Bytes of payload */
u16 nLocal; /* Amount of payload held locally, not on overflow */
u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
u16 nSize; /* Size of the cell content on the main b-tree page */
};
/*
** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
** this will be declared corrupt. This value is calculated based on a
|
| ︙ | ︙ | |||
51766 51767 51768 51769 51770 51771 51772 51773 51774 51775 51776 51777 51778 51779 | BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ u8 *aPgRef; /* 1 bit per page in the db (see above) */ Pgno nPage; /* Number of pages in the database */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int mallocFailed; /* A memory allocation error has occurred */ StrAccum errMsg; /* Accumulate the error message text here */ }; /* ** Routines to read or write a two- and four-byte big-endian integer values. */ #define get2byte(x) ((x)[0]<<8 | (x)[1]) | > > | 51875 51876 51877 51878 51879 51880 51881 51882 51883 51884 51885 51886 51887 51888 51889 51890 | BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ u8 *aPgRef; /* 1 bit per page in the db (see above) */ Pgno nPage; /* Number of pages in the database */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int mallocFailed; /* A memory allocation error has occurred */ const char *zPfx; /* Error message prefix */ int v1, v2; /* Values for up to two %d fields in zPfx */ StrAccum errMsg; /* Accumulate the error message text here */ }; /* ** Routines to read or write a two- and four-byte big-endian integer values. */ #define get2byte(x) ((x)[0]<<8 | (x)[1]) |
| ︙ | ︙ | |||
52552 52553 52554 52555 52556 52557 52558 |
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
BtShared *pBt = pBtree->pBt;
assert( sqlite3BtreeHoldsMutex(pBtree) );
for(p=pBt->pCursor; p; p=p->pNext){
| | > > | 52663 52664 52665 52666 52667 52668 52669 52670 52671 52672 52673 52674 52675 52676 52677 52678 52679 |
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
BtShared *pBt = pBtree->pBt;
assert( sqlite3BtreeHoldsMutex(pBtree) );
for(p=pBt->pCursor; p; p=p->pNext){
if( (p->curFlags & BTCF_Incrblob)!=0
&& (isClearTable || p->info.nKey==iRow)
){
p->eState = CURSOR_INVALID;
}
}
}
#else
/* Stub function when INCRBLOB is omitted */
|
| ︙ | ︙ | |||
52725 52726 52727 52728 52729 52730 52731 | /* This helper routine to saveAllCursors does the actual work of saving ** the cursors if and when a cursor is found that actually requires saving. ** The common case is that no cursors need to be saved, so this routine is ** broken out from its caller to avoid unnecessary stack pointer movement. */ static int SQLITE_NOINLINE saveCursorsOnList( | | | | | 52838 52839 52840 52841 52842 52843 52844 52845 52846 52847 52848 52849 52850 52851 52852 52853 52854 |
/* This helper routine to saveAllCursors does the actual work of saving
** the cursors if and when a cursor is found that actually requires saving.
** The common case is that no cursors need to be saved, so this routine is
** broken out from its caller to avoid unnecessary stack pointer movement.
*/
static int SQLITE_NOINLINE saveCursorsOnList(
BtCursor *p, /* The first cursor that needs saving */
Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */
BtCursor *pExcept /* Do not save this cursor */
){
do{
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
if( p->eState==CURSOR_VALID ){
int rc = saveCursorPosition(p);
if( SQLITE_OK!=rc ){
return rc;
|
| ︙ | ︙ | |||
52839 52840 52841 52842 52843 52844 52845 |
**
** Calling this routine with a NULL cursor pointer returns false.
**
** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor
** back to where it ought to be if this routine returns true.
*/
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
| | | 52952 52953 52954 52955 52956 52957 52958 52959 52960 52961 52962 52963 52964 52965 52966 |
**
** Calling this routine with a NULL cursor pointer returns false.
**
** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor
** back to where it ought to be if this routine returns true.
*/
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
return pCur->eState!=CURSOR_VALID;
}
/*
** This routine restores a cursor back to its original position after it
** has been moved by some outside activity (such as a btree rebalance or
** a row having been deleted out from under the cursor).
**
|
| ︙ | ︙ | |||
53033 53034 53035 53036 53037 53038 53039 | } /* ** Parse a cell content block and fill in the CellInfo structure. There ** are two versions of this function. btreeParseCell() takes a ** cell index as the second argument and btreeParseCellPtr() ** takes a pointer to the body of the cell as its second argument. | < < < | < < < < | < | | > | > > | < | | > > | | | | > | | 53146 53147 53148 53149 53150 53151 53152 53153 53154 53155 53156 53157 53158 53159 53160 53161 53162 53163 53164 53165 53166 53167 53168 53169 53170 53171 53172 53173 53174 53175 53176 53177 53178 53179 53180 53181 53182 53183 53184 53185 53186 53187 53188 53189 53190 53191 53192 53193 53194 53195 53196 53197 |
}
/*
** Parse a cell content block and fill in the CellInfo structure. There
** are two versions of this function. btreeParseCell() takes a
** cell index as the second argument and btreeParseCellPtr()
** takes a pointer to the body of the cell as its second argument.
*/
static void btreeParseCellPtr(
MemPage *pPage, /* Page containing the cell */
u8 *pCell, /* Pointer to the cell text. */
CellInfo *pInfo /* Fill in this structure */
){
u8 *pIter; /* For scanning through pCell */
u32 nPayload; /* Number of bytes of cell payload */
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( pPage->leaf==0 || pPage->leaf==1 );
if( pPage->intKeyLeaf ){
assert( pPage->childPtrSize==0 );
pIter = pCell + getVarint32(pCell, nPayload);
pIter += getVarint(pIter, (u64*)&pInfo->nKey);
}else if( pPage->noPayload ){
assert( pPage->childPtrSize==4 );
pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
pInfo->nPayload = 0;
pInfo->nLocal = 0;
pInfo->iOverflow = 0;
pInfo->pPayload = 0;
return;
}else{
pIter = pCell + pPage->childPtrSize;
pIter += getVarint32(pIter, nPayload);
pInfo->nKey = nPayload;
}
pInfo->nPayload = nPayload;
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==pPage->maxLocal+1 );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
*/
pInfo->nSize = nPayload + (u16)(pIter - pCell);
if( pInfo->nSize<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
pInfo->iOverflow = 0;
}else{
/* If the payload will not fit completely on the local page, we have
** to decide how much to store locally and how much to spill onto
** overflow pages. The strategy is to minimize the amount of unused
** space on overflow pages while keeping the amount of local storage
|
| ︙ | ︙ | |||
53100 53101 53102 53103 53104 53105 53106 |
testcase( surplus==maxLocal );
testcase( surplus==maxLocal+1 );
if( surplus <= maxLocal ){
pInfo->nLocal = (u16)surplus;
}else{
pInfo->nLocal = (u16)minLocal;
}
| | < < | | > | | | > | | > | > > | > > > | | > < < < | > > > | < < < < < < < | | 53210 53211 53212 53213 53214 53215 53216 53217 53218 53219 53220 53221 53222 53223 53224 53225 53226 53227 53228 53229 53230 53231 53232 53233 53234 53235 53236 53237 53238 53239 53240 53241 53242 53243 53244 53245 53246 53247 53248 53249 53250 53251 53252 53253 53254 53255 53256 53257 53258 53259 53260 53261 53262 53263 53264 53265 53266 53267 53268 53269 53270 53271 53272 53273 53274 53275 53276 53277 53278 53279 53280 53281 53282 53283 53284 53285 53286 53287 53288 53289 53290 53291 53292 53293 |
testcase( surplus==maxLocal );
testcase( surplus==maxLocal+1 );
if( surplus <= maxLocal ){
pInfo->nLocal = (u16)surplus;
}else{
pInfo->nLocal = (u16)minLocal;
}
pInfo->iOverflow = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell);
pInfo->nSize = pInfo->iOverflow + 4;
}
}
static void btreeParseCell(
MemPage *pPage, /* Page containing the cell */
int iCell, /* The cell index. First cell is 0 */
CellInfo *pInfo /* Fill in this structure */
){
btreeParseCellPtr(pPage, findCell(pPage, iCell), pInfo);
}
/*
** Compute the total number of bytes that a Cell needs in the cell
** data area of the btree-page. The return number includes the cell
** data header and the local payload, but not any overflow page or
** the space used by the cell pointer.
*/
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */
u8 *pEnd; /* End mark for a varint */
u32 nSize; /* Size value to return */
#ifdef SQLITE_DEBUG
/* The value returned by this function should always be the same as
** the (CellInfo.nSize) value found by doing a full parse of the
** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
** this function verifies that this invariant is not violated. */
CellInfo debuginfo;
btreeParseCellPtr(pPage, pCell, &debuginfo);
#endif
if( pPage->noPayload ){
pEnd = &pIter[9];
while( (*pIter++)&0x80 && pIter<pEnd );
assert( pPage->childPtrSize==4 );
return (u16)(pIter - pCell);
}
nSize = *pIter;
if( nSize>=0x80 ){
pEnd = &pIter[9];
nSize &= 0x7f;
do{
nSize = (nSize<<7) | (*++pIter & 0x7f);
}while( *(pIter)>=0x80 && pIter<pEnd );
}
pIter++;
if( pPage->intKey ){
/* pIter now points at the 64-bit integer key value, a variable length
** integer. The following block moves pIter to point at the first byte
** past the end of the key value. */
pEnd = &pIter[9];
while( (*pIter++)&0x80 && pIter<pEnd );
}
testcase( nSize==pPage->maxLocal );
testcase( nSize==pPage->maxLocal+1 );
if( nSize<=pPage->maxLocal ){
nSize += (u32)(pIter - pCell);
if( nSize<4 ) nSize = 4;
}else{
int minLocal = pPage->minLocal;
nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
testcase( nSize==pPage->maxLocal );
testcase( nSize==pPage->maxLocal+1 );
if( nSize>pPage->maxLocal ){
nSize = minLocal;
}
nSize += 4 + (u16)(pIter - pCell);
}
assert( nSize==debuginfo.nSize || CORRUPT_DB );
return (u16)nSize;
}
#ifdef SQLITE_DEBUG
/* This variation on cellSizePtr() is used inside of assert() statements
** only. */
static u16 cellSize(MemPage *pPage, int iCell){
|
| ︙ | ︙ | |||
53192 53193 53194 53195 53196 53197 53198 |
** for the overflow page.
*/
static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
CellInfo info;
if( *pRC ) return;
assert( pCell!=0 );
btreeParseCellPtr(pPage, pCell, &info);
| < | 53302 53303 53304 53305 53306 53307 53308 53309 53310 53311 53312 53313 53314 53315 |
** for the overflow page.
*/
static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
CellInfo info;
if( *pRC ) return;
assert( pCell!=0 );
btreeParseCellPtr(pPage, pCell, &info);
if( info.iOverflow ){
Pgno ovfl = get4byte(&pCell[info.iOverflow]);
ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
}
}
#endif
|
| ︙ | ︙ | |||
53405 53406 53407 53408 53409 53410 53411 |
** Note that even though the freeblock list was checked by btreeInitPage(),
** that routine will not detect overlap between cells or freeblocks. Nor
** does it detect cells or freeblocks that encrouch into the reserved bytes
** at the end of the page. So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
| | | 53514 53515 53516 53517 53518 53519 53520 53521 53522 53523 53524 53525 53526 53527 53528 |
** Note that even though the freeblock list was checked by btreeInitPage(),
** that routine will not detect overlap between cells or freeblocks. Nor
** does it detect cells or freeblocks that encrouch into the reserved bytes
** at the end of the page. So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
u16 iPtr; /* Address of ptr to next freeblock */
u16 iFreeBlk; /* Address of the next freeblock */
u8 hdr; /* Page header size. 0 or 100 */
u8 nFrag = 0; /* Reduction in fragmentation */
u16 iOrigSize = iSize; /* Original value of iSize */
u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */
u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
|
| ︙ | ︙ | |||
53457 53458 53459 53460 53461 53462 53463 |
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT;
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
| | | | | 53566 53567 53568 53569 53570 53571 53572 53573 53574 53575 53576 53577 53578 53579 53580 53581 53582 |
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT;
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
/* If iPtr is another freeblock (that is, if iPtr is not the freelist
** pointer in the page header) then check to see if iStart should be
** coalesced onto the end of iPtr.
*/
if( iPtr>hdr+1 ){
int iPtrEnd = iPtr + get2byte(&data[iPtr+2]);
if( iPtrEnd+3>=iStart ){
if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT;
nFrag += iStart - iPtrEnd;
iSize = iEnd - iPtr;
|
| ︙ | ︙ | |||
53513 53514 53515 53516 53517 53518 53519 |
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
flagByte &= ~PTF_LEAF;
pPage->childPtrSize = 4-4*pPage->leaf;
pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
pPage->intKey = 1;
| | > | > | 53622 53623 53624 53625 53626 53627 53628 53629 53630 53631 53632 53633 53634 53635 53636 53637 53638 53639 53640 53641 53642 53643 |
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
flagByte &= ~PTF_LEAF;
pPage->childPtrSize = 4-4*pPage->leaf;
pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
pPage->intKey = 1;
pPage->intKeyLeaf = pPage->leaf;
pPage->noPayload = !pPage->leaf;
pPage->maxLocal = pBt->maxLeaf;
pPage->minLocal = pBt->minLeaf;
}else if( flagByte==PTF_ZERODATA ){
pPage->intKey = 0;
pPage->intKeyLeaf = 0;
pPage->noPayload = 0;
pPage->maxLocal = pBt->maxLocal;
pPage->minLocal = pBt->minLocal;
}else{
return SQLITE_CORRUPT_BKPT;
}
pPage->max1bytePayload = pBt->max1bytePayload;
return SQLITE_OK;
|
| ︙ | ︙ | |||
54173 54174 54175 54176 54177 54178 54179 | #else return 1; #endif } /* ** Make sure pBt->pTmpSpace points to an allocation of | | > | > > > > > | > > > | > > | > | 54284 54285 54286 54287 54288 54289 54290 54291 54292 54293 54294 54295 54296 54297 54298 54299 54300 54301 54302 54303 54304 54305 54306 54307 54308 54309 54310 54311 54312 54313 54314 54315 54316 54317 54318 54319 54320 54321 54322 54323 54324 54325 54326 54327 54328 54329 54330 54331 54332 54333 54334 54335 |
#else
return 1;
#endif
}
/*
** Make sure pBt->pTmpSpace points to an allocation of
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
** pointer.
*/
static void allocateTempSpace(BtShared *pBt){
if( !pBt->pTmpSpace ){
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
/* One of the uses of pBt->pTmpSpace is to format cells before
** inserting them into a leaf page (function fillInCell()). If
** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
** by the various routines that manipulate binary cells. Which
** can mean that fillInCell() only initializes the first 2 or 3
** bytes of pTmpSpace, but that the first 4 bytes are copied from
** it into a database page. This is not actually a problem, but it
** does cause a valgrind error when the 1 or 2 bytes of unitialized
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
** Also: Provide four bytes of initialized space before the
** beginning of pTmpSpace as an area available to prepend the
** left-child pointer to the beginning of a cell.
*/
if( pBt->pTmpSpace ){
memset(pBt->pTmpSpace, 0, 8);
pBt->pTmpSpace += 4;
}
}
}
/*
** Free the pBt->pTmpSpace allocation
*/
static void freeTempSpace(BtShared *pBt){
if( pBt->pTmpSpace ){
pBt->pTmpSpace -= 4;
sqlite3PageFree(pBt->pTmpSpace);
pBt->pTmpSpace = 0;
}
}
/*
** Close an open database and invalidate all cursors.
*/
SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
|
| ︙ | ︙ | |||
54692 54693 54694 54695 54696 54697 54698 |
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(BtShared *pBt){
assert( sqlite3_mutex_held(pBt->mutex) );
assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
| > | | | < | 54815 54816 54817 54818 54819 54820 54821 54822 54823 54824 54825 54826 54827 54828 54829 54830 54831 54832 54833 |
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(BtShared *pBt){
assert( sqlite3_mutex_held(pBt->mutex) );
assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
MemPage *pPage1 = pBt->pPage1;
assert( pPage1->aData );
assert( sqlite3PagerRefcount(pBt->pPager)==1 );
pBt->pPage1 = 0;
releasePage(pPage1);
}
}
/*
** If pBt points to an empty file then convert that empty file
** into a new empty database by initializing the first page of
** the database.
|
| ︙ | ︙ | |||
55737 55738 55739 55740 55741 55742 55743 55744 55745 55746 55747 55748 55749 55750 |
assert( p->inTrans>TRANS_NONE );
assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
assert( pBt->pPage1 && pBt->pPage1->aData );
if( NEVER(wrFlag && (pBt->btsFlags & BTS_READ_ONLY)!=0) ){
return SQLITE_READONLY;
}
if( iTable==1 && btreePagecount(pBt)==0 ){
assert( wrFlag==0 );
iTable = 0;
}
/* Now that no other errors can occur, finish filling in the BtCursor
** variables and link the cursor into the BtShared list. */
| > > > > | 55860 55861 55862 55863 55864 55865 55866 55867 55868 55869 55870 55871 55872 55873 55874 55875 55876 55877 |
assert( p->inTrans>TRANS_NONE );
assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
assert( pBt->pPage1 && pBt->pPage1->aData );
if( NEVER(wrFlag && (pBt->btsFlags & BTS_READ_ONLY)!=0) ){
return SQLITE_READONLY;
}
if( wrFlag ){
allocateTempSpace(pBt);
if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM;
}
if( iTable==1 && btreePagecount(pBt)==0 ){
assert( wrFlag==0 );
iTable = 0;
}
/* Now that no other errors can occur, finish filling in the BtCursor
** variables and link the cursor into the BtShared list. */
|
| ︙ | ︙ | |||
55926 55927 55928 55929 55930 55931 55932 55933 |
** Failure is not possible. This function always returns SQLITE_OK.
** It might just as well be a procedure (returning void) but we continue
** to return an integer result code for historical reasons.
*/
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
getCellInfo(pCur);
| > | | 56053 56054 56055 56056 56057 56058 56059 56060 56061 56062 56063 56064 56065 56066 56067 56068 56069 |
** Failure is not possible. This function always returns SQLITE_OK.
** It might just as well be a procedure (returning void) but we continue
** to return an integer result code for historical reasons.
*/
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
getCellInfo(pCur);
*pSize = pCur->info.nPayload;
return SQLITE_OK;
}
/*
** Given the page number of an overflow page in the database (parameter
** ovfl), this function finds the page number of the next page in the
** linked list of overflow pages. If possible, it uses the auto-vacuum
|
| ︙ | ︙ | |||
56078 56079 56080 56081 56082 56083 56084 |
u32 offset, /* Begin reading this far into payload */
u32 amt, /* Read this many bytes */
unsigned char *pBuf, /* Write the bytes into this buffer */
int eOp /* zero to read. non-zero to write. */
){
unsigned char *aPayload;
int rc = SQLITE_OK;
| < > | | | < | > < | < | 56206 56207 56208 56209 56210 56211 56212 56213 56214 56215 56216 56217 56218 56219 56220 56221 56222 56223 56224 56225 56226 56227 56228 56229 56230 56231 56232 56233 56234 56235 56236 56237 56238 56239 56240 56241 |
u32 offset, /* Begin reading this far into payload */
u32 amt, /* Read this many bytes */
unsigned char *pBuf, /* Write the bytes into this buffer */
int eOp /* zero to read. non-zero to write. */
){
unsigned char *aPayload;
int rc = SQLITE_OK;
int iIdx = 0;
MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
unsigned char * const pBufStart = pBuf;
int bEnd; /* True if reading to end of data */
#endif
assert( pPage );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( cursorHoldsMutex(pCur) );
assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
#ifdef SQLITE_DIRECT_OVERFLOW_READ
bEnd = offset+amt==pCur->info.nPayload;
#endif
assert( offset+amt <= pCur->info.nPayload );
if( &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ){
/* Trying to read or write past the end of the data is an error */
return SQLITE_CORRUPT_BKPT;
}
/* Check if data must be read/written to/from the btree page itself. */
if( offset<pCur->info.nLocal ){
int a = amt;
|
| ︙ | ︙ | |||
56157 56158 56159 56160 56161 56162 56163 |
}
}
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
*/
| | > > | 56283 56284 56285 56286 56287 56288 56289 56290 56291 56292 56293 56294 56295 56296 56297 56298 56299 |
}
}
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
*/
if( (pCur->curFlags & BTCF_ValidOvfl)!=0
&& pCur->aOverflow[offset/ovflSize]
){
iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize);
}
for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
|
| ︙ | ︙ | |||
56210 56211 56212 56213 56214 56215 56216 56217 56218 56219 56220 56221 56222 56223 56224 56225 56226 56227 56228 56229 56230 56231 56232 56233 56234 56235 56236 56237 |
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
** 3) the database is file-backed, and
** 4) there is no open write-transaction, and
** 5) the database is not a WAL database,
** 6) all data from the page is being read.
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
if( (eOp&0x01)==0 /* (1) */
&& offset==0 /* (2) */
&& (bEnd || a==ovflSize) /* (6) */
&& pBt->inTransaction==TRANS_READ /* (4) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
&& pBt->pPage1->aData[19]==0x01 /* (5) */
){
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
#endif
| > > > | 56338 56339 56340 56341 56342 56343 56344 56345 56346 56347 56348 56349 56350 56351 56352 56353 56354 56355 56356 56357 56358 56359 56360 56361 56362 56363 56364 56365 56366 56367 56368 |
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
** 3) the database is file-backed, and
** 4) there is no open write-transaction, and
** 5) the database is not a WAL database,
** 6) all data from the page is being read.
** 7) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
if( (eOp&0x01)==0 /* (1) */
&& offset==0 /* (2) */
&& (bEnd || a==ovflSize) /* (6) */
&& pBt->inTransaction==TRANS_READ /* (4) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
&& pBt->pPage1->aData[19]==0x01 /* (5) */
&& &pBuf[-4]>=pBufStart /* (7) */
){
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* hence (7) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
#endif
|
| ︙ | ︙ | |||
56335 56336 56337 56338 56339 56340 56341 | assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); assert( pCur->info.nSize>0 ); *pAmt = pCur->info.nLocal; | | | 56466 56467 56468 56469 56470 56471 56472 56473 56474 56475 56476 56477 56478 56479 56480 | assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); assert( pCur->info.nSize>0 ); *pAmt = pCur->info.nLocal; return (void*)pCur->info.pPayload; } /* ** For the entry that cursor pCur is point to, return as ** many bytes of the key or data as are available on the local ** b-tree page. Write the number of available bytes into *pAmt. |
| ︙ | ︙ | |||
56763 56764 56765 56766 56767 56768 56769 |
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
| | | 56894 56895 56896 56897 56898 56899 56900 56901 56902 56903 56904 56905 56906 56907 56908 |
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
if( pPage->intKeyLeaf ){
while( 0x80 <= *(pCell++) ){
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
}
}
getVarint(pCell, (u64*)&nCellKey);
if( nCellKey<intKey ){
lwr = idx+1;
|
| ︙ | ︙ | |||
57022 57023 57024 57025 57026 57027 57028 | ** Step the cursor to the back to the previous entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. ** ** The main entry point is sqlite3BtreePrevious(). That routine is optimized ** for the common case of merely decrementing the cell counter BtCursor.aiIdx | | | | | 57153 57154 57155 57156 57157 57158 57159 57160 57161 57162 57163 57164 57165 57166 57167 57168 57169 | ** Step the cursor to the back to the previous entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. ** ** The main entry point is sqlite3BtreePrevious(). That routine is optimized ** for the common case of merely decrementing the cell counter BtCursor.aiIdx ** to the previous cell on the current page. The (slower) btreePrevious() ** helper routine is called when it is necessary to move to a different page ** or to restore the cursor. ** ** The calling function will set *pRes to 0 or 1. The initial *pRes value ** will be 1 if the cursor being stepped corresponds to an SQL index and ** if this routine could have been skipped if that SQL index had been ** a unique index. Otherwise the caller will have set *pRes to zero. ** Zero is the common case. The btree implementation is free to use the ** initial *pRes value as a hint to improve performance, but the current |
| ︙ | ︙ | |||
57046 57047 57048 57049 57050 57051 57052 |
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
assert( *pRes==0 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
| < | | 57177 57178 57179 57180 57181 57182 57183 57184 57185 57186 57187 57188 57189 57190 57191 |
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
assert( *pRes==0 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
*pRes = 1;
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
57352 57353 57354 57355 57356 57357 57358 |
*pPgno, closest+1, k, pTrunk->pgno, n-1));
rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc ) goto end_allocate_page;
if( closest<k-1 ){
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
}
put4byte(&aData[4], k-1);
| | | 57482 57483 57484 57485 57486 57487 57488 57489 57490 57491 57492 57493 57494 57495 57496 |
*pPgno, closest+1, k, pTrunk->pgno, n-1));
rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc ) goto end_allocate_page;
if( closest<k-1 ){
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
}
put4byte(&aData[4], k-1);
noContent = !btreeGetHasContent(pBt, *pPgno)? PAGER_GET_NOCONTENT : 0;
rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
}
}
|
| ︙ | ︙ | |||
57385 57386 57387 57388 57389 57390 57391 |
**
** Note that the pager will not actually attempt to load or journal
** content for any page that really does lie past the end of the database
** file on disk. So the effects of disabling the no-content optimization
** here are confined to those pages that lie between the end of the
** database image and the end of the database file.
*/
| | | 57515 57516 57517 57518 57519 57520 57521 57522 57523 57524 57525 57526 57527 57528 57529 |
**
** Note that the pager will not actually attempt to load or journal
** content for any page that really does lie past the end of the database
** file on disk. So the effects of disabling the no-content optimization
** here are confined to those pages that lie between the end of the
** database image and the end of the database file.
*/
int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate))? PAGER_GET_NOCONTENT:0;
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc ) return rc;
pBt->nPage++;
if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;
#ifndef SQLITE_OMIT_AUTOVACUUM
|
| ︙ | ︙ | |||
57584 57585 57586 57587 57588 57589 57590 |
static void freePage(MemPage *pPage, int *pRC){
if( (*pRC)==SQLITE_OK ){
*pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
}
}
/*
| | > > | > > > > > | 57714 57715 57716 57717 57718 57719 57720 57721 57722 57723 57724 57725 57726 57727 57728 57729 57730 57731 57732 57733 57734 57735 57736 57737 57738 57739 57740 57741 57742 57743 57744 57745 57746 |
static void freePage(MemPage *pPage, int *pRC){
if( (*pRC)==SQLITE_OK ){
*pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
}
}
/*
** Free any overflow pages associated with the given Cell. Write the
** local Cell size (the number of bytes on the original page, omitting
** overflow) into *pnSize.
*/
static int clearCell(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
u16 *pnSize /* Write the size of the Cell here */
){
BtShared *pBt = pPage->pBt;
CellInfo info;
Pgno ovflPgno;
int rc;
int nOvfl;
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
btreeParseCellPtr(pPage, pCell, &info);
*pnSize = info.nSize;
if( info.iOverflow==0 ){
return SQLITE_OK; /* No overflow pages. Return without doing anything */
}
if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
}
ovflPgno = get4byte(&pCell[info.iOverflow]);
|
| ︙ | ︙ | |||
57679 57680 57681 57682 57683 57684 57685 | MemPage *pOvfl = 0; MemPage *pToRelease = 0; unsigned char *pPrior; unsigned char *pPayload; BtShared *pBt = pPage->pBt; Pgno pgnoOvfl = 0; int nHeader; | < | < | < | | > | < < < < | < | > > > > > | > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > | | > > > | 57816 57817 57818 57819 57820 57821 57822 57823 57824 57825 57826 57827 57828 57829 57830 57831 57832 57833 57834 57835 57836 57837 57838 57839 57840 57841 57842 57843 57844 57845 57846 57847 57848 57849 57850 57851 57852 57853 57854 57855 57856 57857 57858 57859 57860 57861 57862 57863 57864 57865 57866 57867 57868 57869 57870 57871 57872 57873 57874 57875 57876 57877 57878 57879 57880 57881 57882 57883 57884 57885 57886 57887 57888 57889 57890 57891 57892 57893 57894 57895 57896 57897 57898 57899 57900 57901 57902 57903 57904 57905 57906 |
MemPage *pOvfl = 0;
MemPage *pToRelease = 0;
unsigned char *pPrior;
unsigned char *pPayload;
BtShared *pBt = pPage->pBt;
Pgno pgnoOvfl = 0;
int nHeader;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
/* pPage is not necessarily writeable since pCell might be auxiliary
** buffer space that is separate from the pPage buffer area */
assert( pCell<pPage->aData || pCell>=&pPage->aData[pBt->pageSize]
|| sqlite3PagerIswriteable(pPage->pDbPage) );
/* Fill in the header. */
nHeader = pPage->childPtrSize;
nPayload = nData + nZero;
if( pPage->intKeyLeaf ){
nHeader += putVarint32(&pCell[nHeader], nPayload);
}else{
assert( nData==0 );
assert( nZero==0 );
}
nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey);
/* Fill in the payload size */
if( pPage->intKey ){
pSrc = pData;
nSrc = nData;
nData = 0;
}else{
if( NEVER(nKey>0x7fffffff || pKey==0) ){
return SQLITE_CORRUPT_BKPT;
}
nPayload = (int)nKey;
pSrc = pKey;
nSrc = (int)nKey;
}
if( nPayload<=pPage->maxLocal ){
n = nHeader + nPayload;
testcase( n==3 );
testcase( n==4 );
if( n<4 ) n = 4;
*pnSize = n;
spaceLeft = nPayload;
pPrior = pCell;
}else{
int mn = pPage->minLocal;
n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
testcase( n==pPage->maxLocal );
testcase( n==pPage->maxLocal+1 );
if( n > pPage->maxLocal ) n = mn;
spaceLeft = n;
*pnSize = n + nHeader + 4;
pPrior = &pCell[nHeader+n];
}
pPayload = &pCell[nHeader];
/* At this point variables should be set as follows:
**
** nPayload Total payload size in bytes
** pPayload Begin writing payload here
** spaceLeft Space available at pPayload. If nPayload>spaceLeft,
** that means content must spill into overflow pages.
** *pnSize Size of the local cell (not counting overflow pages)
** pPrior Where to write the pgno of the first overflow page
**
** Use a call to btreeParseCellPtr() to verify that the values above
** were computed correctly.
*/
#if SQLITE_DEBUG
{
CellInfo info;
btreeParseCellPtr(pPage, pCell, &info);
assert( nHeader=(int)(info.pPayload - pCell) );
assert( info.nKey==nKey );
assert( *pnSize == info.nSize );
assert( spaceLeft == info.nLocal );
assert( pPrior == &pCell[info.iOverflow] );
}
#endif
/* Write the payload into the local Cell and any extra into overflow pages */
while( nPayload>0 ){
if( spaceLeft==0 ){
#ifndef SQLITE_OMIT_AUTOVACUUM
Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
if( pBt->autoVacuum ){
do{
pgnoOvfl++;
|
| ︙ | ︙ | |||
57863 57864 57865 57866 57867 57868 57869 | ** If the cell content will fit on the page, then put it there. If it ** will not fit, then make a copy of the cell content into pTemp if ** pTemp is not null. Regardless of pTemp, allocate a new entry ** in pPage->apOvfl[] and make it point to the cell content (either ** in pTemp or the original pCell) and also record its index. ** Allocating a new entry in pPage->aCell[] implies that ** pPage->nOverflow is incremented. | < < < < < < | | 58033 58034 58035 58036 58037 58038 58039 58040 58041 58042 58043 58044 58045 58046 58047 58048 58049 58050 58051 58052 58053 58054 58055 58056 58057 58058 58059 58060 58061 58062 58063 58064 58065 58066 58067 58068 58069 58070 58071 58072 58073 58074 58075 58076 58077 58078 58079 58080 |
** If the cell content will fit on the page, then put it there. If it
** will not fit, then make a copy of the cell content into pTemp if
** pTemp is not null. Regardless of pTemp, allocate a new entry
** in pPage->apOvfl[] and make it point to the cell content (either
** in pTemp or the original pCell) and also record its index.
** Allocating a new entry in pPage->aCell[] implies that
** pPage->nOverflow is incremented.
*/
static void insertCell(
MemPage *pPage, /* Page into which we are copying */
int i, /* New cell becomes the i-th cell of the page */
u8 *pCell, /* Content of the new cell */
int sz, /* Bytes of content in pCell */
u8 *pTemp, /* Temp storage space for pCell, if needed */
Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
int *pRC /* Read and write return code from here */
){
int idx = 0; /* Where to write new cell content in data[] */
int j; /* Loop counter */
int end; /* First byte past the last cell pointer in data[] */
int ins; /* Index in data[] where new cell pointer is inserted */
int cellOffset; /* Address of first cell pointer in data[] */
u8 *data; /* The content of the whole page */
if( *pRC ) return;
assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
assert( MX_CELL(pPage->pBt)<=10921 );
assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB );
assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
/* The cell should normally be sized correctly. However, when moving a
** malformed cell from a leaf page to an interior page, if the cell size
** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
** might be less than 8 (leaf-size + pointer) on the interior node. Hence
** the term after the || in the following assert(). */
assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) );
if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){
memcpy(pTemp, pCell, sz);
pCell = pTemp;
}
if( iChild ){
put4byte(pCell, iChild);
}
j = pPage->nOverflow++;
assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) );
|
| ︙ | ︙ | |||
57931 57932 57933 57934 57935 57936 57937 |
if( rc ){ *pRC = rc; return; }
/* The allocateSpace() routine guarantees the following two properties
** if it returns success */
assert( idx >= end+2 );
assert( idx+sz <= (int)pPage->pBt->usableSize );
pPage->nCell++;
pPage->nFree -= (u16)(2 + sz);
| | | 58095 58096 58097 58098 58099 58100 58101 58102 58103 58104 58105 58106 58107 58108 58109 |
if( rc ){ *pRC = rc; return; }
/* The allocateSpace() routine guarantees the following two properties
** if it returns success */
assert( idx >= end+2 );
assert( idx+sz <= (int)pPage->pBt->usableSize );
pPage->nCell++;
pPage->nFree -= (u16)(2 + sz);
memcpy(&data[idx], pCell, sz);
if( iChild ){
put4byte(&data[idx], iChild);
}
memmove(&data[ins+2], &data[ins], end-ins);
put2byte(&data[ins], idx);
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
#ifndef SQLITE_OMIT_AUTOVACUUM
|
| ︙ | ︙ | |||
58430 58431 58432 58433 58434 58435 58436 | ** apCell[] include child pointers. Either way, all cells in apCell[] ** are alike. ** ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. ** leafData: 1 if pPage holds key+data and pParent holds only keys. */ leafCorrection = apOld[0]->leaf*4; | | | 58594 58595 58596 58597 58598 58599 58600 58601 58602 58603 58604 58605 58606 58607 58608 |
** apCell[] include child pointers. Either way, all cells in apCell[]
** are alike.
**
** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf.
** leafData: 1 if pPage holds key+data and pParent holds only keys.
*/
leafCorrection = apOld[0]->leaf*4;
leafData = apOld[0]->intKeyLeaf;
for(i=0; i<nOld; i++){
int limit;
/* Before doing anything else, take a copy of the i'th original sibling
** The rest of this function will use data from the copies rather
** that the original pages since the original pages will be in the
** process of being overwritten. */
|
| ︙ | ︙ | |||
59006 59007 59008 59009 59010 59011 59012 |
}else{
MemPage * const pParent = pCur->apPage[iPage-1];
int const iIdx = pCur->aiIdx[iPage-1];
rc = sqlite3PagerWrite(pParent->pDbPage);
if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
| | | 59170 59171 59172 59173 59174 59175 59176 59177 59178 59179 59180 59181 59182 59183 59184 |
}else{
MemPage * const pParent = pCur->apPage[iPage-1];
int const iIdx = pCur->aiIdx[iPage-1];
rc = sqlite3PagerWrite(pParent->pDbPage);
if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
if( pPage->intKeyLeaf
&& pPage->nOverflow==1
&& pPage->aiOvfl[0]==pPage->nCell
&& pParent->pgno!=1
&& pParent->nCell==iIdx
){
/* Call balance_quick() to create a new sibling of pPage on which
** to store the overflow cell. balance_quick() inserts a new cell
|
| ︙ | ︙ | |||
59125 59126 59127 59128 59129 59130 59131 |
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
}
assert( cursorHoldsMutex(pCur) );
| | > | 59289 59290 59291 59292 59293 59294 59295 59296 59297 59298 59299 59300 59301 59302 59303 59304 |
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
}
assert( cursorHoldsMutex(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
&& pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
/* Assert that the caller has been consistent. If this cursor was opened
** expecting an index b-tree, then the caller should be inserting blob
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
|
| ︙ | ︙ | |||
59158 59159 59160 59161 59162 59163 59164 |
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
invalidateIncrblobCursors(p, nKey, 0);
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
** call */
| | > < | < | | 59323 59324 59325 59326 59327 59328 59329 59330 59331 59332 59333 59334 59335 59336 59337 59338 59339 59340 59341 59342 59343 59344 59345 59346 59347 59348 59349 59350 59351 59352 59353 59354 59355 59356 59357 59358 59359 59360 59361 59362 59363 59364 59365 59366 59367 59368 59369 59370 59371 59372 59373 59374 59375 |
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
invalidateIncrblobCursors(p, nKey, 0);
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
** call */
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0
&& pCur->info.nKey==nKey-1 ){
loc = -1;
}
}
if( !loc ){
rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
if( rc ) return rc;
}
assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
pPage = pCur->apPage[pCur->iPage];
assert( pPage->intKey || nKey>=0 );
assert( pPage->leaf || !pPage->intKey );
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, nKey, nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
assert( pPage->isInit );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
if( rc ) goto end_insert;
assert( szNew==cellSizePtr(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->aiIdx[pCur->iPage];
if( loc==0 ){
u16 szOld;
assert( idx<pPage->nCell );
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
goto end_insert;
}
oldCell = findCell(pPage, idx);
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
rc = clearCell(pPage, oldCell, &szOld);
dropCell(pPage, idx, szOld, &rc);
if( rc ) goto end_insert;
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->aiIdx[pCur->iPage];
}else{
assert( pPage->leaf );
|
| ︙ | ︙ | |||
59259 59260 59261 59262 59263 59264 59265 59266 59267 59268 59269 59270 59271 59272 | Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; int rc; /* Return code */ MemPage *pPage; /* Page to delete cell from */ unsigned char *pCell; /* Pointer to cell to delete */ int iCellIdx; /* Index of cell to delete */ int iCellDepth; /* Depth of node containing pCell */ assert( cursorHoldsMutex(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); | > | 59423 59424 59425 59426 59427 59428 59429 59430 59431 59432 59433 59434 59435 59436 59437 | Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; int rc; /* Return code */ MemPage *pPage; /* Page to delete cell from */ unsigned char *pCell; /* Pointer to cell to delete */ int iCellIdx; /* Index of cell to delete */ int iCellDepth; /* Depth of node containing pCell */ u16 szCell; /* Size of the cell being deleted */ assert( cursorHoldsMutex(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); |
| ︙ | ︙ | |||
59307 59308 59309 59310 59311 59312 59313 |
** invalidate any incrblob cursors open on the row being deleted. */
if( pCur->pKeyInfo==0 ){
invalidateIncrblobCursors(p, pCur->info.nKey, 0);
}
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
| | | < < | | 59472 59473 59474 59475 59476 59477 59478 59479 59480 59481 59482 59483 59484 59485 59486 59487 59488 59489 59490 59491 59492 59493 59494 59495 59496 59497 59498 59499 59500 59501 59502 59503 59504 59505 |
** invalidate any incrblob cursors open on the row being deleted. */
if( pCur->pKeyInfo==0 ){
invalidateIncrblobCursors(p, pCur->info.nKey, 0);
}
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
rc = clearCell(pPage, pCell, &szCell);
dropCell(pPage, iCellIdx, szCell, &rc);
if( rc ) return rc;
/* If the cell deleted was not located on a leaf page, then the cursor
** is currently pointing to the largest entry in the sub-tree headed
** by the child-page of the cell that was just deleted from an internal
** node. The cell from the leaf node needs to be moved to the internal
** node to replace the deleted cell. */
if( !pPage->leaf ){
MemPage *pLeaf = pCur->apPage[pCur->iPage];
int nCell;
Pgno n = pCur->apPage[iCellDepth+1]->pgno;
unsigned char *pTmp;
pCell = findCell(pLeaf, pLeaf->nCell-1);
nCell = cellSizePtr(pLeaf, pCell);
assert( MX_CELL_SIZE(pBt) >= nCell );
pTmp = pBt->pTmpSpace;
assert( pTmp!=0 );
rc = sqlite3PagerWrite(pLeaf->pDbPage);
insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
if( rc ) return rc;
}
/* Balance the tree. If the entry deleted was located on a leaf page,
|
| ︙ | ︙ | |||
59540 59541 59542 59543 59544 59545 59546 59547 59548 59549 59550 59551 59552 59553 59554 59555 59556 59557 59558 59559 59560 59561 |
int *pnChange /* Add number of Cells freed to this counter */
){
MemPage *pPage;
int rc;
unsigned char *pCell;
int i;
int hdr;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
hdr = pPage->hdrOffset;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
| > | | 59703 59704 59705 59706 59707 59708 59709 59710 59711 59712 59713 59714 59715 59716 59717 59718 59719 59720 59721 59722 59723 59724 59725 59726 59727 59728 59729 59730 59731 59732 59733 |
int *pnChange /* Add number of Cells freed to this counter */
){
MemPage *pPage;
int rc;
unsigned char *pCell;
int i;
int hdr;
u16 szCell;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
hdr = pPage->hdrOffset;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
rc = clearCell(pPage, pCell, &szCell);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}else if( pnChange ){
assert( pPage->intKey );
|
| ︙ | ︙ | |||
59901 59902 59903 59904 59905 59906 59907 | #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Append a message to the error message string. */ static void checkAppendMsg( IntegrityCk *pCheck, | < > | > | | 60065 60066 60067 60068 60069 60070 60071 60072 60073 60074 60075 60076 60077 60078 60079 60080 60081 60082 60083 60084 60085 60086 60087 60088 60089 60090 60091 60092 60093 |
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Append a message to the error message string.
*/
static void checkAppendMsg(
IntegrityCk *pCheck,
const char *zFormat,
...
){
va_list ap;
char zBuf[200];
if( !pCheck->mxErr ) return;
pCheck->mxErr--;
pCheck->nErr++;
va_start(ap, zFormat);
if( pCheck->errMsg.nChar ){
sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
}
if( pCheck->zPfx ){
sqlite3_snprintf(sizeof(zBuf), zBuf, pCheck->zPfx, pCheck->v1, pCheck->v2);
sqlite3StrAccumAppendAll(&pCheck->errMsg, zBuf);
}
sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
va_end(ap);
if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
pCheck->mallocFailed = 1;
}
}
|
| ︙ | ︙ | |||
59952 59953 59954 59955 59956 59957 59958 | ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 or more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ | | | | | < | | | < | | | | | | | | | 60117 60118 60119 60120 60121 60122 60123 60124 60125 60126 60127 60128 60129 60130 60131 60132 60133 60134 60135 60136 60137 60138 60139 60140 60141 60142 60143 60144 60145 60146 60147 60148 60149 60150 60151 60152 60153 60154 60155 60156 60157 60158 60159 60160 60161 60162 60163 60164 60165 60166 60167 60168 60169 60170 60171 60172 60173 60174 60175 60176 60177 60178 60179 60180 60181 60182 60183 60184 60185 60186 60187 60188 60189 60190 60191 60192 60193 60194 60195 60196 60197 60198 60199 60200 60201 60202 60203 60204 60205 60206 60207 60208 60209 60210 60211 60212 60213 60214 60215 60216 60217 60218 60219 60220 60221 60222 60223 60224 60225 60226 60227 60228 60229 60230 60231 60232 60233 60234 60235 60236 |
** Add 1 to the reference count for page iPage. If this is the second
** reference to the page, add an error message to pCheck->zErrMsg.
** Return 1 if there are 2 or more references to the page and 0 if
** if this is the first reference to the page.
**
** Also check that the page number is in bounds.
*/
static int checkRef(IntegrityCk *pCheck, Pgno iPage){
if( iPage==0 ) return 1;
if( iPage>pCheck->nPage ){
checkAppendMsg(pCheck, "invalid page number %d", iPage);
return 1;
}
if( getPageReferenced(pCheck, iPage) ){
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
return 1;
}
setPageReferenced(pCheck, iPage);
return 0;
}
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Check that the entry in the pointer-map for page iChild maps to
** page iParent, pointer type ptrType. If not, append an error message
** to pCheck.
*/
static void checkPtrmap(
IntegrityCk *pCheck, /* Integrity check context */
Pgno iChild, /* Child page number */
u8 eType, /* Expected pointer map type */
Pgno iParent /* Expected pointer map parent page number */
){
int rc;
u8 ePtrmapType;
Pgno iPtrmapParent;
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
return;
}
if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
checkAppendMsg(pCheck,
"Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
iChild, eType, iParent, ePtrmapType, iPtrmapParent);
}
}
#endif
/*
** Check the integrity of the freelist or of an overflow page list.
** Verify that the number of pages on the list is N.
*/
static void checkList(
IntegrityCk *pCheck, /* Integrity checking context */
int isFreeList, /* True for a freelist. False for overflow page list */
int iPage, /* Page number for first page in the list */
int N /* Expected number of pages in the list */
){
int i;
int expected = N;
int iFirst = iPage;
while( N-- > 0 && pCheck->mxErr ){
DbPage *pOvflPage;
unsigned char *pOvflData;
if( iPage<1 ){
checkAppendMsg(pCheck,
"%d of %d pages missing from overflow list starting at %d",
N+1, expected, iFirst);
break;
}
if( checkRef(pCheck, iPage) ) break;
if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){
checkAppendMsg(pCheck, "failed to get page %d", iPage);
break;
}
pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
if( isFreeList ){
int n = get4byte(&pOvflData[4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pCheck->pBt->autoVacuum ){
checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
}
#endif
if( n>(int)pCheck->pBt->usableSize/4-2 ){
checkAppendMsg(pCheck,
"freelist leaf count too big on page %d", iPage);
N--;
}else{
for(i=0; i<n; i++){
Pgno iFreePage = get4byte(&pOvflData[8+i*4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pCheck->pBt->autoVacuum ){
checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0);
}
#endif
checkRef(pCheck, iFreePage);
}
N -= n;
}
}
#ifndef SQLITE_OMIT_AUTOVACUUM
else{
/* If this database supports auto-vacuum and iPage is not the last
** page in this overflow list, check that the pointer-map entry for
** the following page matches iPage.
*/
if( pCheck->pBt->autoVacuum && N>0 ){
i = get4byte(pOvflData);
checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage);
}
}
#endif
iPage = get4byte(pOvflData);
sqlite3PagerUnref(pOvflPage);
}
}
|
| ︙ | ︙ | |||
60091 60092 60093 60094 60095 60096 60097 | ** 7. Verify that the depth of all children is the same. ** 8. Make sure this page is at least 33% full or else it is ** the root of the tree. */ static int checkTreePage( IntegrityCk *pCheck, /* Context for the sanity check */ int iPage, /* Page number of the page to check */ | < < | | > | > > | | > | | > < | > > | < > > | < | | | < | | | | | < | > | | > > | | | | > > | | 60254 60255 60256 60257 60258 60259 60260 60261 60262 60263 60264 60265 60266 60267 60268 60269 60270 60271 60272 60273 60274 60275 60276 60277 60278 60279 60280 60281 60282 60283 60284 60285 60286 60287 60288 60289 60290 60291 60292 60293 60294 60295 60296 60297 60298 60299 60300 60301 60302 60303 60304 60305 60306 60307 60308 60309 60310 60311 60312 60313 60314 60315 60316 60317 60318 60319 60320 60321 60322 60323 60324 60325 60326 60327 60328 60329 60330 60331 60332 60333 60334 60335 60336 60337 60338 60339 60340 60341 60342 60343 60344 60345 60346 60347 60348 60349 60350 60351 60352 60353 60354 60355 60356 60357 60358 60359 60360 60361 60362 60363 60364 60365 60366 60367 60368 60369 60370 60371 60372 60373 60374 60375 60376 60377 60378 60379 60380 60381 60382 60383 60384 60385 60386 60387 60388 60389 60390 60391 60392 60393 60394 60395 60396 60397 60398 60399 60400 60401 60402 60403 60404 60405 60406 60407 60408 60409 60410 60411 60412 60413 60414 60415 60416 60417 60418 60419 60420 60421 60422 60423 60424 60425 60426 60427 60428 60429 60430 60431 60432 60433 60434 60435 60436 60437 60438 60439 60440 60441 60442 60443 |
** 7. Verify that the depth of all children is the same.
** 8. Make sure this page is at least 33% full or else it is
** the root of the tree.
*/
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
i64 *pnParentMinKey,
i64 *pnParentMaxKey
){
MemPage *pPage;
int i, rc, depth, d2, pgno, cnt;
int hdr, cellStart;
int nCell;
u8 *data;
BtShared *pBt;
int usableSize;
char *hit = 0;
i64 nMinKey = 0;
i64 nMaxKey = 0;
const char *saved_zPfx = pCheck->zPfx;
int saved_v1 = pCheck->v1;
int saved_v2 = pCheck->v2;
/* Check that the page exists
*/
pBt = pCheck->pBt;
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage) ) return 0;
pCheck->zPfx = "Page %d: ";
pCheck->v1 = iPage;
if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck,
"unable to get the page. error code=%d", rc);
depth = -1;
goto end_of_check;
}
/* Clear MemPage.isInit to make sure the corruption detection code in
** btreeInitPage() is executed. */
pPage->isInit = 0;
if( (rc = btreeInitPage(pPage))!=0 ){
assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */
checkAppendMsg(pCheck,
"btreeInitPage() returns error code %d", rc);
releasePage(pPage);
depth = -1;
goto end_of_check;
}
/* Check out all the cells.
*/
depth = 0;
for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
u8 *pCell;
u32 sz;
CellInfo info;
/* Check payload overflow pages
*/
pCheck->zPfx = "On tree page %d cell %d: ";
pCheck->v1 = iPage;
pCheck->v2 = i;
pCell = findCell(pPage,i);
btreeParseCellPtr(pPage, pCell, &info);
sz = info.nPayload;
/* For intKey pages, check that the keys are in order.
*/
if( pPage->intKey ){
if( i==0 ){
nMinKey = nMaxKey = info.nKey;
}else if( info.nKey <= nMaxKey ){
checkAppendMsg(pCheck,
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
}
nMaxKey = info.nKey;
}
if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
){
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
}
#endif
checkList(pCheck, 0, pgnoOvfl, nPage);
}
/* Check sanity of left child page.
*/
if( !pPage->leaf ){
pgno = get4byte(pCell);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
}
#endif
d2 = checkTreePage(pCheck, pgno, &nMinKey, i==0?NULL:&nMaxKey);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, "Child page depth differs");
}
depth = d2;
}
}
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
pCheck->zPfx = "On page %d at right child: ";
pCheck->v1 = iPage;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
}
#endif
checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey);
}
/* For intKey leaf pages, check that the min/max keys are in order
** with any left/parent/right pages.
*/
pCheck->zPfx = "Page %d: ";
pCheck->v1 = iPage;
if( pPage->leaf && pPage->intKey ){
/* if we are a left child page */
if( pnParentMinKey ){
/* if we are the left most child page */
if( !pnParentMaxKey ){
if( nMaxKey > *pnParentMinKey ){
checkAppendMsg(pCheck,
"Rowid %lld out of order (max larger than parent min of %lld)",
nMaxKey, *pnParentMinKey);
}
}else{
if( nMinKey <= *pnParentMinKey ){
checkAppendMsg(pCheck,
"Rowid %lld out of order (min less than parent min of %lld)",
nMinKey, *pnParentMinKey);
}
if( nMaxKey > *pnParentMaxKey ){
checkAppendMsg(pCheck,
"Rowid %lld out of order (max larger than parent max of %lld)",
nMaxKey, *pnParentMaxKey);
}
*pnParentMinKey = nMaxKey;
}
/* else if we're a right child page */
} else if( pnParentMaxKey ){
if( nMinKey <= *pnParentMaxKey ){
checkAppendMsg(pCheck,
"Rowid %lld out of order (min less than parent max of %lld)",
nMinKey, *pnParentMaxKey);
}
}
}
/* Check for complete coverage of the page
*/
data = pPage->aData;
hdr = pPage->hdrOffset;
hit = sqlite3PageMalloc( pBt->pageSize );
pCheck->zPfx = 0;
if( hit==0 ){
pCheck->mallocFailed = 1;
}else{
int contentOffset = get2byteNotZero(&data[hdr+5]);
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
memset(hit+contentOffset, 0, usableSize-contentOffset);
memset(hit, 1, contentOffset);
nCell = get2byte(&data[hdr+3]);
cellStart = hdr + 12 - 4*pPage->leaf;
for(i=0; i<nCell; i++){
int pc = get2byte(&data[cellStart+i*2]);
u32 size = 65536;
int j;
if( pc<=usableSize-4 ){
size = cellSizePtr(pPage, &data[pc]);
}
if( (int)(pc+size-1)>=usableSize ){
pCheck->zPfx = 0;
checkAppendMsg(pCheck,
"Corruption detected in cell %d on page %d",i,iPage);
}else{
for(j=pc+size-1; j>=pc; j--) hit[j]++;
}
}
i = get2byte(&data[hdr+1]);
while( i>0 ){
|
| ︙ | ︙ | |||
60281 60282 60283 60284 60285 60286 60287 |
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
i = j;
}
for(i=cnt=0; i<usableSize; i++){
if( hit[i]==0 ){
cnt++;
}else if( hit[i]>1 ){
| | | > > > > > | 60451 60452 60453 60454 60455 60456 60457 60458 60459 60460 60461 60462 60463 60464 60465 60466 60467 60468 60469 60470 60471 60472 60473 60474 60475 60476 60477 60478 60479 60480 60481 60482 |
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
i = j;
}
for(i=cnt=0; i<usableSize; i++){
if( hit[i]==0 ){
cnt++;
}else if( hit[i]>1 ){
checkAppendMsg(pCheck,
"Multiple uses for byte %d of page %d", i, iPage);
break;
}
}
if( cnt!=data[hdr+7] ){
checkAppendMsg(pCheck,
"Fragmentation of %d bytes reported as %d on page %d",
cnt, data[hdr+7], iPage);
}
}
sqlite3PageFree(hit);
releasePage(pPage);
end_of_check:
pCheck->zPfx = saved_zPfx;
pCheck->v1 = saved_v1;
pCheck->v2 = saved_v2;
return depth+1;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** This routine does a complete check of the given BTree file. aRoot[] is
|
| ︙ | ︙ | |||
60334 60335 60336 60337 60338 60339 60340 60341 60342 60343 60344 60345 60346 60347 60348 60349 60350 60351 60352 60353 60354 60355 60356 60357 60358 60359 60360 |
nRef = sqlite3PagerRefcount(pBt->pPager);
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
sCheck.mallocFailed = 0;
*pnErr = 0;
if( sCheck.nPage==0 ){
sqlite3BtreeLeave(p);
return 0;
}
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
if( !sCheck.aPgRef ){
*pnErr = 1;
sqlite3BtreeLeave(p);
return 0;
}
i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
sCheck.errMsg.useMalloc = 2;
/* Check the integrity of the freelist
*/
checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
| > > > > | > | > | > | | | | | 60509 60510 60511 60512 60513 60514 60515 60516 60517 60518 60519 60520 60521 60522 60523 60524 60525 60526 60527 60528 60529 60530 60531 60532 60533 60534 60535 60536 60537 60538 60539 60540 60541 60542 60543 60544 60545 60546 60547 60548 60549 60550 60551 60552 60553 60554 60555 60556 60557 60558 60559 60560 60561 60562 60563 60564 60565 60566 60567 60568 60569 60570 60571 60572 60573 60574 60575 60576 60577 60578 60579 60580 60581 60582 60583 60584 60585 60586 60587 60588 60589 60590 60591 |
nRef = sqlite3PagerRefcount(pBt->pPager);
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
sCheck.mallocFailed = 0;
sCheck.zPfx = 0;
sCheck.v1 = 0;
sCheck.v2 = 0;
*pnErr = 0;
if( sCheck.nPage==0 ){
sqlite3BtreeLeave(p);
return 0;
}
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
if( !sCheck.aPgRef ){
*pnErr = 1;
sqlite3BtreeLeave(p);
return 0;
}
i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
sCheck.errMsg.useMalloc = 2;
/* Check the integrity of the freelist
*/
sCheck.zPfx = "Main freelist: ";
checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
get4byte(&pBt->pPage1->aData[36]));
sCheck.zPfx = 0;
/* Check all the tables.
*/
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
if( aRoot[i]==0 ) continue;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum && aRoot[i]>1 ){
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
}
#endif
sCheck.zPfx = "List of tree roots: ";
checkTreePage(&sCheck, aRoot[i], NULL, NULL);
sCheck.zPfx = 0;
}
/* Make sure every page in the file is referenced
*/
for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
#ifdef SQLITE_OMIT_AUTOVACUUM
if( getPageReferenced(&sCheck, i)==0 ){
checkAppendMsg(&sCheck, "Page %d is never used", i);
}
#else
/* If the database supports auto-vacuum, make sure no tables contain
** references to pointer-map pages.
*/
if( getPageReferenced(&sCheck, i)==0 &&
(PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
checkAppendMsg(&sCheck, "Page %d is never used", i);
}
if( getPageReferenced(&sCheck, i)!=0 &&
(PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
}
#endif
}
/* Make sure this analysis did not leave any unref() pages.
** This is an internal consistency check; an integrity check
** of the integrity check.
*/
if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
checkAppendMsg(&sCheck,
"Outstanding page count goes from %d to %d during this analysis",
nRef, sqlite3PagerRefcount(pBt->pPager)
);
}
/* Clean up and report errors.
*/
|
| ︙ | ︙ | |||
60591 60592 60593 60594 60595 60596 60597 |
return SQLITE_ABORT;
}
/* Save the positions of all other cursors open on this table. This is
** required in case any of them are holding references to an xFetch
** version of the b-tree page modified by the accessPayload call below.
**
| | | 60773 60774 60775 60776 60777 60778 60779 60780 60781 60782 60783 60784 60785 60786 60787 |
return SQLITE_ABORT;
}
/* Save the positions of all other cursors open on this table. This is
** required in case any of them are holding references to an xFetch
** version of the b-tree page modified by the accessPayload call below.
**
** Note that pCsr must be open on a INTKEY table and saveCursorPosition()
** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence
** saveAllCursors can only return SQLITE_OK.
*/
VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
assert( rc==SQLITE_OK );
/* Check some assumptions:
|
| ︙ | ︙ | |||
61459 61460 61461 61462 61463 61464 61465 |
*/
SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
/* If MEM_Dyn is set then Mem.xDel!=0.
** Mem.xDel is might not be initialized if MEM_Dyn is clear.
*/
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
| | > > > | 61641 61642 61643 61644 61645 61646 61647 61648 61649 61650 61651 61652 61653 61654 61655 61656 61657 61658 |
*/
SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
/* If MEM_Dyn is set then Mem.xDel!=0.
** Mem.xDel is might not be initialized if MEM_Dyn is clear.
*/
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
/* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we
** ensure that if Mem.szMalloc>0 then it is safe to do
** Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn.
** That saves a few cycles in inner loops. */
assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 );
/* Cannot be both MEM_Int and MEM_Real at the same time */
assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
|
| ︙ | ︙ | |||
61568 61569 61570 61571 61572 61573 61574 |
pMem->szMalloc = 0;
return SQLITE_NOMEM;
}else{
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}
}
| | | 61753 61754 61755 61756 61757 61758 61759 61760 61761 61762 61763 61764 61765 61766 61767 |
pMem->szMalloc = 0;
return SQLITE_NOMEM;
}else{
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}
}
if( bPreserve && pMem->z && pMem->z!=pMem->zMalloc ){
memcpy(pMem->zMalloc, pMem->z, pMem->n);
}
if( (pMem->flags&MEM_Dyn)!=0 ){
assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
pMem->xDel((void *)(pMem->z));
}
|
| ︙ | ︙ | |||
61595 61596 61597 61598 61599 61600 61601 |
** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null
** values are preserved.
**
** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
** if unable to complete the resizing.
*/
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
| | > | 61780 61781 61782 61783 61784 61785 61786 61787 61788 61789 61790 61791 61792 61793 61794 61795 |
** and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null
** values are preserved.
**
** Return SQLITE_OK on success or an error code (probably SQLITE_NOMEM)
** if unable to complete the resizing.
*/
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
assert( szNew>0 );
assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
if( pMem->szMalloc<szNew ){
return sqlite3VdbeMemGrow(pMem, szNew, 0);
}
assert( (pMem->flags & MEM_Dyn)==0 );
pMem->z = pMem->zMalloc;
pMem->flags &= (MEM_Null|MEM_Int|MEM_Real);
return SQLITE_OK;
|
| ︙ | ︙ | |||
62319 62320 62321 62322 62323 62324 62325 |
int nAlloc = nByte;
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
if( nByte>iLimit ){
return SQLITE_TOOBIG;
}
| > > > | | 62505 62506 62507 62508 62509 62510 62511 62512 62513 62514 62515 62516 62517 62518 62519 62520 62521 62522 |
int nAlloc = nByte;
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
if( nByte>iLimit ){
return SQLITE_TOOBIG;
}
testcase( nAlloc==0 );
testcase( nAlloc==31 );
testcase( nAlloc==32 );
if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){
return SQLITE_NOMEM;
}
memcpy(pMem->z, z, nAlloc);
}else if( xDel==SQLITE_DYNAMIC ){
sqlite3VdbeMemRelease(pMem);
pMem->zMalloc = pMem->z = (char *)z;
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
|
| ︙ | ︙ | |||
62422 62423 62424 62425 62426 62427 62428 | } /* ** The pVal argument is known to be a value other than NULL. ** Convert it into a string with encoding enc and return a pointer ** to a zero-terminated version of that string. */ | | | 62611 62612 62613 62614 62615 62616 62617 62618 62619 62620 62621 62622 62623 62624 62625 |
}
/*
** The pVal argument is known to be a value other than NULL.
** Convert it into a string with encoding enc and return a pointer
** to a zero-terminated version of that string.
*/
static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert( pVal!=0 );
assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
assert( (pVal->flags & MEM_RowSet)==0 );
assert( (pVal->flags & (MEM_Null))==0 );
if( pVal->flags & (MEM_Blob|MEM_Str) ){
pVal->flags |= MEM_Str;
|
| ︙ | ︙ | |||
63749 63750 63751 63752 63753 63754 63755 |
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
if( addr==p->nOp-1 ) p->nOp--;
}
}
/*
| | > | 63938 63939 63940 63941 63942 63943 63944 63945 63946 63947 63948 63949 63950 63951 63952 63953 |
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
if( addr==p->nOp-1 ) p->nOp--;
}
}
/*
** If the last opcode is "op" and it is not a jump destination,
** then remove it. Return true if and only if an opcode was removed.
*/
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
sqlite3VdbeChangeToNoop(p, p->nOp-1);
return 1;
}else{
return 0;
|
| ︙ | ︙ | |||
64741 64742 64743 64744 64745 64746 64747 |
sqlite3BtreeClose(pCx->pBt);
/* The pCx->pCursor will be close automatically, if it exists, by
** the call above. */
}else if( pCx->pCursor ){
sqlite3BtreeCloseCursor(pCx->pCursor);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
| | | 64931 64932 64933 64934 64935 64936 64937 64938 64939 64940 64941 64942 64943 64944 64945 |
sqlite3BtreeClose(pCx->pBt);
/* The pCx->pCursor will be close automatically, if it exists, by
** the call above. */
}else if( pCx->pCursor ){
sqlite3BtreeCloseCursor(pCx->pCursor);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
p->inVtabMethod = 1;
pModule->xClose(pVtabCursor);
p->inVtabMethod = 0;
}
#endif
|
| ︙ | ︙ | |||
64784 64785 64786 64787 64788 64789 64790 |
** open cursors.
*/
static void closeAllCursors(Vdbe *p){
if( p->pFrame ){
VdbeFrame *pFrame;
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
sqlite3VdbeFrameRestore(pFrame);
| < | | > > | 64974 64975 64976 64977 64978 64979 64980 64981 64982 64983 64984 64985 64986 64987 64988 64989 64990 64991 |
** open cursors.
*/
static void closeAllCursors(Vdbe *p){
if( p->pFrame ){
VdbeFrame *pFrame;
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
sqlite3VdbeFrameRestore(pFrame);
p->pFrame = 0;
p->nFrame = 0;
}
assert( p->nFrame==0 );
if( p->apCsr ){
int i;
for(i=0; i<p->nCursor; i++){
VdbeCursor *pC = p->apCsr[i];
if( pC ){
sqlite3VdbeFreeCursor(p, pC);
|
| ︙ | ︙ | |||
64808 64809 64810 64811 64812 64813 64814 |
while( p->pDelFrame ){
VdbeFrame *pDel = p->pDelFrame;
p->pDelFrame = pDel->pParent;
sqlite3VdbeFrameDelete(pDel);
}
/* Delete any auxdata allocations made by the VM */
| | | 64999 65000 65001 65002 65003 65004 65005 65006 65007 65008 65009 65010 65011 65012 65013 |
while( p->pDelFrame ){
VdbeFrame *pDel = p->pDelFrame;
p->pDelFrame = pDel->pParent;
sqlite3VdbeFrameDelete(pDel);
}
/* Delete any auxdata allocations made by the VM */
if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p, -1, 0);
assert( p->pAuxData==0 );
}
/*
** Clean up the VM after a single run.
*/
static void Cleanup(Vdbe *p){
|
| ︙ | ︙ | |||
65674 65675 65676 65677 65678 65679 65680 |
sqlite3DbFree(db, pSub);
}
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
sqlite3DbFree(db, p->pFree);
| < < < < | 65865 65866 65867 65868 65869 65870 65871 65872 65873 65874 65875 65876 65877 65878 |
sqlite3DbFree(db, pSub);
}
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
sqlite3DbFree(db, p->pFree);
}
/*
** Delete an entire VDBE.
*/
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
sqlite3 *db;
|
| ︙ | ︙ | |||
65718 65719 65720 65721 65722 65723 65724 | #ifdef SQLITE_TEST extern int sqlite3_search_count; #endif assert( p->deferredMoveto ); assert( p->isTable ); rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); if( rc ) return rc; | < < | 65905 65906 65907 65908 65909 65910 65911 65912 65913 65914 65915 65916 65917 65918 65919 | #ifdef SQLITE_TEST extern int sqlite3_search_count; #endif assert( p->deferredMoveto ); assert( p->isTable ); rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); if( rc ) return rc; if( res!=0 ) return SQLITE_CORRUPT_BKPT; #ifdef SQLITE_TEST sqlite3_search_count++; #endif p->deferredMoveto = 0; p->cacheStatus = CACHE_STALE; return SQLITE_OK; } |
| ︙ | ︙ | |||
65745 65746 65747 65748 65749 65750 65751 65752 65753 65754 65755 65756 65757 65758 65759 65760 65761 65762 65763 65764 65765 65766 65767 65768 65769 |
assert( p->pCursor!=0 );
assert( sqlite3BtreeCursorHasMoved(p->pCursor) );
rc = sqlite3BtreeCursorRestore(p->pCursor, &isDifferentRow);
p->cacheStatus = CACHE_STALE;
if( isDifferentRow ) p->nullRow = 1;
return rc;
}
/*
** Make sure the cursor p is ready to read or write the row to which it
** was last positioned. Return an error code if an OOM fault or I/O error
** prevents us from positioning the cursor to its correct position.
**
** If a MoveTo operation is pending on the given cursor, then do that
** MoveTo now. If no move is pending, check to see if the row has been
** deleted out from under the cursor and if it has, mark the row as
** a NULL row.
**
** If the cursor is already pointing to the correct row and that row has
** not been deleted out from under the cursor, then this routine is a no-op.
*/
SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
if( p->deferredMoveto ){
return handleDeferredMoveto(p);
}
| > > > > > > > > > > > | | 65930 65931 65932 65933 65934 65935 65936 65937 65938 65939 65940 65941 65942 65943 65944 65945 65946 65947 65948 65949 65950 65951 65952 65953 65954 65955 65956 65957 65958 65959 65960 65961 65962 65963 65964 65965 65966 65967 65968 65969 65970 65971 65972 65973 |
assert( p->pCursor!=0 );
assert( sqlite3BtreeCursorHasMoved(p->pCursor) );
rc = sqlite3BtreeCursorRestore(p->pCursor, &isDifferentRow);
p->cacheStatus = CACHE_STALE;
if( isDifferentRow ) p->nullRow = 1;
return rc;
}
/*
** Check to ensure that the cursor is valid. Restore the cursor
** if need be. Return any I/O error from the restore operation.
*/
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){
if( sqlite3BtreeCursorHasMoved(p->pCursor) ){
return handleMovedCursor(p);
}
return SQLITE_OK;
}
/*
** Make sure the cursor p is ready to read or write the row to which it
** was last positioned. Return an error code if an OOM fault or I/O error
** prevents us from positioning the cursor to its correct position.
**
** If a MoveTo operation is pending on the given cursor, then do that
** MoveTo now. If no move is pending, check to see if the row has been
** deleted out from under the cursor and if it has, mark the row as
** a NULL row.
**
** If the cursor is already pointing to the correct row and that row has
** not been deleted out from under the cursor, then this routine is a no-op.
*/
SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
if( p->deferredMoveto ){
return handleDeferredMoveto(p);
}
if( p->pCursor && sqlite3BtreeCursorHasMoved(p->pCursor) ){
return handleMovedCursor(p);
}
return SQLITE_OK;
}
/*
** The following functions:
|
| ︙ | ︙ | |||
67388 67389 67390 67391 67392 67393 67394 67395 67396 67397 67398 67399 67400 67401 |
const char *z,
sqlite3_uint64 n,
void (*xDel)(void *),
unsigned char enc
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
if( n>0x7fffffff ){
(void)invokeValueDestructor(z, xDel, pCtx);
}else{
setResultStrOrError(pCtx, z, (int)n, enc, xDel);
}
}
#ifndef SQLITE_OMIT_UTF16
| > | 67584 67585 67586 67587 67588 67589 67590 67591 67592 67593 67594 67595 67596 67597 67598 |
const char *z,
sqlite3_uint64 n,
void (*xDel)(void *),
unsigned char enc
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
if( n>0x7fffffff ){
(void)invokeValueDestructor(z, xDel, pCtx);
}else{
setResultStrOrError(pCtx, z, (int)n, enc, xDel);
}
}
#ifndef SQLITE_OMIT_UTF16
|
| ︙ | ︙ | |||
68710 68711 68712 68713 68714 68715 68716 |
}
}
return sqlite3StrAccumFinish(&out);
}
#endif /* #ifndef SQLITE_OMIT_TRACE */
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 68907 68908 68909 68910 68911 68912 68913 68914 68915 68916 68917 68918 68919 68920 |
}
}
return sqlite3StrAccumFinish(&out);
}
#endif /* #ifndef SQLITE_OMIT_TRACE */
/************** End of vdbetrace.c *******************************************/
/************** Begin file vdbe.c ********************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
|
| ︙ | ︙ | |||
69041 69042 69043 69044 69045 69046 69047 69048 69049 69050 69051 69052 69053 69054 |
p->apCsr[iCur] = 0;
}
if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
memset(pCx, 0, sizeof(VdbeCursor));
pCx->iDb = iDb;
pCx->nField = nField;
if( isBtreeCursor ){
pCx->pCursor = (BtCursor*)
&pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
sqlite3BtreeCursorZero(pCx->pCursor);
}
}
return pCx;
| > | 69123 69124 69125 69126 69127 69128 69129 69130 69131 69132 69133 69134 69135 69136 69137 |
p->apCsr[iCur] = 0;
}
if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
memset(pCx, 0, sizeof(VdbeCursor));
pCx->iDb = iDb;
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( isBtreeCursor ){
pCx->pCursor = (BtCursor*)
&pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
sqlite3BtreeCursorZero(pCx->pCursor);
}
}
return pCx;
|
| ︙ | ︙ | |||
70473 70474 70475 70476 70477 70478 70479 | } assert( pOp->p4type==P4_FUNCDEF ); ctx.pFunc = pOp->p4.pFunc; ctx.iOp = pc; ctx.pVdbe = p; MemSetTypeFlag(ctx.pOut, MEM_Null); | < < < < < < < | | 70556 70557 70558 70559 70560 70561 70562 70563 70564 70565 70566 70567 70568 70569 70570 70571 70572 70573 |
}
assert( pOp->p4type==P4_FUNCDEF );
ctx.pFunc = pOp->p4.pFunc;
ctx.iOp = pc;
ctx.pVdbe = p;
MemSetTypeFlag(ctx.pOut, MEM_Null);
ctx.fErrorOrAux = 0;
db->lastRowid = lastRowid;
(*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */
/* If the function returned an error, throw an exception */
if( ctx.fErrorOrAux ){
if( ctx.isError ){
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut));
rc = ctx.isError;
}
|
| ︙ | ︙ | |||
71199 71200 71201 71202 71203 71204 71205 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( p2<pC->nField ); | | | | 71275 71276 71277 71278 71279 71280 71281 71282 71283 71284 71285 71286 71287 71288 71289 71290 71291 71292 71293 71294 71295 71296 71297 71298 71299 71300 |
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( p2<pC->nField );
aOffset = pC->aOffset;
#ifndef SQLITE_OMIT_VIRTUALTABLE
assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
#endif
pCrsr = pC->pCursor;
assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */
assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */
/* If the cursor cache is stale, bring it up-to-date */
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
if( pC->cacheStatus!=p->cacheCtr ){
if( pC->nullRow ){
if( pCrsr==0 ){
assert( pC->pseudoTableReg>0 );
pReg = &aMem[pC->pseudoTableReg];
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
pC->payloadSize = pC->szRow = avail = pReg->n;
|
| ︙ | ︙ | |||
71255 71256 71257 71258 71259 71260 71261 |
goto too_big;
}
}
pC->cacheStatus = p->cacheCtr;
pC->iHdrOffset = getVarint32(pC->aRow, offset);
pC->nHdrParsed = 0;
aOffset[0] = offset;
| < < < < < < < < > > > > > > > > > > > > > > > > > | 71331 71332 71333 71334 71335 71336 71337 71338 71339 71340 71341 71342 71343 71344 71345 71346 71347 71348 71349 71350 71351 71352 71353 71354 71355 71356 71357 71358 71359 71360 71361 71362 71363 71364 71365 71366 71367 71368 71369 71370 71371 71372 71373 71374 71375 71376 71377 71378 71379 71380 71381 71382 71383 71384 |
goto too_big;
}
}
pC->cacheStatus = p->cacheCtr;
pC->iHdrOffset = getVarint32(pC->aRow, offset);
pC->nHdrParsed = 0;
aOffset[0] = offset;
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
**
** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
** types use so much data space that there can only be 4096 and 32 of
** them, respectively. So the maximum header length results from a
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
if( offset > 98307 || offset > pC->payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
}
if( avail<offset ){
/* pC->aRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
** dynamically allocated. */
pC->aRow = 0;
pC->szRow = 0;
}
/* The following goto is an optimization. It can be omitted and
** everything will still work. But OP_Column is measurably faster
** by skipping the subsequent conditional, which is always true.
*/
assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
goto op_column_read_header;
}
/* Make sure at least the first p2+1 entries of the header have been
** parsed and valid information is in aOffset[] and pC->aType[].
*/
if( pC->nHdrParsed<=p2 ){
/* If there is more header available for parsing in the record, try
** to extract additional fields up through the p2+1-th field
*/
op_column_read_header:
if( pC->iHdrOffset<aOffset[0] ){
/* Make sure zData points to enough of the record to cover the header. */
if( pC->aRow==0 ){
memset(&sMem, 0, sizeof(sMem));
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0],
!pC->isTable, &sMem);
if( rc!=SQLITE_OK ){
|
| ︙ | ︙ | |||
71330 71331 71332 71333 71334 71335 71336 |
pC->nHdrParsed = i;
pC->iHdrOffset = (u32)(zHdr - zData);
if( pC->aRow==0 ){
sqlite3VdbeMemRelease(&sMem);
sMem.flags = MEM_Null;
}
| | | > > > | < < > | < | 71415 71416 71417 71418 71419 71420 71421 71422 71423 71424 71425 71426 71427 71428 71429 71430 71431 71432 71433 71434 71435 71436 71437 71438 |
pC->nHdrParsed = i;
pC->iHdrOffset = (u32)(zHdr - zData);
if( pC->aRow==0 ){
sqlite3VdbeMemRelease(&sMem);
sMem.flags = MEM_Null;
}
/* The record is corrupt if any of the following are true:
** (1) the bytes of the header extend past the declared header size
** (zHdr>zEndHdr)
** (2) the entire header was used but not all data was used
** (zHdr==zEndHdr && offset!=pC->payloadSize)
** (3) the end of the data extends beyond the end of the record.
** (offset > pC->payloadSize)
*/
if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset!=pC->payloadSize))
|| (offset > pC->payloadSize)
){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
}
}
/* If after trying to extra new entries from the header, nHdrParsed is
|
| ︙ | ︙ | |||
71529 71530 71531 71532 71533 71534 71535 |
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
pRec = pLast;
do{
assert( memIsValid(pRec) );
| | | 71615 71616 71617 71618 71619 71620 71621 71622 71623 71624 71625 71626 71627 71628 71629 |
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
pRec = pLast;
do{
assert( memIsValid(pRec) );
pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format);
len = sqlite3VdbeSerialTypeLen(serial_type);
if( pRec->flags & MEM_Zero ){
if( nData ){
sqlite3VdbeMemExpandBlob(pRec);
}else{
nZero += pRec->u.nZero;
len -= pRec->u.nZero;
|
| ︙ | ︙ | |||
71578 71579 71580 71581 71582 71583 71584 |
/* Write the record */
i = putVarint32(zNewRecord, nHdr);
j = nHdr;
assert( pData0<=pLast );
pRec = pData0;
do{
| | | 71664 71665 71666 71667 71668 71669 71670 71671 71672 71673 71674 71675 71676 71677 71678 |
/* Write the record */
i = putVarint32(zNewRecord, nHdr);
j = nHdr;
assert( pData0<=pLast );
pRec = pData0;
do{
serial_type = pRec->uTemp;
i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */
}while( (++pRec)<=pLast );
assert( i==nHdr );
assert( j==nByte );
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
| ︙ | ︙ | |||
72203 72204 72205 72206 72207 72208 72209 | pCur->isOrdered = 1; pCur->pgnoRoot = p2; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); | < < < < | 72289 72290 72291 72292 72293 72294 72295 72296 72297 72298 72299 72300 72301 72302 | pCur->isOrdered = 1; pCur->pgnoRoot = p2; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; break; } |
| ︙ | ︙ | |||
72481 72482 72483 72484 72485 72486 72487 |
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so convert it. */
pIn3 = &aMem[pOp->p3];
if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3, 0);
}
iKey = sqlite3VdbeIntValue(pIn3);
| < | 72563 72564 72565 72566 72567 72568 72569 72570 72571 72572 72573 72574 72575 72576 |
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so convert it. */
pIn3 = &aMem[pOp->p3];
if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3, 0);
}
iKey = sqlite3VdbeIntValue(pIn3);
/* If the P3 value could not be converted into an integer without
** loss of information, then special processing is required... */
if( (pIn3->flags & MEM_Int)==0 ){
if( (pIn3->flags & MEM_Real)==0 ){
/* If the P3 value cannot be converted into any kind of a number,
** then the seek is not possible, so jump to P2 */
|
| ︙ | ︙ | |||
72517 72518 72519 72520 72521 72522 72523 72524 72525 72526 |
assert( OP_SeekLE==(OP_SeekLT+1) );
assert( OP_SeekGT==(OP_SeekGE+1) );
assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
| > < < < < | 72598 72599 72600 72601 72602 72603 72604 72605 72606 72607 72608 72609 72610 72611 72612 72613 72614 72615 |
assert( OP_SeekLE==(OP_SeekLT+1) );
assert( OP_SeekGT==(OP_SeekGE+1) );
assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
pC->movetoTarget = iKey; /* Used by OP_Delete */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}else{
nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
assert( nField>0 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)nField;
|
| ︙ | ︙ | |||
72553 72554 72555 72556 72557 72558 72559 |
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
ExpandBlob(r.aMem);
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
| < < < | 72631 72632 72633 72634 72635 72636 72637 72638 72639 72640 72641 72642 72643 72644 72645 72646 72647 72648 72649 72650 72651 72652 72653 72654 72655 72656 72657 72658 72659 72660 72661 72662 72663 72664 |
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
ExpandBlob(r.aMem);
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
if( res<0 || (res==0 && oc==OP_SeekGT) ){
res = 0;
rc = sqlite3BtreeNext(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}else{
res = 0;
}
}else{
assert( oc==OP_SeekLT || oc==OP_SeekLE );
if( res>0 || (res==0 && oc==OP_SeekLT) ){
res = 0;
rc = sqlite3BtreePrevious(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
*/
res = sqlite3BtreeEof(pC->pCursor);
}
}
|
| ︙ | ︙ | |||
72612 72613 72614 72615 72616 72617 72618 | pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pCursor!=0 ); assert( pC->isTable ); pC->nullRow = 0; pIn2 = &aMem[pOp->p2]; pC->movetoTarget = sqlite3VdbeIntValue(pIn2); | < | 72687 72688 72689 72690 72691 72692 72693 72694 72695 72696 72697 72698 72699 72700 | pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pCursor!=0 ); assert( pC->isTable ); pC->nullRow = 0; pIn2 = &aMem[pOp->p2]; pC->movetoTarget = sqlite3VdbeIntValue(pIn2); pC->deferredMoveto = 1; break; } /* Opcode: Found P1 P2 P3 P4 * ** Synopsis: key=r[P3@P4] |
| ︙ | ︙ | |||
72798 72799 72800 72801 72802 72803 72804 | assert( pC->isTable ); assert( pC->pseudoTableReg==0 ); pCrsr = pC->pCursor; assert( pCrsr!=0 ); res = 0; iKey = pIn3->u.i; rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); | | < < | 72872 72873 72874 72875 72876 72877 72878 72879 72880 72881 72882 72883 72884 72885 72886 72887 72888 72889 72890 72891 72892 |
assert( pC->isTable );
assert( pC->pseudoTableReg==0 );
pCrsr = pC->pCursor;
assert( pCrsr!=0 );
res = 0;
iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
pC->movetoTarget = iKey; /* Used by OP_Delete */
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
pC->deferredMoveto = 0;
VdbeBranchTaken(res!=0,2);
if( res!=0 ){
pc = pOp->p2 - 1;
}
pC->seekResult = res;
break;
}
/* Opcode: Sequence P1 P2 * * *
** Synopsis: r[P2]=cursor[P1].ctr++
|
| ︙ | ︙ | |||
72940 72941 72942 72943 72944 72945 72946 |
if( pC->useRandomRowid ){
/* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
** largest possible integer (9223372036854775807) then the database
** engine starts picking positive candidate ROWIDs at random until
** it finds one that is not previously used. */
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
** an AUTOINCREMENT table. */
| < < < < > > > | | < < < < < < < < < < < | 73012 73013 73014 73015 73016 73017 73018 73019 73020 73021 73022 73023 73024 73025 73026 73027 73028 73029 73030 73031 73032 73033 73034 73035 73036 73037 73038 73039 |
if( pC->useRandomRowid ){
/* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
** largest possible integer (9223372036854775807) then the database
** engine starts picking positive candidate ROWIDs at random until
** it finds one that is not previously used. */
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
** an AUTOINCREMENT table. */
cnt = 0;
do{
sqlite3_randomness(sizeof(v), &v);
v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
}while( ((rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v,
0, &res))==SQLITE_OK)
&& (res==0)
&& (++cnt<100));
if( rc==SQLITE_OK && res==0 ){
rc = SQLITE_FULL; /* IMP: R-38219-53002 */
goto abort_due_to_error;
}
assert( v>0 ); /* EV: R-40812-03570 */
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
pOut->u.i = v;
break;
}
|
| ︙ | ︙ | |||
73070 73071 73072 73073 73074 73075 73076 |
}else{
nZero = 0;
}
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
pData->z, pData->n, nZero,
(pOp->p5 & OPFLAG_APPEND)!=0, seekResult
);
| < | 73130 73131 73132 73133 73134 73135 73136 73137 73138 73139 73140 73141 73142 73143 |
}else{
nZero = 0;
}
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
pData->z, pData->n, nZero,
(pOp->p5 & OPFLAG_APPEND)!=0, seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
zDb = db->aDb[pC->iDb].zName;
zTbl = pOp->p4.z;
|
| ︙ | ︙ | |||
73107 73108 73109 73110 73111 73112 73113 |
**
** If P4 is not NULL, then it is the name of the table that P1 is
** pointing to. The update hook will be invoked, if it exists.
** If P4 is not NULL then the P1 cursor must have been positioned
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
| < | | | | | | | < > | < > | | | | 73166 73167 73168 73169 73170 73171 73172 73173 73174 73175 73176 73177 73178 73179 73180 73181 73182 73183 73184 73185 73186 73187 73188 73189 73190 73191 73192 73193 73194 73195 73196 73197 73198 73199 73200 73201 73202 73203 73204 73205 |
**
** If P4 is not NULL, then it is the name of the table that P1 is
** pointing to. The update hook will be invoked, if it exists.
** If P4 is not NULL then the P1 cursor must have been positioned
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
assert( pC->deferredMoveto==0 );
#ifdef SQLITE_DEBUG
/* The seek operation that positioned the cursor prior to OP_Delete will
** have also set the pC->movetoTarget field to the rowid of the row that
** is being deleted */
if( pOp->p4.z && pC->isTable ){
i64 iKey = 0;
sqlite3BtreeKeySize(pC->pCursor, &iKey);
assert( pC->movetoTarget==iKey );
}
#endif
rc = sqlite3BtreeDelete(pC->pCursor);
pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){
db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget);
assert( pC->iDb>=0 );
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
break;
}
/* Opcode: ResetCount * * * * *
**
|
| ︙ | ︙ | |||
73186 73187 73188 73189 73190 73191 73192 |
VdbeBranchTaken(res!=0,2);
if( res ){
pc = pOp->p2-1;
}
break;
};
| | > > > > > > > > > | 73244 73245 73246 73247 73248 73249 73250 73251 73252 73253 73254 73255 73256 73257 73258 73259 73260 73261 73262 73263 73264 73265 73266 73267 73268 73269 73270 73271 73272 73273 73274 73275 73276 73277 73278 73279 |
VdbeBranchTaken(res!=0,2);
if( res ){
pc = pOp->p2-1;
}
break;
};
/* Opcode: SorterData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
** Write into register P2 the current sorter data for sorter cursor P1.
** Then clear the column header cache on cursor P3.
**
** This opcode is normally use to move a record out of the sorter and into
** a register that is the source for a pseudo-table cursor created using
** OpenPseudo. That pseudo-table cursor is the one that is identified by
** parameter P3. Clearing the P3 column cache as part of this opcode saves
** us from having to issue a separate NullRow instruction to clear that cache.
*/
case OP_SorterData: {
VdbeCursor *pC;
pOut = &aMem[pOp->p2];
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
rc = sqlite3VdbeSorterRowkey(pC, pOut);
assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
break;
}
/* Opcode: RowData P1 P2 * * *
** Synopsis: r[P2]=data
**
** Write into register P2 the complete row data for cursor P1.
|
| ︙ | ︙ | |||
73245 73246 73247 73248 73249 73250 73251 | assert( pC->isTable || pOp->opcode!=OP_RowData ); assert( pC->isTable==0 || pOp->opcode==OP_RowData ); assert( pC!=0 ); assert( pC->nullRow==0 ); assert( pC->pseudoTableReg==0 ); assert( pC->pCursor!=0 ); pCrsr = pC->pCursor; | < > > > | < > > | > > | | 73312 73313 73314 73315 73316 73317 73318 73319 73320 73321 73322 73323 73324 73325 73326 73327 73328 73329 73330 73331 73332 73333 73334 73335 73336 73337 73338 73339 73340 73341 73342 73343 73344 73345 73346 73347 73348 73349 73350 73351 73352 73353 73354 73355 73356 73357 |
assert( pC->isTable || pOp->opcode!=OP_RowData );
assert( pC->isTable==0 || pOp->opcode==OP_RowData );
assert( pC!=0 );
assert( pC->nullRow==0 );
assert( pC->pseudoTableReg==0 );
assert( pC->pCursor!=0 );
pCrsr = pC->pCursor;
/* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
** OP_Rewind/Op_Next with no intervening instructions that might invalidate
** the cursor. If this where not the case, on of the following assert()s
** would fail. Should this ever change (because of changes in the code
** generator) then the fix would be to insert a call to
** sqlite3VdbeCursorMoveto().
*/
assert( pC->deferredMoveto==0 );
assert( sqlite3BtreeCursorIsValid(pCrsr) );
#if 0 /* Not required due to the previous to assert() statements */
rc = sqlite3VdbeCursorMoveto(pC);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
#endif
if( pC->isTable==0 ){
assert( !pC->isTable );
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
n = (u32)n64;
}else{
VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
testcase( n==0 );
if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
goto no_mem;
}
pOut->n = n;
MemSetTypeFlag(pOut, MEM_Blob);
if( pC->isTable==0 ){
rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
}else{
|
| ︙ | ︙ | |||
73322 73323 73324 73325 73326 73327 73328 |
pModule = pVtab->pModule;
assert( pModule->xRowid );
rc = pModule->xRowid(pC->pVtabCursor, &v);
sqlite3VtabImportErrmsg(p, pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->pCursor!=0 );
| | < < < | | < < | 73394 73395 73396 73397 73398 73399 73400 73401 73402 73403 73404 73405 73406 73407 73408 73409 73410 73411 73412 73413 73414 73415 73416 73417 73418 73419 73420 73421 73422 73423 73424 73425 73426 73427 73428 73429 |
pModule = pVtab->pModule;
assert( pModule->xRowid );
rc = pModule->xRowid(pC->pVtabCursor, &v);
sqlite3VtabImportErrmsg(p, pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->pCursor!=0 );
rc = sqlite3VdbeCursorRestore(pC);
if( rc ) goto abort_due_to_error;
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */
}
pOut->u.i = v;
break;
}
/* Opcode: NullRow P1 * * * *
**
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
*/
case OP_NullRow: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pC->nullRow = 1;
pC->cacheStatus = CACHE_STALE;
if( pC->pCursor ){
sqlite3BtreeClearCursor(pC->pCursor);
}
break;
}
|
| ︙ | ︙ | |||
73382 73383 73384 73385 73386 73387 73388 | assert( pC!=0 ); pCrsr = pC->pCursor; res = 0; assert( pCrsr!=0 ); rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = (u8)res; pC->deferredMoveto = 0; | < | 73449 73450 73451 73452 73453 73454 73455 73456 73457 73458 73459 73460 73461 73462 |
assert( pC!=0 );
pCrsr = pC->pCursor;
res = 0;
assert( pCrsr!=0 );
rc = sqlite3BtreeLast(pCrsr, &res);
pC->nullRow = (u8)res;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_DEBUG
pC->seekOp = OP_Last;
#endif
if( pOp->p2>0 ){
VdbeBranchTaken(res!=0,2);
if( res ) pc = pOp->p2 - 1;
|
| ︙ | ︙ | |||
73449 73450 73451 73452 73453 73454 73455 |
rc = sqlite3VdbeSorterRewind(pC, &res);
}else{
pCrsr = pC->pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
| < | 73515 73516 73517 73518 73519 73520 73521 73522 73523 73524 73525 73526 73527 73528 |
rc = sqlite3VdbeSorterRewind(pC, &res);
}else{
pCrsr = pC->pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
pC->nullRow = (u8)res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
VdbeBranchTaken(res!=0,2);
if( res ){
pc = pOp->p2 - 1;
}
|
| ︙ | ︙ | |||
73575 73576 73577 73578 73579 73580 73581 |
p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}else{
pC->nullRow = 1;
}
| < | 73640 73641 73642 73643 73644 73645 73646 73647 73648 73649 73650 73651 73652 73653 |
p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}else{
pC->nullRow = 1;
}
goto check_for_interrupt;
}
/* Opcode: IdxInsert P1 P2 P3 * P5
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
|
| ︙ | ︙ | |||
73691 73692 73693 73694 73695 73696 73697 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pCrsr = pC->pCursor; assert( pCrsr!=0 ); pOut->flags = MEM_Null; | > > > > > > > | | | < | 73755 73756 73757 73758 73759 73760 73761 73762 73763 73764 73765 73766 73767 73768 73769 73770 73771 73772 73773 73774 73775 73776 73777 73778 |
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->pCursor;
assert( pCrsr!=0 );
pOut->flags = MEM_Null;
assert( pC->isTable==0 );
assert( pC->deferredMoveto==0 );
/* sqlite3VbeCursorRestore() can only fail if the record has been deleted
** out from under the cursor. That will never happend for an IdxRowid
** opcode, hence the NEVER() arround the check of the return value.
*/
rc = sqlite3VdbeCursorRestore(pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
if( !pC->nullRow ){
rowid = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pOut->u.i = rowid;
|
| ︙ | ︙ | |||
74554 74555 74556 74557 74558 74559 74560 | ctx.pFunc = pOp->p4.pFunc; assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); ctx.pMem = pMem = &aMem[pOp->p3]; pMem->n++; sqlite3VdbeMemInit(&t, db, MEM_Null); ctx.pOut = &t; ctx.isError = 0; | | > < < < < < < | 74624 74625 74626 74627 74628 74629 74630 74631 74632 74633 74634 74635 74636 74637 74638 74639 74640 |
ctx.pFunc = pOp->p4.pFunc;
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
ctx.pMem = pMem = &aMem[pOp->p3];
pMem->n++;
sqlite3VdbeMemInit(&t, db, MEM_Null);
ctx.pOut = &t;
ctx.isError = 0;
ctx.pVdbe = p;
ctx.iOp = pc;
ctx.skipFlag = 0;
(ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
if( ctx.isError ){
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&t));
rc = ctx.isError;
}
if( ctx.skipFlag ){
assert( pOp[-1].opcode==OP_CollSeq );
|
| ︙ | ︙ | |||
78160 78161 78162 78163 78164 78165 78166 |
rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
if( rc==SQLITE_OK ){
#if SQLITE_MAX_WORKER_THREADS
assert( pSorter->bUseThreads==0 || pSorter->nTask>1 );
if( pSorter->bUseThreads ){
int iTask;
| | | 78225 78226 78227 78228 78229 78230 78231 78232 78233 78234 78235 78236 78237 78238 78239 |
rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
if( rc==SQLITE_OK ){
#if SQLITE_MAX_WORKER_THREADS
assert( pSorter->bUseThreads==0 || pSorter->nTask>1 );
if( pSorter->bUseThreads ){
int iTask;
PmaReader *pReadr = 0;
SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1];
rc = vdbeSortAllocUnpacked(pLast);
if( rc==SQLITE_OK ){
pReadr = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader));
pSorter->pReader = pReadr;
if( pReadr==0 ) rc = SQLITE_NOMEM;
}
|
| ︙ | ︙ | |||
81595 81596 81597 81598 81599 81600 81601 81602 81603 81604 81605 81606 81607 81608 |
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
return pNew;
}
#else
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
assert( p==0 );
return 0;
}
| > | 81660 81661 81662 81663 81664 81665 81666 81667 81668 81669 81670 81671 81672 81673 81674 |
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
sqlite3SelectSetName(pNew, p->zSelName);
return pNew;
}
#else
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
assert( p==0 );
return 0;
}
|
| ︙ | ︙ | |||
81737 81738 81739 81740 81741 81742 81743 | sqlite3DbFree(db, pList->a); sqlite3DbFree(db, pList); } /* ** These routines are Walker callbacks. Walker.u.pi is a pointer ** to an integer. These routines are checking an expression to see | | | | | > > > > > > > > | | | | > > > > > > > > > > > > > | 81803 81804 81805 81806 81807 81808 81809 81810 81811 81812 81813 81814 81815 81816 81817 81818 81819 81820 81821 81822 81823 81824 81825 81826 81827 81828 81829 81830 81831 81832 81833 81834 81835 81836 81837 81838 81839 81840 81841 81842 81843 81844 81845 81846 81847 81848 81849 81850 81851 81852 81853 81854 81855 81856 81857 81858 81859 81860 81861 81862 81863 81864 81865 81866 81867 81868 81869 81870 81871 81872 81873 81874 81875 81876 |
sqlite3DbFree(db, pList->a);
sqlite3DbFree(db, pList);
}
/*
** These routines are Walker callbacks. Walker.u.pi is a pointer
** to an integer. These routines are checking an expression to see
** if it is a constant. Set *Walker.u.i to 0 if the expression is
** not constant.
**
** These callback routines are used to implement the following:
**
** sqlite3ExprIsConstant() pWalker->u.i==1
** sqlite3ExprIsConstantNotJoin() pWalker->u.i==2
** sqlite3ExprIsConstantOrFunction() pWalker->u.i==3 or 4
**
** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
** in a CREATE TABLE statement. The Walker.u.i value is 4 when parsing
** an existing schema and 3 when processing a new statement. A bound
** parameter raises an error for new statements, but is silently converted
** to NULL for existing schemas. This allows sqlite_master tables that
** contain a bound parameter because they were generated by older versions
** of SQLite to be parsed by newer versions of SQLite without raising a
** malformed schema error.
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->u.i is 2 then any term of the expression that comes from
** the ON or USING clauses of a join disqualifies the expression
** from being considered constant. */
if( pWalker->u.i==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
pWalker->u.i = 0;
return WRC_Abort;
}
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
** and either pWalker->u.i==3 or 4 or the function as the SQLITE_FUNC_CONST
** flag. */
case TK_FUNCTION:
if( pWalker->u.i>=3 || ExprHasProperty(pExpr,EP_Constant) ){
return WRC_Continue;
}
/* Fall through */
case TK_ID:
case TK_COLUMN:
case TK_AGG_FUNCTION:
case TK_AGG_COLUMN:
testcase( pExpr->op==TK_ID );
testcase( pExpr->op==TK_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
testcase( pExpr->op==TK_AGG_COLUMN );
pWalker->u.i = 0;
return WRC_Abort;
case TK_VARIABLE:
if( pWalker->u.i==4 ){
/* Silently convert bound parameters that appear inside of CREATE
** statements into a NULL when parsing the CREATE statement text out
** of the sqlite_master table */
pExpr->op = TK_NULL;
}else if( pWalker->u.i==3 ){
/* A bound parameter in a CREATE statement that originates from
** sqlite3_prepare() causes an error */
pWalker->u.i = 0;
return WRC_Abort;
}
/* Fall through */
default:
testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
return WRC_Continue;
}
}
static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
|
| ︙ | ︙ | |||
81816 81817 81818 81819 81820 81821 81822 |
/*
** Walk an expression tree. Return 1 if the expression is constant
** that does no originate from the ON or USING clauses of a join.
** Return 0 if it involves variables or function calls or terms from
** an ON or USING clause.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
| | | > | | 81903 81904 81905 81906 81907 81908 81909 81910 81911 81912 81913 81914 81915 81916 81917 81918 81919 81920 81921 81922 81923 81924 81925 81926 81927 81928 81929 81930 81931 |
/*
** Walk an expression tree. Return 1 if the expression is constant
** that does no originate from the ON or USING clauses of a join.
** Return 0 if it involves variables or function calls or terms from
** an ON or USING clause.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
return exprIsConst(p, 2);
}
/*
** Walk an expression tree. Return 1 if the expression is constant
** or a function call with constant arguments. Return and 0 if there
** are any variables.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
assert( isInit==0 || isInit==1 );
return exprIsConst(p, 3+isInit);
}
/*
** If the expression p codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
|
| ︙ | ︙ | |||
83739 83740 83741 83742 83743 83744 83745 | assert( pExpr->op!=TK_REGISTER ); sqlite3ExprCode(pParse, pExpr, target); iMem = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Copy, target, iMem); exprToRegister(pExpr, iMem); } | | | < > > | | < | | | | | | | | | | | | | > | > > > > < | < < < < < < < | < | 83827 83828 83829 83830 83831 83832 83833 83834 83835 83836 83837 83838 83839 83840 83841 83842 83843 83844 83845 83846 83847 83848 83849 83850 83851 83852 83853 83854 83855 83856 83857 83858 83859 83860 83861 83862 83863 83864 83865 83866 83867 83868 83869 83870 83871 83872 83873 83874 83875 83876 83877 83878 83879 83880 83881 83882 83883 83884 83885 83886 83887 83888 83889 83890 83891 83892 83893 83894 83895 83896 83897 83898 83899 83900 83901 83902 83903 83904 83905 83906 83907 83908 83909 83910 83911 83912 83913 83914 83915 83916 83917 83918 83919 83920 |
assert( pExpr->op!=TK_REGISTER );
sqlite3ExprCode(pParse, pExpr, target);
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
exprToRegister(pExpr, iMem);
}
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression tree.
*/
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView);
return;
}
switch( pExpr->op ){
case TK_AGG_COLUMN: {
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
pExpr->iTable, pExpr->iColumn);
break;
}
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
}else{
sqlite3TreeViewLine(pView, "{%d:%d}",
pExpr->iTable, pExpr->iColumn);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3TreeViewLine(pView,"NULL");
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_AS: {
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT: zBinOp = "LT"; break;
case TK_LE: zBinOp = "LE"; break;
case TK_GT: zBinOp = "GT"; break;
case TK_GE: zBinOp = "GE"; break;
|
| ︙ | ︙ | |||
83846 83847 83848 83849 83850 83851 83852 83853 83854 83855 83856 83857 83858 83859 83860 83861 |
case TK_REM: zBinOp = "REM"; break;
case TK_BITAND: zBinOp = "BITAND"; break;
case TK_BITOR: zBinOp = "BITOR"; break;
case TK_SLASH: zBinOp = "DIV"; break;
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
case TK_BITNOT: zUniOp = "BITNOT"; break;
case TK_NOT: zUniOp = "NOT"; break;
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
case TK_COLLATE: {
| > > | < | | | | < | | < | | < | | < | | < | | < | < | < | | | < | | > > > | > | | < | < | | < > | | | > > > > > > > | | < < < | < < | < > | | < | | | < | 83930 83931 83932 83933 83934 83935 83936 83937 83938 83939 83940 83941 83942 83943 83944 83945 83946 83947 83948 83949 83950 83951 83952 83953 83954 83955 83956 83957 83958 83959 83960 83961 83962 83963 83964 83965 83966 83967 83968 83969 83970 83971 83972 83973 83974 83975 83976 83977 83978 83979 83980 83981 83982 83983 83984 83985 83986 83987 83988 83989 83990 83991 83992 83993 83994 83995 83996 83997 83998 83999 84000 84001 84002 84003 84004 84005 84006 84007 84008 84009 84010 84011 84012 84013 84014 84015 84016 84017 84018 84019 84020 84021 84022 84023 84024 84025 84026 84027 84028 84029 84030 84031 84032 84033 84034 84035 84036 84037 84038 84039 84040 84041 84042 84043 84044 84045 84046 84047 84048 84049 84050 84051 84052 84053 84054 84055 84056 84057 84058 84059 84060 84061 84062 84063 84064 84065 84066 84067 84068 84069 84070 84071 84072 84073 84074 84075 84076 84077 84078 84079 84080 84081 84082 84083 84084 84085 84086 84087 84088 84089 84090 84091 84092 84093 84094 84095 84096 84097 84098 84099 |
case TK_REM: zBinOp = "REM"; break;
case TK_BITAND: zBinOp = "BITAND"; break;
case TK_BITOR: zBinOp = "BITOR"; break;
case TK_SLASH: zBinOp = "DIV"; break;
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
case TK_BITNOT: zUniOp = "BITNOT"; break;
case TK_NOT: zUniOp = "NOT"; break;
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
case TK_COLLATE: {
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
pExpr->op2, pExpr->u.zToken);
}else{
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
}
if( pFarg ){
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
sqlite3TreeViewLine(pView, "EXISTS-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
sqlite3TreeViewLine(pView, "SELECT-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3TreeViewLine(pView, "IN");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
break;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** x BETWEEN y AND z
**
** This is equivalent to
**
** x>=y AND x<=z
**
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
Expr *pX = pExpr->pLeft;
Expr *pY = pExpr->x.pList->a[0].pExpr;
Expr *pZ = pExpr->x.pList->a[1].pExpr;
sqlite3TreeViewLine(pView, "BETWEEN");
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
/* If the opcode is TK_TRIGGER, then the expression is a reference
** to a column in the new.* or old.* pseudo-tables available to
** trigger programs. In this case Expr.iTable is set to 1 for the
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affinity ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
sqlite3TreeViewLine(pView, "%s", zBinOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s", zUniOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression list.
*/
SQLITE_PRIVATE void sqlite3TreeViewExprList(
TreeView *pView,
const ExprList *pList,
u8 moreToFollow,
const char *zLabel
){
int i;
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
if( pList==0 ){
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
}else{
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
#if 0
if( pList->a[i].zName ){
sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
}
if( pList->a[i].bSpanIsTab ){
sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
}
#endif
}
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
|
| ︙ | ︙ | |||
87128 87129 87130 87131 87132 87133 87134 | int c; int i; tRowcnt v; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( z==0 ) z = ""; #else | | | | < | < | < > | 87206 87207 87208 87209 87210 87211 87212 87213 87214 87215 87216 87217 87218 87219 87220 87221 87222 87223 87224 87225 87226 87227 87228 87229 87230 87231 87232 87233 87234 87235 87236 |
int c;
int i;
tRowcnt v;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( z==0 ) z = "";
#else
assert( z!=0 );
#endif
for(i=0; *z && i<nOut; i++){
v = 0;
while( (c=z[0])>='0' && c<='9' ){
v = v*10 + c - '0';
z++;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( aOut ) aOut[i] = v;
if( aLog ) aLog[i] = sqlite3LogEst(v);
#else
assert( aOut==0 );
UNUSED_PARAMETER(aOut);
assert( aLog!=0 );
aLog[i] = sqlite3LogEst(v);
#endif
if( *z==' ' ) z++;
}
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
assert( pIndex!=0 );
#else
if( pIndex )
#endif
|
| ︙ | ︙ | |||
87207 87208 87209 87210 87211 87212 87213 87214 |
pIndex = sqlite3PrimaryKeyIndex(pTable);
}else{
pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
}
z = argv[2];
if( pIndex ){
pIndex->bUnordered = 0;
| > > > > > > > > > | | 87283 87284 87285 87286 87287 87288 87289 87290 87291 87292 87293 87294 87295 87296 87297 87298 87299 87300 87301 87302 87303 87304 87305 87306 87307 |
pIndex = sqlite3PrimaryKeyIndex(pTable);
}else{
pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
}
z = argv[2];
if( pIndex ){
int nCol = pIndex->nKeyCol+1;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(
sizeof(tRowcnt) * nCol
);
if( aiRowEst==0 ) pInfo->db->mallocFailed = 1;
#else
tRowcnt * const aiRowEst = 0;
#endif
pIndex->bUnordered = 0;
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
}else{
Index fakeIdx;
fakeIdx.szIdxRow = pTable->szTabRow;
#ifdef SQLITE_ENABLE_COSTMULT
fakeIdx.pTable = pTable;
#endif
|
| ︙ | ︙ | |||
87267 87268 87269 87270 87271 87272 87273 87274 87275 |
** sample columns except the last. The last is always set to 1, as
** once the trailing PK fields are considered all index keys are
** unique. */
nCol = pIdx->nSampleCol-1;
pIdx->aAvgEq[nCol] = 1;
}
for(iCol=0; iCol<nCol; iCol++){
int i; /* Used to iterate through samples */
tRowcnt sumEq = 0; /* Sum of the nEq values */
| > < > > > > > > | > > > > | > | | | < > | | > | | > | | 87352 87353 87354 87355 87356 87357 87358 87359 87360 87361 87362 87363 87364 87365 87366 87367 87368 87369 87370 87371 87372 87373 87374 87375 87376 87377 87378 87379 87380 87381 87382 87383 87384 87385 87386 87387 87388 87389 87390 87391 87392 87393 87394 87395 87396 87397 |
** sample columns except the last. The last is always set to 1, as
** once the trailing PK fields are considered all index keys are
** unique. */
nCol = pIdx->nSampleCol-1;
pIdx->aAvgEq[nCol] = 1;
}
for(iCol=0; iCol<nCol; iCol++){
int nSample = pIdx->nSample;
int i; /* Used to iterate through samples */
tRowcnt sumEq = 0; /* Sum of the nEq values */
tRowcnt avgEq = 0;
tRowcnt nRow; /* Number of rows in index */
i64 nSum100 = 0; /* Number of terms contributing to sumEq */
i64 nDist100; /* Number of distinct values in index */
if( pIdx->aiRowEst==0 || pIdx->aiRowEst[iCol+1]==0 ){
nRow = pFinal->anLt[iCol];
nDist100 = (i64)100 * pFinal->anDLt[iCol];
nSample--;
}else{
nRow = pIdx->aiRowEst[0];
nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1];
}
/* Set nSum to the number of distinct (iCol+1) field prefixes that
** occur in the stat4 table for this index. Set sumEq to the sum of
** the nEq values for column iCol for the same set (adding the value
** only once where there exist duplicate prefixes). */
for(i=0; i<nSample; i++){
if( i==(pIdx->nSample-1)
|| aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol]
){
sumEq += aSample[i].anEq[iCol];
nSum100 += 100;
}
}
if( nDist100>nSum100 ){
avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100);
}
if( avgEq==0 ) avgEq = 1;
pIdx->aAvgEq[iCol] = avgEq;
}
}
}
|
| ︙ | ︙ | |||
87536 87537 87538 87539 87540 87541 87542 87543 87544 87545 87546 87547 87548 87549 |
/* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( rc==SQLITE_OK ){
int lookasideEnabled = db->lookaside.bEnabled;
db->lookaside.bEnabled = 0;
rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bEnabled = lookasideEnabled;
}
#endif
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
return rc;
| > > > > > | 87634 87635 87636 87637 87638 87639 87640 87641 87642 87643 87644 87645 87646 87647 87648 87649 87650 87651 87652 |
/* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( rc==SQLITE_OK ){
int lookasideEnabled = db->lookaside.bEnabled;
db->lookaside.bEnabled = 0;
rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bEnabled = lookasideEnabled;
}
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3_free(pIdx->aiRowEst);
pIdx->aiRowEst = 0;
}
#endif
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
return rc;
|
| ︙ | ︙ | |||
88830 88831 88832 88833 88834 88835 88836 88837 88838 88839 88840 88841 88842 88843 | #ifndef SQLITE_OMIT_ANALYZE sqlite3DeleteIndexSamples(db, p); #endif if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo); sqlite3ExprDelete(db, p->pPartIdxWhere); sqlite3DbFree(db, p->zColAff); if( p->isResized ) sqlite3DbFree(db, p->azColl); sqlite3DbFree(db, p); } /* ** For the index called zIdxName which is found in the database iDb, ** unlike that index from its Table then remove the index from ** the index hash table and free all memory structures associated | > > > | 88933 88934 88935 88936 88937 88938 88939 88940 88941 88942 88943 88944 88945 88946 88947 88948 88949 | #ifndef SQLITE_OMIT_ANALYZE sqlite3DeleteIndexSamples(db, p); #endif if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo); sqlite3ExprDelete(db, p->pPartIdxWhere); sqlite3DbFree(db, p->zColAff); if( p->isResized ) sqlite3DbFree(db, p->azColl); #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3_free(p->aiRowEst); #endif sqlite3DbFree(db, p); } /* ** For the index called zIdxName which is found in the database iDb, ** unlike that index from its Table then remove the index from ** the index hash table and free all memory structures associated |
| ︙ | ︙ | |||
89631 89632 89633 89634 89635 89636 89637 |
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
Table *p;
Column *pCol;
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
if( p!=0 ){
pCol = &(p->aCol[p->nCol-1]);
| | | 89737 89738 89739 89740 89741 89742 89743 89744 89745 89746 89747 89748 89749 89750 89751 |
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
Table *p;
Column *pCol;
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
if( p!=0 ){
pCol = &(p->aCol[p->nCol-1]);
if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
/* A copy of pExpr is used instead of the original, as pExpr contains
** tokens that point to volatile memory. The 'span' of the expression
** is required by pragma table_info.
*/
|
| ︙ | ︙ | |||
91139 91140 91141 91142 91143 91144 91145 |
addr2 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
pIndex->nKeyCol); VdbeCoverage(v);
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
}else{
addr2 = sqlite3VdbeCurrentAddr(v);
}
| | | 91245 91246 91247 91248 91249 91250 91251 91252 91253 91254 91255 91256 91257 91258 91259 |
addr2 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
pIndex->nKeyCol); VdbeCoverage(v);
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
}else{
addr2 = sqlite3VdbeCurrentAddr(v);
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp1(v, OP_Close, iTab);
|
| ︙ | ︙ | |||
94028 94029 94030 94031 94032 94033 94034 |
/* #include <stdlib.h> */
/* #include <assert.h> */
/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
| > > > | | 94134 94135 94136 94137 94138 94139 94140 94141 94142 94143 94144 94145 94146 94147 94148 94149 94150 94151 |
/* #include <stdlib.h> */
/* #include <assert.h> */
/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1];
assert( pOp->opcode==OP_CollSeq );
assert( pOp->p4type==P4_COLLSEQ );
return pOp->p4.pColl;
}
/*
** Indicate that the accumulator load should be skipped on this
** iteration of the aggregate loop.
*/
static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){
|
| ︙ | ︙ | |||
94573 94574 94575 94576 94577 94578 94579 | /* ** For LIKE and GLOB matching on EBCDIC machines, assume that every ** character is exactly one byte in size. Also, all characters are ** able to participate in upper-case-to-lower-case mappings in EBCDIC ** whereas only characters less than 0x80 do in ASCII. */ #if defined(SQLITE_EBCDIC) | | | > | > | | | | | > > > > > > > | < < | | | | > | > > > > > > | > > > | | > | | < | | | | > | | | | | > | > > > > > > > > > | < < | > | | < | < | > > > > > | | | > > | > | | > | < | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < | > > | | | | | | | < < < | 94682 94683 94684 94685 94686 94687 94688 94689 94690 94691 94692 94693 94694 94695 94696 94697 94698 94699 94700 94701 94702 94703 94704 94705 94706 94707 94708 94709 94710 94711 94712 94713 94714 94715 94716 94717 94718 94719 94720 94721 94722 94723 94724 94725 94726 94727 94728 94729 94730 94731 94732 94733 94734 94735 94736 94737 94738 94739 94740 94741 94742 94743 94744 94745 94746 94747 94748 94749 94750 94751 94752 94753 94754 94755 94756 94757 94758 94759 94760 94761 94762 94763 94764 94765 94766 94767 94768 94769 94770 94771 94772 94773 94774 94775 94776 94777 94778 94779 94780 94781 94782 94783 94784 94785 94786 94787 94788 94789 94790 94791 94792 94793 94794 94795 94796 94797 94798 94799 94800 94801 94802 94803 94804 94805 94806 94807 94808 94809 94810 94811 94812 94813 94814 94815 94816 94817 94818 94819 94820 94821 94822 94823 94824 94825 94826 94827 94828 94829 94830 94831 94832 94833 94834 94835 94836 94837 94838 94839 94840 94841 94842 94843 94844 94845 94846 94847 94848 94849 94850 94851 94852 94853 94854 94855 94856 94857 94858 94859 94860 94861 94862 94863 94864 94865 94866 94867 94868 94869 94870 |
/*
** For LIKE and GLOB matching on EBCDIC machines, assume that every
** character is exactly one byte in size. Also, all characters are
** able to participate in upper-case-to-lower-case mappings in EBCDIC
** whereas only characters less than 0x80 do in ASCII.
*/
#if defined(SQLITE_EBCDIC)
# define sqlite3Utf8Read(A) (*((*A)++))
# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
#else
# define GlobUpperToLower(A) if( A<=0x7f ){ A = sqlite3UpperToLower[A]; }
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
#endif
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
/* The correct SQL-92 behavior is for the LIKE operator to ignore
** case. Thus 'a' LIKE 'A' would be true. */
static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
** is case sensitive causing 'a' LIKE 'A' to be false */
static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
/*
** Compare two UTF-8 strings for equality where the first string can
** potentially be a "glob" or "like" expression. Return true (1) if they
** are the same and false (0) if they are different.
**
** Globbing rules:
**
** '*' Matches any sequence of zero or more characters.
**
** '?' Matches exactly one character.
**
** [...] Matches one character from the enclosed list of
** characters.
**
** [^...] Matches one character not in the enclosed list.
**
** With the [...] and [^...] matching, a ']' character can be included
** in the list by making it the first character after '[' or '^'. A
** range of characters can be specified using '-'. Example:
** "[a-z]" matches any single lower-case letter. To match a '-', make
** it the last character in the list.
**
** Like matching rules:
**
** '%' Matches any sequence of zero or more characters
**
*** '_' Matches any one character
**
** Ec Where E is the "esc" character and c is any other
** character, including '%', '_', and esc, match exactly c.
**
** The comments through this routine usually assume glob matching.
**
** This routine is usually quick, but can be N**2 in the worst case.
*/
static int patternCompare(
const u8 *zPattern, /* The glob pattern */
const u8 *zString, /* The string to compare against the glob */
const struct compareInfo *pInfo, /* Information about how to do the compare */
u32 esc /* The escape character */
){
u32 c, c2; /* Next pattern and input string chars */
u32 matchOne = pInfo->matchOne; /* "?" or "_" */
u32 matchAll = pInfo->matchAll; /* "*" or "%" */
u32 matchOther; /* "[" or the escape character */
u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
const u8 *zEscaped = 0; /* One past the last escaped input char */
/* The GLOB operator does not have an ESCAPE clause. And LIKE does not
** have the matchSet operator. So we either have to look for one or
** the other, never both. Hence the single variable matchOther is used
** to store the one we have to look for.
*/
matchOther = esc ? esc : pInfo->matchSet;
while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
if( c==matchAll ){ /* Match "*" */
/* Skip over multiple "*" characters in the pattern. If there
** are also "?" characters, skip those as well, but consume a
** single character of the input string for each "?" skipped */
while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
|| c == matchOne ){
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
return 0;
}
}
if( c==0 ){
return 1; /* "*" at the end of the pattern matches */
}else if( c==matchOther ){
if( esc ){
c = sqlite3Utf8Read(&zPattern);
if( c==0 ) return 0;
}else{
/* "[...]" immediately follows the "*". We have to do a slow
** recursive search in this case, but it is an unusual case. */
assert( matchOther<0x80 ); /* '[' is a single-byte character */
while( *zString
&& patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
SQLITE_SKIP_UTF8(zString);
}
return *zString!=0;
}
}
/* At this point variable c contains the first character of the
** pattern string past the "*". Search in the input string for the
** first matching character and recursively contine the match from
** that point.
**
** For a case-insensitive search, set variable cx to be the same as
** c but in the other case and search the input string for either
** c or cx.
*/
if( c<=0x80 ){
u32 cx;
if( noCase ){
cx = sqlite3Toupper(c);
c = sqlite3Tolower(c);
}else{
cx = c;
}
while( (c2 = *(zString++))!=0 ){
if( c2!=c && c2!=cx ) continue;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
}
}else{
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
if( c2!=c ) continue;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
}
}
return 0;
}
if( c==matchOther ){
if( esc ){
c = sqlite3Utf8Read(&zPattern);
if( c==0 ) return 0;
zEscaped = zPattern;
}else{
u32 prior_c = 0;
int seen = 0;
int invert = 0;
c = sqlite3Utf8Read(&zString);
if( c==0 ) return 0;
c2 = sqlite3Utf8Read(&zPattern);
if( c2=='^' ){
invert = 1;
c2 = sqlite3Utf8Read(&zPattern);
}
if( c2==']' ){
if( c==']' ) seen = 1;
c2 = sqlite3Utf8Read(&zPattern);
}
while( c2 && c2!=']' ){
if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
c2 = sqlite3Utf8Read(&zPattern);
if( c>=prior_c && c<=c2 ) seen = 1;
prior_c = 0;
}else{
if( c==c2 ){
seen = 1;
}
prior_c = c2;
}
c2 = sqlite3Utf8Read(&zPattern);
}
if( c2==0 || (seen ^ invert)==0 ){
return 0;
}
continue;
}
}
c2 = sqlite3Utf8Read(&zString);
if( c==c2 ) continue;
if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
continue;
}
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
return 0;
}
return *zString==0;
}
/*
** The sqlite3_strglob() interface.
*/
|
| ︙ | ︙ | |||
103882 103883 103884 103885 103886 103887 103888 103889 103890 103891 103892 103893 103894 103895 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. */ /* ** An instance of the following object is used to record information about ** how to process the DISTINCT keyword, to simplify passing that information ** into the selectInnerLoop() routine. */ typedef struct DistinctCtx DistinctCtx; | > > > > > > > > > > > > > > | 104020 104021 104022 104023 104024 104025 104026 104027 104028 104029 104030 104031 104032 104033 104034 104035 104036 104037 104038 104039 104040 104041 104042 104043 104044 104045 104046 104047 |
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
*/
/*
** Trace output macros
*/
#if SELECTTRACE_ENABLED
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",(S)->zSelName,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
#endif
/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
** into the selectInnerLoop() routine.
*/
typedef struct DistinctCtx DistinctCtx;
|
| ︙ | ︙ | |||
103994 103995 103996 103997 103998 103999 104000 104001 104002 104003 104004 104005 104006 104007 |
pNew = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
}
assert( pNew!=&standin );
return pNew;
}
/*
** Delete the given Select structure and all of its substructures.
*/
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( p ){
clearSelect(db, p);
| > > > > > > > > > > > > | 104146 104147 104148 104149 104150 104151 104152 104153 104154 104155 104156 104157 104158 104159 104160 104161 104162 104163 104164 104165 104166 104167 104168 104169 104170 104171 |
pNew = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
}
assert( pNew!=&standin );
return pNew;
}
#if SELECTTRACE_ENABLED
/*
** Set the name of a Select object
*/
SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){
if( p && zName ){
sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName);
}
}
#endif
/*
** Delete the given Select structure and all of its substructures.
*/
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( p ){
clearSelect(db, p);
|
| ︙ | ︙ | |||
105024 105025 105026 105027 105028 105029 105030 | int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; int nKey; int iSortTab; /* Sorter cursor to read from */ int nSortData; /* Trailing values to read from sorter */ | < | 105188 105189 105190 105191 105192 105193 105194 105195 105196 105197 105198 105199 105200 105201 |
int eDest = pDest->eDest;
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
int nKey;
int iSortTab; /* Sorter cursor to read from */
int nSortData; /* Trailing values to read from sorter */
int i;
int bSeq; /* True if sorter record includes seq. no. */
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
struct ExprList_item *aOutEx = p->pEList->a;
#endif
if( pSort->labelBkOut ){
|
| ︙ | ︙ | |||
105058 105059 105060 105061 105062 105063 105064 |
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
| | < < < | 105221 105222 105223 105224 105225 105226 105227 105228 105229 105230 105231 105232 105233 105234 105235 105236 105237 105238 105239 105240 105241 105242 105243 105244 |
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
bSeq = 0;
}else{
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
iSortTab = iTab;
bSeq = 1;
}
for(i=0; i<nSortData; i++){
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){
case SRT_Table:
case SRT_EphemTab: {
testcase( eDest==SRT_Table );
testcase( eDest==SRT_EphemTab );
|
| ︙ | ︙ | |||
107224 107225 107226 107227 107228 107229 107230 107231 107232 107233 107234 107235 107236 107237 |
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
}
/***** If we reach this point, flattening is permitted. *****/
/* Authorize the subquery */
pParse->zAuthContext = pSubitem->zName;
TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
| > > | 107384 107385 107386 107387 107388 107389 107390 107391 107392 107393 107394 107395 107396 107397 107398 107399 |
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
}
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n",
pSub->zSelName, pSub, iFrom));
/* Authorize the subquery */
pParse->zAuthContext = pSubitem->zName;
TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
|
| ︙ | ︙ | |||
107276 107277 107278 107279 107280 107281 107282 107283 107284 107285 107286 107287 107288 107289 107290 107291 107292 107293 107294 107295 107296 107297 107298 107299 107300 107301 |
Select *pPrior = p->pPrior;
p->pOrderBy = 0;
p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
p->pOffset = 0;
pNew = sqlite3SelectDup(db, p, 0);
p->pOffset = pOffset;
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
p->op = TK_ALL;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
p->pPrior = pNew;
}
if( db->mallocFailed ) return 1;
}
/* Begin flattening the iFrom-th entry of the FROM clause
** in the outer query.
*/
| > > > > | 107438 107439 107440 107441 107442 107443 107444 107445 107446 107447 107448 107449 107450 107451 107452 107453 107454 107455 107456 107457 107458 107459 107460 107461 107462 107463 107464 107465 107466 107467 |
Select *pPrior = p->pPrior;
p->pOrderBy = 0;
p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
p->pOffset = 0;
pNew = sqlite3SelectDup(db, p, 0);
sqlite3SelectSetName(pNew, pSub->zSelName);
p->pOffset = pOffset;
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
p->op = TK_ALL;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
p->pPrior = pNew;
SELECTTRACE(2,pParse,p,
("compound-subquery flattener creates %s.%p as peer\n",
pNew->zSelName, pNew));
}
if( db->mallocFailed ) return 1;
}
/* Begin flattening the iFrom-th entry of the FROM clause
** in the outer query.
*/
|
| ︙ | ︙ | |||
107417 107418 107419 107420 107421 107422 107423 107424 |
}
substExprList(db, pParent->pEList, iParent, pSub->pEList);
if( isAgg ){
substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
}
if( pSub->pOrderBy ){
assert( pParent->pOrderBy==0 );
| > > > > > > > > > > > > > > > | | 107583 107584 107585 107586 107587 107588 107589 107590 107591 107592 107593 107594 107595 107596 107597 107598 107599 107600 107601 107602 107603 107604 107605 107606 107607 107608 107609 107610 107611 107612 107613 |
}
substExprList(db, pParent->pEList, iParent, pSub->pEList);
if( isAgg ){
substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
}
if( pSub->pOrderBy ){
/* At this point, any non-zero iOrderByCol values indicate that the
** ORDER BY column expression is identical to the iOrderByCol'th
** expression returned by SELECT statement pSub. Since these values
** do not necessarily correspond to columns in SELECT statement pParent,
** zero them before transfering the ORDER BY clause.
**
** Not doing this may cause an error if a subsequent call to this
** function attempts to flatten a compound sub-query into pParent
** (the only way this can happen is if the compound sub-query is
** currently part of pSub->pSrc). See ticket [d11a6e908f]. */
ExprList *pOrderBy = pSub->pOrderBy;
for(i=0; i<pOrderBy->nExpr; i++){
pOrderBy->a[i].u.x.iOrderByCol = 0;
}
assert( pParent->pOrderBy==0 );
assert( pSub->pPrior==0 );
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}else if( pParent->pOrderBy ){
substExprList(db, pParent->pOrderBy, iParent, pSub->pEList);
}
if( pSub->pWhere ){
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
}else{
|
| ︙ | ︙ | |||
107463 107464 107465 107466 107467 107468 107469 107470 107471 107472 107473 107474 107475 107476 |
}
}
/* Finially, delete what is left of the subquery and return
** success.
*/
sqlite3SelectDelete(db, pSub1);
return 1;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** Based on the contents of the AggInfo structure indicated by the first
| > > > > > > > | 107644 107645 107646 107647 107648 107649 107650 107651 107652 107653 107654 107655 107656 107657 107658 107659 107660 107661 107662 107663 107664 |
}
}
/* Finially, delete what is left of the subquery and return
** success.
*/
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
sqlite3DebugPrintf("After flattening:\n");
sqlite3TreeViewSelect(0, p, 0);
}
#endif
return 1;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** Based on the contents of the AggInfo structure indicated by the first
|
| ︙ | ︙ | |||
107934 107935 107936 107937 107938 107939 107940 107941 107942 107943 107944 107945 107946 107947 |
pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
if( pTab->pSelect || IsVirtual(pTab) ){
/* We reach here if the named table is a really a view */
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
sqlite3WalkSelect(pWalker, pFrom->pSelect);
}
#endif
}
/* Locate the index named by the INDEXED BY clause, if any. */
if( sqlite3IndexedByLookup(pParse, pFrom) ){
| > | 108122 108123 108124 108125 108126 108127 108128 108129 108130 108131 108132 108133 108134 108135 108136 |
pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
if( pTab->pSelect || IsVirtual(pTab) ){
/* We reach here if the named table is a really a view */
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
sqlite3SelectSetName(pFrom->pSelect, pTab->zName);
sqlite3WalkSelect(pWalker, pFrom->pSelect);
}
#endif
}
/* Locate the index named by the INDEXED BY clause, if any. */
if( sqlite3IndexedByLookup(pParse, pFrom) ){
|
| ︙ | ︙ | |||
108468 108469 108470 108471 108472 108473 108474 108475 108476 108477 108478 108479 108480 108481 |
db = pParse->db;
if( p==0 || db->mallocFailed || pParse->nErr ){
return 1;
}
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
if( IgnorableOrderby(pDest) ){
assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
| > > > > > > > | 108657 108658 108659 108660 108661 108662 108663 108664 108665 108666 108667 108668 108669 108670 108671 108672 108673 108674 108675 108676 108677 |
db = pParse->db;
if( p==0 || db->mallocFailed || pParse->nErr ){
return 1;
}
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
#if SELECTTRACE_ENABLED
pParse->nSelectIndent++;
SELECTTRACE(1,pParse,p, ("begin processing:\n"));
if( sqlite3SelectTrace & 0x100 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
if( IgnorableOrderby(pDest) ){
assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
|
| ︙ | ︙ | |||
108624 108625 108626 108627 108628 108629 108630 108631 108632 108633 108634 108635 108636 108637 |
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
return rc;
}
#endif
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
| > > > > | 108820 108821 108822 108823 108824 108825 108826 108827 108828 108829 108830 108831 108832 108833 108834 108835 108836 108837 |
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
}
#endif
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
|
| ︙ | ︙ | |||
108959 108960 108961 108962 108963 108964 108965 |
** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
** Then compare the current GROUP BY terms against the GROUP BY terms
** from the previous row currently stored in a0, a1, a2...
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
if( groupBySort ){
| | < | 109159 109160 109161 109162 109163 109164 109165 109166 109167 109168 109169 109170 109171 109172 109173 109174 109175 109176 109177 |
** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
** Then compare the current GROUP BY terms against the GROUP BY terms
** from the previous row currently stored in a0, a1, a2...
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut,sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
}else{
sAggInfo.directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
}
}
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
|
| ︙ | ︙ | |||
109223 109224 109225 109226 109227 109228 109229 109230 109231 109232 |
*/
if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
generateColumnNames(pParse, pTabList, pEList);
}
sqlite3DbFree(db, sAggInfo.aCol);
sqlite3DbFree(db, sAggInfo.aFunc);
return rc;
}
| > > > > | | > > | < | < < | < < | > > > | < | > > > | | | > > > | | | | | | | | | | | > > > | | | > > | | | < | < | | | < | < | | | | | | < < | > > | | > | | < | < < | < < | | < < < | 109422 109423 109424 109425 109426 109427 109428 109429 109430 109431 109432 109433 109434 109435 109436 109437 109438 109439 109440 109441 109442 109443 109444 109445 109446 109447 109448 109449 109450 109451 109452 109453 109454 109455 109456 109457 109458 109459 109460 109461 109462 109463 109464 109465 109466 109467 109468 109469 109470 109471 109472 109473 109474 109475 109476 109477 109478 109479 109480 109481 109482 109483 109484 109485 109486 109487 109488 109489 109490 109491 109492 109493 109494 109495 109496 109497 109498 109499 109500 109501 109502 109503 109504 109505 109506 109507 109508 109509 109510 109511 109512 109513 109514 109515 109516 109517 109518 109519 109520 109521 109522 109523 109524 109525 109526 109527 109528 109529 109530 109531 109532 109533 109534 109535 |
*/
if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
generateColumnNames(pParse, pTabList, pEList);
}
sqlite3DbFree(db, sAggInfo.aCol);
sqlite3DbFree(db, sAggInfo.aFunc);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
}
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable description of a the Select object.
*/
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
sqlite3TreeViewLine(pView, "SELECT%s%s",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : "")
);
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
if( p->pOffset ) n++;
if( p->pPrior ) n++;
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
for(i=0; i<p->pSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
}else if( pItem->zName ){
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
}
if( pItem->pTab ){
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
}
if( pItem->zAlias ){
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
}
if( pItem->jointype & JT_LEFT ){
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
}
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
if( pItem->pSelect ){
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
}
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
sqlite3TreeViewPop(pView);
}
if( p->pGroupBy ){
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
}
if( p->pHaving ){
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOrderBy ){
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOffset ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pOffset, 0);
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
switch( p->op ){
case TK_ALL: zOp = "UNION ALL"; break;
case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break;
}
sqlite3TreeViewItem(pView, zOp, (n--)>0);
sqlite3TreeViewSelect(pView, p->pPrior, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
/************** End of select.c **********************************************/
/************** Begin file table.c *******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
|
| ︙ | ︙ | |||
112309 112310 112311 112312 112313 112314 112315 112316 112317 112318 112319 112320 112321 112322 |
*pzErr = sqlite3MPrintf(db, "%s", zErr);
sqlite3_free(zErr);
}
sqlite3DbFree(db, pVTable);
}else if( ALWAYS(pVTable->pVtab) ){
/* Justification of ALWAYS(): A correct vtab constructor must allocate
** the sqlite3_vtab object if successful. */
pVTable->pVtab->pModule = pMod->pModule;
pVTable->nRef = 1;
if( sCtx.pTab ){
const char *zFormat = "vtable constructor did not declare schema: %s";
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
sqlite3VtabUnlock(pVTable);
rc = SQLITE_ERROR;
| > | 112511 112512 112513 112514 112515 112516 112517 112518 112519 112520 112521 112522 112523 112524 112525 |
*pzErr = sqlite3MPrintf(db, "%s", zErr);
sqlite3_free(zErr);
}
sqlite3DbFree(db, pVTable);
}else if( ALWAYS(pVTable->pVtab) ){
/* Justification of ALWAYS(): A correct vtab constructor must allocate
** the sqlite3_vtab object if successful. */
memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
pVTable->pVtab->pModule = pMod->pModule;
pVTable->nRef = 1;
if( sCtx.pTab ){
const char *zFormat = "vtable constructor did not declare schema: %s";
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
sqlite3VtabUnlock(pVTable);
rc = SQLITE_ERROR;
|
| ︙ | ︙ | |||
113717 113718 113719 113720 113721 113722 113723 | assert( TK_GT>TK_EQ && TK_GT<TK_GE ); assert( TK_LT>TK_EQ && TK_LT<TK_GE ); assert( TK_LE>TK_EQ && TK_LE<TK_GE ); assert( TK_GE==TK_EQ+4 ); return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL; } | < < < < < | 113920 113921 113922 113923 113924 113925 113926 113927 113928 113929 113930 113931 113932 113933 | assert( TK_GT>TK_EQ && TK_GT<TK_GE ); assert( TK_LT>TK_EQ && TK_LT<TK_GE ); assert( TK_LE>TK_EQ && TK_LE<TK_GE ); assert( TK_GE==TK_EQ+4 ); return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL; } /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** ** If left/right precedence rules come into play when determining the ** collating sequence, then COLLATE operators are adjusted to ensure ** that the collating sequence does not change. For example: |
| ︙ | ︙ | |||
115564 115565 115566 115567 115568 115569 115570 115571 115572 115573 115574 115575 |
}else{
/* Note: this call could be optimized away - since the same values must
** have been requested when testing key $P in whereEqualScanEst(). */
whereKeyStats(pParse, p, pRec, 0, a);
iLower = a[0];
iUpper = a[0] + a[1];
}
/* If possible, improve on the iLower estimate using ($P:$L). */
if( pLower ){
int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pLower->pExpr->pRight;
| > > > > > > > > < | < | | 115762 115763 115764 115765 115766 115767 115768 115769 115770 115771 115772 115773 115774 115775 115776 115777 115778 115779 115780 115781 115782 115783 115784 115785 115786 115787 115788 115789 115790 115791 115792 115793 115794 115795 115796 115797 115798 115799 115800 115801 115802 115803 115804 115805 115806 115807 115808 |
}else{
/* Note: this call could be optimized away - since the same values must
** have been requested when testing key $P in whereEqualScanEst(). */
whereKeyStats(pParse, p, pRec, 0, a);
iLower = a[0];
iUpper = a[0] + a[1];
}
assert( pLower==0 || (pLower->eOperator & (WO_GT|WO_GE))!=0 );
assert( pUpper==0 || (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
assert( p->aSortOrder!=0 );
if( p->aSortOrder[nEq] ){
/* The roles of pLower and pUpper are swapped for a DESC index */
SWAP(WhereTerm*, pLower, pUpper);
}
/* If possible, improve on the iLower estimate using ($P:$L). */
if( pLower ){
int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pLower->pExpr->pRight;
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
tRowcnt iNew;
whereKeyStats(pParse, p, pRec, 0, a);
iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
if( iNew>iLower ) iLower = iNew;
nOut--;
pLower = 0;
}
}
/* If possible, improve on the iUpper estimate using ($P:$U). */
if( pUpper ){
int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pUpper->pExpr->pRight;
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
tRowcnt iNew;
whereKeyStats(pParse, p, pRec, 1, a);
iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
if( iNew<iUpper ) iUpper = iNew;
nOut--;
pUpper = 0;
}
}
pBuilder->pRec = pRec;
|
| ︙ | ︙ | |||
116089 116090 116091 116092 116093 116094 116095 | sqlite3StrAccumAppendAll(pStr, zColumn); sqlite3StrAccumAppend(pStr, zOp, 1); sqlite3StrAccumAppend(pStr, "?", 1); } /* ** Argument pLevel describes a strategy for scanning table pTab. This | | | < < < < < | < | < < < < | | | < | < | | | < | 116293 116294 116295 116296 116297 116298 116299 116300 116301 116302 116303 116304 116305 116306 116307 116308 116309 116310 116311 116312 116313 116314 116315 116316 116317 116318 116319 116320 116321 116322 116323 116324 116325 116326 116327 116328 116329 116330 116331 116332 116333 116334 116335 116336 116337 116338 116339 116340 116341 116342 116343 116344 116345 116346 116347 116348 |
sqlite3StrAccumAppendAll(pStr, zColumn);
sqlite3StrAccumAppend(pStr, zOp, 1);
sqlite3StrAccumAppend(pStr, "?", 1);
}
/*
** Argument pLevel describes a strategy for scanning table pTab. This
** function appends text to pStr that describes the subset of table
** rows scanned by the strategy in the form of an SQL expression.
**
** For example, if the query:
**
** SELECT * FROM t1 WHERE a=1 AND b>2;
**
** is run and there is an index on (a, b), then this function returns a
** string similar to:
**
** "a=? AND b>?"
*/
static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop, Table *pTab){
Index *pIndex = pLoop->u.btree.pIndex;
u16 nEq = pLoop->u.btree.nEq;
u16 nSkip = pLoop->u.btree.nSkip;
int i, j;
Column *aCol = pTab->aCol;
i16 *aiColumn = pIndex->aiColumn;
if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return;
sqlite3StrAccumAppend(pStr, " (", 2);
for(i=0; i<nEq; i++){
char *z = aiColumn[i] < 0 ? "rowid" : aCol[aiColumn[i]].zName;
if( i>=nSkip ){
explainAppendTerm(pStr, i, z, "=");
}else{
if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5);
sqlite3XPrintf(pStr, 0, "ANY(%s)", z);
}
}
j = i;
if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
char *z = aiColumn[j] < 0 ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(pStr, i++, z, ">");
}
if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
char *z = aiColumn[j] < 0 ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(pStr, i, z, "<");
}
sqlite3StrAccumAppend(pStr, ")", 1);
}
/*
** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single
** record is added to the output to describe the table scan strategy in
** pLevel.
|
| ︙ | ︙ | |||
116167 116168 116169 116170 116171 116172 116173 |
#ifndef SQLITE_DEBUG
if( pParse->explain==2 )
#endif
{
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
| < > > > > > | | | | | < < | | | > > > | > | | | | | > > > < | | | | > | | > > | > > > > > > > | | 116358 116359 116360 116361 116362 116363 116364 116365 116366 116367 116368 116369 116370 116371 116372 116373 116374 116375 116376 116377 116378 116379 116380 116381 116382 116383 116384 116385 116386 116387 116388 116389 116390 116391 116392 116393 116394 116395 116396 116397 116398 116399 116400 116401 116402 116403 116404 116405 116406 116407 116408 116409 116410 116411 116412 116413 116414 116415 116416 116417 116418 116419 116420 116421 116422 116423 116424 116425 116426 116427 116428 116429 116430 116431 116432 116433 116434 116435 116436 116437 116438 116439 116440 116441 116442 116443 116444 116445 116446 116447 116448 116449 116450 116451 |
#ifndef SQLITE_DEBUG
if( pParse->explain==2 )
#endif
{
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int iId = pParse->iSelectId; /* Select id (left-most output column) */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
u32 flags; /* Flags that describe this loop */
char *zMsg; /* Text to add to EQP output */
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
str.db = db;
sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
if( pItem->pSelect ){
sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId);
}else{
sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName);
}
if( pItem->zAlias ){
sqlite3XPrintf(&str, 0, " AS %s", pItem->zAlias);
}
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
assert( pLoop->u.btree.pIndex!=0 );
pIdx = pLoop->u.btree.pIndex;
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
if( isSearch ){
zFmt = "PRIMARY KEY";
}
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "AUTOMATIC COVERING INDEX";
}else if( flags & WHERE_IDX_ONLY ){
zFmt = "COVERING INDEX %s";
}else{
zFmt = "INDEX %s";
}
if( zFmt ){
sqlite3StrAccumAppend(&str, " USING ", 7);
sqlite3XPrintf(&str, 0, zFmt, pIdx->zName);
explainIndexRange(&str, pLoop, pItem->pTab);
}
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
const char *zRange;
if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
zRange = "(rowid=?)";
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
zRange = "(rowid>? AND rowid<?)";
}else if( flags&WHERE_BTM_LIMIT ){
zRange = "(rowid>?)";
}else{
assert( flags&WHERE_TOP_LIMIT);
zRange = "(rowid<?)";
}
sqlite3StrAccumAppendAll(&str, " USING INTEGER PRIMARY KEY ");
sqlite3StrAccumAppendAll(&str, zRange);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
sqlite3XPrintf(&str, 0, " VIRTUAL TABLE INDEX %d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
if( pLoop->nOut>=10 ){
sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut));
}else{
sqlite3StrAccumAppend(&str, " (~1 row)", 9);
}
#endif
zMsg = sqlite3StrAccumFinish(&str);
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
}
}
#else
# define explainOneScan(u,v,w,x,y,z)
#endif /* SQLITE_OMIT_EXPLAIN */
|
| ︙ | ︙ | |||
116882 116883 116884 116885 116886 116887 116888 |
}
}
/* Run a separate WHERE clause for each term of the OR clause. After
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
| | > | > | 117091 117092 117093 117094 117095 117096 117097 117098 117099 117100 117101 117102 117103 117104 117105 117106 117107 117108 117109 117110 117111 117112 117113 117114 117115 117116 117117 117118 117119 |
}
}
/* Run a separate WHERE clause for each term of the OR clause. After
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
wctrlFlags = WHERE_OMIT_OPEN_CLOSE
| WHERE_FORCE_TABLE
| WHERE_ONETABLE_ONLY;
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
int j1 = 0; /* Address of jump operation */
if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
}
/* Loop through table entries that match term pOrTerm. */
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
wctrlFlags, iCovCur);
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
if( pSubWInfo ){
WhereLoop *pSubLoop;
explainOneScan(
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
|
| ︙ | ︙ | |||
117114 117115 117116 117117 117118 117119 117120 |
pTerm->wtFlags |= TERM_CODED;
}
}
return pLevel->notReady;
}
| | | | > > > | | | | | > | > | | < | > | 117325 117326 117327 117328 117329 117330 117331 117332 117333 117334 117335 117336 117337 117338 117339 117340 117341 117342 117343 117344 117345 117346 117347 117348 117349 117350 117351 117352 117353 117354 117355 117356 117357 117358 |
pTerm->wtFlags |= TERM_CODED;
}
}
return pLevel->notReady;
}
#ifdef WHERETRACE_ENABLED
/*
** Print the content of a WhereTerm object
*/
static void whereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm==0 ){
sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
}else{
char zType[4];
memcpy(zType, "...", 4);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
sqlite3DebugPrintf("TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x\n",
iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
pTerm->eOperator);
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
#endif
#ifdef WHERETRACE_ENABLED
/*
** Print a WhereLoop object for debugging purposes
*/
static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
WhereInfo *pWInfo = pWC->pWInfo;
|
| ︙ | ︙ | |||
117172 117173 117174 117175 117176 117177 117178 |
}
if( p->wsFlags & WHERE_SKIPSCAN ){
sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->u.btree.nSkip);
}else{
sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
}
sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
| < < < < | < < | < < < < < < < < < | 117388 117389 117390 117391 117392 117393 117394 117395 117396 117397 117398 117399 117400 117401 117402 117403 117404 117405 117406 117407 |
}
if( p->wsFlags & WHERE_SKIPSCAN ){
sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->u.btree.nSkip);
}else{
sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
}
sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
int i;
for(i=0; i<p->nLTerm; i++){
whereTermPrint(p->aLTerm[i], i);
}
}
}
#endif
/*
** Convert bulk memory into a valid WhereLoop that can be passed
** to whereLoopClear harmlessly.
*/
|
| ︙ | ︙ | |||
117505 117506 117507 117508 117509 117510 117511 |
ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
if( ppPrev==0 ){
/* There already exists a WhereLoop on the list that is better
** than pTemplate, so just ignore pTemplate */
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
| | | | | 117706 117707 117708 117709 117710 117711 117712 117713 117714 117715 117716 117717 117718 117719 117720 117721 117722 117723 117724 117725 117726 117727 117728 117729 117730 117731 117732 117733 117734 117735 117736 117737 117738 117739 |
ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
if( ppPrev==0 ){
/* There already exists a WhereLoop on the list that is better
** than pTemplate, so just ignore pTemplate */
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(" skip: ");
whereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
return SQLITE_OK;
}else{
p = *ppPrev;
}
/* If we reach this point it means that either p[] should be overwritten
** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
** WhereLoop and insert it.
*/
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
if( p!=0 ){
sqlite3DebugPrintf("replace: ");
whereLoopPrint(p, pBuilder->pWC);
}
sqlite3DebugPrintf(" add: ");
whereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
if( p==0 ){
/* Allocate a new WhereLoop to add to the end of the list */
*ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
if( p==0 ) return SQLITE_NOMEM;
|
| ︙ | ︙ | |||
117548 117549 117550 117551 117552 117553 117554 |
ppTail = whereLoopFindLesser(ppTail, pTemplate);
if( ppTail==0 ) break;
pToDel = *ppTail;
if( pToDel==0 ) break;
*ppTail = pToDel->pNextLoop;
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
| | | 117749 117750 117751 117752 117753 117754 117755 117756 117757 117758 117759 117760 117761 117762 117763 |
ppTail = whereLoopFindLesser(ppTail, pTemplate);
if( ppTail==0 ) break;
pToDel = *ppTail;
if( pToDel==0 ) break;
*ppTail = pToDel->pNextLoop;
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(" delete: ");
whereLoopPrint(pToDel, pBuilder->pWC);
}
#endif
whereLoopDelete(db, pToDel);
}
}
whereLoopXfer(db, p, pTemplate);
|
| ︙ | ︙ | |||
117712 117713 117714 117715 117716 117717 117718 |
pNew->u.btree.nEq++;
pNew->u.btree.nSkip++;
pNew->aLTerm[pNew->nLTerm++] = 0;
pNew->wsFlags |= WHERE_SKIPSCAN;
nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
if( pTerm ){
/* TUNING: When estimating skip-scan for a term that is also indexable,
| | > > > | 117913 117914 117915 117916 117917 117918 117919 117920 117921 117922 117923 117924 117925 117926 117927 117928 117929 117930 117931 117932 117933 117934 |
pNew->u.btree.nEq++;
pNew->u.btree.nSkip++;
pNew->aLTerm[pNew->nLTerm++] = 0;
pNew->wsFlags |= WHERE_SKIPSCAN;
nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
if( pTerm ){
/* TUNING: When estimating skip-scan for a term that is also indexable,
** multiply the cost of the skip-scan by 2.0, to make it a little less
** desirable than the regular index lookup. */
nIter += 10; assert( 10==sqlite3LogEst(2) );
}
pNew->nOut -= nIter;
/* TUNING: Because uncertainties in the estimates for skip-scan queries,
** add a 1.375 fudge factor to make skip-scan slightly less likely. */
nIter += 5;
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul);
pNew->nOut = saved_nOut;
pNew->u.btree.nEq = saved_nEq;
pNew->u.btree.nSkip = saved_nSkip;
}
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */
|
| ︙ | ︙ | |||
118071 118072 118073 118074 118075 118076 118077 |
if( termCanDriveIndex(pTerm, pSrc, 0) ){
pNew->u.btree.nEq = 1;
pNew->u.btree.nSkip = 0;
pNew->u.btree.pIndex = 0;
pNew->nLTerm = 1;
pNew->aLTerm[0] = pTerm;
/* TUNING: One-time cost for computing the automatic index is
| | | > > > > > | > > > | 118275 118276 118277 118278 118279 118280 118281 118282 118283 118284 118285 118286 118287 118288 118289 118290 118291 118292 118293 118294 118295 118296 118297 118298 118299 |
if( termCanDriveIndex(pTerm, pSrc, 0) ){
pNew->u.btree.nEq = 1;
pNew->u.btree.nSkip = 0;
pNew->u.btree.pIndex = 0;
pNew->nLTerm = 1;
pNew->aLTerm[0] = pTerm;
/* TUNING: One-time cost for computing the automatic index is
** estimated to be X*N*log2(N) where N is the number of rows in
** the table being indexed and where X is 7 (LogEst=28) for normal
** tables or 1.375 (LogEst=4) for views and subqueries. The value
** of X is smaller for views and subqueries so that the query planner
** will be more aggressive about generating automatic indexes for
** those objects, since there is no opportunity to add schema
** indexes on subqueries and views. */
pNew->rSetup = rLogSize + rSize + 4;
if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
pNew->rSetup += 24;
}
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
/* TUNING: Each index lookup yields 20 rows in the table. This
** is more than the usual guess of 10 rows, since we have no way
** of knowing how selective the index will ultimately be. It would
** not be unreasonable to make this value much larger. */
pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
|
| ︙ | ︙ | |||
118361 118362 118363 118364 118365 118366 118367 | int iCur; WhereClause tempWC; WhereLoopBuilder sSubBuild; WhereOrSet sSum, sCur; struct SrcList_item *pItem; pWC = pBuilder->pWC; | < > > > > > > > > > > > > > | 118573 118574 118575 118576 118577 118578 118579 118580 118581 118582 118583 118584 118585 118586 118587 118588 118589 118590 118591 118592 118593 118594 118595 118596 118597 118598 118599 118600 118601 118602 118603 118604 118605 118606 118607 118608 118609 118610 118611 118612 118613 118614 118615 118616 118617 118618 118619 118620 118621 118622 118623 118624 118625 118626 118627 118628 118629 118630 118631 118632 118633 118634 118635 118636 118637 118638 118639 118640 118641 |
int iCur;
WhereClause tempWC;
WhereLoopBuilder sSubBuild;
WhereOrSet sSum, sCur;
struct SrcList_item *pItem;
pWC = pBuilder->pWC;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
memset(&sSum, 0, sizeof(sSum));
pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
WhereTerm *pOrTerm;
int once = 1;
int i, j;
sSubBuild = *pBuilder;
sSubBuild.pOrderBy = 0;
sSubBuild.pOrSet = &sCur;
WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm));
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
if( (pOrTerm->eOperator & WO_AND)!=0 ){
sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
}else if( pOrTerm->leftCursor==iCur ){
tempWC.pWInfo = pWC->pWInfo;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.nTerm = 1;
tempWC.a = pOrTerm;
sSubBuild.pWC = &tempWC;
}else{
continue;
}
sCur.n = 0;
#ifdef WHERETRACE_ENABLED
WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n",
(int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm));
if( sqlite3WhereTrace & 0x400 ){
for(i=0; i<sSubBuild.pWC->nTerm; i++){
whereTermPrint(&sSubBuild.pWC->a[i], i);
}
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
rc = whereLoopAddVirtual(&sSubBuild, mExtra);
}else
#endif
{
rc = whereLoopAddBtree(&sSubBuild, mExtra);
}
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mExtra);
}
assert( rc==SQLITE_OK || sCur.n==0 );
if( sCur.n==0 ){
sSum.n = 0;
break;
}else if( once ){
whereOrMove(&sSum, &sCur);
once = 0;
|
| ︙ | ︙ | |||
118448 118449 118450 118451 118452 118453 118454 118455 118456 118457 118458 118459 118460 118461 |
** the planner may elect to "OR" together a full-table scan and an
** index lookup. And other similarly odd results. */
pNew->rRun = sSum.a[i].rRun + 1;
pNew->nOut = sSum.a[i].nOut;
pNew->prereq = sSum.a[i].prereq;
rc = whereLoopInsert(pBuilder, pNew);
}
}
}
return rc;
}
/*
** Add all WhereLoop objects for all tables
| > | 118672 118673 118674 118675 118676 118677 118678 118679 118680 118681 118682 118683 118684 118685 118686 |
** the planner may elect to "OR" together a full-table scan and an
** index lookup. And other similarly odd results. */
pNew->rRun = sSum.a[i].rRun + 1;
pNew->nOut = sSum.a[i].nOut;
pNew->prereq = sSum.a[i].prereq;
rc = whereLoopInsert(pBuilder, pNew);
}
WHERETRACE(0x200, ("End processing OR-clause %p\n", pTerm));
}
}
return rc;
}
/*
** Add all WhereLoop objects for all tables
|
| ︙ | ︙ | |||
118691 118692 118693 118694 118695 118696 118697 |
pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
if( !pColl ) pColl = db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
}
isMatch = 1;
break;
}
| | | 118916 118917 118918 118919 118920 118921 118922 118923 118924 118925 118926 118927 118928 118929 118930 |
pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
if( !pColl ) pColl = db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
}
isMatch = 1;
break;
}
if( isMatch && (wctrlFlags & WHERE_GROUPBY)==0 ){
/* Make sure the sort order is compatible in an ORDER BY clause.
** Sort order is irrelevant for a GROUP BY clause. */
if( revSet ){
if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0;
}else{
rev = revIdx ^ pOrderBy->a[i].sortOrder;
if( rev ) *pRevMask |= MASKBIT(iLoop);
|
| ︙ | ︙ | |||
119156 119157 119158 119159 119160 119161 119162 |
pWInfo->nOBSat = pFrom->isOrdered;
if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
pWInfo->revMask = pFrom->revLoop;
}
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
){
| | | > | > > | 119381 119382 119383 119384 119385 119386 119387 119388 119389 119390 119391 119392 119393 119394 119395 119396 119397 119398 119399 119400 119401 119402 119403 |
pWInfo->nOBSat = pFrom->isOrdered;
if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
pWInfo->revMask = pFrom->revLoop;
}
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
){
Bitmask revMask = 0;
int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy,
pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], &revMask
);
assert( pWInfo->sorted==0 );
if( nOrder==pWInfo->pOrderBy->nExpr ){
pWInfo->sorted = 1;
pWInfo->revMask = revMask;
}
}
}
pWInfo->nRowOut = pFrom->nRow;
/* Free temporary memory and return success */
|
| ︙ | ︙ | |||
119514 119515 119516 119517 119518 119519 119520 119521 |
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
pWInfo->pOrderBy = pResultSet;
}
}
/* Construct the WhereLoop objects */
WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
/* Display all terms of the WHERE clause */
| > < < < < < | < < < < > | 119742 119743 119744 119745 119746 119747 119748 119749 119750 119751 119752 119753 119754 119755 119756 119757 119758 119759 119760 119761 119762 119763 119764 119765 |
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
pWInfo->pOrderBy = pResultSet;
}
}
/* Construct the WhereLoop objects */
WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
#if defined(WHERETRACE_ENABLED)
/* Display all terms of the WHERE clause */
if( sqlite3WhereTrace & 0x100 ){
int i;
for(i=0; i<sWLB.pWC->nTerm; i++){
whereTermPrint(&sWLB.pWC->a[i], i);
}
}
#endif
if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
rc = whereLoopAddAll(&sWLB);
if( rc ) goto whereBeginError;
/* Display all of the WhereLoop objects if wheretrace is enabled */
#ifdef WHERETRACE_ENABLED /* !=0 */
if( sqlite3WhereTrace ){
|
| ︙ | ︙ | |||
120057 120058 120059 120060 120061 120062 120063 |
pOut->zEnd = &pPostOp->z[pPostOp->n];
}
/* A routine to convert a binary TK_IS or TK_ISNOT expression into a
** unary TK_ISNULL or TK_NOTNULL expression. */
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
sqlite3 *db = pParse->db;
| | | 120278 120279 120280 120281 120282 120283 120284 120285 120286 120287 120288 120289 120290 120291 120292 |
pOut->zEnd = &pPostOp->z[pPostOp->n];
}
/* A routine to convert a binary TK_IS or TK_ISNOT expression into a
** unary TK_ISNULL or TK_NOTNULL expression. */
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
sqlite3 *db = pParse->db;
if( pY && pA && pY->op==TK_NULL ){
pA->op = (u8)op;
sqlite3ExprDelete(db, pA->pRight);
pA->pRight = 0;
}
}
/* Construct an expression node for a unary prefix operator
|
| ︙ | ︙ | |||
122316 122317 122318 122319 122320 122321 122322 |
sqlite3DropTable(pParse, yymsp[0].minor.yy65, 1, yymsp[-1].minor.yy328);
}
break;
case 111: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
sqlite3Select(pParse, yymsp[0].minor.yy3, &dest);
| < < < | 122537 122538 122539 122540 122541 122542 122543 122544 122545 122546 122547 122548 122549 122550 |
sqlite3DropTable(pParse, yymsp[0].minor.yy65, 1, yymsp[-1].minor.yy328);
}
break;
case 111: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
sqlite3Select(pParse, yymsp[0].minor.yy3, &dest);
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy3);
}
break;
case 112: /* select ::= with selectnowith */
{
Select *p = yymsp[0].minor.yy3, *pNext, *pLoop;
if( p ){
|
| ︙ | ︙ | |||
122375 122376 122377 122378 122379 122380 122381 122382 122383 122384 122385 122386 122387 122388 |
break;
case 116: /* multiselect_op ::= UNION ALL */
{yygotominor.yy328 = TK_ALL;}
break;
case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy65,yymsp[-4].minor.yy132,yymsp[-3].minor.yy14,yymsp[-2].minor.yy132,yymsp[-1].minor.yy14,yymsp[-7].minor.yy381,yymsp[0].minor.yy476.pLimit,yymsp[0].minor.yy476.pOffset);
}
break;
case 120: /* values ::= VALUES LP nexprlist RP */
{
yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0);
}
break;
| > > > > > > > > > > > > > > > > > > > > > > > > | 122593 122594 122595 122596 122597 122598 122599 122600 122601 122602 122603 122604 122605 122606 122607 122608 122609 122610 122611 122612 122613 122614 122615 122616 122617 122618 122619 122620 122621 122622 122623 122624 122625 122626 122627 122628 122629 122630 |
break;
case 116: /* multiselect_op ::= UNION ALL */
{yygotominor.yy328 = TK_ALL;}
break;
case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy65,yymsp[-4].minor.yy132,yymsp[-3].minor.yy14,yymsp[-2].minor.yy132,yymsp[-1].minor.yy14,yymsp[-7].minor.yy381,yymsp[0].minor.yy476.pLimit,yymsp[0].minor.yy476.pOffset);
#if SELECTTRACE_ENABLED
/* Populate the Select.zSelName[] string that is used to help with
** query planner debugging, to differentiate between multiple Select
** objects in a complex query.
**
** If the SELECT keyword is immediately followed by a C-style comment
** then extract the first few alphanumeric characters from within that
** comment to be the zSelName value. Otherwise, the label is #N where
** is an integer that is incremented with each SELECT statement seen.
*/
if( yygotominor.yy3!=0 ){
const char *z = yymsp[-8].minor.yy0.z+6;
int i;
sqlite3_snprintf(sizeof(yygotominor.yy3->zSelName), yygotominor.yy3->zSelName, "#%d",
++pParse->nSelect);
while( z[0]==' ' ) z++;
if( z[0]=='/' && z[1]=='*' ){
z += 2;
while( z[0]==' ' ) z++;
for(i=0; sqlite3Isalnum(z[i]); i++){}
sqlite3_snprintf(sizeof(yygotominor.yy3->zSelName), yygotominor.yy3->zSelName, "%.*s", i, z);
}
}
#endif /* SELECTRACE_ENABLED */
}
break;
case 120: /* values ::= VALUES LP nexprlist RP */
{
yygotominor.yy3 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0);
}
break;
|
| ︙ | ︙ | |||
123866 123867 123868 123869 123870 123871 123872 123873 123874 123875 123876 123877 123878 123879 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */
};
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
/*
** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
| > | 124108 124109 124110 124111 124112 124113 124114 124115 124116 124117 124118 124119 124120 124121 124122 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */
};
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); }
/*
** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
| ︙ | ︙ | |||
125136 125137 125138 125139 125140 125141 125142 125143 125144 125145 125146 125147 125148 125149 |
*/
typedef void(*LOGFUNC_t)(void*,int,const char*);
sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
break;
}
case SQLITE_CONFIG_URI: {
sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
| > > > > > | 125379 125380 125381 125382 125383 125384 125385 125386 125387 125388 125389 125390 125391 125392 125393 125394 125395 125396 125397 |
*/
typedef void(*LOGFUNC_t)(void*,int,const char*);
sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
break;
}
/* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames
** can be changed at start-time using the
** sqlite3_config(SQLITE_CONFIG_URI,1) or
** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls.
*/
case SQLITE_CONFIG_URI: {
sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
|
| ︙ | ︙ | |||
126873 126874 126875 126876 126877 126878 126879 | char *zFile; char c; int nUri = sqlite3Strlen30(zUri); assert( *pzErrMsg==0 ); if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri) | | | 127121 127122 127123 127124 127125 127126 127127 127128 127129 127130 127131 127132 127133 127134 127135 |
char *zFile;
char c;
int nUri = sqlite3Strlen30(zUri);
assert( *pzErrMsg==0 );
if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
&& nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */
){
char *zOpt;
int eState; /* Parser state when parsing URI */
int iIn; /* Input character index */
int iOut = 0; /* Output character index */
int nByte = nUri+2; /* Bytes of space to allocate */
|
| ︙ | ︙ | |||
127103 127104 127105 127106 127107 127108 127109 | */ assert( SQLITE_OPEN_READONLY == 0x01 ); assert( SQLITE_OPEN_READWRITE == 0x02 ); assert( SQLITE_OPEN_CREATE == 0x04 ); testcase( (1<<(flags&7))==0x02 ); /* READONLY */ testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ | | > > | 127351 127352 127353 127354 127355 127356 127357 127358 127359 127360 127361 127362 127363 127364 127365 127366 127367 |
*/
assert( SQLITE_OPEN_READONLY == 0x01 );
assert( SQLITE_OPEN_READWRITE == 0x02 );
assert( SQLITE_OPEN_CREATE == 0x04 );
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
if( ((1<<(flags&7)) & 0x46)==0 ){
return SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
}
if( sqlite3GlobalConfig.bCoreMutex==0 ){
isThreadsafe = 0;
}else if( flags & SQLITE_OPEN_NOMUTEX ){
isThreadsafe = 0;
}else if( flags & SQLITE_OPEN_FULLMUTEX ){
isThreadsafe = 1;
|
| ︙ | ︙ | |||
127987 127988 127989 127990 127991 127992 127993 |
** undo this setting.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
break;
}
| < < < < < < < < < < < < < < < < | 128237 128238 128239 128240 128241 128242 128243 128244 128245 128246 128247 128248 128249 128250 |
** undo this setting.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
**
** Set or clear a flag that indicates that the database file is always well-
** formed and never corrupt. This flag is clear by default, indicating that
** database files might have arbitrary corruption. Setting the flag during
** testing causes certain assert() statements in the code to be activated
** that demonstrat invariants on well-formed database files.
|
| ︙ | ︙ | |||
132462 132463 132464 132465 132466 132467 132468 132469 132470 132471 132472 132473 132474 132475 | if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; assert( iIdx==nVal ); /* In case the cursor has been used before, clear it now. */ sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr->aDoclist); sqlite3Fts3ExprFree(pCsr->pExpr); memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); /* Set the lower and upper bounds on docids to return */ pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); | > | 132696 132697 132698 132699 132700 132701 132702 132703 132704 132705 132706 132707 132708 132709 132710 | if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; assert( iIdx==nVal ); /* In case the cursor has been used before, clear it now. */ sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr->aDoclist); sqlite3_free(pCsr->aMatchinfo); sqlite3Fts3ExprFree(pCsr->pExpr); memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); /* Set the lower and upper bounds on docids to return */ pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64); |
| ︙ | ︙ | |||
133772 133773 133774 133775 133776 133777 133778 |
for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
iMax = a[i].iDocid;
bMaxSet = 1;
}
}
| | | 134007 134008 134009 134010 134011 134012 134013 134014 134015 134016 134017 134018 134019 134020 134021 |
for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
iMax = a[i].iDocid;
bMaxSet = 1;
}
}
assert( rc!=SQLITE_OK || (p->nToken>=1 && a[p->nToken-1].bIgnore==0) );
assert( rc!=SQLITE_OK || bMaxSet );
/* Keep advancing iterators until they all point to the same document */
for(i=0; i<p->nToken; i++){
while( rc==SQLITE_OK && bEof==0
&& a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
){
|
| ︙ | ︙ | |||
135889 135890 135891 135892 135893 135894 135895 |
sqlite3_tokenizer_cursor *pCursor;
Fts3Expr *pRet = 0;
int i = 0;
/* Set variable i to the maximum number of bytes of input to tokenize. */
for(i=0; i<n; i++){
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
| | | 136124 136125 136126 136127 136128 136129 136130 136131 136132 136133 136134 136135 136136 136137 136138 |
sqlite3_tokenizer_cursor *pCursor;
Fts3Expr *pRet = 0;
int i = 0;
/* Set variable i to the maximum number of bytes of input to tokenize. */
for(i=0; i<n; i++){
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
if( z[i]=='"' ) break;
}
*pnConsumed = i;
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
|
| ︙ | ︙ |
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.7" #define SQLITE_VERSION_NUMBER 3008007 | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.7" #define SQLITE_VERSION_NUMBER 3008007 #define SQLITE_SOURCE_ID "2014-10-17 11:24:17 e4ab094f8afce0817f4074e823fabe59fc29ebb4" /* ** 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 |
| ︙ | ︙ | |||
2665 2666 2667 2668 2669 2670 2671 | ** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] ** object.)^ ^(If the database is opened (and/or created) successfully, then ** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The ** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain ** an English language description of the error following a failure of any ** of the sqlite3_open() routines. ** | | | | | 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 | ** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] ** object.)^ ^(If the database is opened (and/or created) successfully, then ** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The ** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain ** an English language description of the error following a failure of any ** of the sqlite3_open() routines. ** ** ^The default encoding will be UTF-8 for databases created using ** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases ** created using sqlite3_open16() will be UTF-16 in the native byte order. ** ** 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 |
| ︙ | ︙ | |||
2755 2756 2757 2758 2759 2760 2761 | ** present, is ignored. ** ** ^SQLite uses the path component of the URI as the name of the disk file ** which contains the database. ^If the path begins with a '/' character, ** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) ** then the path is interpreted as a relative path. | | | > | | 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 | ** present, is ignored. ** ** ^SQLite uses the path component of the URI as the name of the disk file ** which contains the database. ^If the path begins with a '/' character, ** then it is interpreted as an absolute path. ^If the path does not begin ** with a '/' (meaning that the authority section is omitted from the URI) ** then the path is interpreted as a relative path. ** ^(On windows, the first component of an absolute path ** is a drive specification (e.g. "C:").)^ ** ** [[core URI query parameters]] ** The query component of a URI may contain parameters that are interpreted ** either by SQLite itself, or by a [VFS | custom VFS implementation]. ** SQLite and its built-in [VFSes] interpret the ** following query parameters: ** ** <ul> ** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of ** a VFS object that provides the operating system interface that should ** be used to access the database file on disk. ^If this option is set to ** an empty string the default VFS object is used. ^Specifying an unknown ** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is |
| ︙ | ︙ | |||
2796 2797 2798 2799 2800 2801 2802 | ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** | | < | < | 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 | ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** ** <li> <b>psow</b>: ^The psow parameter indicates whether or not the ** [powersafe overwrite] property does or does not apply to the ** storage media on which the database file resides. ** ** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter ** which if set disables file locking in rollback journal modes. This ** is useful for accessing a database on a filesystem that does not ** support locking. Caution: Database corruption might result if two ** or more processes write to the same database and any one of those ** processes uses nolock=1. |
| ︙ | ︙ | |||
3395 3396 3397 3398 3399 3400 3401 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occur at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** | | | | < | | 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occur at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces ** is a destructor used to dispose of the BLOB or ** string after SQLite has finished with it. ^The destructor is called ** to dispose of the BLOB or string even if the call to bind API fails. ** ^If the fifth argument is ** the special value [SQLITE_STATIC], then SQLite assumes that the ** information is in static, unmanaged space and does not need to be freed. ** ^If the fifth argument has the value [SQLITE_TRANSIENT], then ** SQLite makes its own private copy of the data immediately, before ** the sqlite3_bind_*() routine returns. ** ** ^The sixth argument to sqlite3_bind_text64() must be one of ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] ** to specify the encoding of the text in the third parameter. If ** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior ** is undefined. ** ** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that ** is filled with zeroes. ^A zeroblob uses a fixed amount of memory ** (just an integer to hold its size) while it is being processed. |
| ︙ | ︙ | |||
4446 4447 4448 4449 4450 4451 4452 | ** of the application-defined function to be the 64-bit signed integer ** value given in the 2nd argument. ** ** ^The sqlite3_result_null() interface sets the return value ** of the application-defined function to be NULL. ** ** ^The sqlite3_result_text(), sqlite3_result_text16(), | | | 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 | ** of the application-defined function to be the 64-bit signed integer ** value given in the 2nd argument. ** ** ^The sqlite3_result_null() interface sets the return value ** of the application-defined function to be NULL. ** ** ^The sqlite3_result_text(), sqlite3_result_text16(), ** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. ** ^The sqlite3_result_text64() interface sets the return value of an ** application-defined function to be a text string in an encoding ** specified by the fifth (and last) parameter, which must be one ** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. |
| ︙ | ︙ | |||
6206 6207 6208 6209 6210 6211 6212 | #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 | | | 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 | #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_LAST 24 |
| ︙ | ︙ |
Changes to src/stash.c.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 | #include <assert.h> /* ** SQL code to implement the tables needed by the stash. */ static const char zStashInit[] = | | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #include <assert.h> /* ** SQL code to implement the tables needed by the stash. */ static const char zStashInit[] = @ CREATE TABLE IF NOT EXISTS "%w".stash( @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier @ vid INTEGER, -- The baseline check-out for this stash @ comment TEXT, -- Comment for this stash. Or NULL @ ctime TIMESTAMP -- When the stash was created @ ); @ CREATE TABLE IF NOT EXISTS "%w".stashfile( @ stashid INTEGER REFERENCES stash, -- Stash that contains this file @ rid INTEGER, -- Baseline content in BLOB table or 0. @ isAdded BOOLEAN, -- True if this is an added file @ isRemoved BOOLEAN, -- True if this file is deleted @ isExec BOOLEAN, -- True if file is executable @ isLink BOOLEAN, -- True if file is a symlink @ origname TEXT, -- Original filename |
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
Stmt q; /* Query against the vfile table */
Stmt ins; /* Insert statement */
zFile = mprintf("%/", zFName);
file_tree_name(zFile, &fname, 1);
zTreename = blob_str(&fname);
blob_zero(&sql);
| | | | | 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 |
Stmt q; /* Query against the vfile table */
Stmt ins; /* Insert statement */
zFile = mprintf("%/", zFName);
file_tree_name(zFile, &fname, 1);
zTreename = blob_str(&fname);
blob_zero(&sql);
blob_append_sql(&sql,
"SELECT deleted, isexe, islink, mrid, pathname, coalesce(origname,pathname)"
" FROM vfile"
" WHERE vid=%d AND (chnged OR deleted OR origname NOT NULL OR mrid==0)",
vid
);
if( fossil_strcmp(zTreename,".")!=0 ){
blob_append_sql(&sql,
" AND (pathname GLOB '%q/*' OR origname GLOB '%q/*'"
" OR pathname=%Q OR origname=%Q)",
zTreename, zTreename, zTreename, zTreename
);
}
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
db_prepare(&ins,
"INSERT INTO stashfile(stashid, rid, isAdded, isRemoved, isExec, isLink,"
"origname, newname, delta)"
"VALUES(%d,:rid,:isadd,:isrm,:isexe,:islink,:orig,:new,:content)",
stashid
);
|
| ︙ | ︙ | |||
479 480 481 482 483 484 485 |
int nCmd;
int stashid = 0;
undo_capture_command_line();
db_must_be_within_tree();
db_open_config(0);
db_begin_transaction();
zDb = db_name("localdb");
| | | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 |
int nCmd;
int stashid = 0;
undo_capture_command_line();
db_must_be_within_tree();
db_open_config(0);
db_begin_transaction();
zDb = db_name("localdb");
db_multi_exec(zStashInit /*works-like:"%w,%w"*/, zDb, zDb);
if( g.argc<=2 ){
zCmd = "save";
}else{
zCmd = g.argv[2];
}
nCmd = strlen(zCmd);
if( memcmp(zCmd, "save", nCmd)==0 ){
|
| ︙ | ︙ | |||
532 533 534 535 536 537 538 |
if( !verboseFlag ){
verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
}
verify_all_options();
db_prepare(&q,
"SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"
" comment, datetime(ctime) FROM stash"
| | | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 |
if( !verboseFlag ){
verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
}
verify_all_options();
db_prepare(&q,
"SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"
" comment, datetime(ctime) FROM stash"
" ORDER BY ctime"
);
if( verboseFlag ){
db_prepare(&q2, "SELECT isAdded, isRemoved, origname, newname"
" FROM stashfile WHERE stashid=$id");
}
while( db_step(&q)==SQLITE_ROW ){
int stashid = db_column_int(&q, 0);
|
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
135 136 137 138 139 140 141 |
@ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid())
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
@ <tr><th>Repository Rebuilt:</th><td>
@ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
@ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
@ <tr><th>Database Stats:</th><td>
zDb = db_name("repository");
| | | | | | | < < | > > > > > | > > > > > > > | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
@ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid())
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
@ <tr><th>Repository Rebuilt:</th><td>
@ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
@ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
@ <tr><th>Database Stats:</th><td>
zDb = db_name("repository");
@ %d(db_int(0, "PRAGMA \"%w\".page_count", zDb)) pages,
@ %d(db_int(0, "PRAGMA \"%w\".page_size", zDb)) bytes/page,
@ %d(db_int(0, "PRAGMA \"%w\".freelist_count", zDb)) free pages,
@ %s(db_text(0, "PRAGMA \"%w\".encoding", zDb)),
@ %s(db_text(0, "PRAGMA \"%w\".journal_mode", zDb)) mode
@ </td></tr>
@ </table>
style_footer();
}
/*
** COMMAND: dbstat*
**
** Usage: %fossil dbstat OPTIONS
**
** Shows statistics and global information about the repository.
**
** Options:
**
** --brief|-b Only show essential elements
** --db-check Run a PRAGMA quick_check on the repository database
** --omit-version-info Omit the SQLite and Fossil version information
*/
void dbstat_cmd(void){
i64 t, fsize;
int n, m;
int szMax, szAvg;
const char *zDb;
int brief;
int omitVers; /* Omit Fossil and SQLite version information */
int dbCheck; /* True for the --db-check option */
char zBuf[100];
const int colWidth = -19 /* printf alignment/width for left column */;
const char *p, *z;
brief = find_option("brief", "b",0)!=0;
omitVers = find_option("omit-version-info", 0, 0)!=0;
dbCheck = find_option("db-check",0,0)!=0;
db_find_and_open_repository(0,0);
/* We should be done with options.. */
verify_all_options();
if( (z = db_get("project-name",0))!=0
|| (z = db_get("short-project-name",0))!=0
){
fossil_print("%*s%s\n", colWidth, "project-name:", z);
}
fsize = file_size(g.zRepositoryName);
bigSizeName(sizeof(zBuf), zBuf, fsize);
fossil_print( "%*s%s\n", colWidth, "repository-size:", zBuf );
if( !brief ){
n = db_int(0, "SELECT count(*) FROM blob");
m = db_int(0, "SELECT count(*) FROM delta");
fossil_print("%*s%d (stored as %d full text and %d delta blobs)\n",
|
| ︙ | ︙ | |||
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
" WHERE tagname GLOB 'tkt-*'");
m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'");
fossil_print("%*s%d (%d changes)\n", colWidth, "tickets:", n, m);
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'");
fossil_print("%*s%d\n", colWidth, "events:", n);
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
fossil_print("%*s%d\n", colWidth, "tagchanges:", n);
}
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
" + 0.99");
fossil_print("%*s%d days or approximately %.2f years.\n",
colWidth, "project-age:", n, n/365.2425);
p = db_get("project-code", 0);
if( p ){
fossil_print("%*s%s\n", colWidth, "project-id:", p);
}
fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code", 0));
| > > > > > > > > > | | | | | | | | > | | | | > > > | | | 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 |
" WHERE tagname GLOB 'tkt-*'");
m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'");
fossil_print("%*s%d (%d changes)\n", colWidth, "tickets:", n, m);
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'");
fossil_print("%*s%d\n", colWidth, "events:", n);
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
fossil_print("%*s%d\n", colWidth, "tagchanges:", n);
z = db_text(0, "SELECT datetime(mtime) || ' - about ' ||"
" CAST(julianday('now') - mtime AS INTEGER)"
" || ' days ago' FROM event "
" ORDER BY mtime DESC LIMIT 1");
fossil_print("%*s%s\n", colWidth, "latest-change:", z);
}
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
" + 0.99");
fossil_print("%*s%d days or approximately %.2f years.\n",
colWidth, "project-age:", n, n/365.2425);
p = db_get("project-code", 0);
if( p ){
fossil_print("%*s%s\n", colWidth, "project-id:", p);
}
#if 0
/* Server-id is not useful information any more */
fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code", 0));
#endif
if( !omitVers ){
fossil_print("%*s%s %s [%s] (%s)\n",
colWidth, "fossil-version:",
MANIFEST_DATE, MANIFEST_VERSION, RELEASE_VERSION,
COMPILER_NAME);
fossil_print("%*s%.19s [%.10s] (%s)\n",
colWidth, "sqlite-version:",
sqlite3_sourceid(), &sqlite3_sourceid()[20],
sqlite3_libversion());
}
zDb = db_name("repository");
fossil_print("%*s%d pages, %d bytes/pg, %d free pages, "
"%s, %s mode\n",
colWidth, "database-stats:",
db_int(0, "PRAGMA \"%w\".page_count", zDb),
db_int(0, "PRAGMA \"%w\".page_size", zDb),
db_int(0, "PRAGMA \"%w\".freelist_count", zDb),
db_text(0, "PRAGMA \"%w\".encoding", zDb),
db_text(0, "PRAGMA \"%w\".journal_mode", zDb));
if( dbCheck ){
fossil_print("%*s%s\n", colWidth, "database-check:",
db_text(0, "PRAGMA quick_check(1)"));
}
}
/*
** WEBPAGE: urllist
**
** Show ways in which this repository has been accessed
*/
|
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
173 174 175 176 177 178 179 |
@ gebi("a%d(i+1)").href="%s(aHref[i])";
}
}
for(i=0; i<nFormAction; i++){
@ gebi("form%d(i+1)").action="%s(aFormAction[i])";
}
@ }
| | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
@ gebi("a%d(i+1)").href="%s(aHref[i])";
}
}
for(i=0; i<nFormAction; i++){
@ gebi("form%d(i+1)").action="%s(aFormAction[i])";
}
@ }
if( sqlite3_strglob("*Opera Mini/[1-9]*", P("HTTP_USER_AGENT"))==0 ){
/* Special case for Opera Mini, which executes JS server-side */
@ var isOperaMini = Object.prototype.toString.call(window.operamini)
@ === "[object OperaMini]";
@ if( isOperaMini ){
@ setTimeout("setAllHrefs();",%d(nDelay));
@ }
}else if( db_get_boolean("auto-hyperlink-mouseover",0) ){
|
| ︙ | ︙ | |||
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 |
@ text-align: right;
@ vertical-align: top;
@ white-space: nowrap;
},
{ "span.ueditInheritNobody",
"color for capabilities, inherited by nobody",
@ color: green;
},
{ "span.ueditInheritDeveloper",
"color for capabilities, inherited by developer",
@ color: red;
},
{ "span.ueditInheritReader",
"color for capabilities, inherited by reader",
@ color: black;
},
{ "span.ueditInheritAnonymous",
"color for capabilities, inherited by anonymous",
@ color: blue;
},
{ "span.capability",
"format for capabilities, mentioned on the user edit page",
@ font-weight: bold;
},
{ "span.usertype",
"format for different user types, mentioned on the user edit page",
| > > > > | 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 |
@ text-align: right;
@ vertical-align: top;
@ white-space: nowrap;
},
{ "span.ueditInheritNobody",
"color for capabilities, inherited by nobody",
@ color: green;
@ padding: .2em;
},
{ "span.ueditInheritDeveloper",
"color for capabilities, inherited by developer",
@ color: red;
@ padding: .2em;
},
{ "span.ueditInheritReader",
"color for capabilities, inherited by reader",
@ color: black;
@ padding: .2em;
},
{ "span.ueditInheritAnonymous",
"color for capabilities, inherited by anonymous",
@ color: blue;
@ padding: .2em;
},
{ "span.capability",
"format for capabilities, mentioned on the user edit page",
@ font-weight: bold;
},
{ "span.usertype",
"format for different user types, mentioned on the user edit page",
|
| ︙ | ︙ | |||
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 |
{ "tr.row0",
"even table row color",
@ /* use default */
},
{ "tr.row1",
"odd table row color",
@ /* Use default */
},
{ "#canvas", "timeline graph node colors",
@ color: black;
@ background-color: white;
},
{ 0,
0,
| > > > > | 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 |
{ "tr.row0",
"even table row color",
@ /* use default */
},
{ "tr.row1",
"odd table row color",
@ /* Use default */
},
{ "#usetupEditCapability",
"format for capabilities string, mentioned on the user edit page",
@ font-weight: bold;
},
{ "#canvas", "timeline graph node colors",
@ color: black;
@ background-color: white;
},
{ 0,
0,
|
| ︙ | ︙ |
Changes to src/tag.c.
| ︙ | ︙ | |||
211 212 213 214 215 216 217 |
db_multi_exec(
"INSERT OR IGNORE INTO private(rid) VALUES(%d);",
rid
);
}
}
if( zCol ){
| | > | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
db_multi_exec(
"INSERT OR IGNORE INTO private(rid) VALUES(%d);",
rid
);
}
}
if( zCol ){
db_multi_exec("UPDATE event SET \"%w\"=%Q WHERE objid=%d",
zCol, zValue, rid);
if( tagid==TAG_COMMENT ){
char *zCopy = mprintf("%s", zValue);
wiki_extract_links(zCopy, rid, 0, mtime, 1, WIKI_INLINE);
free(zCopy);
}
}
if( tagid==TAG_DATE ){
|
| ︙ | ︙ | |||
435 436 437 438 439 440 441 |
const char *zType = find_option("type","t",1);
Blob sql = empty_blob;
if( zType==0 || zType[0]==0 ) zType = "*";
if( g.argc!=4 ){
usage("find ?--raw? ?-t|--type TYPE? ?-n|--limit #? TAGNAME");
}
if( fRaw ){
| | | | | | | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
const char *zType = find_option("type","t",1);
Blob sql = empty_blob;
if( zType==0 || zType[0]==0 ) zType = "*";
if( g.argc!=4 ){
usage("find ?--raw? ?-t|--type TYPE? ?-n|--limit #? TAGNAME");
}
if( fRaw ){
blob_append_sql(&sql,
"SELECT blob.uuid FROM tagxref, blob"
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
" AND tagxref.tagtype>0"
" AND blob.rid=tagxref.rid",
g.argv[3]
);
if( nFindLimit>0 ){
blob_append_sql(&sql, " LIMIT %d", nFindLimit);
}
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%s\n", db_column_text(&q, 0));
}
db_finalize(&q);
}else{
int tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",
g.argv[3]);
if( tagid>0 ){
blob_append_sql(&sql,
"%s"
" AND event.type GLOB '%q'"
" AND blob.rid IN ("
" SELECT rid FROM tagxref"
" WHERE tagtype>0 AND tagid=%d"
")"
" ORDER BY event.mtime DESC",
timeline_query_for_tty(), zType, tagid
);
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
print_timeline(&q, nFindLimit, 79, 0);
db_finalize(&q);
}
}
}else
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
391 392 393 394 395 396 397 |
** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
wiki_convert(&comment, 0, WIKI_INLINE);
}else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
Blob truncated;
blob_zero(&truncated);
blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
blob_append(&truncated, "...", 3);
| | | | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
wiki_convert(&comment, 0, WIKI_INLINE);
}else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
Blob truncated;
blob_zero(&truncated);
blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
blob_append(&truncated, "...", 3);
@ <span class="timelineComment">%W(blob_str(&truncated))</span>
blob_reset(&truncated);
}else{
@ <span class="timelineComment">%W(blob_str(&comment))</span>
}
blob_reset(&comment);
/* Generate the "user: USERNAME" at the end of the comment, together
** with a hyperlink to another timeline for that user.
*/
if( zTagList && zTagList[0]==0 ) zTagList = 0;
|
| ︙ | ︙ | |||
858 859 860 861 862 863 864 |
@ etype TEXT,
@ taglist TEXT,
@ tagid INTEGER,
@ short TEXT,
@ sortby REAL
@ )
;
| | | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 |
@ etype TEXT,
@ taglist TEXT,
@ tagid INTEGER,
@ short TEXT,
@ sortby REAL
@ )
;
db_multi_exec("%s", zSql/*safe-for-%s*/);
}
/*
** Return a pointer to a constant string that forms the basis
** for a timeline query for the WWW interface.
*/
const char *timeline_query_for_www(void){
|
| ︙ | ︙ | |||
887 888 889 890 891 892 893 |
@ tagid AS tagid,
@ brief AS brief,
@ event.mtime AS mtime
@ FROM event CROSS JOIN blob
@ WHERE blob.rid=event.objid
;
if( zBase==0 ){
| | | 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 |
@ tagid AS tagid,
@ brief AS brief,
@ event.mtime AS mtime
@ FROM event CROSS JOIN blob
@ WHERE blob.rid=event.objid
;
if( zBase==0 ){
zBase = mprintf(zBaseSql /*works-like: "%s"*/, timeline_utc());
}
return zBase;
}
/*
** Generate a submenu element with a single parameter change.
*/
|
| ︙ | ︙ | |||
963 964 965 966 967 968 969 |
*/
char *names_of_file(const char *zUuid){
Stmt q;
Blob out;
const char *zSep = "";
db_prepare(&q,
"SELECT DISTINCT filename.name FROM mlink, filename"
| | | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 |
*/
char *names_of_file(const char *zUuid){
Stmt q;
Blob out;
const char *zSep = "";
db_prepare(&q,
"SELECT DISTINCT filename.name FROM mlink, filename"
" WHERE mlink.fid=(SELECT rid FROM blob WHERE uuid=%Q)"
" AND filename.fnid=mlink.fnid",
zUuid
);
blob_zero(&out);
while( db_step(&q)==SQLITE_ROW ){
const char *zFN = db_column_text(&q, 0);
blob_appendf(&out, "%s%z%h</a>", zSep,
|
| ︙ | ︙ | |||
1127 1128 1129 1130 1131 1132 1133 |
blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
blob_append(&sql, timeline_query_for_www(), -1);
if( P("fc")!=0 || P("v")!=0 || P("detail")!=0 ){
tmFlags |= TIMELINE_FCHANGES;
url_add_parameter(&url, "v", 0);
}
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
| > | | | > | 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 |
blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
blob_append(&sql, timeline_query_for_www(), -1);
if( P("fc")!=0 || P("v")!=0 || P("detail")!=0 ){
tmFlags |= TIMELINE_FCHANGES;
url_add_parameter(&url, "v", 0);
}
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
blob_append_sql(&sql,
" AND NOT EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)",
TAG_HIDDEN
);
}
if( !useDividers ) url_add_parameter(&url, "nd", 0);
if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
/* If from= and to= are present, display all nodes on a path connecting
** the two */
PathNode *p = 0;
const char *zFrom = 0;
|
| ︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 |
p = path_first();
}
zFrom = P("me");
zTo = P("you");
}
blob_append(&sql, " AND event.objid IN (0", -1);
while( p ){
| | | | | | | 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 |
p = path_first();
}
zFrom = P("me");
zTo = P("you");
}
blob_append(&sql, " AND event.objid IN (0", -1);
while( p ){
blob_append_sql(&sql, ",%d", p->rid);
p = p->u.pTo;
}
blob_append(&sql, ")", -1);
path_reset();
blob_append(&desc, "All nodes on the path from ", -1);
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
blob_append(&desc, " to ", -1);
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
tmFlags |= TIMELINE_DISJOINT;
db_multi_exec("%s", blob_sql_text(&sql));
}else if( (p_rid || d_rid) && g.perm.Read ){
/* If p= or d= is present, ignore all other parameters other than n= */
char *zUuid;
int np, nd;
if( p_rid && d_rid ){
if( p_rid!=d_rid ) p_rid = d_rid;
if( P("n")==0 ) nEntry = 10;
}
db_multi_exec(
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY)"
);
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d",
p_rid ? p_rid : d_rid);
blob_append_sql(&sql, " AND event.objid IN ok");
nd = 0;
if( d_rid ){
compute_descendants(d_rid, nEntry+1);
nd = db_int(0, "SELECT count(*)-1 FROM ok");
if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql));
if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
if( useDividers ) timeline_add_dividers(0, d_rid);
db_multi_exec("DELETE FROM ok");
}
if( p_rid ){
compute_ancestors(p_rid, nEntry+1, 0);
np = db_int(0, "SELECT count(*)-1 FROM ok");
if( np>0 ){
if( nd>0 ) blob_appendf(&desc, " and ");
blob_appendf(&desc, "%d ancestors", np);
db_multi_exec("%s", blob_sql_text(&sql));
}
if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
}
blob_appendf(&desc, " of %z[%S]</a>",
href("%R/info/%s", zUuid), zUuid);
if( p_rid ){
url_add_parameter(&url, "p", zUuid);
|
| ︙ | ︙ | |||
1233 1234 1235 1236 1237 1238 1239 |
db_multi_exec(
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
"INSERT INTO ok VALUES(%d);"
"INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;"
"INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;",
f_rid, f_rid, f_rid
);
| | | | | | | | | | | > | | | > | | | | | | | | | | | | | | | | | | | | 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 |
db_multi_exec(
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
"INSERT INTO ok VALUES(%d);"
"INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;"
"INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;",
f_rid, f_rid, f_rid
);
blob_append_sql(&sql, " AND event.objid IN ok");
db_multi_exec("%s", blob_sql_text(&sql));
if( useDividers ) timeline_add_dividers(0, f_rid);
blob_appendf(&desc, "Parents and children of check-in ");
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%s", zUuid), zUuid);
tmFlags |= TIMELINE_DISJOINT;
url_add_parameter(&url, "f", zUuid);
if( tmFlags & TIMELINE_FCHANGES ){
timeline_submenu(&url, "Hide Files", "v", 0, 0);
}else{
timeline_submenu(&url, "Show Files", "v", "", 0);
}
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
timeline_submenu(&url, "Unhide", "unhide", "", 0);
}
}else{
/* Otherwise, a timeline based on a span of time */
int n;
const char *zEType = "timeline item";
char *zDate;
if( zUses ){
blob_append_sql(&sql, " AND event.objid IN usesfile ");
}
if( renameOnly ){
blob_append_sql(&sql, " AND event.objid IN rnfile ");
}
if( zYearMonth ){
blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ",
zYearMonth);
}
else if( zYearWeek ){
blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ",
zYearWeek);
}
if( tagid>0 ){
blob_append_sql(&sql,
"AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
if( zBrName ){
url_add_parameter(&url, "r", zBrName);
/* The next two blob_appendf() calls add SQL that causes checkins that
** are not part of the branch which are parents or children of the
** branch to be included in the report. This related check-ins are
** useful in helping to visualize what has happened on a quiescent
** branch that is infrequently merged with a much more activate branch.
*/
blob_append_sql(&sql,
" OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=cid"
" WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)",
tagid
);
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
blob_append_sql(&sql,
" AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=cid"
" WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)",
TAG_HIDDEN
);
}
if( P("mionly")==0 ){
blob_append_sql(&sql,
" OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid"
" WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
tagid
);
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
blob_append_sql(&sql,
" AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid"
" WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
TAG_HIDDEN
);
}
}else{
url_add_parameter(&url, "mionly", "1");
}
}else{
url_add_parameter(&url, "t", zTagName);
}
blob_append_sql(&sql, ")");
}
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 = "all";
}
if( zType[0]=='a' ){
if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){
char cSep = '(';
blob_append_sql(&sql, " AND event.type IN ");
if( g.perm.Read ){
blob_append_sql(&sql, "%c'ci','g'", cSep);
cSep = ',';
}
if( g.perm.RdWiki ){
blob_append_sql(&sql, "%c'w','e'", cSep);
cSep = ',';
}
if( g.perm.RdTkt ){
blob_append_sql(&sql, "%c't'", cSep);
cSep = ',';
}
blob_append_sql(&sql, ")");
}
}else{ /* zType!="all" */
blob_append_sql(&sql, " AND event.type=%Q", zType);
url_add_parameter(&url, "y", zType);
if( zType[0]=='c' ){
zEType = "checkin";
}else if( zType[0]=='w' ){
zEType = "wiki edit";
}else if( zType[0]=='t' ){
zEType = "ticket change";
}else if( zType[0]=='e' ){
zEType = "event";
}else if( zType[0]=='g' ){
zEType = "tag";
}
}
if( zUser ){
blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)",
zUser, zUser);
url_add_parameter(&url, "u", zUser);
zThisUser = zUser;
}
if( zSearch ){
blob_append_sql(&sql,
" AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
zSearch, zSearch);
url_add_parameter(&url, "s", zSearch);
}
rBefore = symbolic_name_to_mtime(zBefore);
rAfter = symbolic_name_to_mtime(zAfter);
rCirca = symbolic_name_to_mtime(zCirca);
if( rAfter>0.0 ){
if( rBefore>0.0 ){
blob_append_sql(&sql,
" AND event.mtime>=%.17g AND event.mtime<=%.17g"
" ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND);
url_add_parameter(&url, "a", zAfter);
url_add_parameter(&url, "b", zBefore);
nEntry = 1000000;
}else{
blob_append_sql(&sql,
" AND event.mtime>=%.17g ORDER BY event.mtime ASC",
rAfter-ONE_SECOND);
url_add_parameter(&url, "a", zAfter);
}
}else if( rBefore>0.0 ){
blob_append_sql(&sql,
" AND event.mtime<=%.17g ORDER BY event.mtime DESC",
rBefore+ONE_SECOND);
url_add_parameter(&url, "b", zBefore);
}else if( rCirca>0.0 ){
Blob sql2;
blob_init(&sql2, blob_sql_text(&sql), -1);
blob_append_sql(&sql2,
" AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d",
rCirca, (nEntry+1)/2
);
db_multi_exec("%s", blob_sql_text(&sql2));
blob_reset(&sql2);
blob_append_sql(&sql,
" AND event.mtime>=%f ORDER BY event.mtime ASC",
rCirca
);
nEntry -= (nEntry+1)/2;
if( useDividers ) timeline_add_dividers(rCirca, 0);
url_add_parameter(&url, "c", zCirca);
}else{
blob_append_sql(&sql, " ORDER BY event.mtime DESC");
}
blob_append_sql(&sql, " LIMIT %d", nEntry);
db_multi_exec("%s", blob_sql_text(&sql));
n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/");
if( zYearMonth ){
blob_appendf(&desc, "%s events for %h", zEType, zYearMonth);
}else if( zYearWeek ){
blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek);
}else if( zAfter==0 && zBefore==0 && zCirca==0 ){
|
| ︙ | ︙ | |||
1504 1505 1506 1507 1508 1509 1510 |
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
timeline_submenu(&url, "Unhide", "unhide", "", 0);
}
}
}
}
if( P("showsql") ){
| | | 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 |
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
timeline_submenu(&url, "Unhide", "unhide", "", 0);
}
}
}
}
if( P("showsql") ){
@ <blockquote>%h(blob_sql_text(&sql))</blockquote>
}
blob_zero(&sql);
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
@ <h2>%b(&desc)</h2>
blob_reset(&desc);
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
db_finalize(&q);
|
| ︙ | ︙ | |||
1653 1654 1655 1656 1657 1658 1659 |
}
/*
** Return a pointer to a static string that forms the basis for
** a timeline query for display on a TTY.
*/
const char *timeline_query_for_tty(void){
| < | < | < < | 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 |
}
/*
** Return a pointer to a static string that forms the basis for
** a timeline query for display on a TTY.
*/
const char *timeline_query_for_tty(void){
static const char zBaseSql[] =
@ SELECT
@ blob.rid AS rid,
@ uuid,
@ datetime(event.mtime%s) AS mDateTime,
@ 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
@ AND tagxref.rid=blob.rid AND tagxref.tagtype>0))
@ || ')' as comment,
@ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim)
@ AS primPlinkCount,
@ (SELECT count(*) FROM plink WHERE cid=blob.rid) AS plinkCount,
@ event.mtime AS mtime,
@ tagxref.value AS branch
@ FROM tag CROSS JOIN event CROSS JOIN blob
@ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
@ AND tagxref.tagtype>0
@ AND tagxref.rid=blob.rid
@ WHERE blob.rid=event.objid
@ AND tag.tagname='branch'
;
return mprintf(zBaseSql /*works-like: "%s"*/, timeline_utc());
}
/*
** Return true if the input string is a date in the ISO 8601 format:
** YYYY-MM-DD.
*/
static int isIsoDate(const char *z){
|
| ︙ | ︙ | |||
1737 1738 1739 1740 1741 1742 1743 |
** >20 or 0 (= no limit, resulting in a single line per
** entry).
** -R REPO_FILE Specifies the repository db to use. Default is
** the current checkout's repository.
*/
void timeline_cmd(void){
Stmt q;
| | > > | 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 |
** >20 or 0 (= no limit, resulting in a single line per
** entry).
** -R REPO_FILE Specifies the repository db to use. Default is
** the current checkout's repository.
*/
void timeline_cmd(void){
Stmt q;
int n, k, width, i;
const char *zLimit;
const char *zWidth;
const char *zOffset;
const char *zType;
char *zOrigin;
char *zDate;
Blob sql;
int objid = 0;
Blob uuid;
int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */
int verboseFlag = 0 ;
int iOffset;
const char *zFilePattern = 0;
Blob treeName;
verboseFlag = find_option("verbose","v", 0)!=0;
if( !verboseFlag){
verboseFlag = find_option("showfiles","f", 0)!=0; /* deprecated */
}
db_find_and_open_repository(0, 0);
zLimit = find_option("limit","n",1);
|
| ︙ | ︙ | |||
1781 1782 1783 1784 1785 1786 1787 |
}
zOffset = find_option("offset",0,1);
iOffset = zOffset ? atoi(zOffset) : 0;
/* We should be done with options.. */
verify_all_options();
| > > > | | > | | | | | | | | | | | | < < < | | | < | | > | | | < > > | 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 |
}
zOffset = find_option("offset",0,1);
iOffset = zOffset ? atoi(zOffset) : 0;
/* We should be done with options.. */
verify_all_options();
zOrigin = "now";
zFilePattern = 0;
for(i=2; i<g.argc; i++){
char *zArg = g.argv[i];
k = strlen(zArg);
if( mode==0 ){
if( strncmp(zArg,"before",k)==0 ){
mode = 1;
}else if( strncmp(zArg,"after",k)==0 && k>1 ){
mode = 2;
}else if( strncmp(zArg,"descendants",k)==0 ){
mode = 3;
}else if( strncmp(zArg,"children",k)==0 ){
mode = 3;
}else if( strncmp(zArg,"ancestors",k)==0 && k>1 ){
mode = 4;
}else if( strncmp(zArg,"parents",k)==0 ){
mode = 4;
}
if( mode ){
if( i<g.argc-1 ) zOrigin = g.argv[++i];
continue;
}
}
if( zFilePattern==0 ){
zFilePattern = zArg;
}else{
usage("?WHEN? ?CHECKIN|DATETIME? ?FILE? ?OPTIONS?");
}
}
k = strlen(zOrigin);
blob_zero(&uuid);
blob_append(&uuid, zOrigin, -1);
if( fossil_strcmp(zOrigin, "now")==0 ){
if( mode==3 || mode==4 ){
fossil_fatal("cannot compute descendants or ancestors of a date");
|
| ︙ | ︙ | |||
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 |
fossil_fatal("cannot compute descendants or ancestors of a date");
}
if( mode==0 ){
if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
}
zDate = mprintf("(SELECT julianday(%Q%s, 'utc'))", zOrigin, zShift);
}
if( mode==0 ) mode = 1;
blob_zero(&sql);
blob_append(&sql, timeline_query_for_tty(), -1);
| > > > > > > > > > > > > > > > | | | | > > > > > > > > > > > > > > > > > > > > | | | | 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 |
fossil_fatal("cannot compute descendants or ancestors of a date");
}
if( mode==0 ){
if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
}
zDate = mprintf("(SELECT julianday(%Q%s, 'utc'))", zOrigin, zShift);
}
if( zFilePattern ){
if( zType==0 ){
/* When zFilePattern is specified and type is not specified, only show
* file checkins */
zType="ci";
}
file_tree_name(zFilePattern, &treeName, 1);
if( fossil_strcmp(blob_str(&treeName), ".")==0 ){
/* When zTreeName refers to g.zLocalRoot, it's like not specifying
* zFilePattern. */
zFilePattern = 0;
}
}
if( mode==0 ) mode = 1;
blob_zero(&sql);
blob_append(&sql, timeline_query_for_tty(), -1);
blob_append_sql(&sql, " AND event.mtime %s %s",
(mode==1 || mode==4) ? "<=" : ">=",
zDate /*safe-for-%s*/
);
if( mode==3 || mode==4 ){
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
if( mode==3 ){
compute_descendants(objid, n);
}else{
compute_ancestors(objid, n, 0);
}
blob_append_sql(&sql, "\n AND blob.rid IN ok");
}
if( zType && (zType[0]!='a') ){
blob_append_sql(&sql, "\n AND event.type=%Q ", zType);
}
if( zFilePattern ){
blob_append(&sql,
"\n AND EXISTS(SELECT 1 FROM mlink\n"
" WHERE mlink.mid=event.objid\n"
" AND mlink.fnid IN ", -1);
if( filenames_are_case_sensitive() ){
blob_append_sql(&sql,
"(SELECT fnid FROM filename"
" WHERE name=%Q"
" OR name GLOB '%q/*')",
blob_str(&treeName), blob_str(&treeName));
}else{
blob_append_sql(&sql,
"(SELECT fnid FROM filename"
" WHERE name=%Q COLLATE nocase"
" OR lower(name) GLOB lower('%q/*'))",
blob_str(&treeName), blob_str(&treeName));
}
blob_append(&sql, ")", -1);
}
blob_append_sql(&sql, "\nORDER BY event.mtime DESC");
if( iOffset>0 ){
/* Don't handle LIMIT here, otherwise print_timeline()
* will not determine the end-marker correctly! */
blob_append_sql(&sql, "\n LIMIT -1 OFFSET %d", iOffset);
}
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
print_timeline(&q, n, width, verboseFlag);
db_finalize(&q);
}
/*
** Return one of two things:
|
| ︙ | ︙ | |||
2176 2177 2178 2179 2180 2181 2182 |
int iterations = 0; /* number of weeks/months we iterate
over */
stats_report_init_view();
stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL );
blob_appendf(&header, "Timeline Events (%s) by year%s",
stats_report_label_for_type(),
(includeMonth ? "/month" : ""));
| | | | | 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 |
int iterations = 0; /* number of weeks/months we iterate
over */
stats_report_init_view();
stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL );
blob_appendf(&header, "Timeline Events (%s) by year%s",
stats_report_label_for_type(),
(includeMonth ? "/month" : ""));
blob_append_sql(&sql,
"SELECT substr(date(mtime),1,%d) AS timeframe, "
"count(*) AS eventCount "
"FROM v_reports ",
includeMonth ? 7 : 4);
if(zUserName&&*zUserName){
blob_append_sql(&sql, " WHERE user=%Q ", zUserName);
blob_appendf(&header," for user %q", zUserName);
}
blob_append(&sql,
" GROUP BY timeframe"
" ORDER BY timeframe DESC",
-1);
db_prepare(&query, "%s", blob_sql_text(&sql));
blob_reset(&sql);
@ <h1>%b(&header)</h1>
@ <table class='statistics-report-table-events' border='0' cellpadding='2'
@ cellspacing='0' id='statsTable'>
@ <thead>
@ <th>%s(zTimeLabel)</th>
@ <th>Events</th>
|
| ︙ | ︙ | |||
2319 2320 2321 2322 2323 2324 2325 |
*/
static void stats_report_by_user(){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int nEventTotal = 0; /* Total event count */
int rowClass = 0; /* counter for alternating
row colors */
| < | | < < < | 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 |
*/
static void stats_report_by_user(){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int nEventTotal = 0; /* Total event count */
int rowClass = 0; /* counter for alternating
row colors */
int nMaxEvents = 1; /* max number of events for
all rows. */
stats_report_init_view();
stats_report_event_types_menu("byuser", NULL);
db_prepare(&query,
"SELECT user, "
"COUNT(*) AS eventCount "
"FROM v_reports "
"GROUP BY user ORDER BY eventCount DESC");
@ <h1>Timeline Events
@ (%s(stats_report_label_for_type())) by User</h1>
@ <table class='statistics-report-table-events' border='0'
@ cellpadding='2' cellspacing='0' id='statsTable'>
@ <thead><tr>
@ <th>User</th>
@ <th>Events</th>
|
| ︙ | ︙ | |||
2386 2387 2388 2389 2390 2391 2392 |
*/
static void stats_report_day_of_week(){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int nEventTotal = 0; /* Total event count */
int rowClass = 0; /* counter for alternating
row colors */
| < | | < < < | 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 |
*/
static void stats_report_day_of_week(){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int nEventTotal = 0; /* Total event count */
int rowClass = 0; /* counter for alternating
row colors */
int nMaxEvents = 1; /* max number of events for
all rows. */
static const char *const daysOfWeek[] = {
"Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"
};
stats_report_init_view();
stats_report_event_types_menu("byweekday", NULL);
db_prepare(&query,
"SELECT cast(mtime %% 7 AS INTEGER) dow, "
"COUNT(*) AS eventCount "
"FROM v_reports "
"GROUP BY dow ORDER BY dow");
@ <h1>Timeline Events
@ (%s(stats_report_label_for_type())) by Day of the Week</h1>
@ <table class='statistics-report-table-events' border='0'
@ cellpadding='2' cellspacing='0' id='statsTable'>
@ <thead><tr>
@ <th>DoW</th>
@ <th>Day</th>
|
| ︙ | ︙ | |||
2475 2476 2477 2478 2479 2480 2481 |
}else{
stats_report_event_types_menu("byweek", NULL);
}
blob_append(&sql,
"SELECT DISTINCT substr(date(mtime),1,4) AS y "
"FROM v_reports WHERE 1 ", -1);
if(zUserName&&*zUserName){
| | | | 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 |
}else{
stats_report_event_types_menu("byweek", NULL);
}
blob_append(&sql,
"SELECT DISTINCT substr(date(mtime),1,4) AS y "
"FROM v_reports WHERE 1 ", -1);
if(zUserName&&*zUserName){
blob_append_sql(&sql,"AND user=%Q ", zUserName);
}
blob_append(&sql,"GROUP BY y ORDER BY y", -1);
db_prepare(&qYears, "%s", blob_sql_text(&sql));
blob_reset(&sql);
cgi_printf("Select year: ");
while( SQLITE_ROW == db_step(&qYears) ){
const char *zT = db_column_text(&qYears, 0);
if( i++ ){
cgi_printf(" ");
}
|
| ︙ | ︙ | |||
2508 2509 2510 2511 2512 2513 2514 |
Stmt stWeek = empty_Stmt;
int rowCount = 0;
int total = 0;
Blob header = empty_blob;
blob_appendf(&header, "Timeline events (%s) for the calendar weeks "
"of %h", stats_report_label_for_type(),
zYear);
| | | | | | 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 |
Stmt stWeek = empty_Stmt;
int rowCount = 0;
int total = 0;
Blob header = empty_blob;
blob_appendf(&header, "Timeline events (%s) for the calendar weeks "
"of %h", stats_report_label_for_type(),
zYear);
blob_append_sql(&sql,
"SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
"count(*) AS n "
"FROM v_reports "
"WHERE %Q=substr(date(mtime),1,4) "
"AND mtime < current_timestamp ",
zYear);
if(zUserName&&*zUserName){
blob_append_sql(&sql, " AND user=%Q ", zUserName);
blob_appendf(&header," for user %h", zUserName);
}
blob_append_sql(&sql, "GROUP BY wk ORDER BY wk DESC");
cgi_printf("<h1>%h</h1>", blob_str(&header));
blob_reset(&header);
cgi_printf("<table class='statistics-report-table-events' "
"border='0' cellpadding='2' width='100%%' "
"cellspacing='0' id='statsTable'>");
cgi_printf("<thead><tr>"
"<th>Week</th>"
"<th>Events</th>"
"<th width='90%%'><!-- relative commits graph --></th>"
"</tr></thead>"
"<tbody>");
db_prepare(&stWeek, "%s", blob_sql_text(&sql));
blob_reset(&sql);
while( SQLITE_ROW == db_step(&stWeek) ){
const int nCount = db_column_int(&stWeek, 1);
if(nCount>nMaxEvents){
nMaxEvents = nCount;
}
++iterations;
|
| ︙ | ︙ |
Changes to src/tkt.c.
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
"VALUES(%Q, 0)", p->zTicketUuid);
tktid = db_last_insert_rowid();
}
blob_zero(&sql1);
blob_zero(&sql2);
blob_zero(&sql3);
| | | | | | | | | | | | > | | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
"VALUES(%Q, 0)", p->zTicketUuid);
tktid = db_last_insert_rowid();
}
blob_zero(&sql1);
blob_zero(&sql2);
blob_zero(&sql3);
blob_append_sql(&sql1, "UPDATE OR REPLACE ticket SET tkt_mtime=:mtime");
if( haveTicketCTime ){
blob_append_sql(&sql1, ", tkt_ctime=coalesce(tkt_ctime,:mtime)");
}
aUsed = fossil_malloc( nField );
memset(aUsed, 0, nField);
for(i=0; i<p->nField; i++){
const char *zName = p->aField[i].zName;
const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
j = fieldId(zBaseName);
if( j<0 ) continue;
aUsed[j] = 1;
if( aField[j].mUsed & USEDBY_TICKET ){
if( zName[0]=='+' ){
zName++;
blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q",
zName, zName, p->aField[i].zValue);
}else{
blob_append_sql(&sql1,", \"%w\"=%Q", zName, p->aField[i].zValue);
}
}
if( aField[j].mUsed & USEDBY_TICKETCHNG ){
blob_append_sql(&sql2, ",\"%w\"", zName);
blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
}
if( rid>0 ){
wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0);
}
}
blob_append_sql(&sql1, " WHERE tkt_id=%d", tktid);
db_prepare(&q, "%s", blob_sql_text(&sql1));
db_bind_double(&q, ":mtime", p->rDate);
db_step(&q);
db_finalize(&q);
blob_reset(&sql1);
if( blob_size(&sql2)>0 || haveTicketChngRid ){
int fromTkt = 0;
if( haveTicketChngRid ){
blob_append(&sql2, ",tkt_rid", -1);
blob_append_sql(&sql3, ",%d", rid);
}
for(i=0; i<nField; i++){
if( aUsed[i]==0
&& (aField[i].mUsed & USEDBY_BOTH)==USEDBY_BOTH
){
const char *z = aField[i].zName;
if( z[0]=='+' ) z++;
fromTkt = 1;
blob_append_sql(&sql2, ",\"%w\"", z);
blob_append_sql(&sql3, ",\"%w\"", z);
}
}
if( fromTkt ){
db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
"SELECT %d,:mtime%s FROM ticket WHERE tkt_id=%d",
blob_sql_text(&sql2), tktid,
blob_sql_text(&sql3), tktid);
}else{
db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
"VALUES(%d,:mtime%s)",
blob_sql_text(&sql2), tktid, blob_sql_text(&sql3));
}
db_bind_double(&q, ":mtime", p->rDate);
db_step(&q);
db_finalize(&q);
}
blob_reset(&sql2);
blob_reset(&sql3);
|
| ︙ | ︙ | |||
366 367 368 369 370 371 372 |
"DROP TABLE IF EXISTS ticketchng;"
);
zSql = ticket_table_schema();
if( separateConnection ){
db_end_transaction(0);
db_init_database(g.zRepositoryName, zSql, 0);
}else{
| | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
"DROP TABLE IF EXISTS ticketchng;"
);
zSql = ticket_table_schema();
if( separateConnection ){
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.
*/
|
| ︙ | ︙ | |||
549 550 551 552 553 554 555 |
int rid = content_put_ex(pTicket, 0, 0, 0, needMod);
if( rid==0 ){
fossil_fatal("trouble committing ticket: %s", g.zErrMsg);
}
if( needMod ){
moderation_table_create();
db_multi_exec(
| | | 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
int rid = content_put_ex(pTicket, 0, 0, 0, needMod);
if( rid==0 ){
fossil_fatal("trouble committing ticket: %s", g.zErrMsg);
}
if( needMod ){
moderation_table_create();
db_multi_exec(
"INSERT INTO modreq(objid, tktid) VALUES(%d,%Q)",
rid, zTktId
);
}else{
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid);
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid);
}
manifest_crosslink_begin();
|
| ︙ | ︙ | |||
853 854 855 856 857 858 859 |
style_submenu_element("Status", "Status",
"%s/info/%s", g.zTop, zUuid);
if( zType[0]=='c' ){
zTitle = mprintf("Check-Ins Associated With Ticket %h", zUuid);
}else{
zTitle = mprintf("Timeline Of Ticket %h", zUuid);
}
| | < | 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 |
style_submenu_element("Status", "Status",
"%s/info/%s", g.zTop, zUuid);
if( zType[0]=='c' ){
zTitle = mprintf("Check-Ins Associated With Ticket %h", zUuid);
}else{
zTitle = mprintf("Timeline Of Ticket %h", zUuid);
}
style_header("%z", zTitle);
sqlite3_snprintf(6, zGlobPattern, "%s", zUuid);
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();
|
| ︙ | ︙ | |||
887 888 889 890 891 892 893 |
" AND '%s' GLOB (target||'*')"
" UNION SELECT attachid FROM attachment"
" WHERE target=%Q) "
"ORDER BY mtime DESC",
timeline_query_for_www(), tagid, zFullUuid, zFullUuid, zFullUuid
);
}
| | < | 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 |
" 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);
db_finalize(&q);
style_footer();
}
/*
|
| ︙ | ︙ | |||
925 926 927 928 929 930 931 |
if( P("plaintext")!=0 ){
style_submenu_element("Formatted", "Formatted",
"%R/tkthistory/%s", zUuid);
}else{
style_submenu_element("Plaintext", "Plaintext",
"%R/tkthistory/%s?plaintext", zUuid);
}
| | < | 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 |
if( P("plaintext")!=0 ){
style_submenu_element("Formatted", "Formatted",
"%R/tkthistory/%s", zUuid);
}else{
style_submenu_element("Plaintext", "Plaintext",
"%R/tkthistory/%s?plaintext", zUuid);
}
style_header("%z", zTitle);
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;
}
|
| ︙ | ︙ | |||
1211 1212 1213 1214 1215 1216 1217 |
}else{
eCmd = set;
}
if( g.argc==3 ){
usage("set|change|history TICKETUUID");
}
zTktUuid = db_text(0,
| | | 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 |
}else{
eCmd = set;
}
if( g.argc==3 ){
usage("set|change|history TICKETUUID");
}
zTktUuid = db_text(0,
"SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", g.argv[3]
);
if( !zTktUuid ){
fossil_fatal("unknown ticket: '%s'!",g.argv[3]);
}
i=4;
}else if( strncmp(g.argv[2],"add",n)==0 ){
eCmd = add;
|
| ︙ | ︙ | |||
1290 1291 1292 1293 1294 1295 1296 |
fossil_print(" Append to ");
z++;
}else{
fossil_print(" Change ");
}
fossil_print("%h: ",z);
if( blob_size(&val)>50 || contains_newline(&val)) {
| | | 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 |
fossil_print(" Append to ");
z++;
}else{
fossil_print(" Change ");
}
fossil_print("%h: ",z);
if( blob_size(&val)>50 || contains_newline(&val)) {
fossil_print("\n ");
comment_print(blob_str(&val),0,4,-1,g.comFmtFlags);
}else{
fossil_print("%s\n",blob_str(&val));
}
blob_reset(&val);
}
}
|
| ︙ | ︙ |
Changes to src/translate.c.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** | | | | | | 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 | ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** SYNOPSIS: ** ** Input lines that begin with the "@" character are translated into ** either cgi_printf() statements or string literals and the ** translated code is written on standard output. ** ** The problem this program is attempt to solve is as follows: When ** writing CGI programs in C, we typically want to output a lot of HTML ** text to standard output. In pure C code, this involves doing a ** printf() with a big string containing all that text. But we have ** to insert special codes (ex: \n and \") for many common characters, ** which interferes with the readability of the HTML. ** ** This tool allows us to put raw HTML, without the special codes, in ** the middle of a C program. This program then translates the text ** into standard C by inserting all necessary backslashes and other ** punctuation. ** ** Enhancement #1: ** ** If the last non-whitespace character prior to the first "@" of a ** @-block is "=" or "," then the @-block is a string literal initializer ** rather than text that is to be output via cgi_printf(). Render it ** as such. ** ** Enhancement #2: ** ** Comments of the form: "/* @-comment: CC" cause CC to become a ** comment character for the @-substitution. Typical values for CC are ** "--" (for SQL text) or "#" (for TCL script) or "//" (for C++ code). ** Lines of subsequent @-blocks that begin with CC are omitted from the ** output. ** */ #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> /* |
| ︙ | ︙ | |||
120 121 122 123 124 125 126 |
i++;
if( isspace(zLine[i]) ){ i++; }
indent = i - 2;
if( indent<0 ) indent = 0;
omitline = 0;
for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){
if( zLine[i]==c1 && (c2==' ' || zLine[i+1]==c2) ){
| | | | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
i++;
if( isspace(zLine[i]) ){ i++; }
indent = i - 2;
if( indent<0 ) indent = 0;
omitline = 0;
for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){
if( zLine[i]==c1 && (c2==' ' || zLine[i+1]==c2) ){
omitline = 1; break;
}
if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; }
zOut[j++] = zLine[i];
}
while( j>0 && isspace(zOut[j-1]) ){ j--; }
zOut[j] = 0;
if( j<=0 && omitline ){
fprintf(out,"\n");
}else{
fprintf(out,"%*s\"%s\\n\"\n",indent, "", zOut);
}
}else{
/* Otherwise (if the last non-whitespace was not '=') then generate
** a cgi_printf() statement whose format is the text following the '@'.
** Substrings of the form "%C(...)" (where C is any sequence of
** characters other than \000 and '(') will put "%C" in the
** format and add the "(...)" as an argument to the cgi_printf call.
*/
int indent;
int nC;
char c;
i++;
|
| ︙ | ︙ | |||
172 173 174 175 176 177 178 |
zOut[j] = 0;
if( !inPrint ){
fprintf(out,"%*scgi_printf(\"%s\\n\"",indent-2,"", zOut);
inPrint = 1;
}else{
fprintf(out,"\n%*s\"%s\\n\"",indent+5, "", zOut);
}
| | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
zOut[j] = 0;
if( !inPrint ){
fprintf(out,"%*scgi_printf(\"%s\\n\"",indent-2,"", zOut);
inPrint = 1;
}else{
fprintf(out,"\n%*s\"%s\\n\"",indent+5, "", zOut);
}
}
}
}
int main(int argc, char **argv){
if( argc==2 ){
char *arg;
FILE *in = fopen(argv[1], "r");
|
| ︙ | ︙ |
Changes to src/undo.c.
| ︙ | ︙ | |||
141 142 143 144 145 146 147 |
"CREATE TEMP TABLE undo_vmerge_2 AS SELECT * FROM vmerge;"
"DELETE FROM vmerge;"
"INSERT INTO vmerge SELECT * FROM undo_vmerge;"
"DELETE FROM undo_vmerge;"
"INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;"
"DROP TABLE undo_vmerge_2;"
);
| | > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
"CREATE TEMP TABLE undo_vmerge_2 AS SELECT * FROM vmerge;"
"DELETE FROM vmerge;"
"INSERT INTO vmerge SELECT * FROM undo_vmerge;"
"DELETE FROM undo_vmerge;"
"INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;"
"DROP TABLE undo_vmerge_2;"
);
if(db_exists("SELECT 1 FROM \"%w\".sqlite_master"
" WHERE name='undo_stash'", zDb) ){
if( redoFlag ){
db_multi_exec(
"DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);"
"DELETE FROM stashfile"
" WHERE stashid NOT IN (SELECT stashid FROM stash);"
);
}else{
|
| ︙ | ︙ | |||
172 173 174 175 176 177 178 |
static const char zSql[] =
@ DROP TABLE IF EXISTS undo;
@ DROP TABLE IF EXISTS undo_vfile;
@ DROP TABLE IF EXISTS undo_vmerge;
@ DROP TABLE IF EXISTS undo_stash;
@ DROP TABLE IF EXISTS undo_stashfile;
;
| | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
static const char zSql[] =
@ DROP TABLE IF EXISTS undo;
@ DROP TABLE IF EXISTS undo_vfile;
@ DROP TABLE IF EXISTS undo_vmerge;
@ DROP TABLE IF EXISTS undo_stash;
@ DROP TABLE IF EXISTS undo_stashfile;
;
db_multi_exec(zSql /*works-like:""*/);
db_lset_int("undo_available", 0);
db_lset_int("undo_checkout", 0);
}
/*
** The following variable stores the original command-line of the
** command that is a candidate to be undone.
|
| ︙ | ︙ | |||
217 218 219 220 221 222 223 |
/*
** Begin capturing a snapshot that can be undone.
*/
void undo_begin(void){
int cid;
const char *zDb = db_name("localdb");
static const char zSql[] =
| | | | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
/*
** Begin capturing a snapshot that can be undone.
*/
void undo_begin(void){
int cid;
const char *zDb = db_name("localdb");
static const char zSql[] =
@ CREATE TABLE "%w".undo(
@ pathname TEXT UNIQUE, -- Name of the file
@ redoflag BOOLEAN, -- 0 for undoable. 1 for redoable
@ existsflag BOOLEAN, -- True if the file exists
@ isExe BOOLEAN, -- True if the file is executable
@ isLink BOOLEAN, -- True if the file is symlink
@ content BLOB -- Saved content
@ );
@ CREATE TABLE "%w".undo_vfile AS SELECT * FROM vfile;
@ CREATE TABLE "%w".undo_vmerge AS SELECT * FROM vmerge;
;
if( undoDisable ) return;
undo_reset();
db_multi_exec(zSql/*works-like:"%w,%w,%w"*/, zDb, zDb, zDb);
cid = db_lget_int("checkout", 0);
db_lset_int("undo_checkout", cid);
db_lset_int("undo_available", 1);
db_lset("undo_cmdline", undoCmd);
undoActive = 1;
}
|
| ︙ | ︙ | |||
299 300 301 302 303 304 305 |
/*
** Make the current state of stashid undoable.
*/
void undo_save_stash(int stashid){
const char *zDb = db_name("localdb");
db_multi_exec(
| | | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
/*
** Make the current state of stashid undoable.
*/
void undo_save_stash(int stashid){
const char *zDb = db_name("localdb");
db_multi_exec(
"CREATE TABLE IF NOT EXISTS \"%w\".undo_stash"
" AS SELECT * FROM stash WHERE 0;"
"INSERT INTO undo_stash"
" SELECT * FROM stash WHERE stashid=%d;",
zDb, stashid
);
db_multi_exec(
"CREATE TABLE IF NOT EXISTS \"%w\".undo_stashfile"
" AS SELECT * FROM stashfile WHERE 0;"
"INSERT INTO undo_stashfile"
" SELECT * FROM stashfile WHERE stashid=%d;",
zDb, stashid
);
}
|
| ︙ | ︙ |
Changes to src/update.c.
| ︙ | ︙ | |||
355 356 357 358 359 360 361 |
blob_zero(&sql);
blob_append(&sql, "DELETE FROM fv WHERE ", -1);
zSep = "";
for(i=3; i<g.argc; i++){
file_tree_name(g.argv[i], &treename, 1);
if( file_wd_isdir(g.argv[i])==1 ){
if( blob_size(&treename) != 1 || blob_str(&treename)[0] != '.' ){
| | > | > | | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
blob_zero(&sql);
blob_append(&sql, "DELETE FROM fv WHERE ", -1);
zSep = "";
for(i=3; i<g.argc; i++){
file_tree_name(g.argv[i], &treename, 1);
if( file_wd_isdir(g.argv[i])==1 ){
if( blob_size(&treename) != 1 || blob_str(&treename)[0] != '.' ){
blob_append_sql(&sql, "%sfn NOT GLOB '%q/*' ",
zSep /*safe-for-%s*/, blob_str(&treename));
}else{
blob_reset(&sql);
break;
}
}else{
blob_append_sql(&sql, "%sfn<>%Q ",
zSep /*safe-for-%s*/, blob_str(&treename));
}
zSep = "AND ";
blob_reset(&treename);
}
db_multi_exec("%s", blob_sql_text(&sql));
blob_reset(&sql);
}
/*
** Alter the content of the checkout so that it conforms with the
** target
*/
|
| ︙ | ︙ |
Changes to src/user.c.
| ︙ | ︙ | |||
449 450 451 452 453 454 455 |
"(SELECT rowid FROM accesslog ORDER BY rowid DESC"
" LIMIT -1 OFFSET 200)");
cgi_redirectf("%s/access_log?y=%d&n=%d", g.zTop, y, n);
return;
}
style_header("Access Log");
blob_zero(&sql);
| | | | | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
"(SELECT rowid FROM accesslog ORDER BY rowid DESC"
" LIMIT -1 OFFSET 200)");
cgi_redirectf("%s/access_log?y=%d&n=%d", g.zTop, y, n);
return;
}
style_header("Access Log");
blob_zero(&sql);
blob_append_sql(&sql,
"SELECT uname, ipaddr, datetime(mtime%s), success"
" FROM accesslog", timeline_utc()
);
if( y==1 ){
blob_append(&sql, " WHERE success", -1);
}else if( y==2 ){
blob_append(&sql, " WHERE NOT success", -1);
}
blob_append_sql(&sql," ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip);
if( skip ){
style_submenu_element("Newer", "Newer entries",
"%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0,
n, y);
}
rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql));
@ <center><table border="1" cellpadding="5">
@ <tr><th width="33%%">Date</th><th width="34%%">User</th>
@ <th width="33%%">IP Address</th></tr>
while( rc==SQLITE_OK && db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zIP = db_column_text(&q, 1);
const char *zDate = db_column_text(&q, 2);
|
| ︙ | ︙ |
Changes to src/util.c.
| ︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | rc = _wsystem(zUnicode); fossil_unicode_free(zUnicode); free(zNewCmd); #else /* On unix, evaluate the command directly. */ if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd); rc = system(zOrigCmd); #endif return rc; } /* ** Like strcmp() except that it accepts NULL pointers. NULL sorts before | > > > > > > > > > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | rc = _wsystem(zUnicode); fossil_unicode_free(zUnicode); free(zNewCmd); #else /* On unix, evaluate the command directly. */ if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd); /* Unix systems should never shell-out while processing an HTTP request, ** either via CGI, SCGI, or direct HTTP. The following assert verifies ** this. And the following assert proves that Fossil is not vulnerable ** to the ShellShock or BashDoor bug. */ assert( g.cgiOutput==0 ); /* The regular system() call works to get a shell on unix */ rc = system(zOrigCmd); #endif return rc; } /* ** Like strcmp() except that it accepts NULL pointers. NULL sorts before |
| ︙ | ︙ |
Changes to src/vfile.c.
| ︙ | ︙ | |||
395 396 397 398 399 400 401 |
"baseline",
"merge",
"original",
"output",
};
int i, j, n;
| | | | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
"baseline",
"merge",
"original",
"output",
};
int i, j, n;
if( sqlite3_strglob("ci-comment-????????????.txt", zName)==0 ) return 1;
for(; zName[0]!=0; zName++){
if( zName[0]=='/' && sqlite3_strglob("/ci-comment-????????????.txt", zName)==0 ){
return 1;
}
if( zName[0]!='-' ) continue;
for(i=0; i<sizeof(azTemp)/sizeof(azTemp[0]); i++){
n = (int)strlen(azTemp[i]);
if( memcmp(azTemp[i], zName+1, n) ) continue;
if( zName[n+1]==0 ) return 1;
|
| ︙ | ︙ |
Changes to src/wiki.c.
| ︙ | ︙ | |||
290 291 292 293 294 295 296 |
}
if( g.perm.Hyperlink ){
style_submenu_element("History", "History", "%s/whistory?name=%T",
g.zTop, zPageName);
}
}
style_set_current_page("%T?name=%T", g.zPath, zPageName);
| | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
}
if( g.perm.Hyperlink ){
style_submenu_element("History", "History", "%s/whistory?name=%T",
g.zTop, zPageName);
}
}
style_set_current_page("%T?name=%T", g.zPath, zPageName);
style_header("%s", zPageName);
blob_init(&wiki, zBody, -1);
wiki_render_by_mimetype(&wiki, zMimetype);
blob_reset(&wiki);
attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>");
manifest_destroy(pWiki);
style_footer();
}
|
| ︙ | ︙ | |||
647 648 649 650 651 652 653 |
Blob cksum;
Blob body;
Blob wiki;
Manifest *pWiki = 0;
blob_zero(&body);
if( isSandbox ){
| | | 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 |
Blob cksum;
Blob body;
Blob wiki;
Manifest *pWiki = 0;
blob_zero(&body);
if( isSandbox ){
blob_append(&body, db_get("sandbox",""), -1);
appendRemark(&body, zMimetype);
db_set("sandbox", blob_str(&body), 0);
}else{
login_verify_csrf_secret();
pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
if( pWiki ){
blob_append(&body, pWiki->zWiki, -1);
|
| ︙ | ︙ | |||
744 745 746 747 748 749 750 |
** WEBPAGE: whistory
** URL: /whistory?name=PAGENAME
**
** Show the complete change history for a single wiki page.
*/
void whistory_page(void){
Stmt q;
| < < | < < | < < < | < < | 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 |
** WEBPAGE: whistory
** URL: /whistory?name=PAGENAME
**
** Show the complete change history for a single wiki page.
*/
void whistory_page(void){
Stmt q;
const char *zPageName;
login_check_credentials();
if( !g.perm.Hyperlink ){ login_needed(); return; }
zPageName = PD("name","");
style_header("History Of %s", zPageName);
db_prepare(&q, "%s AND event.objid IN "
" (SELECT rid FROM tagxref WHERE tagid="
"(SELECT tagid FROM tag WHERE tagname='wiki-%q')"
" UNION SELECT attachid FROM attachment"
" WHERE target=%Q)"
"ORDER BY mtime DESC",
timeline_query_for_www(), zPageName, zPageName);
zWikiPageName = zPageName;
www_print_timeline(&q, TIMELINE_ARTID, 0, 0, wiki_history_extra);
db_finalize(&q);
style_footer();
}
/*
** WEBPAGE: wdiff
** URL: /whistory?name=PAGENAME&a=RID1&b=RID2
**
** Show the difference between two wiki pages.
*/
void wdiff_page(void){
int rid1, rid2;
const char *zPageName;
Manifest *pW1, *pW2 = 0;
Blob w1, w2, d;
u64 diffFlags;
login_check_credentials();
rid1 = atoi(PD("a","0"));
if( !g.perm.Hyperlink ){ login_needed(); return; }
if( rid1==0 ) fossil_redirect_home();
rid2 = atoi(PD("b","0"));
zPageName = PD("name","");
style_header("Changes To %s", zPageName);
if( rid2==0 ){
rid2 = db_int(0,
"SELECT objid FROM event JOIN tagxref ON objid=rid AND tagxref.tagid="
"(SELECT tagid FROM tag WHERE tagname='wiki-%q')"
" WHERE event.mtime<(SELECT mtime FROM event WHERE objid=%d)"
" ORDER BY event.mtime DESC LIMIT 1",
|
| ︙ | ︙ |
Changes to src/wikiformat.c.
| ︙ | ︙ | |||
1044 1045 1046 1047 1048 1049 1050 |
/*
** Begin a new paragraph if that something that is needed.
*/
static void startAutoParagraph(Renderer *p){
if( p->wantAutoParagraph==0 ) return;
if( p->state & WIKI_LINKSONLY ) return;
if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
| | | 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 |
/*
** Begin a new paragraph if that something that is needed.
*/
static void startAutoParagraph(Renderer *p){
if( p->wantAutoParagraph==0 ) return;
if( p->state & WIKI_LINKSONLY ) return;
if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
blob_append(p->pOut, "<p>", -1);
p->wantAutoParagraph = 0;
p->inAutoParagraph = 1;
}
/*
** End a paragraph if we are in one.
*/
|
| ︙ | ︙ | |||
1119 1120 1121 1122 1123 1124 1125 |
memcpy(zUpper, zLower, n+1);
zUpper[n-1]++;
if( once ){
const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
db_static_prepare(&q,
"SELECT %s FROM ticket "
" WHERE tkt_uuid>=:lwr AND tkt_uuid<:upr",
| | | 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 |
memcpy(zUpper, zLower, n+1);
zUpper[n-1]++;
if( once ){
const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
db_static_prepare(&q,
"SELECT %s FROM ticket "
" WHERE tkt_uuid>=:lwr AND tkt_uuid<:upr",
zClosedExpr /*safe-for-%s*/
);
once = 0;
}
db_bind_text(&q, ":lwr", zLower);
db_bind_text(&q, ":upr", zUpper);
if( db_step(&q)==SQLITE_ROW ){
rc = 1;
|
| ︙ | ︙ | |||
1241 1242 1243 1244 1245 1246 1247 |
zTerm = "]";
}
}
}else if( !in_this_repo(zTarget) ){
if( (p->state & (WIKI_LINKSONLY|WIKI_NOBADLINKS))!=0 ){
zTerm = "";
}else{
| | | 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 |
zTerm = "]";
}
}
}else if( !in_this_repo(zTarget) ){
if( (p->state & (WIKI_LINKSONLY|WIKI_NOBADLINKS))!=0 ){
zTerm = "";
}else{
blob_appendf(p->pOut, "<span class=\"brokenlink\">[");
zTerm = "]</span>";
}
}else if( g.perm.Hyperlink ){
blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget));
zTerm = "]</a>";
}
}else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
|
| ︙ | ︙ | |||
1326 1327 1328 1329 1330 1331 1332 |
blob_append(p->pOut, " ", -1);
}else{
if( p->wikiList ){
popStackToTag(p, p->wikiList);
p->wikiList = 0;
}
endAutoParagraph(p);
| | | 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 |
blob_append(p->pOut, " ", -1);
}else{
if( p->wikiList ){
popStackToTag(p, p->wikiList);
p->wikiList = 0;
}
endAutoParagraph(p);
blob_append(p->pOut, "\n\n", 1);
p->wantAutoParagraph = 1;
}
p->state |= AT_PARAGRAPH|AT_NEWLINE;
break;
}
case TOKEN_NEWLINE: {
blob_append(p->pOut, "\n", 1);
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
return atoi(&zHdr[17]);
}
}
zHdr++;
}
return 0;
}
/*
** Process a single incoming HTTP request.
*/
static void win32_http_request(void *pAppData){
HttpRequest *p = (HttpRequest*)pAppData;
FILE *in = 0, *out = 0;
| > > > > > > > > > > > | 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 |
return atoi(&zHdr[17]);
}
}
zHdr++;
}
return 0;
}
/*
** Issue a fatal error.
*/
static NORETURN void winhttp_fatal(
const char *zOp,
const char *zService,
const char *zErr
){
fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
}
/*
** Process a single incoming HTTP request.
*/
static void win32_http_request(void *pAppData){
HttpRequest *p = (HttpRequest*)pAppData;
FILE *in = 0, *out = 0;
|
| ︙ | ︙ | |||
295 296 297 298 299 300 301 |
fossil_fatal("unable to get path to the temporary directory.");
}
zTempPrefix = mprintf("%sfossil_server_P%d_",
fossil_unicode_to_utf8(zTmpPath), iPort);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags&HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
if( zBrowser ){
| | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
fossil_fatal("unable to get path to the temporary directory.");
}
zTempPrefix = mprintf("%sfossil_server_P%d_",
fossil_unicode_to_utf8(zTmpPath), iPort);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags&HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
if( zBrowser ){
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
fossil_print("Launch webbrowser: %s\n", zBrowser);
fossil_system(zBrowser);
}
fossil_print("Type Ctrl-C to stop the HTTP server\n");
/* Set the service status to running and pass the listener socket to the
** service handling procedures. */
win32_http_service_running(s);
|
| ︙ | ︙ | |||
677 678 679 680 681 682 683 |
n = strlen(zMethod);
if( strncmp(zMethod, "create", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_DESCRIPTIONW
svcDescr = {L"Fossil - Distributed Software Configuration Management"};
| < | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
n = strlen(zMethod);
if( strncmp(zMethod, "create", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_DESCRIPTIONW
svcDescr = {L"Fossil - Distributed Software Configuration Management"};
DWORD dwStartType = SERVICE_DEMAND_START;
const char *zDisplay = find_option("display", "D", 1);
const char *zStart = find_option("start", "S", 1);
const char *zUsername = find_option("username", "U", 1);
const char *zPassword = find_option("password", "W", 1);
const char *zPort = find_option("port", "P", 1);
const char *zNotFound = find_option("notfound", 0, 1);
|
| ︙ | ︙ | |||
712 713 714 715 716 717 718 |
}
if( zStart ){
if( strncmp(zStart, "auto", strlen(zStart))==0 ){
dwStartType = SERVICE_AUTO_START;
}else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
dwStartType = SERVICE_DEMAND_START;
}else{
| | | | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 |
}
if( zStart ){
if( strncmp(zStart, "auto", strlen(zStart))==0 ){
dwStartType = SERVICE_AUTO_START;
}else if( strncmp(zStart, "manual", strlen(zStart))==0 ){
dwStartType = SERVICE_DEMAND_START;
}else{
winhttp_fatal("create", zSvcName,
"specify 'auto' or 'manual' for the '-S|--start' option");
}
}
/* Process options for Fossil running as server. */
if( zPort && (atoi(zPort)<=0) ){
winhttp_fatal("create", zSvcName,
"port number must be in the range 1 - 65535.");
}
if( !zRepository ){
db_must_be_within_tree();
}else if( file_isdir(zRepository)==1 ){
g.zRepositoryName = mprintf("%s", zRepository);
file_simplify_name(g.zRepositoryName, -1, 0);
|
| ︙ | ︙ | |||
741 742 743 744 745 746 747 |
if( useSCGI ) blob_appendf(&binPath, " --scgi");
if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound);
if( zFileGlob ) blob_appendf(&binPath, " --files-urlenc %T", zFileGlob);
if( zLocalAuth ) blob_append(&binPath, " --localauth", -1);
blob_appendf(&binPath, " \"%s\"", g.zRepositoryName);
/* Create the service. */
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
| | | < | | | | < | 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 |
if( useSCGI ) blob_appendf(&binPath, " --scgi");
if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound);
if( zFileGlob ) blob_appendf(&binPath, " --files-urlenc %T", zFileGlob);
if( zLocalAuth ) blob_append(&binPath, " --localauth", -1);
blob_appendf(&binPath, " \"%s\"", g.zRepositoryName);
/* Create the service. */
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if( !hScm ) winhttp_fatal("create", zSvcName, win32_get_last_errmsg());
hSvc = CreateServiceW(
hScm, /* Handle to the SCM */
fossil_utf8_to_unicode(zSvcName), /* Name of the service */
fossil_utf8_to_unicode(zDisplay), /* Display name */
SERVICE_ALL_ACCESS, /* Desired access */
SERVICE_WIN32_OWN_PROCESS, /* Service type */
dwStartType, /* Start type */
SERVICE_ERROR_NORMAL, /* Error control */
fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
NULL, /* Load ordering group */
NULL, /* Tag value */
NULL, /* Service dependencies */
zUsername ? fossil_utf8_to_unicode(zUsername) : 0, /* Account */
fossil_utf8_to_unicode(zPassword) /* Account password */
);
if( !hSvc ) winhttp_fatal("create", zSvcName, win32_get_last_errmsg());
/* Set the service description. */
ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
fossil_print("Service '%s' successfully created.\n", zSvcName);
CloseServiceHandle(hSvc);
CloseServiceHandle(hScm);
}else
if( strncmp(zMethod, "delete", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_STATUS sstat;
verify_all_options();
if( g.argc==4 ){
zSvcName = g.argv[3];
}else if( g.argc>4 ){
fossil_fatal("too many arguments for delete method.");
}
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if( !hScm ) winhttp_fatal("delete", zSvcName, win32_get_last_errmsg());
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
SERVICE_ALL_ACCESS);
if( !hSvc ) winhttp_fatal("delete", zSvcName, win32_get_last_errmsg());
QueryServiceStatus(hSvc, &sstat);
if( sstat.dwCurrentState!=SERVICE_STOPPED ){
fossil_print("Stopping service '%s'", zSvcName);
if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
if( !ControlService(hSvc, SERVICE_CONTROL_STOP, &sstat) ){
winhttp_fatal("delete", zSvcName, win32_get_last_errmsg());
}
}
while( sstat.dwCurrentState!=SERVICE_STOPPED ){
Sleep(100);
fossil_print(".");
QueryServiceStatus(hSvc, &sstat);
}
fossil_print("\nService '%s' stopped.\n", zSvcName);
}
if( !DeleteService(hSvc) ){
if( GetLastError()==ERROR_SERVICE_MARKED_FOR_DELETE ){
fossil_warning("Service '%s' already marked for delete.\n", zSvcName);
}else{
winhttp_fatal("delete", zSvcName, win32_get_last_errmsg());
}
}else{
fossil_print("Service '%s' successfully deleted.\n", zSvcName);
}
CloseServiceHandle(hSvc);
CloseServiceHandle(hScm);
}else
if( strncmp(zMethod, "show", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_STATUS sstat;
LPQUERY_SERVICE_CONFIGW pSvcConfig;
LPSERVICE_DESCRIPTIONW pSvcDescr;
BOOL bStatus;
DWORD nRequired;
static const char *const zSvcTypes[] = {
"Driver service",
"File system driver service",
"Service runs in its own process",
"Service shares a process with other services",
"Service can interact with the desktop"
};
|
| ︙ | ︙ | |||
846 847 848 849 850 851 852 |
verify_all_options();
if( g.argc==4 ){
zSvcName = g.argv[3];
}else if( g.argc>4 ){
fossil_fatal("too many arguments for show method.");
}
hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ);
| | | | | | | | | 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 |
verify_all_options();
if( g.argc==4 ){
zSvcName = g.argv[3];
}else if( g.argc>4 ){
fossil_fatal("too many arguments for show method.");
}
hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ);
if( !hScm ) winhttp_fatal("show", zSvcName, win32_get_last_errmsg());
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
if( !hSvc ) winhttp_fatal("show", zSvcName, win32_get_last_errmsg());
/* Get the service configuration */
bStatus = QueryServiceConfigW(hSvc, NULL, 0, &nRequired);
if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
winhttp_fatal("show", zSvcName, win32_get_last_errmsg());
}
pSvcConfig = fossil_malloc(nRequired);
bStatus = QueryServiceConfigW(hSvc, pSvcConfig, nRequired, &nRequired);
if( !bStatus ) winhttp_fatal("show", zSvcName, win32_get_last_errmsg());
/* Translate the service type */
switch( pSvcConfig->dwServiceType ){
case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break;
case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break;
case SERVICE_WIN32_OWN_PROCESS: zSvcType = zSvcTypes[2]; break;
case SERVICE_WIN32_SHARE_PROCESS: zSvcType = zSvcTypes[3]; break;
case SERVICE_INTERACTIVE_PROCESS: zSvcType = zSvcTypes[4]; break;
}
/* Translate the service start type */
switch( pSvcConfig->dwStartType ){
case SERVICE_BOOT_START: zSvcStartType = zSvcStartTypes[0]; break;
case SERVICE_SYSTEM_START: zSvcStartType = zSvcStartTypes[1]; break;
case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break;
case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break;
case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break;
}
/* Get the service description. */
bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION,
NULL, 0, &nRequired);
if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
winhttp_fatal("show", zSvcName, win32_get_last_errmsg());
}
pSvcDescr = fossil_malloc(nRequired);
bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION,
(LPBYTE)pSvcDescr, nRequired, &nRequired);
if( !bStatus ) winhttp_fatal("show", zSvcName, win32_get_last_errmsg());
/* Retrieves the current status of the specified service. */
bStatus = QueryServiceStatus(hSvc, &sstat);
if( !bStatus ) winhttp_fatal("show", zSvcName, win32_get_last_errmsg());
/* Translate the current state. */
switch( sstat.dwCurrentState ){
case SERVICE_STOPPED: zSvcState = zSvcStates[0]; break;
case SERVICE_START_PENDING: zSvcState = zSvcStates[1]; break;
case SERVICE_STOP_PENDING: zSvcState = zSvcStates[2]; break;
case SERVICE_RUNNING: zSvcState = zSvcStates[3]; break;
case SERVICE_CONTINUE_PENDING: zSvcState = zSvcStates[4]; break;
|
| ︙ | ︙ | |||
919 920 921 922 923 924 925 |
CloseServiceHandle(hSvc);
CloseServiceHandle(hScm);
}else
if( strncmp(zMethod, "start", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_STATUS sstat;
| < | | | < | | | | 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 |
CloseServiceHandle(hSvc);
CloseServiceHandle(hScm);
}else
if( strncmp(zMethod, "start", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_STATUS sstat;
verify_all_options();
if( g.argc==4 ){
zSvcName = g.argv[3];
}else if( g.argc>4 ){
fossil_fatal("too many arguments for start method.");
}
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if( !hScm ) winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
SERVICE_ALL_ACCESS);
if( !hSvc ) winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
QueryServiceStatus(hSvc, &sstat);
if( sstat.dwCurrentState!=SERVICE_RUNNING ){
fossil_print("Starting service '%s'", zSvcName);
if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
if( !StartServiceW(hSvc, 0, NULL) ){
winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
}
}
while( sstat.dwCurrentState!=SERVICE_RUNNING ){
Sleep(100);
fossil_print(".");
QueryServiceStatus(hSvc, &sstat);
}
fossil_print("\nService '%s' started.\n", zSvcName);
}else{
fossil_print("Service '%s' is already started.\n", zSvcName);
}
CloseServiceHandle(hSvc);
CloseServiceHandle(hScm);
}else
if( strncmp(zMethod, "stop", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_STATUS sstat;
verify_all_options();
if( g.argc==4 ){
zSvcName = g.argv[3];
}else if( g.argc>4 ){
fossil_fatal("too many arguments for stop method.");
}
hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if( !hScm ) winhttp_fatal("stop", zSvcName, win32_get_last_errmsg());
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
SERVICE_ALL_ACCESS);
if( !hSvc ) winhttp_fatal("stop", zSvcName, win32_get_last_errmsg());
QueryServiceStatus(hSvc, &sstat);
if( sstat.dwCurrentState!=SERVICE_STOPPED ){
fossil_print("Stopping service '%s'", zSvcName);
if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
if( !ControlService(hSvc, SERVICE_CONTROL_STOP, &sstat) ){
winhttp_fatal("stop", zSvcName, win32_get_last_errmsg());
}
}
while( sstat.dwCurrentState!=SERVICE_STOPPED ){
Sleep(100);
fossil_print(".");
QueryServiceStatus(hSvc, &sstat);
}
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
309 310 311 312 313 314 315 |
};
int i;
Blob src, delta;
int size = 0;
int srcId = 0;
for(i=0; srcId==0 && i<count(azQuery); i++){
| | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
};
int i;
Blob src, delta;
int size = 0;
int srcId = 0;
for(i=0; srcId==0 && i<count(azQuery); i++){
srcId = db_int(0, azQuery[i] /*works-like:"%d"*/, rid);
}
if( srcId>0
&& (pXfer->syncPrivate || !content_is_private(srcId))
&& content_get(srcId, &src)
){
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcId);
blob_delta_create(&src, pContent, &delta);
|
| ︙ | ︙ | |||
420 421 422 423 424 425 426 |
if( uuid_is_shunned(blob_str(pUuid)) ){
blob_reset(&uuid);
return;
}
if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
pXfer->mxSend<=blob_size(pXfer->pOut) ){
const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
| | | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
if( uuid_is_shunned(blob_str(pUuid)) ){
blob_reset(&uuid);
return;
}
if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
pXfer->mxSend<=blob_size(pXfer->pOut) ){
const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
blob_appendf(pXfer->pOut, zFormat /*works-like:"%b"*/, pUuid);
pXfer->nIGotSent++;
blob_reset(&uuid);
return;
}
if( nativeDelta ){
size = send_delta_native(pXfer, rid, isPriv, pUuid);
if( size ){
|
| ︙ | ︙ | |||
452 453 454 455 456 457 458 |
}
blob_reset(&content);
}
remote_has(rid);
blob_reset(&uuid);
#if 0
if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
| | | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
}
blob_reset(&content);
}
remote_has(rid);
blob_reset(&uuid);
#if 0
if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
blob_append(pXfer->pOut, "\n", 1);
}
#endif
}
/*
** Send the file identified by rid as a compressed artifact. Basically,
** send the content exactly as it appears in the BLOB table using
|
| ︙ | ︙ | |||
512 513 514 515 516 517 518 |
pXfer->nDeltaSent++;
}else{
pXfer->nFileSent++;
}
blob_appendf(pXfer->pOut, "%d %d\n", szU, szC);
blob_append(pXfer->pOut, zContent, szC);
if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
| | | 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
pXfer->nDeltaSent++;
}else{
pXfer->nFileSent++;
}
blob_appendf(pXfer->pOut, "%d %d\n", szU, szC);
blob_append(pXfer->pOut, zContent, szC);
if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
blob_append(pXfer->pOut, "\n", 1);
}
if( !isPrivate && srcIsPrivate ){
blob_reset(&fullContent);
}
}
db_reset(&q1);
}
|
| ︙ | ︙ | |||
709 710 711 712 713 714 715 |
md5sum_blob(&cluster, &cksum);
blob_appendf(&cluster, "Z %b\n", &cksum);
blob_reset(&cksum);
rid = content_put(&cluster);
blob_reset(&cluster);
nUncl -= nRow;
nRow = 0;
| | | | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 |
md5sum_blob(&cluster, &cksum);
blob_appendf(&cluster, "Z %b\n", &cksum);
blob_reset(&cksum);
rid = content_put(&cluster);
blob_reset(&cluster);
nUncl -= nRow;
nRow = 0;
blob_append_sql(&deleteWhere, ",%d", rid);
}
}
db_finalize(&q);
db_multi_exec(
"DELETE FROM unclustered WHERE rid NOT IN (0 %s)"
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=unclustered.rid)",
blob_sql_text(&deleteWhere)
);
blob_reset(&deleteWhere);
if( nRow>0 ){
md5sum_blob(&cluster, &cksum);
blob_appendf(&cluster, "Z %b\n", &cksum);
blob_reset(&cksum);
content_put(&cluster);
|
| ︙ | ︙ | |||
1494 1495 1496 1497 1498 1499 1500 |
if( syncFlags & SYNC_PUSH ){
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
nCardSent++;
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
}
if( syncFlags & SYNC_VERBOSE ){
| > | | 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 |
if( syncFlags & SYNC_PUSH ){
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
nCardSent++;
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
}
if( syncFlags & SYNC_VERBOSE ){
fossil_print(zLabelFormat /*works-like:"%s%s%s%s%d"*/,
"", "Bytes", "Cards", "Artifacts", "Deltas");
}
while( go ){
int newPhantom = 0;
char *zRandomness;
db_begin_transaction();
db_record_repository_filename(0);
|
| ︙ | ︙ | |||
1591 1592 1593 1594 1595 1596 1597 |
nErr++;
go = 2;
break;
}
/* Output current stats */
if( syncFlags & SYNC_VERBOSE ){
| | > | | 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 |
nErr++;
go = 2;
break;
}
/* Output current stats */
if( syncFlags & SYNC_VERBOSE ){
fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
xfer.nFileSent, xfer.nDeltaSent);
}else{
nRoundtrip++;
nArtifactSent += xfer.nFileSent + xfer.nDeltaSent;
fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
nRoundtrip, nArtifactSent, nArtifactRcvd);
}
nCardSent = 0;
nCardRcvd = 0;
xfer.nFileSent = 0;
xfer.nDeltaSent = 0;
xfer.nGimmeSent = 0;
xfer.nIGotSent = 0;
|
| ︙ | ︙ | |||
1812 1813 1814 1815 1816 1817 1818 |
**
** If the "login failed" message is seen, clear the sync password prior
** to the next cycle.
*/
if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
char *zMsg = blob_terminate(&xfer.aToken[1]);
defossilize(zMsg);
| | | 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 |
**
** If the "login failed" message is seen, clear the sync password prior
** to the next cycle.
*/
if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
char *zMsg = blob_terminate(&xfer.aToken[1]);
defossilize(zMsg);
if( (syncFlags & SYNC_PUSH) && zMsg && sqlite3_strglob("pull only *", zMsg)==0 ){
syncFlags &= ~SYNC_PUSH;
zMsg = 0;
}
if( zMsg && zMsg[0] ){
fossil_force_newline();
fossil_print("Server says: %s\n", zMsg);
}
|
| ︙ | ︙ | |||
1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 |
go = 1;
if( g.cgiOutput==0 ){
g.url.flags |= URL_PROMPT_PW;
g.url.flags &= ~URL_PROMPTED;
url_prompt_for_password();
url_remember();
}
}
}else{
blob_appendf(&xfer.err, "server says: %s\n", zMsg);
nErr++;
}
break;
}
| > > | 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 |
go = 1;
if( g.cgiOutput==0 ){
g.url.flags |= URL_PROMPT_PW;
g.url.flags &= ~URL_PROMPTED;
url_prompt_for_password();
url_remember();
}
}else{
nErr++;
}
}else{
blob_appendf(&xfer.err, "server says: %s\n", zMsg);
nErr++;
}
break;
}
|
| ︙ | ︙ | |||
1896 1897 1898 1899 1900 1901 1902 |
if( (configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT))!=0
&& (configRcvMask & CONFIGSET_OLDFORMAT)!=0
){
configure_finalize_receive();
}
origConfigRcvMask = 0;
if( nCardRcvd>0 && (syncFlags & SYNC_VERBOSE) ){
| | > | | 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 |
if( (configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT))!=0
&& (configRcvMask & CONFIGSET_OLDFORMAT)!=0
){
configure_finalize_receive();
}
origConfigRcvMask = 0;
if( nCardRcvd>0 && (syncFlags & SYNC_VERBOSE) ){
fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Received:",
blob_size(&recv), nCardRcvd,
xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
}else{
fossil_print(zBriefFormat /*works-like:"%d%d%d"*/,
nRoundtrip, nArtifactSent, nArtifactRcvd);
}
blob_reset(&recv);
nCycle++;
/* If we received one or more files on the previous exchange but
** there are still phantoms, then go another round.
*/
|
| ︙ | ︙ |
Changes to win/Makefile.dmc.
| ︙ | ︙ | |||
38 39 40 41 42 43 44 | RC=$(DMDIR)\bin\rcc RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ APPNAME = $(OBJDIR)\fossil$(E) all: $(APPNAME) | | > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | RC=$(DMDIR)\bin\rcc RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ APPNAME = $(OBJDIR)\fossil$(E) all: $(APPNAME) $(APPNAME) : translate$E mkindex$E codecheck1$E headers $(OBJ) $(OBJDIR)\link cd $(OBJDIR) codecheck1$E $(SRC) $(DMDIR)\bin\link @link $(OBJDIR)\fossil.res: $B\win\fossil.rc $(RC) $(RCFLAGS) -o$@ $** $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res +echo add allrepo attach bag bisect blob branch browse cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| ︙ | ︙ | |||
62 63 64 65 66 67 68 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) -o$@ $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) -o$@ $** | | > > > | | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) -o$@ $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) -o$@ $** mkversion$E: $(SRCDIR)\mkversion.c $(BCC) -o$@ $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) -o$@ $** $(OBJDIR)\shell$O : $(SRCDIR)\shell.c $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $** $(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c $(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $** $(OBJDIR)\th$O : $(SRCDIR)\th.c $(TCC) -o$@ -c $** $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c $(TCC) -o$@ -c $** $(OBJDIR)\cson_amalgamation.h : $(SRCDIR)\cson_amalgamation.h cp $@ $@ VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION +$** > $@ page_index.h: mkindex$E $(SRC) +$** > $@ clean: -del $(OBJDIR)\*.obj -del *.obj *_.c *.h *.map realclean: -del $(APPNAME) translate$E mkindex$E makeheaders$E mkversion$E codecheck1$E $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h |
| ︙ | ︙ |
Changes to win/Makefile.mingw.
| ︙ | ︙ | |||
111 112 113 114 115 116 117 | ZLIBDIR = $(SRCDIR)/../compat/zlib #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | ZLIBDIR = $(SRCDIR)/../compat/zlib #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1j/include OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1j #### Either the directory where the Tcl library is installed or the Tcl # source code directory resides (depending on the value of the macro # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, # this directory must have "include" and "lib" sub-directories. If # this points to the Tcl source code directory, this directory must # have "generic" and "win" sub-directories. The recommended usage |
| ︙ | ︙ | |||
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | # recognized internally by make. # ifdef USE_WINDOWS TRANSLATE = $(subst /,\,$(OBJDIR)/translate.exe) MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe) MKINDEX = $(subst /,\,$(OBJDIR)/mkindex.exe) VERSION = $(subst /,\,$(OBJDIR)/version.exe) CAT = type CP = copy GREP = find MV = copy RM = del /Q MKDIR = -mkdir RMDIR = rmdir /S /Q else TRANSLATE = $(OBJDIR)/translate.exe MAKEHEADERS = $(OBJDIR)/makeheaders.exe MKINDEX = $(OBJDIR)/mkindex.exe VERSION = $(OBJDIR)/version.exe CAT = cat CP = cp GREP = grep MV = mv RM = rm -f MKDIR = -mkdir -p RMDIR = rm -rf | > > | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | # recognized internally by make. # ifdef USE_WINDOWS TRANSLATE = $(subst /,\,$(OBJDIR)/translate.exe) MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe) MKINDEX = $(subst /,\,$(OBJDIR)/mkindex.exe) VERSION = $(subst /,\,$(OBJDIR)/version.exe) CODECHECK1 = $(subst /,\,$(OBJDIR)/codecheck1.exe) CAT = type CP = copy GREP = find MV = copy RM = del /Q MKDIR = -mkdir RMDIR = rmdir /S /Q else TRANSLATE = $(OBJDIR)/translate.exe MAKEHEADERS = $(OBJDIR)/makeheaders.exe MKINDEX = $(OBJDIR)/mkindex.exe VERSION = $(OBJDIR)/version.exe CODECHECK1 = $(OBJDIR)/codecheck1.exe CAT = cat CP = cp GREP = grep MV = mv RM = rm -f MKDIR = -mkdir -p RMDIR = rm -rf |
| ︙ | ︙ | |||
748 749 750 751 752 753 754 755 756 757 758 759 760 761 | $(MKINDEX): $(SRCDIR)/mkindex.c $(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c $(VERSION): $(SRCDIR)/mkversion.c $(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION) | > > > | 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 | $(MKINDEX): $(SRCDIR)/mkindex.c $(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c $(VERSION): $(SRCDIR)/mkversion.c $(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c $(CODECHECK1): $(SRCDIR)/codecheck1.c $(BCC) -o $(CODECHECK1) $(SRCDIR)/codecheck1.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION) |
| ︙ | ︙ | |||
813 814 815 816 817 818 819 | APPTARGETS += $(LIBTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif | | > | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 | APPTARGETS += $(LIBTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif $(APPNAME): $(OBJDIR)/headers $(CODECHECK1) $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(APPTARGETS) $(CODECHECK1) $(TRANS_SRC) $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop |
| ︙ | ︙ |
Changes to win/Makefile.mingw.mistachkin.
| ︙ | ︙ | |||
111 112 113 114 115 116 117 | ZLIBDIR = $(SRCDIR)/../compat/zlib #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | ZLIBDIR = $(SRCDIR)/../compat/zlib #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1j/include OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1j #### Either the directory where the Tcl library is installed or the Tcl # source code directory resides (depending on the value of the macro # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, # this directory must have "include" and "lib" sub-directories. If # this points to the Tcl source code directory, this directory must # have "generic" and "win" sub-directories. The recommended usage |
| ︙ | ︙ | |||
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | # recognized internally by make. # ifdef USE_WINDOWS TRANSLATE = $(subst /,\,$(OBJDIR)/translate.exe) MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe) MKINDEX = $(subst /,\,$(OBJDIR)/mkindex.exe) VERSION = $(subst /,\,$(OBJDIR)/version.exe) CAT = type CP = copy GREP = find MV = copy RM = del /Q MKDIR = -mkdir RMDIR = rmdir /S /Q else TRANSLATE = $(OBJDIR)/translate.exe MAKEHEADERS = $(OBJDIR)/makeheaders.exe MKINDEX = $(OBJDIR)/mkindex.exe VERSION = $(OBJDIR)/version.exe CAT = cat CP = cp GREP = grep MV = mv RM = rm -f MKDIR = -mkdir -p RMDIR = rm -rf | > > | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | # recognized internally by make. # ifdef USE_WINDOWS TRANSLATE = $(subst /,\,$(OBJDIR)/translate.exe) MAKEHEADERS = $(subst /,\,$(OBJDIR)/makeheaders.exe) MKINDEX = $(subst /,\,$(OBJDIR)/mkindex.exe) VERSION = $(subst /,\,$(OBJDIR)/version.exe) CODECHECK1 = $(subst /,\,$(OBJDIR)/codecheck1.exe) CAT = type CP = copy GREP = find MV = copy RM = del /Q MKDIR = -mkdir RMDIR = rmdir /S /Q else TRANSLATE = $(OBJDIR)/translate.exe MAKEHEADERS = $(OBJDIR)/makeheaders.exe MKINDEX = $(OBJDIR)/mkindex.exe VERSION = $(OBJDIR)/version.exe CODECHECK1 = $(OBJDIR)/codecheck1.exe CAT = cat CP = cp GREP = grep MV = mv RM = rm -f MKDIR = -mkdir -p RMDIR = rm -rf |
| ︙ | ︙ | |||
748 749 750 751 752 753 754 755 756 757 758 759 760 761 | $(MKINDEX): $(SRCDIR)/mkindex.c $(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c $(VERSION): $(SRCDIR)/mkversion.c $(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION) | > > > | 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 | $(MKINDEX): $(SRCDIR)/mkindex.c $(BCC) -o $(MKINDEX) $(SRCDIR)/mkindex.c $(VERSION): $(SRCDIR)/mkversion.c $(BCC) -o $(VERSION) $(SRCDIR)/mkversion.c $(CODECHECK1): $(SRCDIR)/codecheck1.c $(BCC) -o $(CODECHECK1) $(SRCDIR)/codecheck1.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION) |
| ︙ | ︙ | |||
813 814 815 816 817 818 819 | APPTARGETS += $(LIBTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif | | > | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 | APPTARGETS += $(LIBTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif $(APPNAME): $(OBJDIR)/headers $(CODECHECK1) $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(APPTARGETS) $(CODECHECK1) $(TRANS_SRC) $(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB) $(OBJDIR)/fossil.o # This rule prevents make from using its default rules to try build # an executable named "manifest" out of the file named "manifest.c" # $(SRCDIR)/../manifest: # noop |
| ︙ | ︙ |
Changes to win/Makefile.msc.
1 2 3 4 5 6 7 8 9 10 11 | # ############################################################################## # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl") ############################################################################## # # This file is automatically generated. Instead of editing this # file, edit "makemake.tcl" then run "tclsh makemake.tcl" # to regenerate this file. # B = .. SRCDIR = $B\src | > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "src/makemake.tcl")
##############################################################################
#
# This Makefile will only function correctly if used from a sub-directory
# that is a direct child of the top-level directory for this project.
#
!if !exist("..\.fossil-settings")
!error "Please change the current directory to the one containing this file."
!endif
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B = ..
SRCDIR = $B\src
|
| ︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # be built from source code. The PERLDIR variable should point to # the directory containing the main Perl binary (i.e. "perl.exe"). PERLDIR = C:\Perl\bin PERL = perl.exe # Uncomment to enable debug symbols # DEBUG = 1 # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable miniz usage # FOSSIL_ENABLE_MINIZ = 1 | > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # be built from source code. The PERLDIR variable should point to # the directory containing the main Perl binary (i.e. "perl.exe"). PERLDIR = C:\Perl\bin PERL = perl.exe # Uncomment to enable debug symbols # DEBUG = 1 # Uncomment to support Windows XP with Visual Studio 201x # FOSSIL_ENABLE_WINXP = 1 # Uncomment to enable JSON API # FOSSIL_ENABLE_JSON = 1 # Uncomment to enable miniz usage # FOSSIL_ENABLE_MINIZ = 1 |
| ︙ | ︙ | |||
42 43 44 45 46 47 48 | # Uncomment to enable TH1 hooks # FOSSIL_ENABLE_TH1_HOOKS = 1 # Uncomment to enable Tcl support # FOSSIL_ENABLE_TCL = 1 !ifdef FOSSIL_ENABLE_SSL | | > | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | # Uncomment to enable TH1 hooks # FOSSIL_ENABLE_TH1_HOOKS = 1 # Uncomment to enable Tcl support # FOSSIL_ENABLE_TCL = 1 !ifdef FOSSIL_ENABLE_SSL SSLDIR = $(B)\compat\openssl-1.0.1j SSLINCDIR = $(SSLDIR)\inc32 SSLLIBDIR = $(SSLDIR)\out32 SSLLFLAGS = /nologo /opt:ref /debug SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" !message Using 'x64' platform for OpenSSL... SSLCONFIG = VC-WIN64A no-asm SSLSETUP = ms\do_win64a.bat SSLNMAKE = ms\nt.mak all !elseif "$(PLATFORM)"=="ia64" |
| ︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 101 102 103 104 | !ifdef FOSSIL_ENABLE_TCL INCL = $(INCL) /I$(TCLINCDIR) !endif CFLAGS = /nologo LDFLAGS = /NODEFAULTLIB:msvcrt /MANIFEST:NO !ifdef DEBUG CFLAGS = $(CFLAGS) /Zi /MTd /Od LDFLAGS = $(LDFLAGS) /DEBUG !else CFLAGS = $(CFLAGS) /MT /O2 !endif | > > > > > > > > > > > | 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 | !ifdef FOSSIL_ENABLE_TCL INCL = $(INCL) /I$(TCLINCDIR) !endif CFLAGS = /nologo LDFLAGS = /NODEFAULTLIB:msvcrt /MANIFEST:NO !ifdef FOSSIL_ENABLE_WINXP XPCFLAGS = $(XPCFLAGS) /D_USING_V110_SDK71_=1 CFLAGS = $(CFLAGS) $(XPCFLAGS) !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" XPLDFLAGS = $(XPLDFLAGS) /SUBSYSTEM:CONSOLE,5.02 !else XPLDFLAGS = $(XPLDFLAGS) /SUBSYSTEM:CONSOLE,5.01 !endif LDFLAGS = $(LDFLAGS) $(XPLDFLAGS) !endif !ifdef DEBUG CFLAGS = $(CFLAGS) /Zi /MTd /Od LDFLAGS = $(LDFLAGS) /DEBUG !else CFLAGS = $(CFLAGS) /MT /O2 !endif |
| ︙ | ︙ | |||
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | PDBNAME = $(OX)\fossil$(P) APPTARGETS = all: $(OX) $(APPNAME) zlib: @echo Building zlib from "$(ZLIBDIR)"... @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) && popd !ifdef FOSSIL_ENABLE_SSL openssl: @echo Building OpenSSL from "$(SSLDIR)"... !if "$(PERLDIR)" != "" @set PATH=$(PERLDIR);$(PATH) !endif @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd !endif !ifndef FOSSIL_ENABLE_MINIZ APPTARGETS = $(APPTARGETS) zlib !endif !ifdef FOSSIL_ENABLE_SSL !ifdef FOSSIL_BUILD_SSL APPTARGETS = $(APPTARGETS) openssl !endif !endif | > > > > > > > > | > | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | PDBNAME = $(OX)\fossil$(P) APPTARGETS = all: $(OX) $(APPNAME) zlib: @echo Building zlib from "$(ZLIBDIR)"... !ifdef FOSSIL_ENABLE_WINXP @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) "CC=cl $(XPCFLAGS)" "LD=link $(XPLDFLAGS)" && popd !else @pushd "$(ZLIBDIR)" && $(MAKE) /f win32\Makefile.msc $(ZLIB) && popd !endif !ifdef FOSSIL_ENABLE_SSL openssl: @echo Building OpenSSL from "$(SSLDIR)"... !if "$(PERLDIR)" != "" @set PATH=$(PERLDIR);$(PATH) !endif @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd !ifdef FOSSIL_ENABLE_WINXP @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd !else @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd !endif !endif !ifndef FOSSIL_ENABLE_MINIZ APPTARGETS = $(APPTARGETS) zlib !endif !ifdef FOSSIL_ENABLE_SSL !ifdef FOSSIL_BUILD_SSL APPTARGETS = $(APPTARGETS) openssl !endif !endif $(APPNAME) : $(APPTARGETS) translate$E mkindex$E codecheck1$E headers $(OBJ) $(OX)\linkopts cd $(OX) codecheck1$E $(SRC) link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts $(OX)\linkopts: $B\win\Makefile.msc echo $(OX)\add.obj > $@ echo $(OX)\allrepo.obj >> $@ echo $(OX)\attach.obj >> $@ echo $(OX)\bag.obj >> $@ |
| ︙ | ︙ | |||
575 576 577 578 579 580 581 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) $** | | > > > | 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 | makeheaders$E: $(SRCDIR)\makeheaders.c $(BCC) $** mkindex$E: $(SRCDIR)\mkindex.c $(BCC) $** mkversion$E: $(SRCDIR)\mkversion.c $(BCC) $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) $** $(OX)\shell$O : $(SRCDIR)\shell.c $B\win\Makefile.msc $(TCC) /Fo$@ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) -c $(SRCDIR)\shell.c $(OX)\sqlite3$O : $(SRCDIR)\sqlite3.c $B\win\Makefile.msc $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SRCDIR)\sqlite3.c |
| ︙ | ︙ | |||
627 628 629 630 631 632 633 634 635 636 637 638 639 640 | -del translate$P -del mkindex$E -del mkindex$P -del makeheaders$E -del makeheaders$P -del mkversion$E -del mkversion$P $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h | > > | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 | -del translate$P -del mkindex$E -del mkindex$P -del makeheaders$E -del makeheaders$P -del mkversion$E -del mkversion$P -del codecheck1$E -del codecheck1$P $(OBJDIR)\json$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_artifact$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_branch$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_config$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_diff$O : $(SRCDIR)\json_detail.h $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h |
| ︙ | ︙ |
Changes to win/buildmsvc.bat.
| ︙ | ︙ | |||
190 191 192 193 194 195 196 197 198 199 200 | %__ECHO2% PUSHD "%ROOT%\msvcbld" IF ERRORLEVEL 1 ( ECHO Could not change to directory "%ROOT%\msvcbld". GOTO errors ) REM REM NOTE: Attempt to execute NMAKE for the Fossil MSVC makefile, passing REM anything extra from our command line along (e.g. extra options). REM | > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
%__ECHO2% PUSHD "%ROOT%\msvcbld"
IF ERRORLEVEL 1 (
ECHO Could not change to directory "%ROOT%\msvcbld".
GOTO errors
)
REM
REM NOTE: If requested, setup the build environment to refer to the Windows
REM SDK v7.1A, which is required if the binaries are being built with
REM Visual Studio 201x and need to work on Windows XP.
REM
IF DEFINED USE_V110SDK71A (
%_AECHO% Forcing use of the Windows SDK v7.1A...
CALL :fn_UseV110Sdk71A
)
%_VECHO% Path = '%PATH%'
%_VECHO% Include = '%INCLUDE%'
%_VECHO% Lib = '%LIB%'
%_VECHO% NmakeArgs = '%NMAKE_ARGS%'
REM
REM NOTE: Attempt to execute NMAKE for the Fossil MSVC makefile, passing
REM anything extra from our command line along (e.g. extra options).
REM
%__ECHO% nmake /f "%TOOLS%\Makefile.msc" %NMAKE_ARGS% %*
IF ERRORLEVEL 1 (
GOTO errors
)
REM
REM NOTE: Attempt to restore the previously saved directory.
REM
%__ECHO2% POPD
IF ERRORLEVEL 1 (
ECHO Could not restore directory.
GOTO errors
)
GOTO no_errors
:fn_UseV110Sdk71A
IF "%PROCESSOR_ARCHITECTURE%" == "x86" GOTO set_v110Sdk71A_x86
SET PFILES_SDK71A=%ProgramFiles(x86)%
GOTO set_v110Sdk71A_done
:set_v110Sdk71A_x86
SET PFILES_SDK71A=%ProgramFiles%
:set_v110Sdk71A_done
SET PATH=%PFILES_SDK71A%\Microsoft SDKs\Windows\7.1A\Bin;%PATH%
SET INCLUDE=%PFILES_SDK71A%\Microsoft SDKs\Windows\7.1A\Include;%INCLUDE%
IF "%PLATFORM%" == "x64" (
SET LIB=%PFILES_SDK71A%\Microsoft SDKs\Windows\7.1A\Lib\x64;%LIB%
) ELSE (
SET LIB=%PFILES_SDK71A%\Microsoft SDKs\Windows\7.1A\Lib;%LIB%
)
CALL :fn_UnsetVariable PFILES_SDK71A
SET NMAKE_ARGS=%NMAKE_ARGS% FOSSIL_ENABLE_WINXP=1
GOTO :EOF
:fn_UnsetVariable
IF NOT "%1" == "" (
SET %1=
CALL :fn_ResetErrorLevel
)
GOTO :EOF
:fn_ResetErrorLevel
VERIFY > NUL
GOTO :EOF
:fn_SetErrorLevel
VERIFY MAYBE 2> NUL
|
| ︙ | ︙ |
Changes to www/build.wiki.
| ︙ | ︙ | |||
120 121 122 123 124 125 126 | file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to detect and use the latest installed version of MSVC.<br><br>To enable the optional <a href="https://www.openssl.org/">OpenSSL</a> support, first <a href="https://www.openssl.org/source/">download the official source code for OpenSSL</a> and extract it to an appropriately named "<b>openssl-X.Y.ZA</b>" subdirectory within the local [/tree?ci=trunk&name=compat | compat] directory (e.g. | | | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to detect and use the latest installed version of MSVC.<br><br>To enable the optional <a href="https://www.openssl.org/">OpenSSL</a> support, first <a href="https://www.openssl.org/source/">download the official source code for OpenSSL</a> and extract it to an appropriately named "<b>openssl-X.Y.ZA</b>" subdirectory within the local [/tree?ci=trunk&name=compat | compat] directory (e.g. "<b>compat/openssl-1.0.1j</b>"), then make sure that some recent <a href="http://www.perl.org/">Perl</a> binaries are installed locally, and finally run one of the following commands: <blockquote><pre> nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin </pre></blockquote> <blockquote><pre> buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| ︙ | ︙ |