Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge updates from trunk. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | tclRdOnly |
| Files: | files | file ages | folders |
| SHA1: |
ce3b312a1500692ae15bad8b4a5c27db |
| User & Date: | mistachkin 2012-10-16 23:14:32.395 |
Context
|
2012-12-08
| ||
| 06:46 | Merge updates from trunk. check-in: fc7e8d01d4 user: mistachkin tags: tclRdOnly | |
|
2012-10-16
| ||
| 23:14 | Merge updates from trunk. check-in: ce3b312a15 user: mistachkin tags: tclRdOnly | |
| 01:11 | unused variable includeDotFiles <p>struct utimbuf -> struct _utimbuf (compiler warning with mingw-w64) <p>a few "const" additions (lower memory footprint, allows C-compiler to optimize better) check-in: 6032dd51f2 user: jan.nijtmans tags: trunk | |
|
2012-10-07
| ||
| 14:49 | Add the new 'tcl-rdonly' setting to the list of those that should be transferred. check-in: 2335ae4f22 user: mistachkin tags: tclRdOnly | |
Changes
Changes to src/add.c.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 | ** from the local repository. */ #include "config.h" #include "add.h" #include <assert.h> #include <dirent.h> | < < < < < < | | 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 |
** from the local repository.
*/
#include "config.h"
#include "add.h"
#include <assert.h>
#include <dirent.h>
/*
** This routine returns the names of files in a working checkout that
** are created by Fossil itself, and hence should not be added, deleted,
** or merge, and should be omitted from "clean" and "extra" lists.
**
** Return the N-th name. The first name has N==0. When all names have
** been used, return 0.
*/
const char *fossil_reserved_name(int N){
/* Possible names of the local per-checkout database file and
** its associated journals
*/
static const char *const azName[] = {
"_FOSSIL_",
"_FOSSIL_-journal",
"_FOSSIL_-wal",
"_FOSSIL_-shm",
".fslckout",
".fslckout-journal",
".fslckout-wal",
|
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
".fos-wal",
".fos-shm",
};
/* Names of auxiliary files generated by SQLite when the "manifest"
** properity is enabled
*/
| | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
".fos-wal",
".fos-shm",
};
/* Names of auxiliary files generated by SQLite when the "manifest"
** properity is enabled
*/
static const char *const azManifest[] = {
"manifest",
"manifest.uuid",
};
/* Cached setting "manifest" */
static int cachedManifest = -1;
|
| ︙ | ︙ | |||
214 215 216 217 218 219 220 221 222 |
void add_cmd(void){
int i; /* Loop counter */
int vid; /* Currently checked out version */
int nRoot; /* Full path characters in g.zLocalRoot */
const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
Glob *pIgnore; /* Ignore everything matching this glob pattern */
int caseSensitive; /* True if filenames are case sensitive */
zIgnoreFlag = find_option("ignore",0,1);
| > | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
void add_cmd(void){
int i; /* Loop counter */
int vid; /* Currently checked out version */
int nRoot; /* Full path characters in g.zLocalRoot */
const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
Glob *pIgnore; /* Ignore everything matching this glob pattern */
int caseSensitive; /* True if filenames are case sensitive */
unsigned scanFlags = 0; /* Flags passed to vfile_scan() */
zIgnoreFlag = find_option("ignore",0,1);
if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
capture_case_sensitive_option();
db_must_be_within_tree();
caseSensitive = filenames_are_case_sensitive();
if( zIgnoreFlag==0 ){
zIgnoreFlag = db_get("ignore-glob", 0);
}
vid = db_lget_int("checkout",0);
|
| ︙ | ︙ | |||
248 249 250 251 252 253 254 |
int isDir;
Blob fullName;
file_canonical_name(g.argv[i], &fullName, 0);
zName = blob_str(&fullName);
isDir = file_wd_isdir(zName);
if( isDir==1 ){
| | | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
int isDir;
Blob fullName;
file_canonical_name(g.argv[i], &fullName, 0);
zName = blob_str(&fullName);
isDir = file_wd_isdir(zName);
if( isDir==1 ){
vfile_scan(&fullName, nRoot-1, scanFlags, pIgnore);
}else if( isDir==0 ){
fossil_warning("not found: %s", zName);
}else if( file_access(zName, R_OK) ){
fossil_fatal("cannot open %s", zName);
}else{
char *zTreeName = &zName[nRoot];
db_multi_exec(
|
| ︙ | ︙ | |||
431 432 433 434 435 436 437 |
** --test If given, display instead of run actions
**
** See also: add, rm
*/
void addremove_cmd(void){
Blob path;
const char *zIgnoreFlag = find_option("ignore",0,1);
| | | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
** --test If given, display instead of run actions
**
** See also: add, rm
*/
void addremove_cmd(void){
Blob path;
const char *zIgnoreFlag = find_option("ignore",0,1);
unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
int isTest = find_option("test",0,0)!=0;
int caseSensitive;
int n;
Stmt q;
int vid;
int nAdd = 0;
int nDelete = 0;
|
| ︙ | ︙ | |||
464 465 466 467 468 469 470 |
** the files in the sfile temp table to the set of managed files.
*/
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
n = strlen(g.zLocalRoot);
blob_init(&path, g.zLocalRoot, n-1);
/* now we read the complete file structure into a temp table */
pIgnore = glob_create(zIgnoreFlag);
| | | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
** the files in the sfile temp table to the set of managed files.
*/
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
n = strlen(g.zLocalRoot);
blob_init(&path, g.zLocalRoot, n-1);
/* now we read the complete file structure into a temp table */
pIgnore = glob_create(zIgnoreFlag);
vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
glob_free(pIgnore);
nAdd = add_files_in_sfile(vid, caseSensitive);
/* step 2: search for missing files */
db_prepare(&q,
"SELECT pathname, %Q || pathname, deleted FROM vfile"
" WHERE NOT deleted"
|
| ︙ | ︙ |
Changes to src/browse.c.
| ︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
@ %s(blob_str(&dirname))</h2>
zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix);
if( zD ){
style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
style_submenu_element("All", "All", "%R/dir?name=%t", zD);
}else{
style_submenu_element("All", "All", "%R/dir");
}
}else{
int hasTrunk;
@ <h2>The union of all files from all check-ins
@ %s(blob_str(&dirname))</h2>
hasTrunk = db_exists(
"SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
| > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
@ %s(blob_str(&dirname))</h2>
zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix);
if( zD ){
style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
style_submenu_element("All", "All", "%R/dir?name=%t", zD);
}else{
style_submenu_element("All", "All", "%R/dir");
style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%S",
zUuid);
}
}else{
int hasTrunk;
@ <h2>The union of all files from all check-ins
@ %s(blob_str(&dirname))</h2>
hasTrunk = db_exists(
"SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
|
| ︙ | ︙ | |||
291 292 293 294 295 296 297 |
}
}
db_finalize(&q);
manifest_destroy(pM);
@ </ul></td></tr></table>
style_footer();
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
}
}
db_finalize(&q);
manifest_destroy(pM);
@ </ul></td></tr></table>
style_footer();
}
/*
** Look at all file containing in the version "vid". Construct a
** temporary table named "fileage" that contains the file-id for each
** files, the pathname, the check-in where the file was added, and the
** mtime on that checkin.
*/
int compute_fileage(int vid){
Manifest *pManifest;
ManifestFile *pFile;
int nFile = 0;
double vmtime;
Stmt ins;
Stmt q1, q2, q3;
Stmt upd;
db_multi_exec(
/*"DROP TABLE IF EXISTS temp.fileage;"*/
"CREATE TEMP TABLE fileage("
" fid INTEGER,"
" mid INTEGER,"
" mtime DATETIME,"
" pathname TEXT"
");"
"CREATE INDEX fileage_fid ON fileage(fid);"
);
pManifest = manifest_get(vid, CFTYPE_MANIFEST);
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 ){
db_bind_text(&ins, ":uuid", pFile->zUuid);
db_bind_text(&ins, ":path", pFile->zName);
db_step(&ins);
db_reset(&ins);
nFile++;
}
db_finalize(&ins);
manifest_destroy(pManifest);
db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid");
db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime"
" WHERE fid=:fid AND mid IS NULL");
db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim");
db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid");
while( nFile>0 && vid>0 ){
db_bind_int(&q3, ":vid", vid);
if( db_step(&q3)==SQLITE_ROW ){
vmtime = db_column_double(&q3, 0);
}else{
break;
}
db_reset(&q3);
db_bind_int(&q1, ":mid", vid);
db_bind_int(&upd, ":mid", vid);
db_bind_double(&upd, ":vmtime", vmtime);
while( db_step(&q1)==SQLITE_ROW ){
db_bind_int(&upd, ":fid", db_column_int(&q1, 0));
db_step(&upd);
nFile -= db_changes();
db_reset(&upd);
}
db_reset(&q1);
db_bind_int(&q2, ":vid", vid);
if( db_step(&q2)!=SQLITE_ROW ) break;
vid = db_column_int(&q2, 0);
db_reset(&q2);
}
db_finalize(&q1);
db_finalize(&upd);
db_finalize(&q2);
db_finalize(&q3);
return 0;
}
/*
** WEBPAGE: fileage
**
** Parameters:
** name=VERSION
*/
void fileage_page(void){
int rid;
const char *zName;
char *zBaseTime;
Stmt q;
double baseTime;
int lastMid = -1;
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
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_header("File Ages", zName);
compute_fileage(rid);
baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
zBaseTime = db_text("","SELECT datetime(%.20g,'localtime')", baseTime);
@ <h2>File Ages For Check-in
@ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
@
@ <p>The times given are relative
@ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the
@ check-in time for
@ %z(href("%R/info?name=%T",zName))%h(zName)</a></p>
@
@ <table border=0 cellspacing=0 cellpadding=0>
db_prepare(&q,
"SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname"
" FROM fileage"
" ORDER BY mtime DESC, mid, pathname"
);
while( db_step(&q)==SQLITE_ROW ){
double age = baseTime - db_column_double(&q, 0);
int mid = db_column_int(&q, 2);
const char *zFUuid = db_column_text(&q, 1);
char zAge[200];
if( lastMid!=mid ){
@ <tr><td colspan=3><hr></tr>
lastMid = mid;
if( age*86400.0<120 ){
sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0));
}else if( age*1440.0<90 ){
sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0);
}else if( age*24.0<36 ){
sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0);
}else if( age<365.0 ){
sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age);
}else{
sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0);
}
}else{
zAge[0] = 0;
}
@ <tr>
@ <td>%s(zAge)
@ <td width="25">
@ <td>%z(href("%R/artifact/%S?ln", zFUuid))%h(db_column_text(&q, 3))</a>
@ </tr>
@
}
@ <tr><td colspan=3><hr></tr>
@ </table>
db_finalize(&q);
style_footer();
}
|
Changes to src/captcha.c.
| ︙ | ︙ | |||
96 97 98 99 100 101 102 | z[k] = 0; return z; } #endif /* CAPTCHA==1 */ #if CAPTCHA==2 | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
z[k] = 0;
return z;
}
#endif /* CAPTCHA==1 */
#if CAPTCHA==2
static const char *const azFont2[] = {
/* 0 */
" __ ",
" / \\ ",
"| () |",
" \\__/ ",
/* 1 */
|
| ︙ | ︙ | |||
221 222 223 224 225 226 227 | } z[k] = 0; return z; } #endif /* CAPTCHA==2 */ #if CAPTCHA==3 | | | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
}
z[k] = 0;
return z;
}
#endif /* CAPTCHA==2 */
#if CAPTCHA==3
static const char *const azFont3[] = {
/* 0 */
" ___ ",
" / _ \\ ",
"| | | |",
"| | | |",
"| |_| |",
" \\___/ ",
|
| ︙ | ︙ |
Changes to src/cgi.c.
| ︙ | ︙ | |||
1352 1353 1354 1355 1356 1357 1358 | return 0; } /* ** Name of days and months. */ | | | | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 |
return 0;
}
/*
** Name of days and months.
*/
static const char *const azDays[] =
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0};
static const char *const azMonths[] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
/*
** Returns an RFC822-formatted time string suitable for HTTP headers.
** The timezone is always GMT. The value returned is always a
|
| ︙ | ︙ |
Changes to src/checkin.c.
| ︙ | ︙ | |||
158 159 160 161 162 163 164 |
int showHdr = find_option("header",0,0)!=0;
int verbose = find_option("verbose","v",0)!=0;
int cwdRelative = 0;
db_must_be_within_tree();
cwdRelative = determine_cwd_relative_option();
blob_zero(&report);
vid = db_lget_int("checkout", 0);
| | | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
int showHdr = find_option("header",0,0)!=0;
int verbose = find_option("verbose","v",0)!=0;
int cwdRelative = 0;
db_must_be_within_tree();
cwdRelative = determine_cwd_relative_option();
blob_zero(&report);
vid = db_lget_int("checkout", 0);
vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0);
status_report(&report, "", 0, cwdRelative);
if( verbose && blob_size(&report)==0 ){
blob_append(&report, " (none)\n", -1);
}
if( showHdr && blob_size(&report)>0 ){
fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
g.zLocalRoot);
|
| ︙ | ︙ | |||
203 204 205 206 207 208 209 210 211 212 213 |
vid = db_lget_int("checkout", 0);
if( vid ){
show_common_info(vid, "checkout:", 1, 1);
}
db_record_repository_filename(0);
changes_cmd();
}
/*
** COMMAND: ls
**
| > > > > > | | > > > > > > > > > > > > | > | > > > > > > > | | | | > > > | | 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 |
vid = db_lget_int("checkout", 0);
if( vid ){
show_common_info(vid, "checkout:", 1, 1);
}
db_record_repository_filename(0);
changes_cmd();
}
/*
** Implementation of the checkin_mtime SQL function
*/
/*
** COMMAND: ls
**
** Usage: %fossil ls ?OPTIONS? ?VERSION?
**
** Show the names of all files in the current checkout. The -l provides
** extra information about each file.
**
** Options:
** -l Provide extra information about each file.
** --age Show when each file was committed
**
** See also: changes, extra, status
*/
void ls_cmd(void){
int vid;
Stmt q;
int isBrief;
int showAge;
char *zOrderBy = "pathname";
isBrief = find_option("l","l", 0)==0;
showAge = find_option("age",0,0)!=0;
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
if( find_option("t","t",0)!=0 ){
if( showAge ){
zOrderBy = mprintf("checkin_mtime(%d,rid) DESC", vid);
}else{
zOrderBy = "mtime DESC";
}
}
verify_all_options();
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','localtime')"
" FROM vfile"
" ORDER BY %s", vid, zOrderBy
);
}else{
db_prepare(&q,
"SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
" FROM vfile"
" ORDER BY %s", zOrderBy
);
}
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;
int chnged = db_column_int(&q,3);
int renamed = db_column_int(&q,4);
char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
if( showAge ){
fossil_print("%s %s\n", db_column_text(&q, 5), zPathname);
}else if( isBrief ){
fossil_print("%s\n", zPathname);
}else if( isNew ){
fossil_print("ADDED %s\n", zPathname);
}else if( isDeleted ){
fossil_print("DELETED %s\n", zPathname);
}else if( !file_wd_isfile_or_link(zFullName) ){
if( file_access(zFullName, 0)==0 ){
|
| ︙ | ︙ | |||
294 295 296 297 298 299 300 |
*/
void extra_cmd(void){
Blob path;
Blob repo;
Stmt q;
int n;
const char *zIgnoreFlag = find_option("ignore",0,1);
| | > | | 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 |
*/
void extra_cmd(void){
Blob path;
Blob repo;
Stmt q;
int n;
const char *zIgnoreFlag = find_option("ignore",0,1);
unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
int cwdRelative = 0;
Glob *pIgnore;
Blob rewrittenPathname;
const char *zPathname, *zDisplayName;
if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
db_must_be_within_tree();
cwdRelative = determine_cwd_relative_option();
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
filename_collation());
n = strlen(g.zLocalRoot);
blob_init(&path, g.zLocalRoot, n-1);
if( zIgnoreFlag==0 ){
zIgnoreFlag = db_get("ignore-glob", 0);
}
pIgnore = glob_create(zIgnoreFlag);
vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
glob_free(pIgnore);
db_prepare(&q,
"SELECT x FROM sfile"
" WHERE x NOT IN (%s)"
" ORDER BY 1",
fossil_all_reserved_names()
);
|
| ︙ | ︙ | |||
365 366 367 368 369 370 371 372 373 374 375 376 |
** is used if the --ignore option is omitted.
**
** Options:
** --dotfiles include files beginning with a dot (".")
** --force Remove files without prompting
** --ignore <CSG> ignore files matching patterns from the
** comma separated list of glob patterns.
**
** See also: addremove, extra, status
*/
void clean_cmd(void){
int allFlag;
| > | | > | | 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 |
** is used if the --ignore option is omitted.
**
** Options:
** --dotfiles include files beginning with a dot (".")
** --force Remove files without prompting
** --ignore <CSG> ignore files matching patterns from the
** comma separated list of glob patterns.
** --temp Remove only Fossil-generated temporary files
**
** See also: addremove, extra, status
*/
void clean_cmd(void){
int allFlag;
unsigned scanFlags = 0;
const char *zIgnoreFlag;
Blob path, repo;
Stmt q;
int n;
Glob *pIgnore;
allFlag = find_option("force","f",0)!=0;
if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
zIgnoreFlag = find_option("ignore",0,1);
db_must_be_within_tree();
if( zIgnoreFlag==0 ){
zIgnoreFlag = db_get("ignore-glob", 0);
}
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
n = strlen(g.zLocalRoot);
blob_init(&path, g.zLocalRoot, n-1);
pIgnore = glob_create(zIgnoreFlag);
vfile_scan(&path, blob_size(&path), scanFlags, pIgnore);
glob_free(pIgnore);
db_prepare(&q,
"SELECT %Q || x FROM sfile"
" WHERE x NOT IN (%s)"
" ORDER BY 1",
g.zLocalRoot, fossil_all_reserved_names()
);
|
| ︙ | ︙ | |||
801 802 803 804 805 806 807 |
blob_appendf(pOut, "T *branch * %F\n", zBranch);
blob_appendf(pOut, "T *sym-%F *\n", zBranch);
}
if( zColor && zColor[0] ){
/* One-time background color */
blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
}
| < < < < | 832 833 834 835 836 837 838 839 840 841 842 843 844 845 |
blob_appendf(pOut, "T *branch * %F\n", zBranch);
blob_appendf(pOut, "T *sym-%F *\n", zBranch);
}
if( zColor && zColor[0] ){
/* One-time background color */
blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
}
if( azTag ){
for(i=0; azTag[i]; i++){
/* Add a symbolic tag to this check-in. The tag names have already
** been sorted and converted using the %F format */
blob_appendf(pOut, "T +sym-%s *\n", azTag[i]);
}
}
|
| ︙ | ︙ |
Changes to src/checkout.c.
| ︙ | ︙ | |||
31 32 33 34 35 36 37 |
** 2: There is no existing checkout
*/
int unsaved_changes(void){
int vid;
db_must_be_within_tree();
vid = db_lget_int("checkout",0);
if( vid==0 ) return 2;
| | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
** 2: There is no existing checkout
*/
int unsaved_changes(void){
int vid;
db_must_be_within_tree();
vid = db_lget_int("checkout",0);
if( vid==0 ) return 2;
vfile_check_signature(vid, CKSIG_ENOTFILE);
return db_exists("SELECT 1 FROM vfile WHERE chnged"
" OR coalesce(origname!=pathname,0)");
}
/*
** Undo the current check-out. Unlink all files from the disk.
** Clear the VFILE table.
|
| ︙ | ︙ |
Changes to src/content.c.
| ︙ | ︙ | |||
892 893 894 895 896 897 898 |
blob_reset(&content);
n2++;
}
db_finalize(&q);
fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
n2, n1, nErr);
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 |
blob_reset(&content);
n2++;
}
db_finalize(&q);
fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
n2, n1, nErr);
}
/*
** COMMAND: test-orphans
**
** Search the repository for orphaned artifacts
*/
void test_orphans(void){
Stmt q;
int cnt = 0;
db_find_and_open_repository(0, 0);
db_multi_exec(
"CREATE TEMP TABLE used(id INTEGER PRIMARY KEY ON CONFLICT IGNORE);"
"INSERT INTO used SELECT mid FROM mlink;" /* Manifests */
"INSERT INTO used SELECT fid FROM mlink;" /* Files */
"INSERT INTO used SELECT srcid FROM tagxref WHERE srcid>0;" /* Tags */
"INSERT INTO used SELECT rid FROM tagxref;" /* Wiki & tickets */
"INSERT INTO used SELECT rid FROM attachment JOIN blob ON src=uuid;"
"INSERT INTO used SELECT attachid FROM attachment;"
"INSERT INTO used SELECT objid FROM event;"
);
db_prepare(&q, "SELECT rid, uuid, size FROM blob WHERE rid NOT IN used");
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%7d %s size: %d\n",
db_column_int(&q, 0),
db_column_text(&q, 1),
db_column_int(&q,2));
cnt++;
}
db_finalize(&q);
fossil_print("%d orphans\n", cnt);
}
|
Changes to src/db.c.
| ︙ | ︙ | |||
674 675 676 677 678 679 680 681 682 683 684 685 686 687 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_result_int64(context, time(0));
}
/*
** Open a database file. Return a pointer to the new database
** connection. An error results in process abort.
*/
static sqlite3 *openDatabase(const char *zDbName){
int rc;
| > > > > > > > > > > > > > > > > | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_result_int64(context, time(0));
}
/*
** Function to return the check-in time for a file.
*/
void db_checkin_mtime_function(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
i64 mtime;
int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
sqlite3_value_int(argv[1]), &mtime);
if( rc==0 ){
sqlite3_result_int64(context, mtime);
}
}
/*
** Open a database file. Return a pointer to the new database
** connection. An error results in process abort.
*/
static sqlite3 *openDatabase(const char *zDbName){
int rc;
|
| ︙ | ︙ | |||
696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
);
if( rc!=SQLITE_OK ){
db_err(sqlite3_errmsg(db));
}
sqlite3_busy_timeout(db, 5000);
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
return db;
}
/*
** Detaches the zLabel database.
*/
| > > | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 |
);
if( rc!=SQLITE_OK ){
db_err(sqlite3_errmsg(db));
}
sqlite3_busy_timeout(db, 5000);
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
db_checkin_mtime_function, 0, 0);
return db;
}
/*
** Detaches the zLabel database.
*/
|
| ︙ | ︙ | |||
720 721 722 723 724 725 726 | } /* ** 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. */ | | | 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 |
}
/*
** 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.
*/
void db_open_or_attach(const char *zDbName, const char *zLabel){
if( !g.db ){
g.db = openDatabase(zDbName);
g.zMainDbType = zLabel;
db_connection_init();
}else{
db_attach(zDbName, zLabel);
}
|
| ︙ | ︙ | |||
1589 1590 1591 1592 1593 1594 1595 |
}
}
/*
** Return true if the string zVal represents "true" (or "false").
*/
int is_truth(const char *zVal){
| | | | 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 |
}
}
/*
** Return true if the string zVal represents "true" (or "false").
*/
int is_truth(const char *zVal){
static const char *const azOn[] = { "on", "yes", "true", "1" };
int i;
for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
}
return 0;
}
int is_false(const char *zVal){
static const char *const azOff[] = { "off", "no", "false", "0" };
int i;
for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
}
return 0;
}
|
| ︙ | ︙ |
Changes to src/descendants.c.
| ︙ | ︙ | |||
154 155 156 157 158 159 160 | } } /* ** Load the record ID rid and up to N-1 closest ancestors into ** the "ok" table. */ | | | > | 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 |
}
}
/*
** Load the record ID rid and up to N-1 closest ancestors into
** the "ok" table.
*/
void compute_ancestors(int rid, int N, int directOnly){
Bag seen;
PQueue queue;
Stmt ins;
Stmt q;
bag_init(&seen);
pqueuex_init(&queue);
bag_insert(&seen, rid);
pqueuex_insert(&queue, rid, 0.0, 0);
db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
db_prepare(&q,
"SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
" WHERE a.cid=:rid %s",
directOnly ? " AND a.isprim" : ""
);
while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){
db_bind_int(&ins, ":rid", rid);
db_step(&ins);
db_reset(&ins);
db_bind_int(&q, ":rid", rid);
while( db_step(&q)==SQLITE_ROW ){
|
| ︙ | ︙ | |||
200 201 202 203 204 205 206 |
** direct ancestor as the largest generation number.
*/
void compute_direct_ancestors(int rid, int N){
Stmt ins;
Stmt q;
int gen = 0;
db_multi_exec(
| | > | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
** direct ancestor as the largest generation number.
*/
void compute_direct_ancestors(int rid, int N){
Stmt ins;
Stmt q;
int gen = 0;
db_multi_exec(
"CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER,"
" generation INTEGER PRIMARY KEY);"
"DELETE FROM ancestor;"
"INSERT INTO ancestor VALUES(%d, 0);", rid
);
db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
db_prepare(&q,
"SELECT pid FROM plink"
" WHERE cid=:rid AND isprim"
|
| ︙ | ︙ | |||
223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
db_bind_int(&ins, ":gen", gen);
db_step(&ins);
db_reset(&ins);
}
db_finalize(&ins);
db_finalize(&q);
}
/*
** Load the record ID rid and up to N-1 closest descendants into
** the "ok" table.
*/
void compute_descendants(int rid, int N){
Bag seen;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
db_bind_int(&ins, ":gen", gen);
db_step(&ins);
db_reset(&ins);
}
db_finalize(&ins);
db_finalize(&q);
}
/*
** Compute the "mtime" of the file given whose blob.rid is "fid" that
** is part of check-in "vid". The mtime will be the mtime on vid or
** some ancestor of vid where fid first appears.
*/
int mtime_of_manifest_file(
int vid, /* The check-in that contains fid */
int fid, /* The id of the file whose check-in time is sought */
i64 *pMTime /* Write result here */
){
static int prevVid = -1;
static Stmt q;
if( prevVid!=vid ){
prevVid = vid;
db_multi_exec("DROP TABLE IF EXISTS temp.ok;"
"CREATE TEMP TABLE ok(x INTEGER PRIMARY KEY);");
compute_ancestors(vid, 100000000, 1);
}
db_static_prepare(&q,
"SELECT (max(event.mtime)-2440587.5)*86400 FROM mlink, event"
" WHERE mlink.mid=event.objid"
" AND +mlink.mid IN ok"
" AND mlink.fid=:fid");
db_bind_int(&q, ":fid", fid);
if( db_step(&q)!=SQLITE_ROW ){
db_reset(&q);
return 1;
}
*pMTime = db_column_int64(&q, 0);
db_reset(&q);
return 0;
}
/*
** Load the record ID rid and up to N-1 closest descendants into
** the "ok" table.
*/
void compute_descendants(int rid, int N){
Bag seen;
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
320 321 322 323 324 325 326 |
int vid;
Blob sql;
Stmt q;
int asNewFile; /* Treat non-existant files as empty files */
asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
vid = db_lget_int("checkout", 0);
| | | 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
int vid;
Blob sql;
Stmt q;
int asNewFile; /* Treat non-existant files as empty files */
asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
vid = db_lget_int("checkout", 0);
vfile_check_signature(vid, CKSIG_ENOTFILE);
blob_zero(&sql);
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);
}
|
| ︙ | ︙ |
Changes to src/file.c.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 | /* ** On Windows, include the Platform SDK header file. */ #ifdef _WIN32 # include <direct.h> # include <windows.h> #endif /* ** The file status information from the most recent stat() call. ** ** Use _stati64 rather than stat on windows, in order to handle files ** larger than 2GB. | > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /* ** On Windows, include the Platform SDK header file. */ #ifdef _WIN32 # include <direct.h> # include <windows.h> # include <sys/utime.h> #endif /* ** The file status information from the most recent stat() call. ** ** Use _stati64 rather than stat on windows, in order to handle files ** larger than 2GB. |
| ︙ | ︙ | |||
387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
chmod(zFilename, buf.st_mode & ~0111);
rc = 1;
}
}
#endif /* _WIN32 */
return rc;
}
/*
** Delete a file.
*/
void file_delete(const char *zFilename){
#ifdef _WIN32
wchar_t *z = fossil_utf8_to_unicode(zFilename);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
chmod(zFilename, buf.st_mode & ~0111);
rc = 1;
}
}
#endif /* _WIN32 */
return rc;
}
/*
** Set the mtime for a file.
*/
void file_set_mtime(const char *zFilename, i64 newMTime){
#if !defined(_WIN32)
struct timeval tv[2];
memset(tv, 0, sizeof(tv[0])*2);
tv[0].tv_sec = newMTime;
tv[1].tv_sec = newMTime;
utimes(zFilename, tv);
#else
struct _utimbuf tb;
wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
tb.actime = newMTime;
tb.modtime = newMTime;
_wutime(zMbcs, &tb);
fossil_mbcs_free(zMbcs);
#endif
}
/*
** COMMAND: test-set-mtime
**
** Usage: %fossil test-set-mtime FILENAME DATE/TIME
**
** Sets the mtime of the named file to the date/time shown.
*/
void test_set_mtime(void){
const char *zFile;
char *zDate;
i64 iMTime;
if( g.argc!=4 ){
usage("test-set-mtime FILENAME DATE/TIME");
}
db_open_or_attach(":memory:", "mem");
iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]);
zFile = g.argv[2];
file_set_mtime(zFile, iMTime);
iMTime = file_wd_mtime(zFile);
zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime);
fossil_print("Set mtime of \"%s\" to %s (%lld)\n", zFile, zDate, iMTime);
}
/*
** Delete a file.
*/
void file_delete(const char *zFilename){
#ifdef _WIN32
wchar_t *z = fossil_utf8_to_unicode(zFilename);
|
| ︙ | ︙ |
Changes to src/finfo.c.
| ︙ | ︙ | |||
64 65 66 67 68 69 70 |
int vid;
if( g.argc!=3 ) usage("-s|--status FILENAME");
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_panic("no checkout to finfo files in");
}
| | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
int vid;
if( g.argc!=3 ) usage("-s|--status FILENAME");
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_panic("no checkout to finfo files in");
}
vfile_check_signature(vid, CKSIG_ENOTFILE);
file_tree_name(g.argv[2], &fname, 1);
db_prepare(&q,
"SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
" FROM vfile WHERE vfile.pathname=%B %s",
&fname, filename_collation());
blob_zero(&line);
if ( db_step(&q)==SQLITE_ROW ) {
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
@ ZIP archive</a>
fossil_free(zUrl);
}
@ </td></tr>
@ <tr><th>Other Links:</th>
@ <td>
@ %z(href("%R/dir?ci=%S",zUuid))files</a>
@ | %z(href("%R/artifact/%S",zUuid))manifest</a>
if( g.perm.Write ){
@ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
}
@ </td>
@ </tr>
}
| > | 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
@ ZIP archive</a>
fossil_free(zUrl);
}
@ </td></tr>
@ <tr><th>Other Links:</th>
@ <td>
@ %z(href("%R/dir?ci=%S",zUuid))files</a>
@ | %z(href("%R/fileage?name=%S",zUuid))file ages</a>
@ | %z(href("%R/artifact/%S",zUuid))manifest</a>
if( g.perm.Write ){
@ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
}
@ </td>
@ </tr>
}
|
| ︙ | ︙ | |||
964 965 966 967 968 969 970 |
}else if( pFileTo==0 ){
cmp = -1;
}else{
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
}
if( cmp<0 ){
append_file_change_line(pFileFrom->zName,
| | | | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 |
}else if( pFileTo==0 ){
cmp = -1;
}else{
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
}
if( cmp<0 ){
append_file_change_line(pFileFrom->zName,
pFileFrom->zUuid, 0, 0, diffFlags, 0);
pFileFrom = manifest_file_next(pFrom, 0);
}else if( cmp>0 ){
append_file_change_line(pFileTo->zName,
0, pFileTo->zUuid, 0, diffFlags,
manifest_file_mperm(pFileTo));
pFileTo = manifest_file_next(pTo, 0);
}else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
/* No changes */
pFileFrom = manifest_file_next(pFrom, 0);
pFileTo = manifest_file_next(pTo, 0);
}else{
|
| ︙ | ︙ | |||
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 |
if( !g.perm.Read ){ login_needed(); return; }
if( rid==0 ) fossil_redirect_home();
zMime = P("m");
if( zMime==0 ){
char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
" WHERE mlink.fid=%d"
" AND filename.fnid=mlink.fnid", rid);
if( zFName ) zMime = mimetype_from_name(zFName);
if( zMime==0 ) zMime = "application/x-fossil-artifact";
}
content_get(rid, &content);
cgi_set_content_type(zMime);
cgi_set_content(&content);
}
| > > > > > > | 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 |
if( !g.perm.Read ){ login_needed(); return; }
if( rid==0 ) fossil_redirect_home();
zMime = P("m");
if( zMime==0 ){
char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
" WHERE mlink.fid=%d"
" AND filename.fnid=mlink.fnid", rid);
if( !zFName ){
/* Look also at the attachment table */
zFName = db_text(0, "SELECT attachment.filename FROM attachment, blob"
" WHERE blob.rid=%d"
" AND attachment.src=blob.uuid", rid);
}
if( zFName ) zMime = mimetype_from_name(zFName);
if( zMime==0 ) zMime = "application/x-fossil-artifact";
}
content_get(rid, &content);
cgi_set_content_type(zMime);
cgi_set_content(&content);
}
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
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 |
i += 2;
while( i<g.argc ) newArgv[j++] = g.argv[i++];
newArgv[j] = 0;
g.argc = j;
g.argv = newArgv;
}
/*
** Make a deep copy of the provided argument array and return it.
*/
static char **copy_args(int argc, char **argv){
char **zNewArgv;
int i;
zNewArgv = fossil_malloc( sizeof(char*)*(argc+1) );
memset(zNewArgv, 0, sizeof(char*)*(argc+1));
for(i=0; i<argc; i++){
zNewArgv[i] = fossil_strdup(argv[i]);
}
return zNewArgv;
}
/*
** This procedure runs first.
*/
int main(int argc, char **argv)
{
const char *zCmdName = "unknown";
| > > | 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 |
i += 2;
while( i<g.argc ) newArgv[j++] = g.argv[i++];
newArgv[j] = 0;
g.argc = j;
g.argv = newArgv;
}
#ifdef FOSSIL_ENABLE_TCL
/*
** Make a deep copy of the provided argument array and return it.
*/
static char **copy_args(int argc, char **argv){
char **zNewArgv;
int i;
zNewArgv = fossil_malloc( sizeof(char*)*(argc+1) );
memset(zNewArgv, 0, sizeof(char*)*(argc+1));
for(i=0; i<argc; i++){
zNewArgv[i] = fossil_strdup(argv[i]);
}
return zNewArgv;
}
#endif
/*
** This procedure runs first.
*/
int main(int argc, char **argv)
{
const char *zCmdName = "unknown";
|
| ︙ | ︙ |
Changes to src/merge.c.
| ︙ | ︙ | |||
187 188 189 190 191 192 193 |
" Use --force to override.\n");
return;
}
if( detailFlag ){
print_checkin_description(mid, 12, "merge-from:");
print_checkin_description(pid, 12, "baseline:");
}
| | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
" Use --force to override.\n");
return;
}
if( detailFlag ){
print_checkin_description(mid, 12, "merge-from:");
print_checkin_description(pid, 12, "baseline:");
}
vfile_check_signature(vid, CKSIG_ENOTFILE);
db_begin_transaction();
if( !nochangeFlag ) undo_begin();
load_vfile_from_rid(mid);
load_vfile_from_rid(pid);
if( debugFlag ){
char *z;
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
|
| ︙ | ︙ |
Changes to src/name.c.
| ︙ | ︙ | |||
251 252 253 254 255 256 257 |
zTag, zType
);
if( rid>0 ) return rid;
/* Undocumented: numeric tags get translated directly into the RID */
for(i=0; fossil_isdigit(zTag[i]); i++){}
if( zTag[i]==0 ){
| > > > | | | | | > | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
zTag, zType
);
if( rid>0 ) return rid;
/* Undocumented: numeric tags get translated directly into the RID */
for(i=0; fossil_isdigit(zTag[i]); i++){}
if( zTag[i]==0 ){
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, zType);
}
}
return rid;
}
/*
** This routine takes a user-entered UUID which might be in mixed
|
| ︙ | ︙ |
Changes to src/rebuild.c.
| ︙ | ︙ | |||
923 924 925 926 927 928 929 930 931 932 933 934 935 936 |
** If -L|--prefixlength is given, the length (default 2) of the directory
** prefix can be set to 0,1,..,9 characters.
**
** Options:
** -R|--repository REPOSITORY deconstruct given REPOSITORY
** -L|--prefixlength N set the length of the names of the DESTINATION
** subdirectories to N
**
** See also: rebuild, reconstruct
*/
void deconstruct_cmd(void){
const char *zDestDir;
const char *zPrefixOpt;
Stmt s;
| > | < < < | < < < < < > > > > > > > > > > > > > | < | > | > | 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 |
** If -L|--prefixlength is given, the length (default 2) of the directory
** prefix can be set to 0,1,..,9 characters.
**
** Options:
** -R|--repository REPOSITORY deconstruct given REPOSITORY
** -L|--prefixlength N set the length of the names of the DESTINATION
** subdirectories to N
** --private Include private artifacts.
**
** See also: rebuild, reconstruct
*/
void deconstruct_cmd(void){
const char *zDestDir;
const char *zPrefixOpt;
Stmt s;
int privateFlag;
/* get and check prefix length argument and build format string */
zPrefixOpt=find_option("prefixlength","L",1);
if( !zPrefixOpt ){
prefixLength = 2;
}else{
if( zPrefixOpt[0]>='0' && zPrefixOpt[0]<='9' && !zPrefixOpt[1] ){
prefixLength = (int)(*zPrefixOpt-'0');
}else{
fossil_fatal("N(%s) is not a a valid prefix length!",zPrefixOpt);
}
}
/* open repository and open query for all artifacts */
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
privateFlag = find_option("private",0,0)!=0;
verify_all_options();
/* check number of arguments */
if( g.argc!=3 ){
usage ("?OPTIONS? DESTINATION");
}
/* get and check argument destination directory */
zDestDir = g.argv[g.argc-1];
if( !*zDestDir || !file_isdir(zDestDir)) {
fossil_fatal("DESTINATION(%s) is not a directory!",zDestDir);
}
#ifndef _WIN32
if( file_access(zDestDir, W_OK) ){
fossil_fatal("DESTINATION(%s) is not writeable!",zDestDir);
}
#else
/* write access on windows is not checked, errors will be
** dected on blob_write_to_file
*/
#endif
if( prefixLength ){
zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength);
}else{
zFNameFormat = mprintf("%s/%%s",zDestDir);
}
bag_init(&bagDone);
ttyOutput = 1;
processCnt = 0;
if (!g.fQuiet) {
fossil_print("0 (0%%)...\r");
fflush(stdout);
}
totalSize = db_int(0, "SELECT count(*) FROM blob");
db_prepare(&s,
"SELECT rid, size FROM blob /*scan*/"
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
" AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid) %s",
privateFlag==0 ? "AND rid NOT IN private" : ""
);
while( db_step(&s)==SQLITE_ROW ){
int rid = db_column_int(&s, 0);
int size = db_column_int(&s, 1);
if( size>=0 ){
Blob content;
content_get(rid, &content);
rebuild_step(rid, size, &content);
}
}
db_finalize(&s);
db_prepare(&s,
"SELECT rid, size FROM blob"
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
privateFlag==0 ? "AND rid NOT IN private" : ""
);
while( db_step(&s)==SQLITE_ROW ){
int rid = db_column_int(&s, 0);
int size = db_column_int(&s, 1);
if( size>=0 ){
if( !bag_find(&bagDone, rid) ){
Blob content;
|
| ︙ | ︙ |
Changes to src/report.c.
| ︙ | ︙ | |||
168 169 170 171 172 173 174 |
}
switch( code ){
case SQLITE_SELECT:
case SQLITE_FUNCTION: {
break;
}
case SQLITE_READ: {
| | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
}
switch( code ){
case SQLITE_SELECT:
case SQLITE_FUNCTION: {
break;
}
case SQLITE_READ: {
static const char *const azAllowed[] = {
"ticket",
"blob",
"filename",
"mlink",
"plink",
"event",
"tag",
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
*/
void sqlite3_cmd(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);
}
/*
** 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){
| > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
*/
void sqlite3_cmd(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){
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
| ︙ | ︙ | |||
671 672 673 674 675 676 677 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 | | | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 #define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" /* ** 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 |
| ︙ | ︙ | |||
8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 | SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); /* ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta ** should be one of the following values. The integer values are assigned ** to constants so that the offset of the corresponding field in an ** SQLite database header may be found using the following formula: ** ** offset = 36 + (idx * 4) | > > | 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 | SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); /* ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta ** should be one of the following values. The integer values are assigned ** to constants so that the offset of the corresponding field in an ** SQLite database header may be found using the following formula: ** ** offset = 36 + (idx * 4) |
| ︙ | ︙ | |||
9161 9162 9163 9164 9165 9166 9167 | SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); | > | | | | | > > | 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 | SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); #ifndef SQLITE_OMIT_WAL SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); #endif #ifdef SQLITE_ENABLE_ZIPVFS SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); #endif /* Functions used to query pager state and configuration. */ SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| ︙ | ︙ | |||
12239 12240 12241 12242 12243 12244 12245 | SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); SQLITE_PRIVATE const char *sqlite3JournalModename(int); | > | | > | 12244 12245 12246 12247 12248 12249 12250 12251 12252 12253 12254 12255 12256 12257 12258 12259 12260 12261 | SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*); SQLITE_PRIVATE const char *sqlite3JournalModename(int); #ifndef SQLITE_OMIT_WAL SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). |
| ︙ | ︙ | |||
24940 24941 24942 24943 24944 24945 24946 |
return SQLITE_OK;
}
/*
** Close a file. Make sure the lock has been released before closing.
*/
static int dotlockClose(sqlite3_file *id) {
| | < | > | 24947 24948 24949 24950 24951 24952 24953 24954 24955 24956 24957 24958 24959 24960 24961 24962 24963 24964 24965 24966 24967 |
return SQLITE_OK;
}
/*
** Close a file. Make sure the lock has been released before closing.
*/
static int dotlockClose(sqlite3_file *id) {
int rc = SQLITE_OK;
if( id ){
unixFile *pFile = (unixFile*)id;
dotlockUnlock(id, NO_LOCK);
sqlite3_free(pFile->lockingContext);
rc = closeUnixFile(id);
}
return rc;
}
/****************** End of the dot-file lock implementation *******************
******************************************************************************/
/******************************************************************************
************************** Begin flock Locking ********************************
|
| ︙ | ︙ | |||
25150 25151 25152 25153 25154 25155 25156 25157 25158 25159 |
}
}
/*
** Close a file.
*/
static int flockClose(sqlite3_file *id) {
if( id ){
flockUnlock(id, NO_LOCK);
}
| > > | | 25157 25158 25159 25160 25161 25162 25163 25164 25165 25166 25167 25168 25169 25170 25171 25172 25173 25174 25175 25176 |
}
}
/*
** Close a file.
*/
static int flockClose(sqlite3_file *id) {
int rc = SQLITE_OK;
if( id ){
flockUnlock(id, NO_LOCK);
rc = closeUnixFile(id);
}
return rc;
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
/******************* End of the flock lock implementation *********************
******************************************************************************/
|
| ︙ | ︙ | |||
26952 26953 26954 26955 26956 26957 26958 |
}
pShmNode->apRegion = apNew;
while(pShmNode->nRegion<=iRegion){
void *pMem;
if( pShmNode->h>=0 ){
pMem = mmap(0, szRegion,
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
| | | 26961 26962 26963 26964 26965 26966 26967 26968 26969 26970 26971 26972 26973 26974 26975 |
}
pShmNode->apRegion = apNew;
while(pShmNode->nRegion<=iRegion){
void *pMem;
if( pShmNode->h>=0 ){
pMem = mmap(0, szRegion,
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
goto shmpage_out;
}
}else{
pMem = sqlite3_malloc(szRegion);
|
| ︙ | ︙ | |||
29991 29992 29993 29994 29995 29996 29997 29998 29999 30000 30001 30002 30003 30004 | ** available in Windows platforms based on the NT kernel. */ #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) # error "WAL mode requires support from the Windows NT kernel, compile\ with SQLITE_OMIT_WAL." #endif /* ** Macro to find the minimum of two numeric values. */ #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 30000 30001 30002 30003 30004 30005 30006 30007 30008 30009 30010 30011 30012 30013 30014 30015 30016 30017 30018 30019 30020 30021 30022 30023 30024 30025 30026 30027 30028 30029 30030 30031 30032 30033 30034 30035 30036 30037 30038 30039 30040 30041 30042 30043 30044 30045 30046 30047 30048 30049 30050 30051 30052 30053 30054 30055 30056 30057 30058 30059 30060 30061 30062 30063 30064 |
** available in Windows platforms based on the NT kernel.
*/
#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
# error "WAL mode requires support from the Windows NT kernel, compile\
with SQLITE_OMIT_WAL."
#endif
/*
** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
** based on the sub-platform)?
*/
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
# define SQLITE_WIN32_HAS_ANSI
#endif
/*
** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
** based on the sub-platform)?
*/
#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
# define SQLITE_WIN32_HAS_WIDE
#endif
/*
** Do we need to manually define the Win32 file mapping APIs for use with WAL
** mode (e.g. these APIs are available in the Windows CE SDK; however, they
** are not present in the header file)?
*/
#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
/*
** Two of the file mapping APIs are different under WinRT. Figure out which
** set we need.
*/
#if SQLITE_OS_WINRT
WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
#else
#if defined(SQLITE_WIN32_HAS_ANSI)
WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
DWORD, DWORD, DWORD, LPCSTR);
#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
#if defined(SQLITE_WIN32_HAS_WIDE)
WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
DWORD, DWORD, DWORD, LPCWSTR);
#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#endif /* SQLITE_OS_WINRT */
/*
** This file mapping API is common to both Win32 and WinRT.
*/
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
/*
** Macro to find the minimum of two numeric values.
*/
#ifndef MIN
# define MIN(x,y) ((x)<(y)?(x):(y))
#endif
|
| ︙ | ︙ | |||
30196 30197 30198 30199 30200 30201 30202 | */ #ifdef SQLITE_TEST SQLITE_API int sqlite3_os_type = 0; #else static int sqlite3_os_type = 0; #endif | < < < < < < < < | 30256 30257 30258 30259 30260 30261 30262 30263 30264 30265 30266 30267 30268 30269 | */ #ifdef SQLITE_TEST SQLITE_API int sqlite3_os_type = 0; #else static int sqlite3_os_type = 0; #endif #ifndef SYSCALL # define SYSCALL sqlite3_syscall_ptr #endif /* ** This function is not available on Windows CE or WinRT. */ |
| ︙ | ︙ | |||
42767 42768 42769 42770 42771 42772 42773 | # define DIRECT_MODE 0 assert( isDirectMode==0 ); UNUSED_PARAMETER(isDirectMode); #else # define DIRECT_MODE isDirectMode #endif | | | 42819 42820 42821 42822 42823 42824 42825 42826 42827 42828 42829 42830 42831 42832 42833 |
# define DIRECT_MODE 0
assert( isDirectMode==0 );
UNUSED_PARAMETER(isDirectMode);
#else
# define DIRECT_MODE isDirectMode
#endif
if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
PgHdr *pPgHdr; /* Reference to page 1 */
assert( !pPager->tempFile && isOpen(pPager->fd) );
/* Open page 1 of the file for writing. */
rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
assert( pPgHdr==0 || rc==SQLITE_OK );
|
| ︙ | ︙ | |||
44018 44019 44020 44021 44022 44023 44024 44025 44026 44027 44028 44029 44030 44031 |
pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0;
}
}
return rc;
}
#ifdef SQLITE_ENABLE_ZIPVFS
/*
** A read-lock must be held on the pager when this function is called. If
** the pager is in WAL mode and the WAL file currently contains one or more
** frames, return the size in bytes of the page images stored within the
** WAL frames. Otherwise, if this is not a WAL database or the WAL file
** is empty, return 0.
| > > | 44070 44071 44072 44073 44074 44075 44076 44077 44078 44079 44080 44081 44082 44083 44084 44085 |
pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0;
}
}
return rc;
}
#endif /* !SQLITE_OMIT_WAL */
#ifdef SQLITE_ENABLE_ZIPVFS
/*
** A read-lock must be held on the pager when this function is called. If
** the pager is in WAL mode and the WAL file currently contains one or more
** frames, return the size in bytes of the page images stored within the
** WAL frames. Otherwise, if this is not a WAL database or the WAL file
** is empty, return 0.
|
| ︙ | ︙ | |||
44047 44048 44049 44050 44051 44052 44053 |
SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
void *aData = 0;
CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
return aData;
}
#endif /* SQLITE_HAS_CODEC */
| < < | 44101 44102 44103 44104 44105 44106 44107 44108 44109 44110 44111 44112 44113 44114 |
SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
void *aData = 0;
CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
return aData;
}
#endif /* SQLITE_HAS_CODEC */
#endif /* SQLITE_OMIT_DISKIO */
/************** End of pager.c ***********************************************/
/************** Begin file wal.c *********************************************/
/*
** 2010 February 1
**
|
| ︙ | ︙ | |||
46572 46573 46574 46575 46576 46577 46578 |
** are no outstanding references to any page other than page 1. And
** page 1 is never written to the log until the transaction is
** committed. As a result, the call to xUndo may not fail.
*/
assert( walFramePgno(pWal, iFrame)!=1 );
rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
}
| | | 46624 46625 46626 46627 46628 46629 46630 46631 46632 46633 46634 46635 46636 46637 46638 |
** are no outstanding references to any page other than page 1. And
** page 1 is never written to the log until the transaction is
** committed. As a result, the call to xUndo may not fail.
*/
assert( walFramePgno(pWal, iFrame)!=1 );
rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
}
if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
assert( rc==SQLITE_OK );
return rc;
}
/*
** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
|
| ︙ | ︙ | |||
50625 50626 50627 50628 50629 50630 50631 50632 50633 50634 50635 50636 50637 50638 | put4byte(&data[36 + 4*4], pBt->autoVacuum); put4byte(&data[36 + 7*4], pBt->incrVacuum); #endif pBt->nPage = 1; data[31] = 1; return SQLITE_OK; } /* ** Attempt to start a new transaction. A write-transaction ** is started if the second argument is nonzero, otherwise a read- ** transaction. If the second argument is 2 or more and exclusive ** transaction is started, meaning that no other process is allowed ** to access the database. A preexisting transaction may not be | > > > > > > > > > > > > > > | 50677 50678 50679 50680 50681 50682 50683 50684 50685 50686 50687 50688 50689 50690 50691 50692 50693 50694 50695 50696 50697 50698 50699 50700 50701 50702 50703 50704 |
put4byte(&data[36 + 4*4], pBt->autoVacuum);
put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif
pBt->nPage = 1;
data[31] = 1;
return SQLITE_OK;
}
/*
** Initialize the first page of the database file (creating a database
** consisting of a single page and no schema objects). Return SQLITE_OK
** if successful, or an SQLite error code otherwise.
*/
SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
int rc;
sqlite3BtreeEnter(p);
p->pBt->nPage = 0;
rc = newDatabase(p->pBt);
sqlite3BtreeLeave(p);
return rc;
}
/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
** transaction. If the second argument is 2 or more and exclusive
** transaction is started, meaning that no other process is allowed
** to access the database. A preexisting transaction may not be
|
| ︙ | ︙ | |||
56843 56844 56845 56846 56847 56848 56849 |
/* Update the schema version field in the destination database. This
** is to make sure that the schema-version really does change in
** the case where the source and destination databases have the
** same schema version.
*/
if( rc==SQLITE_DONE ){
| > > > > > | > | 56909 56910 56911 56912 56913 56914 56915 56916 56917 56918 56919 56920 56921 56922 56923 56924 56925 56926 56927 56928 56929 |
/* Update the schema version field in the destination database. This
** is to make sure that the schema-version really does change in
** the case where the source and destination databases have the
** same schema version.
*/
if( rc==SQLITE_DONE ){
if( nSrcPage==0 ){
rc = sqlite3BtreeNewDb(p->pDest);
nSrcPage = 1;
}
if( rc==SQLITE_OK || rc==SQLITE_DONE ){
rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
}
if( rc==SQLITE_OK ){
if( p->pDestDb ){
sqlite3ResetAllSchemasOfConnection(p->pDestDb);
}
if( destMode==PAGER_JOURNALMODE_WAL ){
rc = sqlite3BtreeSetVersion(p->pDest, 2);
}
|
| ︙ | ︙ | |||
56877 56878 56879 56880 56881 56882 56883 56884 56885 56886 56887 56888 56889 56890 56891 56892 56893 56894 56895 56896 56897 56898 56899 56900 56901 |
nDestTruncate = (nSrcPage+ratio-1)/ratio;
if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
nDestTruncate--;
}
}else{
nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
}
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
if( pgszSrc<pgszDest ){
/* If the source page-size is smaller than the destination page-size,
** two extra things may need to happen:
**
** * The destination may need to be truncated, and
**
** * Data stored on the pages immediately following the
** pending-byte page in the source database may need to be
** copied into the destination database.
*/
const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
i64 iOff;
i64 iEnd;
assert( pFile );
| > > | | 56949 56950 56951 56952 56953 56954 56955 56956 56957 56958 56959 56960 56961 56962 56963 56964 56965 56966 56967 56968 56969 56970 56971 56972 56973 56974 56975 56976 56977 56978 56979 56980 56981 56982 56983 |
nDestTruncate = (nSrcPage+ratio-1)/ratio;
if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
nDestTruncate--;
}
}else{
nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
}
assert( nDestTruncate>0 );
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
if( pgszSrc<pgszDest ){
/* If the source page-size is smaller than the destination page-size,
** two extra things may need to happen:
**
** * The destination may need to be truncated, and
**
** * Data stored on the pages immediately following the
** pending-byte page in the source database may need to be
** copied into the destination database.
*/
const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
i64 iOff;
i64 iEnd;
assert( pFile );
assert( nDestTruncate==0
|| (i64)nDestTruncate*(i64)pgszDest >= iSize || (
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
));
/* This call ensures that all data required to recreate the original
** database has been stored in the journal for pDestPager and the
** journal synced to disk. So at this point we may safely modify
|
| ︙ | ︙ | |||
72392 72393 72394 72395 72396 72397 72398 | struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int isTrigger = 0; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ | | | 72466 72467 72468 72469 72470 72471 72472 72473 72474 72475 72476 72477 72478 72479 72480 | struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int isTrigger = 0; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; ExprSetIrreducible(pExpr); /* Start at the inner-most context and move outward until a match is found */ |
| ︙ | ︙ | |||
82394 82395 82396 82397 82398 82399 82400 82401 82402 82403 82404 82405 82406 82407 |
iLargest = iIdx;
}
}
if( iLargest==0 ){
return;
}else{
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
destroyRootPage(pParse, iLargest, iDb);
iDestroyed = iLargest;
}
}
#endif
}
| > | 82468 82469 82470 82471 82472 82473 82474 82475 82476 82477 82478 82479 82480 82481 82482 |
iLargest = iIdx;
}
}
if( iLargest==0 ){
return;
}else{
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
assert( iDb>=0 && iDb<pParse->db->nDb );
destroyRootPage(pParse, iLargest, iDb);
iDestroyed = iLargest;
}
}
#endif
}
|
| ︙ | ︙ | |||
82952 82953 82954 82955 82956 82957 82958 |
sqlite3FixSrcList(&sFix, pTblName)
){
/* Because the parser constructs pTblName from a single identifier,
** sqlite3FixSrcList can never fail. */
assert(0);
}
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
| > | | 83027 83028 83029 83030 83031 83032 83033 83034 83035 83036 83037 83038 83039 83040 83041 83042 |
sqlite3FixSrcList(&sFix, pTblName)
){
/* Because the parser constructs pTblName from a single identifier,
** sqlite3FixSrcList can never fail. */
assert(0);
}
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
assert( db->mallocFailed==0 || pTab==0 );
if( pTab==0 ) goto exit_create_index;
assert( db->aDb[iDb].pSchema==pTab->pSchema );
}else{
assert( pName==0 );
assert( pStart==0 );
pTab = pParse->pNewTable;
if( !pTab ) goto exit_create_index;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
| ︙ | ︙ | |||
89475 89476 89477 89478 89479 89480 89481 |
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
pParse->ckBase = regData;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; i<pCheck->nExpr; i++){
int allOk = sqlite3VdbeMakeLabel(v);
Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
| > | | | | | | | | | | | | | | | > | 89551 89552 89553 89554 89555 89556 89557 89558 89559 89560 89561 89562 89563 89564 89565 89566 89567 89568 89569 89570 89571 89572 89573 89574 89575 89576 89577 89578 89579 89580 89581 |
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
pParse->ckBase = regData;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; i<pCheck->nExpr; i++){
int allOk = sqlite3VdbeMakeLabel(v);
Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
if( !db->mallocFailed ){
assert( pDup!=0 );
sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
if( onError==OE_Ignore ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
}else{
char *zConsName = pCheck->a[i].zName;
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
if( zConsName ){
zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
}else{
zConsName = 0;
}
sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
}
sqlite3VdbeResolveLabel(v, allOk);
}
sqlite3ExprDelete(db, pDup);
}
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
** of the new record does not previously exist. Except, if this
|
| ︙ | ︙ | |||
92936 92937 92938 92939 92940 92941 92942 |
int i;
sqlite3VdbeSetNumCols(v, 2);
pParse->nMem = 2;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
for(i=0; i<db->nDb; i++){
Btree *pBt;
| < | | 93014 93015 93016 93017 93018 93019 93020 93021 93022 93023 93024 93025 93026 93027 93028 93029 93030 93031 93032 93033 |
int i;
sqlite3VdbeSetNumCols(v, 2);
pParse->nMem = 2;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
for(i=0; i<db->nDb; i++){
Btree *pBt;
const char *zState = "unknown";
int j;
if( db->aDb[i].zName==0 ) continue;
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
pBt = db->aDb[i].pBt;
if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
zState = "closed";
}else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
zState = azLockName[j];
}
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
|
| ︙ | ︙ | |||
96981 96982 96983 96984 96985 96986 96987 |
**
** We look at every expression in the outer query and every place we see
** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
*/
pList = pParent->pEList;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].zName==0 ){
| | | | < | 97058 97059 97060 97061 97062 97063 97064 97065 97066 97067 97068 97069 97070 97071 97072 97073 97074 |
**
** We look at every expression in the outer query and every place we see
** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
*/
pList = pParent->pEList;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].zName==0 ){
char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
sqlite3Dequote(zName);
pList->a[i].zName = zName;
}
}
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);
}
|
| ︙ | ︙ | |||
100629 100630 100631 100632 100633 100634 100635 100636 100637 100638 100639 100640 100641 100642 |
** with 2.0.0, SQLite no longer uses GDBM so this command has
** become a no-op.
*/
SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
}
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
| > | 100705 100706 100707 100708 100709 100710 100711 100712 100713 100714 100715 100716 100717 100718 100719 |
** with 2.0.0, SQLite no longer uses GDBM so this command has
** become a no-op.
*/
SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
sqlite3VdbeUsesBtree(v, 0);
}
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
|
| ︙ | ︙ | |||
101156 101157 101158 101159 101160 101161 101162 |
** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->azModuleArg ){
int i;
| < | | 101233 101234 101235 101236 101237 101238 101239 101240 101241 101242 101243 101244 101245 101246 101247 101248 |
** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
}
sqlite3DbFree(db, p->azModuleArg);
}
}
/*
** Add a new module argument to pTable->azModuleArg[].
|
| ︙ | ︙ | |||
103439 103440 103441 103442 103443 103444 103445 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } | < < < < < < < < < < < < < < < < | 103515 103516 103517 103518 103519 103520 103521 103522 103523 103524 103525 103526 103527 103528 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } /* ** This function searches the expression list passed as the second argument ** for an expression of type TK_COLUMN that refers to the same column and ** uses the same collation sequence as the iCol'th column of index pIdx. ** Argument iBase is the cursor number used for the table that pIdx refers ** to. ** |
| ︙ | ︙ | |||
104723 104724 104725 104726 104727 104728 104729 | } return rc; } #endif /* defined(SQLITE_ENABLE_STAT3) */ /* ** Check to see if column iCol of the table with cursor iTab will appear | | | > < | | > > | > > > > | < < | 104783 104784 104785 104786 104787 104788 104789 104790 104791 104792 104793 104794 104795 104796 104797 104798 104799 104800 104801 104802 104803 104804 104805 104806 104807 104808 104809 104810 104811 104812 104813 104814 104815 104816 104817 104818 104819 104820 |
}
return rc;
}
#endif /* defined(SQLITE_ENABLE_STAT3) */
/*
** Check to see if column iCol of the table with cursor iTab will appear
** in sorted order according to the current query plan.
**
** Return values:
**
** 0 iCol is not ordered
** 1 iCol has only a single value
** 2 iCol is in ASC order
** 3 iCol is in DESC order
*/
static int isOrderedColumn(
WhereBestIdx *p,
int iTab,
int iCol
){
int i, j;
WhereLevel *pLevel = &p->aLevel[p->i-1];
Index *pIdx;
u8 sortOrder;
for(i=p->i-1; i>=0; i--, pLevel--){
if( pLevel->iTabCur!=iTab ) continue;
if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
return 1;
}
assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
if( iCol<0 ){
sortOrder = 0;
testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
}else{
int n = pIdx->nColumn;
for(j=0; j<n; j++){
|
| ︙ | ︙ | |||
104766 104767 104768 104769 104770 104771 104772 |
testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
}
if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
assert( sortOrder==0 || sortOrder==1 );
testcase( sortOrder==1 );
sortOrder = 1 - sortOrder;
}
| < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | > > > | | | < > > < < < < < < < | > > > > > > | | | | | | > > | > > | > | | < < < < < | > > > | | > | > > | < < < < > > > | | < > | < < < | | | | > > | | | > > > > | > > > > > > > > > > > > > > > > > > | | > > > > > | | | > > > > > > > > > > > | > > | > | > > > > > > > > > > > | | < < < < < | 104830 104831 104832 104833 104834 104835 104836 104837 104838 104839 104840 104841 104842 104843 104844 104845 104846 104847 104848 104849 104850 104851 104852 104853 104854 104855 104856 104857 104858 104859 104860 104861 104862 104863 104864 104865 104866 104867 104868 104869 104870 104871 104872 104873 104874 104875 104876 104877 104878 104879 104880 104881 104882 104883 104884 104885 104886 104887 104888 104889 104890 104891 104892 104893 104894 104895 104896 104897 104898 104899 104900 104901 104902 104903 104904 104905 104906 104907 104908 104909 104910 104911 104912 104913 104914 104915 104916 104917 104918 104919 104920 104921 104922 104923 104924 104925 104926 104927 104928 104929 104930 104931 104932 104933 104934 104935 104936 104937 104938 104939 104940 104941 104942 104943 104944 104945 104946 104947 104948 104949 104950 104951 104952 104953 104954 104955 104956 104957 104958 104959 104960 104961 104962 104963 104964 104965 104966 104967 104968 104969 104970 104971 104972 104973 104974 104975 104976 104977 104978 104979 104980 104981 104982 104983 104984 104985 104986 104987 104988 104989 104990 104991 104992 104993 104994 104995 104996 104997 104998 104999 105000 105001 105002 105003 105004 105005 105006 105007 105008 105009 105010 105011 105012 105013 105014 105015 105016 105017 105018 105019 105020 105021 105022 105023 105024 105025 105026 105027 105028 105029 105030 105031 105032 105033 105034 105035 105036 105037 105038 105039 105040 105041 105042 105043 105044 105045 105046 105047 105048 105049 105050 |
testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
}
if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
assert( sortOrder==0 || sortOrder==1 );
testcase( sortOrder==1 );
sortOrder = 1 - sortOrder;
}
return sortOrder+2;
}
return 0;
}
/*
** This routine decides if pIdx can be used to satisfy the ORDER BY
** clause, either in whole or in part. The return value is the
** cumulative number of terms in the ORDER BY clause that are satisfied
** by the index pIdx and other indices in outer loops.
**
** The table being queried has a cursor number of "base". pIdx is the
** index that is postulated for use to access the table.
**
** The *pbRev value is set to 0 order 1 depending on whether or not
** pIdx should be run in the forward order or in reverse order.
*/
static int isSortingIndex(
WhereBestIdx *p, /* Best index search context */
Index *pIdx, /* The index we are testing */
int base, /* Cursor number for the table to be sorted */
int *pbRev /* Set to 1 for reverse-order scan of pIdx */
){
int i; /* Number of pIdx terms used */
int j; /* Number of ORDER BY terms satisfied */
int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */
int nTerm; /* Number of ORDER BY terms */
struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
Table *pTab = pIdx->pTable; /* Table that owns index pIdx */
ExprList *pOrderBy; /* The ORDER BY clause */
Parse *pParse = p->pParse; /* Parser context */
sqlite3 *db = pParse->db; /* Database connection */
int nPriorSat; /* ORDER BY terms satisfied by outer loops */
int seenRowid = 0; /* True if an ORDER BY rowid term is seen */
int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */
if( p->i==0 ){
nPriorSat = 0;
}else{
nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
if( (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){
/* This loop cannot be ordered unless the next outer loop is
** also ordered */
return nPriorSat;
}
if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
/* Only look at the outer-most loop if the OrderByIdxJoin
** optimization is disabled */
return nPriorSat;
}
}
pOrderBy = p->pOrderBy;
assert( pOrderBy!=0 );
if( pIdx->bUnordered ){
/* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
** be used for sorting */
return nPriorSat;
}
nTerm = pOrderBy->nExpr;
uniqueNotNull = pIdx->onError!=OE_None;
assert( nTerm>0 );
/* Argument pIdx must either point to a 'real' named index structure,
** or an index structure allocated on the stack by bestBtreeIndex() to
** represent the rowid index that is part of every table. */
assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
/* Match terms of the ORDER BY clause against columns of
** the index.
**
** Note that indices have pIdx->nColumn regular columns plus
** one additional column containing the rowid. The rowid column
** of the index is also allowed to match against the ORDER BY
** clause.
*/
j = nPriorSat;
for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
Expr *pOBExpr; /* The expression of the ORDER BY pOBItem */
CollSeq *pColl; /* The collating sequence of pOBExpr */
int termSortOrder; /* Sort order for this term */
int iColumn; /* The i-th column of the index. -1 for rowid */
int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
int isEq; /* Subject to an == or IS NULL constraint */
int isMatch; /* ORDER BY term matches the index term */
const char *zColl; /* Name of collating sequence for i-th index term */
WhereTerm *pConstraint; /* A constraint in the WHERE clause */
/* If the next term of the ORDER BY clause refers to anything other than
** a column in the "base" table, then this index will not be of any
** further use in handling the ORDER BY. */
pOBExpr = pOBItem->pExpr;
if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
break;
}
/* Find column number and collating sequence for the next entry
** in the index */
if( pIdx->zName && i<pIdx->nColumn ){
iColumn = pIdx->aiColumn[i];
if( iColumn==pIdx->pTable->iPKey ){
iColumn = -1;
}
iSortOrder = pIdx->aSortOrder[i];
zColl = pIdx->azColl[i];
assert( zColl!=0 );
}else{
iColumn = -1;
iSortOrder = 0;
zColl = 0;
}
/* Check to see if the column number and collating sequence of the
** index match the column number and collating sequence of the ORDER BY
** clause entry. Set isMatch to 1 if they both match. */
if( pOBExpr->iColumn==iColumn ){
if( zColl ){
pColl = sqlite3ExprCollSeq(pParse, pOBExpr);
if( !pColl ) pColl = db->pDfltColl;
isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
}else{
isMatch = 1;
}
}else{
isMatch = 0;
}
/* termSortOrder is 0 or 1 for whether or not the access loop should
** run forward or backwards (respectively) in order to satisfy this
** term of the ORDER BY clause. */
assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
assert( iSortOrder==0 || iSortOrder==1 );
termSortOrder = iSortOrder ^ pOBItem->sortOrder;
/* If X is the column in the index and ORDER BY clause, check to see
** if there are any X= or X IS NULL constraints in the WHERE clause. */
pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
WO_EQ|WO_ISNULL|WO_IN, pIdx);
if( pConstraint==0 ){
isEq = 0;
}else if( pConstraint->eOperator==WO_IN ){
/* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
** because we do not know in what order the values on the RHS of the IN
** operator will occur. */
break;
}else if( pConstraint->eOperator==WO_ISNULL ){
uniqueNotNull = 0;
isEq = 1; /* "X IS NULL" means X has only a single value */
}else if( pConstraint->prereqRight==0 ){
isEq = 1; /* Constraint "X=constant" means X has only a single value */
}else{
Expr *pRight = pConstraint->pExpr->pRight;
if( pRight->op==TK_COLUMN ){
WHERETRACE((" .. isOrderedColumn(tab=%d,col=%d)",
pRight->iTable, pRight->iColumn));
isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
WHERETRACE((" -> isEq=%d\n", isEq));
/* If the constraint is of the form X=Y where Y is an ordered value
** in an outer loop, then make sure the sort order of Y matches the
** sort order required for X. */
if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
testcase( isEq==2 );
testcase( isEq==3 );
break;
}
}else{
isEq = 0; /* "X=expr" places no ordering constraints on X */
}
}
if( !isMatch ){
if( isEq==0 ){
break;
}else{
continue;
}
}else if( isEq!=1 ){
if( sortOrder==2 ){
sortOrder = termSortOrder;
}else if( termSortOrder!=sortOrder ){
break;
}
}
j++;
pOBItem++;
if( iColumn<0 ){
seenRowid = 1;
break;
}else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
testcase( isEq==0 );
testcase( isEq==2 );
testcase( isEq==3 );
uniqueNotNull = 0;
}
}
/* If we have not found at least one ORDER BY term that matches the
** index, then show no progress. */
if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
/* Return the necessary scan order back to the caller */
*pbRev = sortOrder & 1;
/* If there was an "ORDER BY rowid" term that matched, or it is only
** possible for a single row from this table to match, then skip over
** any additional ORDER BY terms dealing with this table.
*/
if( seenRowid || (uniqueNotNull && i>=pIdx->nColumn) ){
/* Advance j over additional ORDER BY terms associated with base */
WhereMaskSet *pMS = p->pWC->pMaskSet;
Bitmask m = ~getMask(pMS, base);
while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
j++;
}
}
|
| ︙ | ︙ | |||
105061 105062 105063 105064 105065 105066 105067 |
/* Loop over all indices looking for the best one to use
*/
for(; pProbe; pIdx=pProbe=pProbe->pNext){
const tRowcnt * const aiRowEst = pProbe->aiRowEst;
WhereCost pc; /* Cost of using pProbe */
double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */
| < | 105142 105143 105144 105145 105146 105147 105148 105149 105150 105151 105152 105153 105154 105155 |
/* Loop over all indices looking for the best one to use
*/
for(; pProbe; pIdx=pProbe=pProbe->pNext){
const tRowcnt * const aiRowEst = pProbe->aiRowEst;
WhereCost pc; /* Cost of using pProbe */
double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */
/* The following variables are populated based on the properties of
** index being evaluated. They are then used to determine the expected
** cost and number of rows returned.
**
** pc.plan.nEq:
** Number of equality terms that can be implemented using the index.
|
| ︙ | ︙ | |||
105092 105093 105094 105095 105096 105097 105098 |
**
** nInMul is set to 1.
**
** If there exists a WHERE term of the form "x IN (SELECT ...)", then
** the sub-select is assumed to return 25 rows for the purposes of
** determining nInMul.
**
| < < < < | 105172 105173 105174 105175 105176 105177 105178 105179 105180 105181 105182 105183 105184 105185 |
**
** nInMul is set to 1.
**
** If there exists a WHERE term of the form "x IN (SELECT ...)", then
** the sub-select is assumed to return 25 rows for the purposes of
** determining nInMul.
**
** bInEst:
** Set to true if there was at least one "x IN (SELECT ...)" term used
** in determining the value of nInMul. Note that the RHS of the
** IN operator must be a SELECT, not a value list, for this variable
** to be true.
**
** rangeDiv:
|
| ︙ | ︙ | |||
105133 105134 105135 105136 105137 105138 105139 |
** two queries requires table b-tree lookups in order to find the value
** of column c, but the first does not because columns a and b are
** both available in the index.
**
** SELECT a, b FROM tbl WHERE a = 1;
** SELECT a, b, c FROM tbl WHERE a = 1;
*/
| < > > > > | < < < < | 105209 105210 105211 105212 105213 105214 105215 105216 105217 105218 105219 105220 105221 105222 105223 105224 105225 105226 105227 105228 105229 105230 105231 105232 105233 105234 105235 105236 105237 105238 105239 105240 105241 105242 105243 105244 105245 105246 105247 105248 105249 105250 105251 105252 105253 105254 105255 105256 105257 105258 105259 105260 105261 105262 105263 105264 105265 105266 105267 105268 105269 105270 105271 105272 |
** two queries requires table b-tree lookups in order to find the value
** of column c, but the first does not because columns a and b are
** both available in the index.
**
** SELECT a, b FROM tbl WHERE a = 1;
** SELECT a, b, c FROM tbl WHERE a = 1;
*/
int bInEst = 0; /* True if "x IN (SELECT...)" seen */
int nInMul = 1; /* Number of distinct equalities to lookup */
double rangeDiv = (double)1; /* Estimated reduction in search space */
int nBound = 0; /* Number of range constraints seen */
int bSort; /* True if external sort required */
int bDist; /* True if index cannot help with DISTINCT */
int bLookup = 0; /* True if not a covering index */
int nPriorSat; /* ORDER BY terms satisfied by outer loops */
int nOrderBy; /* Number of ORDER BY terms */
WhereTerm *pTerm; /* A single term of the WHERE clause */
#ifdef SQLITE_ENABLE_STAT3
WhereTerm *pFirstTerm = 0; /* First term matching the index */
#endif
WHERETRACE((
" %s(%s):\n",
pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
));
memset(&pc, 0, sizeof(pc));
nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
if( p->i ){
nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat;
bSort = nPriorSat<nOrderBy;
bDist = 0;
}else{
nPriorSat = pc.plan.nOBSat = 0;
bSort = nOrderBy>0;
bDist = p->pDistinct!=0;
}
/* Determine the values of pc.plan.nEq and nInMul */
for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
int j = pProbe->aiColumn[pc.plan.nEq];
pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
if( pTerm==0 ) break;
pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
testcase( pTerm->pWC!=pWC );
if( pTerm->eOperator & WO_IN ){
Expr *pExpr = pTerm->pExpr;
pc.plan.wsFlags |= WHERE_COLUMN_IN;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */
nInMul *= 25;
bInEst = 1;
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
nInMul *= pExpr->x.pList->nExpr;
}
}else if( pTerm->eOperator & WO_ISNULL ){
pc.plan.wsFlags |= WHERE_COLUMN_NULL;
}
#ifdef SQLITE_ENABLE_STAT3
if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
#endif
pc.used |= pTerm->prereqRight;
}
|
| ︙ | ︙ | |||
105238 105239 105240 105241 105242 105243 105244 |
}
/* If there is an ORDER BY clause and the index being considered will
** naturally scan rows in the required order, set the appropriate flags
** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
** the index will scan rows in a different order, set the bSort
** variable. */
| < | | < < > | > | | 105313 105314 105315 105316 105317 105318 105319 105320 105321 105322 105323 105324 105325 105326 105327 105328 105329 105330 105331 105332 |
}
/* If there is an ORDER BY clause and the index being considered will
** naturally scan rows in the required order, set the appropriate flags
** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
** the index will scan rows in a different order, set the bSort
** variable. */
if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
int bRev = 2;
WHERETRACE((" --> before isSortingIndex: nPriorSat=%d\n",nPriorSat));
pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n",
bRev, pc.plan.nOBSat));
if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){
pc.plan.wsFlags |= WHERE_ORDERED;
}
if( nOrderBy==pc.plan.nOBSat ){
bSort = 0;
pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
}
|
| ︙ | ︙ | |||
105362 105363 105364 105365 105366 105367 105368 |
** the cost function to err on the side of choosing an index over
** choosing a full scan. This 4x full-scan penalty is an arguable
** decision and one which we expect to revisit in the future. But
** it seems to be working well enough at the moment.
*/
pc.rCost = aiRowEst[0]*4;
pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
| > | > > | 105436 105437 105438 105439 105440 105441 105442 105443 105444 105445 105446 105447 105448 105449 105450 105451 105452 105453 |
** the cost function to err on the side of choosing an index over
** choosing a full scan. This 4x full-scan penalty is an arguable
** decision and one which we expect to revisit in the future. But
** it seems to be working well enough at the moment.
*/
pc.rCost = aiRowEst[0]*4;
pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
if( pIdx ){
pc.plan.wsFlags &= ~WHERE_ORDERED;
pc.plan.nOBSat = nPriorSat;
}
}else{
log10N = estLog(aiRowEst[0]);
pc.rCost = pc.plan.nRow;
if( pIdx ){
if( bLookup ){
/* For an index lookup followed by a table lookup:
** nInMul index searches to find the start of each index range
|
| ︙ | ︙ | |||
105467 105468 105469 105470 105471 105472 105473 |
}
}
if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
}
WHERETRACE((
| < | | | < | | 105544 105545 105546 105547 105548 105549 105550 105551 105552 105553 105554 105555 105556 105557 105558 105559 105560 105561 105562 |
}
}
if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
}
WHERETRACE((
" nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
" notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
" used=0x%llx nOBSat=%d\n",
pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
pc.plan.nOBSat
));
/* If this index is the best we have seen so far, then record this
** index and its cost in the p->cost structure.
*/
if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
|
| ︙ | ︙ | |||
105511 105512 105513 105514 105515 105516 105517 |
assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
assert( pSrc->pIndex==0
|| p->cost.plan.u.pIdx==0
|| p->cost.plan.u.pIdx==pSrc->pIndex
);
| | | 105586 105587 105588 105589 105590 105591 105592 105593 105594 105595 105596 105597 105598 105599 105600 |
assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
assert( pSrc->pIndex==0
|| p->cost.plan.u.pIdx==0
|| p->cost.plan.u.pIdx==pSrc->pIndex
);
WHERETRACE((" best index is: %s\n",
p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));
bestOrClauseIndex(p);
bestAutomaticIndex(p);
p->cost.plan.wsFlags |= eqTermMask;
}
|
| ︙ | ︙ | |||
106603 106604 106605 106606 106607 106608 106609 |
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
}
}
}
pLevel->u.pCovidx = pCov;
| | | 106678 106679 106680 106681 106682 106683 106684 106685 106686 106687 106688 106689 106690 106691 106692 |
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
}
}
}
pLevel->u.pCovidx = pCov;
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
sqlite3ExprDelete(pParse->db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
|
| ︙ | ︙ | |||
107061 107062 107063 107064 107065 107066 107067 |
if( (m & sWBI.notValid)==0 ){
if( j==iFrom ) iFrom++;
continue;
}
sWBI.notReady = (isOptimal ? m : sWBI.notValid);
if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
| | | 107136 107137 107138 107139 107140 107141 107142 107143 107144 107145 107146 107147 107148 107149 107150 |
if( (m & sWBI.notValid)==0 ){
if( j==iFrom ) iFrom++;
continue;
}
sWBI.notReady = (isOptimal ? m : sWBI.notValid);
if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
j, sWBI.pSrc->pTab->zName, isOptimal));
assert( sWBI.pSrc->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(sWBI.pSrc->pTab) ){
sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
bestVirtualIndex(&sWBI);
}else
|
| ︙ | ︙ | |||
107114 107115 107116 107117 107118 107119 107120 |
&& (bestJ<0 || (notIndexed&m)!=0 /* (2) */
|| (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
|| (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
&& (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
|| NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
&& (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
){
| | | | 107189 107190 107191 107192 107193 107194 107195 107196 107197 107198 107199 107200 107201 107202 107203 107204 |
&& (bestJ<0 || (notIndexed&m)!=0 /* (2) */
|| (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
|| (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
&& (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
|| NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
&& (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
){
WHERETRACE((" === table %d (%s) is best so far\n"
" cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
j, sWBI.pSrc->pTab->zName,
sWBI.cost.rCost, sWBI.cost.plan.nRow,
sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
bestPlan = sWBI.cost;
bestJ = j;
}
if( doNotReorder ) break;
|
| ︙ | ︙ | |||
110699 110700 110701 110702 110703 110704 110705 110706 110707 110708 110709 110710 110711 110712 |
/* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
/* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
/* (324) anylist ::= */ yytestcase(yyruleno==324);
/* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
/* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
break;
};
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact < YYNSTATE ){
#ifdef NDEBUG
/* If we are not debugging and the reduce action popped at least
| > | 110774 110775 110776 110777 110778 110779 110780 110781 110782 110783 110784 110785 110786 110787 110788 |
/* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
/* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
/* (324) anylist ::= */ yytestcase(yyruleno==324);
/* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
/* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
break;
};
assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact < YYNSTATE ){
#ifdef NDEBUG
/* If we are not debugging and the reduce action popped at least
|
| ︙ | ︙ |
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.7.15" #define SQLITE_VERSION_NUMBER 3007015 | | | 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.7.15" #define SQLITE_VERSION_NUMBER 3007015 #define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ |
Changes to src/stash.c.
| ︙ | ︙ | |||
170 171 172 173 174 175 176 |
prompt_for_user_comment(&comment, &prompt);
blob_reset(&prompt);
zComment = blob_str(&comment);
}
stashid = db_lget_int("stash-next", 1);
db_lset_int("stash-next", stashid+1);
vid = db_lget_int("checkout", 0);
| | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
prompt_for_user_comment(&comment, &prompt);
blob_reset(&prompt);
zComment = blob_str(&comment);
}
stashid = db_lget_int("stash-next", 1);
db_lset_int("stash-next", stashid+1);
vid = db_lget_int("checkout", 0);
vfile_check_signature(vid, 0);
db_multi_exec(
"INSERT INTO stash(stashid,vid,comment,ctime)"
"VALUES(%d,%d,%Q,julianday('now'))",
stashid, vid, zComment
);
if( g.argc>3 ){
int i;
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
1021 1022 1023 1024 1025 1026 1027 |
nd = db_int(0, "SELECT count(*)-1 FROM ok");
if( nd>=0 ) db_multi_exec("%s", blob_str(&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 ){
| | | 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 |
nd = db_int(0, "SELECT count(*)-1 FROM ok");
if( nd>=0 ) db_multi_exec("%s", blob_str(&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_str(&sql));
}
if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
|
| ︙ | ︙ | |||
1536 1537 1538 1539 1540 1541 1542 |
);
if( mode==3 || mode==4 ){
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
if( mode==3 ){
compute_descendants(objid, n);
}else{
| | | 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 |
);
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_appendf(&sql, " AND blob.rid IN ok");
}
if( zType && (zType[0]!='a') ){
blob_appendf(&sql, " AND event.type=%Q ", zType);
}
blob_appendf(&sql, " ORDER BY event.mtime DESC");
|
| ︙ | ︙ |
Changes to src/tkt.c.
| ︙ | ︙ | |||
431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
const char **argv,
int *argl
){
char *zDate;
const char *zUuid;
int i;
int rid;
Blob tktchng, cksum;
login_verify_csrf_secret();
zUuid = (const char *)pUuid;
blob_zero(&tktchng);
zDate = date_in_standard_format("now");
blob_appendf(&tktchng, "D %s\n", zDate);
| > | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
const char **argv,
int *argl
){
char *zDate;
const char *zUuid;
int i;
int rid;
int nJ = 0;
Blob tktchng, cksum;
login_verify_csrf_secret();
zUuid = (const char *)pUuid;
blob_zero(&tktchng);
zDate = date_in_standard_format("now");
blob_appendf(&tktchng, "D %s\n", zDate);
|
| ︙ | ︙ | |||
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 |
if( strncmp(zValue, azValue[i], nValue) || strlen(azValue[i])!=nValue ){
if( strncmp(azField[i], "private_", 8)==0 ){
zValue = db_conceal(zValue, nValue);
blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
}else{
blob_appendf(&tktchng, "J %s %#F\n", azField[i], nValue, zValue);
}
}
}
}
if( *(char**)pUuid ){
zUuid = db_text(0,
"SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", P("name")
);
}else{
zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))");
}
*(const char**)pUuid = zUuid;
blob_appendf(&tktchng, "K %s\n", zUuid);
blob_appendf(&tktchng, "U %F\n", g.zLogin ? g.zLogin : "");
md5sum_blob(&tktchng, &cksum);
blob_appendf(&tktchng, "Z %b\n", &cksum);
if( g.zPath[0]=='d' ){
/* If called from /debug_tktnew or /debug_tktedit... */
@ <font color="blue">
@ <p>Ticket artifact that would have been submitted:</p>
@ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
@ <hr /></font>
return TH_OK;
| > > > > > | 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 |
if( strncmp(zValue, azValue[i], nValue) || strlen(azValue[i])!=nValue ){
if( strncmp(azField[i], "private_", 8)==0 ){
zValue = db_conceal(zValue, nValue);
blob_appendf(&tktchng, "J %s %s\n", azField[i], zValue);
}else{
blob_appendf(&tktchng, "J %s %#F\n", azField[i], nValue, zValue);
}
nJ++;
}
}
}
if( *(char**)pUuid ){
zUuid = db_text(0,
"SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", P("name")
);
}else{
zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))");
}
*(const char**)pUuid = zUuid;
blob_appendf(&tktchng, "K %s\n", zUuid);
blob_appendf(&tktchng, "U %F\n", g.zLogin ? g.zLogin : "");
md5sum_blob(&tktchng, &cksum);
blob_appendf(&tktchng, "Z %b\n", &cksum);
if( nJ==0 ){
blob_reset(&tktchng);
return TH_OK;
}
if( g.zPath[0]=='d' ){
/* If called from /debug_tktnew or /debug_tktedit... */
@ <font color="blue">
@ <p>Ticket artifact that would have been submitted:</p>
@ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
@ <hr /></font>
return TH_OK;
|
| ︙ | ︙ |
Changes to src/update.c.
| ︙ | ︙ | |||
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 |
int vid; /* Current version */
int tid=0; /* Target version - version we are changing to */
Stmt q;
int latestFlag; /* --latest. Pick the latest version if true */
int nochangeFlag; /* -n or --nochange. Do a dry run */
int verboseFlag; /* -v or --verbose. Output extra information */
int debugFlag; /* --debug option */
int nChng; /* Number of file renames */
int *aChng; /* Array of file renames */
int i; /* Loop counter */
int nConflict = 0; /* Number of merge conflicts */
int nOverwrite = 0; /* Number of unmanaged files overwritten */
int nUpdate = 0; /* Number of chagnes of any kind */
Stmt mtimeXfer; /* Statment to transfer mtimes */
if( !internalUpdate ){
undo_capture_command_line();
url_proxy_options();
}
latestFlag = find_option("latest",0, 0)!=0;
nochangeFlag = find_option("nochange","n",0)!=0;
verboseFlag = find_option("verbose","v",0)!=0;
debugFlag = find_option("debug",0,0)!=0;
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("cannot find current version");
}
if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
| > > | 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 |
int vid; /* Current version */
int tid=0; /* Target version - version we are changing to */
Stmt q;
int latestFlag; /* --latest. Pick the latest version if true */
int nochangeFlag; /* -n or --nochange. Do a dry run */
int verboseFlag; /* -v or --verbose. Output extra information */
int debugFlag; /* --debug option */
int setmtimeFlag; /* --setmtime. Set mtimes on files */
int nChng; /* Number of file renames */
int *aChng; /* Array of file renames */
int i; /* Loop counter */
int nConflict = 0; /* Number of merge conflicts */
int nOverwrite = 0; /* Number of unmanaged files overwritten */
int nUpdate = 0; /* Number of chagnes of any kind */
Stmt mtimeXfer; /* Statment to transfer mtimes */
if( !internalUpdate ){
undo_capture_command_line();
url_proxy_options();
}
latestFlag = find_option("latest",0, 0)!=0;
nochangeFlag = find_option("nochange","n",0)!=0;
verboseFlag = find_option("verbose","v",0)!=0;
debugFlag = find_option("debug",0,0)!=0;
setmtimeFlag = find_option("setmtime",0,0)!=0;
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("cannot find current version");
}
if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
|
| ︙ | ︙ | |||
192 193 194 195 196 197 198 |
}
if( tid==0 ){
fossil_panic("Internal Error: unable to find a version to update to.");
}
db_begin_transaction();
| | | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
}
if( tid==0 ){
fossil_panic("Internal Error: unable to find a version to update to.");
}
db_begin_transaction();
vfile_check_signature(vid, CKSIG_ENOTFILE);
if( !nochangeFlag && !internalUpdate ) undo_begin();
load_vfile_from_rid(tid);
/*
** The record.fn field is used to match files against each other. The
** FV table contains one row for each each unique filename in
** in the current checkout, the pivot, and the version being merged.
|
| ︙ | ︙ | |||
527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
db_lset_int("checkout", tid);
}else{
/* A subset of files have been checked out. Keep the current
** checkout unchanged. */
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
}
if( !internalUpdate ) undo_finish();
db_end_transaction(0);
}
}
/*
** Make sure empty directories are created
*/
| > | 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
db_lset_int("checkout", tid);
}else{
/* A subset of files have been checked out. Keep the current
** checkout unchanged. */
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
}
if( !internalUpdate ) undo_finish();
if( setmtimeFlag ) vfile_check_signature(vid, CKSIG_SETMTIME);
db_end_transaction(0);
}
}
/*
** Make sure empty directories are created
*/
|
| ︙ | ︙ | |||
694 695 696 697 698 699 700 |
file_tree_name(zFile, &fname, 1);
db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname);
blob_reset(&fname);
}
}else{
int vid;
vid = db_lget_int("checkout", 0);
| | | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
file_tree_name(zFile, &fname, 1);
db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname);
blob_reset(&fname);
}
}else{
int vid;
vid = db_lget_int("checkout", 0);
vfile_check_signature(vid, 0);
db_multi_exec(
"DELETE FROM vmerge;"
"INSERT INTO torevert "
"SELECT pathname"
" FROM vfile "
" WHERE chnged OR deleted OR rid=0 OR pathname!=origname;"
);
|
| ︙ | ︙ |
Changes to src/vfile.c.
| ︙ | ︙ | |||
116 117 118 119 120 121 122 123 | } db_finalize(&ridq); db_finalize(&ins); manifest_destroy(p); db_end_transaction(0); } /* | > > > > > > > > > > > | | | | | | > | | 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 |
}
db_finalize(&ridq);
db_finalize(&ins);
manifest_destroy(p);
db_end_transaction(0);
}
#if INTERFACE
/*
** The cksigFlags parameter to vfile_check_signature() is an OR-ed
** combination of the following bits:
*/
#define CKSIG_ENOTFILE 0x001 /* non-file FS objects throw an error */
#define CKSIG_SHA1 0x002 /* Verify file content using sha1sum */
#define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */
#endif /* INTERFACE */
/*
** Look at every VFILE entry with the given vid and update
** VFILE.CHNGED field according to whether or not
** the file has changed. 0 means no change. 1 means edited. 2 means
** the file has changed due to a merge. 3 means the file was added
** by a merge.
**
** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
** removed from configuration management via "fossil rm" or added via
** "fossil add", respectively, and in both cases we always know that
** the file has changed without having the check the size, mtime,
** or on-disk content.
**
** If the size of the file has changed, then we always know that the file
** changed without having to look at the mtime or on-disk content.
**
** The mtime of the file is only a factor if the mtime-changes setting
** is false and the useSha1sum flag is false. If the mtime-changes
** setting is true (or undefined - it defaults to true) or if useSha1sum
** is true, then we do not trust the mtime and will examine the on-disk
** content to determine if a file really is the same.
**
** If the mtime is used, it is used only to determine if files are the same.
** If the mtime of a file has changed, we still examine the on-disk content
** to see whether or not the edit was a null-edit.
*/
void vfile_check_signature(int vid, unsigned int cksigFlags){
int nErr = 0;
Stmt q;
Blob fileCksum, origCksum;
int useMtime = (cksigFlags & CKSIG_SHA1)==0
&& db_get_boolean("mtime-changes", 1);
db_begin_transaction();
db_prepare(&q, "SELECT id, %Q || pathname,"
" vfile.mrid, deleted, chnged, uuid, size, mtime"
" FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
" WHERE vid=%d ", g.zLocalRoot, vid);
while( db_step(&q)==SQLITE_ROW ){
|
| ︙ | ︙ | |||
176 177 178 179 180 181 182 |
currentSize = file_wd_size(zName);
origSize = db_column_int64(&q, 6);
currentMtime = file_wd_mtime(0);
if( chnged==0 && (isDeleted || rid==0) ){
/* "fossil rm" or "fossil add" always change the file */
chnged = 1;
}else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
| | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
currentSize = file_wd_size(zName);
origSize = db_column_int64(&q, 6);
currentMtime = file_wd_mtime(0);
if( chnged==0 && (isDeleted || rid==0) ){
/* "fossil rm" or "fossil add" always change the file */
chnged = 1;
}else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
if( cksigFlags & CKSIG_ENOTFILE ){
fossil_warning("not an ordinary file: %s", zName);
nErr++;
}
chnged = 1;
}
if( origSize!=currentSize ){
if( chnged!=1 ){
|
| ︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
blob_zero(&fileCksum);
}
if( blob_compare(&fileCksum, &origCksum) ){
chnged = 1;
}
blob_reset(&origCksum);
blob_reset(&fileCksum);
}
if( currentMtime!=oldMtime || chnged!=oldChnged ){
db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
currentMtime, chnged, id);
}
}
db_finalize(&q);
| > > > > > > > > > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
blob_zero(&fileCksum);
}
if( blob_compare(&fileCksum, &origCksum) ){
chnged = 1;
}
blob_reset(&origCksum);
blob_reset(&fileCksum);
}
if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2) ){
i64 desiredMtime;
if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
if( currentMtime!=desiredMtime ){
file_set_mtime(zName, desiredMtime);
currentMtime = file_wd_mtime(zName);
}
}
}
if( currentMtime!=oldMtime || chnged!=oldChnged ){
db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d",
currentMtime, chnged, id);
}
}
db_finalize(&q);
|
| ︙ | ︙ | |||
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
zFile = mprintf("%s/.fos", zPath);
fileFound = file_size(zFile)>=1024;
fossil_free(zFile);
}
return fileFound;
}
/*
** Load into table SFILE the name of every ordinary file in
** the directory pPath. Omit the first nPrefix characters of
** of pPath when inserting into the SFILE table.
**
** Subdirectories are scanned recursively.
** Omit files named in VFILE.
**
** Files whose names begin with "." are omitted unless allFlag is true.
**
** Any files or directories that match the glob pattern pIgnore are
** excluded from the scan. Name matching occurs after the first
** nPrefix characters are elided from the filename.
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 |
zFile = mprintf("%s/.fos", zPath);
fileFound = file_size(zFile)>=1024;
fossil_free(zFile);
}
return fileFound;
}
/*
** Return TRUE if zFile is a temporary file. Return FALSE if not.
*/
static int is_temporary_file(const char *zName){
static const char *const azTemp[] = {
"baseline",
"merge",
"original",
"output",
};
int i, j, n;
if( strglob("ci-comment-????????????.txt", zName) ) return 1;
for(; zName[0]!=0; zName++){
if( zName[0]=='/' && strglob("/ci-comment-????????????.txt", zName) ){
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;
if( zName[n+1]=='-' ){
for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){}
if( zName[j]==0 ) return 1;
}
}
}
return 0;
}
#if INTERFACE
/*
** Values for the scanFlags parameter to vfile_scan().
*/
#define SCAN_ALL 0x001 /* Includes files that begin with "." */
#define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */
#endif /* INTERFACE */
/*
** Load into table SFILE the name of every ordinary file in
** the directory pPath. Omit the first nPrefix characters of
** of pPath when inserting into the SFILE table.
**
** Subdirectories are scanned recursively.
** Omit files named in VFILE.
**
** Files whose names begin with "." are omitted unless allFlag is true.
**
** Any files or directories that match the glob pattern pIgnore are
** excluded from the scan. Name matching occurs after the first
** nPrefix characters are elided from the filename.
*/
void vfile_scan(Blob *pPath, int nPrefix, unsigned scanFlags, Glob *pIgnore){
DIR *d;
int origSize;
const char *zDir;
struct dirent *pEntry;
int skipAll = 0;
static Stmt ins;
static int depth = 0;
|
| ︙ | ︙ | |||
407 408 409 410 411 412 413 |
zMbcs = fossil_utf8_to_unicode(zDir);
d = opendir(zMbcs);
if( d ){
while( (pEntry=readdir(d))!=0 ){
char *zPath;
char *zUtf8;
if( pEntry->d_name[0]=='.' ){
| | < | > | | | | > > | 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 |
zMbcs = fossil_utf8_to_unicode(zDir);
d = opendir(zMbcs);
if( d ){
while( (pEntry=readdir(d))!=0 ){
char *zPath;
char *zUtf8;
if( pEntry->d_name[0]=='.' ){
if( (scanFlags & SCAN_ALL)==0 ) continue;
if( pEntry->d_name[1]==0 ) continue;
if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
}
zUtf8 = fossil_unicode_to_utf8(pEntry->d_name);
blob_appendf(pPath, "/%s", zUtf8);
zPath = blob_str(pPath);
if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
/* do nothing */
}else if( file_wd_isdir(zPath)==1 ){
if( !vfile_top_of_checkout(zPath) ){
vfile_scan(pPath, nPrefix, scanFlags, pIgnore);
}
}else if( file_wd_isfile_or_link(zPath) ){
if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){
db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
db_step(&ins);
db_reset(&ins);
}
}
fossil_mbcs_free(zUtf8);
blob_resize(pPath, origSize);
}
closedir(d);
}
fossil_mbcs_free(zMbcs);
depth--;
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
268 269 270 271 272 273 274 |
static int send_delta_parent(
Xfer *pXfer, /* The transfer context */
int rid, /* record id of the file to send */
int isPrivate, /* True if rid is a private artifact */
Blob *pContent, /* The content of the file to send */
Blob *pUuid /* The UUID of the file to send */
){
| | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
static int send_delta_parent(
Xfer *pXfer, /* The transfer context */
int rid, /* record id of the file to send */
int isPrivate, /* True if rid is a private artifact */
Blob *pContent, /* The content of the file to send */
Blob *pUuid /* The UUID of the file to send */
){
static const char *const azQuery[] = {
"SELECT pid FROM plink x"
" WHERE cid=%d"
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
" AND NOT EXISTS(SELECT 1 FROM plink y"
" WHERE y.pid=x.cid AND y.cid=x.pid)",
"SELECT pid FROM mlink x"
|
| ︙ | ︙ |