Fossil

Changes On Branch ssh-test-http
Login

Changes On Branch ssh-test-http

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch ssh-test-http Excluding Merge-Ins

This is equivalent to a diff from 308f52a63a to ef8b9da03f

2013-09-07
21:50
Move the SSH shared account code back to the branch to keep the development of this new feature separate. ... (Closed-Leaf check-in: 56169d0775 user: andybradford tags: ssh-shared-account)
21:21
Separate SSH transport changes from shared account features to simplify integration. ... (check-in: 915c79cb4f user: andybradford tags: ssh-transport-changes)
2013-08-30
14:07
Merge in latest features and fixes from trunk. ... (Closed-Leaf check-in: ef8b9da03f user: andybradford tags: ssh-test-http)
12:32
Be sure to finalize all queries on the /info page. ... (check-in: cca1adad02 user: drh tags: trunk)
2013-08-25
03:25
Move some posix only includes so they are not used on _WIN32. Can compile again on MinGW. ... (check-in: 8278a03f0e user: mgagnon tags: ssh-test-http)
2013-08-09
07:29
Reimplement the default test-http behavior while retaining the ability to use http to take advantage of Fossil capabilities with SSH URLs. ... (check-in: 7c9347f9c7 user: andybradford tags: ssh-test-http)
07:23
Avoid zombies on client side by waiting for children. This can happen when there are a large number of changes to transmit. ... (Closed-Leaf check-in: 308f52a63a user: andybradford tags: ssh-shared-account)
04:38
Get capabilities fix et al. ... (check-in: ebafd0c335 user: andybradford tags: ssh-shared-account)

Changes to src/add.c.
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276







-
+







    zCleanFlag = db_get("clean-glob", 0);
  }
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  vid = db_lget_int("checkout",0);
  if( vid==0 ){
    fossil_panic("no checkout to add to");
    fossil_fatal("no checkout to add to");
  }
  db_begin_transaction();
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());
  pClean = glob_create(zCleanFlag);
  pIgnore = glob_create(zIgnoreFlag);
  nRoot = strlen(g.zLocalRoot);
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343







-
+







  int vid;
  Stmt loop;

  capture_case_sensitive_option();
  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_panic("no checkout to remove from");
    fossil_fatal("no checkout to remove from");
  }
  db_begin_transaction();
  db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
                filename_collation());
  for(i=2; i<g.argc; i++){
    Blob treeName;
    char *zTreeName;
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
504
505
506
507
508
509
510

511
512
513
514
515
516
517
518







-
+







    zCleanFlag = db_get("clean-glob", 0);
  }
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  vid = db_lget_int("checkout",0);
  if( vid==0 ){
    fossil_panic("no checkout to add to");
    fossil_fatal("no checkout to add to");
  }
  db_begin_transaction();

  /* step 1:  
  ** Populate the temp table "sfile" with the names of all unmanaged
  ** files currently in the check-out, except for files that match the
  ** --ignore or ignore-glob patterns and dot-files.  Then add all of
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623







-
+







  Blob dest;
  Stmt q;

  capture_case_sensitive_option();
  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_panic("no checkout rename files in");
    fossil_fatal("no checkout rename files in");
  }
  if( g.argc<4 ){
    usage("OLDNAME NEWNAME");
  }
  zDest = g.argv[g.argc-1];
  db_begin_transaction();
  file_tree_name(zDest, &dest, 1);
Changes to src/allrepo.c.
151
152
153
154
155
156
157

158
159
160
161
162
163
164
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165







+







    collect_argument(&extra, "analyze",0);
    collect_argument(&extra, "wal",0);
    collect_argument(&extra, "stats",0);
  }else if( strncmp(zCmd, "sync", n)==0 ){
    zCmd = "sync -autourl -R";
    collect_argument(&extra, "verbose","v");
  }else if( strncmp(zCmd, "test-integrity", n)==0 ){
    collect_argument(&extra, "parse", 0);
    zCmd = "test-integrity";
  }else if( strncmp(zCmd, "test-orphans", n)==0 ){
    zCmd = "test-orphans -R";
  }else if( strncmp(zCmd, "test-missing", n)==0 ){
    zCmd = "test-missing -q -R";
    collect_argument(&extra, "notshunned",0);
  }else if( strncmp(zCmd, "changes", n)==0 ){
Changes to src/attach.c.
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317







-
+







    blob_appendf(&manifest, "A %F%s %F %s\n",
                 zName, addCompress ? ".gz" : "", zTarget, zUUID);
    zComment = PD("comment", "");
    while( fossil_isspace(zComment[0]) ) zComment++;
    n = strlen(zComment);
    while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
    if( n>0 ){
      blob_appendf(&manifest, "C %F\n", zComment);
      blob_appendf(&manifest, "C %#F\n", n, zComment);
    }
    zDate = date_in_standard_format("now");
    blob_appendf(&manifest, "D %s\n", zDate);
    blob_appendf(&manifest, "U %F\n", g.zLogin ? g.zLogin : "nobody");
    md5sum_blob(&manifest, &cksum);
    blob_appendf(&manifest, "Z %b\n", &cksum);
    attach_put(&manifest, rid, needModerator);
335
336
337
338
339
340
341
342

343
344
345
346
347
348
349
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349







-
+







  }else{
    @ <input type="hidden" name="page" value="%h(zPage)" />
  }
  @ <input type="hidden" name="from" value="%h(zFrom)" />
  @ <input type="submit" name="ok" value="Add Attachment" />
  @ <input type="submit" name="cancel" value="Cancel" />
  @ </div>
  captcha_generate();
  captcha_generate(0);
  @ </form>
  style_footer();
}

/*
** WEBPAGE: ainfo
** URL: /ainfo?name=ARTIFACTID
Changes to src/blob.c.
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726

727
728
729
730
731
732
733
698
699
700
701
702
703
704

705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733







-
+




















-
+








/*
** Initialize a blob to be the content of a file.  If the filename
** is blank or "-" then read from standard input.
**
** Any prior content of the blob is discarded, not freed.
**
** Return the number of bytes read. Calls fossil_panic() error (i.e.
** Return the number of bytes read. Calls fossil_fatal() error (i.e.
** it exit()s and does not return).
*/
int blob_read_from_file(Blob *pBlob, const char *zFilename){
  int size, got;
  FILE *in;
  if( zFilename==0 || zFilename[0]==0
        || (zFilename[0]=='-' && zFilename[1]==0) ){
    return blob_read_from_channel(pBlob, stdin, -1);
  }
  size = file_wd_size(zFilename);
  blob_zero(pBlob);
  if( size<0 ){
    fossil_fatal("no such file: %s", zFilename);
  }
  if( size==0 ){
    return 0;
  }
  blob_resize(pBlob, size);
  in = fossil_fopen(zFilename, "rb");
  if( in==0 ){
    fossil_panic("cannot open %s for reading", zFilename);
    fossil_fatal("cannot open %s for reading", zFilename);
  }
  got = fread(blob_buffer(pBlob), 1, size, in);
  fclose(in);
  if( got<size ){
    blob_resize(pBlob, got);
  }
  return got;
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756







-
+







** On windows, zeros blob and returns 0.
*/
int blob_read_link(Blob *pBlob, const char *zFilename){
#if !defined(_WIN32)
  char zBuf[1024];
  ssize_t len = readlink(zFilename, zBuf, 1023);
  if( len < 0 ){
    fossil_panic("cannot read symbolic link %s", zFilename);
    fossil_fatal("cannot read symbolic link %s", zFilename);
  }
  zBuf[len] = 0;   /* null-terminate */
  blob_zero(pBlob);
  blob_appendf(pBlob, "%s", zBuf);
  return len;
#else
  blob_zero(pBlob);
764
765
766
767
768
769
770
771

772
773
774

775
776
777


778
779
780

781
782
783
784
785
786
787
788
764
765
766
767
768
769
770

771
772
773

774
775


776
777
778
779

780

781
782
783
784
785
786
787







-
+


-
+

-
-
+
+


-
+
-







**
** If the filename is blank or "-" then write to standard output.
**
** Return the number of bytes written.
*/
int blob_write_to_file(Blob *pBlob, const char *zFilename){
  FILE *out;
  int wrote;
  int nWrote;

  if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
    int n = blob_size(pBlob);
    nWrote = blob_size(pBlob);
#if defined(_WIN32)
    if( fossil_utf8_to_console(blob_buffer(pBlob), n, 0) >= 0 ){
      return n;
    if( fossil_utf8_to_console(blob_buffer(pBlob), nWrote, 0) >= 0 ){
      return nWrote;
    }
#endif
    fwrite(blob_buffer(pBlob), 1, n, stdout);
    fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
    return n;
  }else{
    int i, nName;
    char *zName, zBuf[1000];

    nName = strlen(zFilename);
    if( nName>=sizeof(zBuf) ){
      zName = mprintf("%s", zFilename);
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829









830
831
832
833
834
835
836
813
814
815
816
817
818
819









820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







    }
    out = fossil_fopen(zName, "wb");
    if( out==0 ){
      fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
      return 0;
    }
    if( zName!=zBuf ) free(zName);
  }
  blob_is_init(pBlob);
  wrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
  fclose(out);
  if( wrote!=blob_size(pBlob) && out!=stdout ){
    fossil_fatal_recursive("short write: %d of %d bytes to %s", wrote,
       blob_size(pBlob), zFilename);
  }
  return wrote;
    blob_is_init(pBlob);
    nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
    fclose(out);
    if( nWrote!=blob_size(pBlob) ){
      fossil_fatal_recursive("short write: %d of %d bytes to %s", nWrote,
         blob_size(pBlob), zFilename);
    }
  }
  return nWrote;
}

/*
** Compress a blob pIn.  Store the result in pOut.  It is ok for pIn and
** pOut to be the same blob.
**
** pOut must either be the same as pIn or else uninitialized.
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
991
992

993
994
995
996
997
998
999
975
976
977
978
979
980
981

982
983
984
985
986
987
988
989
990

991
992
993
994
995
996
997
998







-
+








-
+







  int i;
  Blob b1, b2, b3;
  for(i=2; i<g.argc; i++){
    blob_read_from_file(&b1, g.argv[i]);
    blob_compress(&b1, &b2);
    blob_uncompress(&b2, &b3);
    if( blob_compare(&b1, &b3) ){
      fossil_panic("compress/uncompress cycle failed for %s", g.argv[i]);
      fossil_fatal("compress/uncompress cycle failed for %s", g.argv[i]);
    }
    blob_reset(&b1);
    blob_reset(&b2);
    blob_reset(&b3);
  }
  fossil_print("ok\n");
}

#if defined(_WIN32)
#if defined(_WIN32) || defined(__CYGWIN__)
/*
** Convert every \n character in the given blob into \r\n.
*/
void blob_add_cr(Blob *p){
  char *z = p->aData;
  int j   = p->nUsed;
  int i, n;
Changes to src/branch.c.
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68







-
+







  }
  db_find_and_open_repository(0, 0);
  noSign = db_get_int("omitsign", 0)|noSign;

  /* fossil branch new name */
  zBranch = g.argv[3];
  if( zBranch==0 || zBranch[0]==0 ){
    fossil_panic("branch name cannot be empty");
    fossil_fatal("branch name cannot be empty");
  }
  if( db_exists(
        "SELECT 1 FROM tagxref"
        " WHERE tagtype>0"
        "   AND tagid=(SELECT tagid FROM tag WHERE tagname='sym-%q')",
        zBranch)!=0 ){
    fossil_fatal("branch \"%s\" already exists", zBranch);
148
149
150
151
152
153
154
155

156
157
158
159

160
161
162
163
164
165
166
148
149
150
151
152
153
154

155
156
157
158

159
160
161
162
163
164
165
166







-
+



-
+







      db_end_transaction(1);
      fossil_exit(1);
    }
  }

  brid = content_put_ex(&branch, 0, 0, 0, isPrivate);
  if( brid==0 ){
    fossil_panic("trouble committing manifest: %s", g.zErrMsg);
    fossil_fatal("trouble committing manifest: %s", g.zErrMsg);
  }
  db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
  if( manifest_crosslink(brid, &branch)==0 ){
    fossil_panic("unable to install new manifest");
    fossil_fatal("unable to install new manifest");
  }
  assert( blob_is_reset(&branch) );
  content_deltify(rootid, brid, 0);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
  fossil_print("New branch: %s\n", zUuid);
  if( g.argc==3 ){
    fossil_print(
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291







-
+







    while( db_step(&q)==SQLITE_ROW ){
      const char *zBr = db_column_text(&q, 0);
      int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
      fossil_print("%s%s\n", (isCur ? "* " : "  "), zBr);
    }
    db_finalize(&q);
  }else{
    fossil_panic("branch subcommand should be one of: "
    fossil_fatal("branch subcommand should be one of: "
                 "new list ls");
  }
}

/*
** WEBPAGE: brlist
**
Changes to src/captcha.c.
67
68
69
70
71
72
73
74

75
76
77
78
79

80
81
82
83
84
85
86
67
68
69
70
71
72
73

74
75
76
77
78

79
80
81
82
83
84
85
86







-
+




-
+








/*
** Render an 8-character hexadecimal string as ascii art.
** Space to hold the result is obtained from malloc() and should be freed
** by the caller.
*/
char *captcha_render(const char *zPw){
  char *z = fossil_malloc( 500 );
  char *z = fossil_malloc( 9*6*strlen(zPw) + 7 );
  int i, j, k, m;

  k = 0;
  for(i=0; i<6; i++){
    for(j=0; j<8; j++){
    for(j=0; zPw[j]; j++){
      unsigned char v = hexValue(zPw[j]);
      v = (aFont1[v] >> ((5-i)*4)) & 0xf;
      for(m=8; m>=1; m = m>>1){
        if( v & m ){
          z[k++] = 'X';
          z[k++] = 'X';
        }else{
200
201
202
203
204
205
206
207

208
209
210
211
212
213

214
215
216
217
218
219
220
200
201
202
203
204
205
206

207
208
209
210
211
212

213
214
215
216
217
218
219
220







-
+





-
+








/*
** Render an 8-digit hexadecimal string as ascii arg.
** Space to hold the result is obtained from malloc() and should be freed
** by the caller.
*/
char *captcha_render(const char *zPw){
  char *z = fossil_malloc( 300 );
  char *z = fossil_malloc( 7*4*strlen(zPw) + 5 );
  int i, j, k, m;
  const char *zChar;

  k = 0;
  for(i=0; i<4; i++){
    for(j=0; j<8; j++){
    for(j=0; zPw[j]; j++){
      unsigned char v = hexValue(zPw[j]);
      zChar = azFont2[4*v + i];
      for(m=0; zChar[m]; m++){
        z[k++] = zChar[m];
      }
    }
    z[k++] = '\n';
357
358
359
360
361
362
363
364

365
366


367
368
369

370

371




























372


373
374
375
376
377
378
379
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







-
+


+
+



+
-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+








/*
** Render an 8-digit hexadecimal string as ascii arg.
** Space to hold the result is obtained from malloc() and should be freed
** by the caller.
*/
char *captcha_render(const char *zPw){
  char *z = fossil_malloc( 600 );
  char *z = fossil_malloc( 10*6*strlen(zPw) + 7 );
  int i, j, k, m;
  const char *zChar;
  unsigned char x;
  int y;

  k = 0;
  for(i=0; i<6; i++){
    x = 0;
    for(j=0; j<8; j++){
    for(j=0; zPw[j]; j++){
      unsigned char v = hexValue(zPw[j]);
      x = (x<<4) + v;
      switch( x ){
        case 0x7a:
        case 0xfa:
          y = 3;
          break;
        case 0x47:
          y = 2;
          break;
        case 0xf6:
        case 0xa9:
        case 0xa4:
        case 0xa1:
        case 0x9a:
        case 0x76:
        case 0x61:
        case 0x67:
        case 0x69:
        case 0x41:
        case 0x42:
        case 0x43:
        case 0x4a:
          y = 1;
          break;
        default:
          y = 0;
          break;
      }
      zChar = azFont3[6*v + i];
      while( y && zChar[0]==' ' ){ y--; zChar++; }
      while( y && z[k-1]==' ' ){ y--; k--; }
      for(m=0; zChar[m]; m++){
        z[k++] = zChar[m];
      }
    }
    z[k++] = '\n';
  }
  z[k] = 0;
494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
509
510
511
512
513
514
515



516
517























































527
528
529
530
531
532
533

534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608







-
+














+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
** Generate a captcha display together with the necessary hidden parameter
** for the seed and the entry box into which the user will type the text of
** the captcha.  This is typically done at the very bottom of a form.
**
** This routine is a no-op if no captcha is required.
*/
void captcha_generate(void){
void captcha_generate(int showButton){
  unsigned int uSeed;
  const char *zDecoded;
  char *zCaptcha;

  if( !captcha_needed() ) return;
  uSeed = captcha_seed();
  zDecoded = captcha_decode(uSeed);
  zCaptcha = captcha_render(zDecoded);
  @ <div class="captcha"><table class="captcha"><tr><td><pre>
  @ %h(zCaptcha)
  @ </pre>
  @ Enter security code shown above:
  @ <input type="hidden" name="captchaseed" value="%u(uSeed)" />
  @ <input type="text" name="captcha" size=8 />
  if( showButton ){
    @ <input type="submit" value="Submit">
  }
  @ </td></tr></table></div>
}

/*
** WEBPAGE: test-captcha
*/
void captcha_test(void){
  const char *zPw = P("name");
  if( zPw==0 || zPw[0]==0 ){
    u64 x;
    sqlite3_randomness(sizeof(x), &x);
    zPw = mprintf("%016llx", x);
  }
  style_header("Captcha Test");
  @ <pre>
  @ %s(captcha_render(zPw))
  @ </pre>
  style_footer();
}

/*
** Check to see if the current request is coming from an agent that might
** be a spider.  If the agent is not a spider, then return 0 without doing
** anything.  But if the user agent appears to be a spider, offer
** a captcha challenge to allow the user agent to prove that it is human
** and return non-zero.
*/
int exclude_spiders(const char *zPage){
  const char *zCookieValue;
  char *zCookieName;
  if( g.isHuman ) return 0;
#if 0
  {
    const char *zReferer = P("HTTP_REFERER");
    if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
      return 0;
    }
  }
#endif
  zCookieName = mprintf("fossil-cc-%.10s", db_get("project-code","x"));
  zCookieValue = P(zCookieName);
  if( zCookieValue && atoi(zCookieValue)==1 ) return 0;
  if( captcha_is_correct() ){
    cgi_set_cookie(zCookieName, "1", login_cookie_path(), 8*3600);
    return 0;
  }

  /* This appears to be a spider.  Offer the captcha */
  style_header("Verification");
  form_begin(0, "%s", zPage);
  cgi_query_parameters_to_hidden();
  @ <p>Please demonstrate that you are human, not a spider or robot</p>
  captcha_generate(1);
  @ </form>
  style_footer();
  return 1;
}
Changes to src/cgi.c.
57
58
59
60
61
62
63







64
65
66
67
68
69
70
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77







+
+
+
+
+
+
+








/*
** Destinations for output text.
*/
#define CGI_HEADER   0
#define CGI_BODY     1

/*
** Flags for SSH HTTP clients
*/
#define CGI_SSH_CLIENT           0x0001     /* Client is SSH */
#define CGI_SSH_COMPAT           0x0002     /* Compat for old SSH transport */
#define CGI_SSH_FOSSIL           0x0004     /* Use new Fossil SSH transport */

#endif /* INTERFACE */

/*
** The HTTP reply is generated in two pieces: the header and the body.
** These pieces are generated separately because they are not necessary
** produced in order.  Parts of the header might be built after all or
** part of the body.  The header and body are accumulated in separate
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456

457
458
459
460

461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464

465
466
467
468

469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
484







+










-
+














+












-
+









-
+



-
+







-
+







static int nUsedQP = 0;  /* Space actually used in aParamQP[] */
static int sortQP = 0;   /* True if aParamQP[] needs sorting */
static int seqQP = 0;    /* Sequence numbers */
static struct QParam {   /* One entry for each query parameter or cookie */
  const char *zName;        /* Parameter or cookie name */
  const char *zValue;       /* Value of the query parameter or cookie */
  int seq;                  /* Order of insertion */
  int isQP;                 /* True for query parameters */
} *aParamQP;             /* An array of all parameters and cookies */

/*
** Add another query parameter or cookie to the parameter set.
** zName is the name of the query parameter or cookie and zValue
** is its fully decoded value.
**
** zName and zValue are not copied and must not change or be
** deallocated after this routine returns.
*/
void cgi_set_parameter_nocopy(const char *zName, const char *zValue){
void cgi_set_parameter_nocopy(const char *zName, const char *zValue, int isQP){
  if( nAllocQP<=nUsedQP ){
    nAllocQP = nAllocQP*2 + 10;
    if( nAllocQP>1000 ){
      /* Prevent a DOS service attack against the framework */
      fossil_fatal("Too many query parameters");
    }
    aParamQP = fossil_realloc( aParamQP, nAllocQP*sizeof(aParamQP[0]) );
  }
  aParamQP[nUsedQP].zName = zName;
  aParamQP[nUsedQP].zValue = zValue;
  if( g.fHttpTrace ){
    fprintf(stderr, "# cgi: %s = [%s]\n", zName, zValue);
  }
  aParamQP[nUsedQP].seq = seqQP++;
  aParamQP[nUsedQP].isQP = isQP;
  nUsedQP++;
  sortQP = 1;
}

/*
** Add another query parameter or cookie to the parameter set.
** zName is the name of the query parameter or cookie and zValue
** is its fully decoded value.
**
** Copies are made of both the zName and zValue parameters.
*/
void cgi_set_parameter(const char *zName, const char *zValue){
  cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue));
  cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue), 0);
}

/*
** Replace a parameter with a new value.
*/
void cgi_replace_parameter(const char *zName, const char *zValue){
  int i;
  for(i=0; i<nUsedQP; i++){
    if( fossil_strcmp(aParamQP[i].zName,zName)==0 ){
      aParamQP[i].zValue = zValue;
      aParamQP[i].zValue = mprintf("%s",zValue);
      return;
    }
  }
  cgi_set_parameter_nocopy(zName, zValue);
  cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
}

/*
** Add a query parameter.  The zName portion is fixed but a copy
** must be made of zValue.
*/
void cgi_setenv(const char *zName, const char *zValue){
  cgi_set_parameter_nocopy(zName, mprintf("%s",zValue));
  cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
}
 

/*
** Add a list of query parameters or cookies to the parameter set.
**
** Each parameter is of the form NAME=VALUE.  Both the NAME and the
491
492
493
494
495
496
497

498
499
500
501
502
503
504
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514







+







** before the NAME is ignored.
**
** The input string "z" is modified but no copies is made.  "z"
** should not be deallocated or changed again after this routine
** returns or it will corrupt the parameter table.
*/
static void add_param_list(char *z, int terminator){
  int isQP = terminator=='&';
  while( *z ){
    char *zName;
    char *zValue;
    while( fossil_isspace(*z) ){ z++; }
    zName = z;
    while( *z && *z!='=' && *z!=terminator ){ z++; }
    if( *z=='=' ){
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
522
523
524
525
526
527
528

529
530
531
532
533
534
535
536







-
+







      }
      dehttpize(zValue);
    }else{
      if( *z ){ *z++ = 0; }
      zValue = "";
    }
    if( fossil_islower(zName[0]) ){
      cgi_set_parameter_nocopy(zName, zValue);
      cgi_set_parameter_nocopy(zName, zValue, isQP);
    }
#ifdef FOSSIL_ENABLE_JSON
    json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
#endif /* FOSSIL_ENABLE_JSON */
  }
}

656
657
658
659
660
661
662
663

664
665
666

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686
687
688
689

690
691
692
693
694
695
696
666
667
668
669
670
671
672

673
674
675

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692

693
694
695
696
697
698

699
700
701
702
703
704
705
706







-
+


-
+
















-
+





-
+







  zBoundry = get_line_from_string(&z, &len);
  if( zBoundry==0 ) return;
  while( (zLine = get_line_from_string(&z, &len))!=0 ){
    if( zLine[0]==0 ){
      int nContent = 0;
      zValue = get_bounded_content(&z, &len, zBoundry, &nContent);
      if( zName && zValue && fossil_islower(zName[0]) ){
        cgi_set_parameter_nocopy(zName, zValue);
        cgi_set_parameter_nocopy(zName, zValue, 1);
        if( showBytes ){
          cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
               mprintf("%d",nContent));
               mprintf("%d",nContent), 1);
        }
      }
      zName = 0;
      showBytes = 0;
    }else{
      nArg = tokenize_line(zLine, sizeof(azArg)/sizeof(azArg[0]), azArg);
      for(i=0; i<nArg; i++){
        int c = fossil_tolower(azArg[i][0]);
        int n = strlen(azArg[i]);
        if( c=='c' && sqlite3_strnicmp(azArg[i],"content-disposition:",n)==0 ){
          i++;
        }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){
          zName = azArg[++i];
        }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){
          char *z = azArg[++i];
          if( zName && z && fossil_islower(zName[0]) ){
            cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z);
            cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1);
          }
          showBytes = 1;
        }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){
          char *z = azArg[++i];
          if( zName && z && fossil_islower(zName[0]) ){
            cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z);
            cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
          }
        }
      }
    }
  }        
}

810
811
812
813
814
815
816


817
818
819
820
821
822
823
824
825
826



827
828
829
830
831








832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853


854
855
856
857
858
859
860
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874


875
876
877
878
879
880
881
882
883







+
+










+
+
+





+
+
+
+
+
+
+
+




















-
-
+
+







      fprintf(stderr, "# failed to open %s\n", zFile);
      return;
    }
  }
  fputs(z, pLog);
}

/* Forward declaration */
static NORETURN void malformed_request(const char *zMsg);

/*
** Initialize the query parameter database.  Information is pulled from
** the QUERY_STRING environment variable (if it exists), from standard
** input if there is POST data, and from HTTP_COOKIE.
*/
void cgi_init(void){
  char *z;
  const char *zType;
  int len;
  const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
  const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);

#ifdef FOSSIL_ENABLE_JSON
  json_main_bootstrap();
#endif
  g.isHTTP = 1;
  cgi_destination(CGI_BODY);
  if( zRequestUri==0 ) malformed_request("missing REQUEST_URI");
  if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
  if( cgi_parameter("PATH_INFO",0)==0 ){
    int i, j;
    for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){}
    for(j=i; zRequestUri[j] && zRequestUri[j]!='?'; j++){}
    cgi_set_parameter("PATH_INFO", mprintf("%.*s", j-i, zRequestUri+i));
  }

  z = (char*)P("HTTP_COOKIE");
  if( z ){
    z = mprintf("%s",z);
    add_param_list(z, ';');
  }
  
  z = (char*)P("QUERY_STRING");
  if( z ){
    z = mprintf("%s",z);
    add_param_list(z, '&');
  }

  z = (char*)P("REMOTE_ADDR");
  if( z ){
    g.zIpAddr = mprintf("%s", z);
  }

  len = atoi(PD("CONTENT_LENGTH", "0"));
  g.zContentType = zType = P("CONTENT_TYPE");
  if( len>0 && zType ){
    blob_zero(&g.cgiIn);
  blob_zero(&g.cgiIn);
  if( len>0 && zType ){
    if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0 
         || strncmp(zType,"multipart/form-data",19)==0 ){
      z = fossil_malloc( len+1 );
      len = fread(z, 1, len, g.httpIn);
      z[len] = 0;
      cgi_trace(z);
      if( zType[0]=='a' ){
965
966
967
968
969
970
971
972

973
974
975
976
977
978
979
988
989
990
991
992
993
994

995
996
997
998
999
1000
1001
1002







-
+







  /* If no match is found and the name begins with an upper-case
  ** letter, then check to see if there is an environment variable
  ** with the given name.
  */
  if( fossil_isupper(zName[0]) ){
    const char *zValue = fossil_getenv(zName);
    if( zValue ){
      cgi_set_parameter_nocopy(zName, zValue);
      cgi_set_parameter_nocopy(zName, zValue, 0);
      CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
      return zValue;
    }
  }
  CGIDEBUG(("no-match [%s]\n", zName));
  return zDefault;
}
1066
1067
1068
1069
1070
1071
1072















1073
1074
1075
1076
1077
1078
1079
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    if( !showAll ){
      if( fossil_stricmp("HTTP_COOKIE",zName)==0 ) continue;
      if( fossil_strnicmp("fossil-",zName,7)==0 ) continue;
    }
    cgi_printf("%h = %h  <br />\n", zName, aParamQP[i].zValue);
  }
}

/*
** Export all query parameters (but not cookies or environment variables)
** as hidden values of a form.
*/
void cgi_query_parameters_to_hidden(void){
  int i;
  const char *zN, *zV;
  for(i=0; i<nUsedQP; i++){
    if( aParamQP[i].isQP==0 ) continue;
    zN = aParamQP[i].zName;
    zV = aParamQP[i].zValue;
    @ <input type="hidden" name="%h(zN)" value="%h(zV)">
  }
}

/*
** This routine works like "printf" except that it has the
** extra formatting capabilities such as %h and %t.
*/
void cgi_printf(const char *zFormat, ...){
  va_list ap;
1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137

1138
1139
1140
1141
1142
1143
1144
1145







-
+


-
+







  vxprintf(pContent,zFormat,ap);
}


/*
** Send a reply indicating that the HTTP request was malformed
*/
static NORETURN void malformed_request(void){
static NORETURN void malformed_request(const char *zMsg){
  cgi_set_status(501, "Not Implemented");
  cgi_printf(
    "<html><body>Unrecognized HTTP Request</body></html>\n"
    "<html><body><p>Bad Request: %s</p></body></html>\n", zMsg
  );
  cgi_reply();
  fossil_exit(0);
}

/*
** Panic and die while processing a webpage.
1185
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198

1199
1200
1201
1202

1203
1204
1205
1206
1207
1208

1209
1210

1211
1212
1213
1214
1215
1216
1217
1223
1224
1225
1226
1227
1228
1229

1230
1231
1232
1233
1234
1235

1236
1237
1238
1239

1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256







-
+





-
+



-
+





-
+


+







  char *z, *zToken;
  int i;
  struct sockaddr_in remoteName;
  socklen_t size = sizeof(struct sockaddr_in);
  char zLine[2000];     /* A single line of input. */
  g.fullHttpReply = 1;
  if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
    malformed_request();
    malformed_request("missing HTTP header");
  }
  blob_append(&g.httpHeader, zLine, -1);
  cgi_trace(zLine);
  zToken = extract_token(zLine, &z);
  if( zToken==0 ){
    malformed_request();
    malformed_request("malformed HTTP header");
  }
  if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0
      && fossil_strcmp(zToken,"HEAD")!=0 ){
    malformed_request();
    malformed_request("unsupported HTTP method");
  }
  cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
  cgi_setenv("REQUEST_METHOD",zToken);
  zToken = extract_token(z, &z);
  if( zToken==0 ){
    malformed_request();
    malformed_request("malformed URL in HTTP header");
  }
  cgi_setenv("REQUEST_URI", zToken);
  cgi_setenv("SCRIPT_NAME", "");
  for(i=0; zToken[i] && zToken[i]!='?'; i++){}
  if( zToken[i] ) zToken[i++] = 0;
  cgi_setenv("PATH_INFO", zToken);
  cgi_setenv("QUERY_STRING", &zToken[i]);
  if( zIpAddr==0 &&
        getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName, 
                                &size)>=0
1267
1268
1269
1270
1271
1272
1273









































































































































































































































































1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+







        cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
      }
    }
  }
  cgi_init();
  cgi_trace(0);
}

/*
** This routine handles a single HTTP request from an SSH client which is
** coming in on g.httpIn and which replies on g.httpOut
**
** Once all the setup is finished, this procedure returns
** and subsequent code handles the actual generation of the webpage.
**
** It is called in a loop so some variables will need to be replaced
*/
void cgi_handle_ssh_http_request(const char *zIpAddr){
  static int nCycles = 0;
  static char *zCmd = 0;
  char *z, *zToken;
  const char *zType;
  int i, content_length;
  char zLine[2000];     /* A single line of input. */

  if( zIpAddr ){
    if( nCycles==0 ){   
      cgi_setenv("REMOTE_ADDR", zIpAddr);
      g.zIpAddr = mprintf("%s", zIpAddr);
    }
  }else{
    fossil_panic("missing SSH IP address");
  }
  if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
    malformed_request("missing HTTP header");
  }
  cgi_trace(zLine);
  zToken = extract_token(zLine, &z);
  if( zToken==0 ){
    malformed_request("malformed HTTP header");
  }

  if( fossil_strcmp(zToken, "echo")==0 ){
    /* start looking for probes to complete transport_open */
    zCmd = cgi_handle_ssh_probes(zLine, sizeof(zLine), z, zToken);
    if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
      malformed_request("missing HTTP header");
    }
    cgi_trace(zLine);
    zToken = extract_token(zLine, &z);
    if( zToken==0 ){
      malformed_request("malformed HTTP header");
    }
  }else if( zToken && strlen(zToken)==0 && zCmd ){
    /* transport_flip request and continued transport_open */
    cgi_handle_ssh_transport(zCmd);
    if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
      malformed_request("missing HTTP header");
    }
    cgi_trace(zLine);
    zToken = extract_token(zLine, &z);
    if( zToken==0 ){
      malformed_request("malformed HTTP header");
    }
  }

  if( fossil_strcmp(zToken,"GET")!=0 && fossil_strcmp(zToken,"POST")!=0
      && fossil_strcmp(zToken,"HEAD")!=0 ){
    malformed_request("unsupported HTTP method");
  }

  if( nCycles==0 ){
    cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
    cgi_setenv("REQUEST_METHOD",zToken);
  }

  zToken = extract_token(z, &z);
  if( zToken==0 ){
    malformed_request("malformed URL in HTTP header");
  }
  if( nCycles==0 ){
    cgi_setenv("REQUEST_URI", zToken);
    cgi_setenv("SCRIPT_NAME", "");
  }

  for(i=0; zToken[i] && zToken[i]!='?'; i++){}
  if( zToken[i] ) zToken[i++] = 0;
  if( nCycles==0 ){
    cgi_setenv("PATH_INFO", zToken);
  }else{
    cgi_replace_parameter("PATH_INFO", zToken);
  }
 
  /* Get all the optional fields that follow the first line.
  */
  while( fgets(zLine,sizeof(zLine),g.httpIn) ){
    char *zFieldName;
    char *zVal;

    cgi_trace(zLine);
    zFieldName = extract_token(zLine,&zVal);
    if( zFieldName==0 || *zFieldName==0 ) break;
    while( fossil_isspace(*zVal) ){ zVal++; }
    i = strlen(zVal);
    while( i>0 && fossil_isspace(zVal[i-1]) ){ i--; }
    zVal[i] = 0;
    for(i=0; zFieldName[i]; i++){
      zFieldName[i] = fossil_tolower(zFieldName[i]);
    }
    if( fossil_strcmp(zFieldName,"content-length:")==0 ){
      content_length = atoi(zVal);
    }else if( fossil_strcmp(zFieldName,"content-type:")==0 ){
      g.zContentType = zType = mprintf("%s", zVal);
    }else if( fossil_strcmp(zFieldName,"host:")==0 ){
      if( nCycles==0 ){
        cgi_setenv("HTTP_HOST", zVal);
      }
    }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
      if( nCycles==0 ){
        cgi_setenv("HTTP_USER_AGENT", zVal);
      }
    }else if( fossil_strcmp(zFieldName,"x-fossil-transport:")==0 ){
      if( fossil_strnicmp(zVal, "ssh", 3)==0 ){
        if( nCycles==0 ){
          g.fSshClient |= CGI_SSH_FOSSIL;
          g.fullHttpReply = 0;
          cgi_setenv("X-FOSSIL_TRANSPORT", zVal);
        }
      }
    }
  }

  if( nCycles==0 ){
    if( ! ( g.fSshClient & CGI_SSH_FOSSIL ) ){
      /* did not find new fossil ssh transport */
      g.fSshClient &= ~CGI_SSH_CLIENT;
      g.fullHttpReply = 1;
      cgi_replace_parameter("REMOTE_ADDR", "127.0.0.1");
    }
  }

  cgi_reset_content();
  cgi_destination(CGI_BODY);

  if( content_length>0 && zType ){
    blob_zero(&g.cgiIn);
    if( fossil_strcmp(zType, "application/x-fossil")==0 ){
      blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
      blob_uncompress(&g.cgiIn, &g.cgiIn);
    }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
      blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
    }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
      blob_read_from_channel(&g.cgiIn, g.httpIn, content_length);
    }
  }
  cgi_trace(0);
  nCycles++;
}

/*
** This routine handles the old fossil SSH probes
*/
char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){
  /* Start looking for probes */
  while( fossil_strcmp(zToken, "echo")==0 ){
    zToken = extract_token(z, &z);
    if( zToken==0 ){
      malformed_request("malformed probe");
    }
    if( fossil_strncmp(zToken, "test", 4)==0 ||
        fossil_strncmp(zToken, "probe-", 6)==0 ){
      fprintf(g.httpOut, "%s\n", zToken);
      fflush(g.httpOut);
    }else{
      malformed_request("malformed probe");
    }
    if( fgets(zLine, zSize, g.httpIn)==0 ){
      malformed_request("malformed probe");
    }
    cgi_trace(zLine);
    zToken = extract_token(zLine, &z);
    if( zToken==0 ){
      malformed_request("malformed probe");
    }
  }

  /* Got all probes now first transport_open is completed
  ** so return the command that was requested
  */
  g.fSshClient |= CGI_SSH_COMPAT;
  return mprintf("%s", zToken);
}

/*
** This routine handles the old fossil SSH transport_flip
** and transport_open communications if detected.
*/
void cgi_handle_ssh_transport(const char *zCmd){
  char *z, *zToken;
  char zLine[2000];     /* A single line of input. */

  /* look for second newline of transport_flip */
  if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
    malformed_request("incorrect transport_flip");
  }
  cgi_trace(zLine);
  zToken = extract_token(zLine, &z);
  if( zToken && strlen(zToken)==0 ){
    /* look for path to fossil */
    if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
      if ( zCmd==0 ){
        malformed_request("missing fossil command");
      }else{
        /* no new command so exit */
        fossil_exit(0);
      }
    }
    cgi_trace(zLine);
    zToken = extract_token(zLine, &z);
    if( zToken==0 ){
      malformed_request("malformed fossil command");
    }
    /* see if we've seen the command */
    if( zCmd && zCmd[0] && fossil_strcmp(zToken, zCmd)==0 ){
      return;
    }else{
      malformed_request("transport_open failed");
    }
  }else{
    malformed_request("transport_flip failed");
  }
}

/*
** This routine handles a single SCGI request which is coming in on
** g.httpIn and which replies on g.httpOut
**
** The SCGI request is read from g.httpIn and is used to initialize
** entries in the cgi_parameter() hash, as if those entries were
** environment variables.  A call to cgi_init() completes
** the setup.  Once all the setup is finished, this procedure returns
** and subsequent code handles the actual generation of the webpage.
*/
void cgi_handle_scgi_request(void){
  char *zHdr;
  char *zToFree;
  int nHdr = 0;
  int nRead;
  int n, m;
  char c;

  while( (c = fgetc(g.httpIn))!=EOF && fossil_isdigit(c) ){
    nHdr = nHdr*10 + c - '0';
  }
  if( nHdr<16 ) malformed_request("SCGI header too short");
  zToFree = zHdr = fossil_malloc(nHdr);
  nRead = (int)fread(zHdr, 1, nHdr, g.httpIn);
  if( nRead<nHdr ) malformed_request("cannot read entire SCGI header");
  nHdr = nRead;
  while( nHdr ){
    for(n=0; n<nHdr && zHdr[n]; n++){}
    for(m=n+1; m<nHdr && zHdr[m]; m++){}
    if( m>=nHdr ) malformed_request("SCGI header formatting error");
    cgi_set_parameter(zHdr, zHdr+n+1);
    zHdr += m+1;
    nHdr -= m+1;
  }
  fossil_free(zToFree);
  fgetc(g.httpIn);  /* Read past the "," separating header from content */
  cgi_init();
}


#if INTERFACE
/* 
** Bitmap values for the flags parameter to cgi_http_server().
*/
#define HTTP_SERVER_LOCALHOST      0x0001     /* Bind to 127.0.0.1 only */
#define HTTP_SERVER_SCGI           0x0002     /* SCGI instead of HTTP */

#endif /* INTERFACE */

/*
** Maximum number of child processes that we can have running
** at one time before we start slowing things down.
*/
1354
1355
1356
1357
1358
1359
1360
1361


1362
1363
1364
1365
1366
1367
1368
1659
1660
1661
1662
1663
1664
1665

1666
1667
1668
1669
1670
1671
1672
1673
1674







-
+
+







      fossil_fatal("unable to open listening socket on any"
                   " port in the range %d..%d", mnPort, mxPort);
    }
  }
  if( iPort>mxPort ) return 1;
  listen(listener,10);
  if( iPort>mnPort ){
    fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
    fossil_print("Listening for %s requests on TCP port %d\n",
       (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP",  iPort);
    fflush(stdout);
  }
  if( zBrowser ){
    zBrowser = mprintf(zBrowser, iPort);
    if( system(zBrowser)<0 ){
      fossil_warning("cannot start browser: %s\n", zBrowser);
    }
Changes to src/checkin.c.
621
622
623
624
625
626
627
628

629
630





631
632
633
634
635
636
637
621
622
623
624
625
626
627

628
629

630
631
632
633
634
635
636
637
638
639
640
641







-
+

-
+
+
+
+
+







  zEditor = db_get("editor", 0);
  if( zEditor==0 ){
    zEditor = fossil_getenv("VISUAL");
  }
  if( zEditor==0 ){
    zEditor = fossil_getenv("EDITOR");
  }
#ifdef _WIN32
#if defined(_WIN32) || defined(__CYGWIN__)
  if( zEditor==0 ){
    zEditor = mprintf("%s\\notepad.exe", fossil_getenv("SystemRoot"));
    zEditor = mprintf("%s\\notepad.exe", fossil_getenv("SYSTEMROOT"));
#if defined(__CYGWIN__)
    zEditor = fossil_utf8_to_filename(zEditor);
    blob_add_cr(pPrompt);
#endif
  }
#endif
  if( zEditor==0 ){
    blob_append(pPrompt,
       "#\n"
       "# Since no default text editor is set using EDITOR or VISUAL\n"
       "# environment variables or the \"fossil set editor\" command,\n"
899
900
901
902
903
904
905
906

907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

926




927
928
929
930
931
932
933
903
904
905
906
907
908
909

910

911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938
939
940







-
+
-


















+
-
+
+
+
+







  CheckinInfo *p,             /* Information about the check-in */
  int *pnFBcard               /* OUT: Number of generated B- and F-cards */
){
  char *zDate;                /* Date of the check-in */
  char *zParentUuid;          /* UUID of parent check-in */
  Blob filename;              /* A single filename */
  int nBasename;              /* Size of base filename */
  Stmt q;                     /* Query of files changed */
  Stmt q;                     /* Various queries */
  Stmt q2;                    /* Query of merge parents */
  Blob mcksum;                /* Manifest checksum */
  ManifestFile *pFile;        /* File from the baseline */
  int nFBcard = 0;            /* Number of B-cards and F-cards */
  int i;                      /* Loop counter */
  const char *zColor;         /* Modified value of p->zColor */

  assert( pBaseline==0 || pBaseline->zBaseline==0 );
  assert( pBaseline==0 || zBaselineUuid!=0 );
  blob_zero(pOut);
  zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
  if( pBaseline ){
    blob_appendf(pOut, "B %s\n", zBaselineUuid);
    manifest_file_rewind(pBaseline);
    pFile = manifest_file_next(pBaseline, 0);
    nFBcard++;
  }else{
    pFile = 0;
  }
  if( blob_size(p->pComment)!=0 ){
  blob_appendf(pOut, "C %F\n", blob_str(p->pComment));
    blob_appendf(pOut, "C %F\n", blob_str(p->pComment));
  }else{
    blob_append(pOut, "C (no\\scomment)\n", 16);
  }
  zDate = date_in_standard_format(p->zDateOvrd ? p->zDateOvrd : "now");
  blob_appendf(pOut, "D %s\n", zDate);
  zDate[10] = ' ';
  db_prepare(&q,
    "SELECT pathname, uuid, origname, blob.rid, isexe, islink,"
    "       is_selected(vfile.id)"
    "  FROM vfile JOIN blob ON vfile.mrid=blob.rid"
1004
1005
1006
1007
1008
1009
1010
1011
1012


1013
1014
1015


1016
1017
1018
1019
1020
1021
1022
1023

1024
1025
1026
1027
1028


1029
1030
1031
1032
1033
1034
1035
1036
1037








1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053












1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1011
1012
1013
1014
1015
1016
1017


1018
1019
1020


1021
1022
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033


1034
1035
1036
1037
1038
1039





1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092







-
-
+
+

-
-
+
+







-
+



-
-
+
+




-
-
-
-
-
+
+
+
+
+
+
+
+
















+
+
+
+
+
+
+
+
+
+
+
+










-







  }
  if( p->zMimetype && p->zMimetype[0] ){
    blob_appendf(pOut, "N %F\n", p->zMimetype);
  }
  blob_appendf(pOut, "P %s", zParentUuid);
  if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
  free(zParentUuid);
  db_prepare(&q2, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
  while( db_step(&q2)==SQLITE_ROW ){
  db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
  while( db_step(&q)==SQLITE_ROW ){
    char *zMergeUuid;
    int mid = db_column_int(&q2, 0);
    if( !g.markPrivate && content_is_private(mid) ) continue;
    int mid = db_column_int(&q, 0);
    if( (!g.markPrivate && content_is_private(mid)) || (mid == vid) ) continue;
    zMergeUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
    if( zMergeUuid ){
      blob_appendf(pOut, " %s", zMergeUuid);
      if( p->verifyDate ) checkin_verify_younger(mid, zMergeUuid, zDate);
      free(zMergeUuid);
    }
  }
  db_finalize(&q2);
  db_finalize(&q);
  free(zDate);
  blob_appendf(pOut, "\n");

  db_prepare(&q2,
    "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid"
  db_prepare(&q,
    "SELECT CASE vmerge.id WHEN -1 THEN '+' ELSE '-' END || blob.uuid, merge"
    "  FROM vmerge, blob"
    " WHERE (vmerge.id=-1 OR vmerge.id=-2)"
    "   AND blob.rid=vmerge.merge"
    " ORDER BY 1");
  while( db_step(&q2)==SQLITE_ROW ){
    const char *zCherrypickUuid = db_column_text(&q2, 0);
    blob_appendf(pOut, "Q %s\n", zCherrypickUuid);
  }
  db_finalize(&q2);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zCherrypickUuid = db_column_text(&q, 0);
    int mid = db_column_int(&q, 1);
    if( mid != vid ){
      blob_appendf(pOut, "Q %s\n", zCherrypickUuid);
    }
  }
  db_finalize(&q);

  if( p->pCksum ) blob_appendf(pOut, "R %b\n", p->pCksum);
  zColor = p->zColor;
  if( p->zBranch && p->zBranch[0] ){
    /* Set tags for the new branch */
    if( p->zBrClr && p->zBrClr[0] ){
      zColor = 0;
      blob_appendf(pOut, "T *bgcolor * %F\n", p->zBrClr);
    }
    blob_appendf(pOut, "T *branch * %F\n", p->zBranch);
    blob_appendf(pOut, "T *sym-%F *\n", p->zBranch);
  }
  if( zColor && zColor[0] ){
    /* One-time background color */
    blob_appendf(pOut, "T +bgcolor * %F\n", zColor);
  }
  db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
                 " WHERE id=-4 ORDER BY 1");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zIntegrateUuid = db_column_text(&q, 0);
    int rid = db_column_int(&q, 1);
    if( is_a_leaf(rid) && !db_exists("SELECT 1 FROM tagxref "
        " WHERE tagid=%d AND rid=%d AND tagtype>0", TAG_CLOSED, rid)){
      blob_appendf(pOut, "T +closed %s\n", zIntegrateUuid);
    }
  }
  db_finalize(&q);

  if( p->azTag ){
    for(i=0; p->azTag[i]; i++){
      /* Add a symbolic tag to this check-in.  The tag names have already
      ** been sorted and converted using the %F format */
      assert( i==0 || strcmp(p->azTag[i-1], p->azTag[i])<=0 );
      blob_appendf(pOut, "T +sym-%s *\n", p->azTag[i]);
    }
  }
  if( p->zBranch && p->zBranch[0] ){
    /* For a new branch, cancel all prior propagating tags */
    Stmt q;
    db_prepare(&q,
        "SELECT tagname FROM tagxref, tag"
        " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
        "   AND tagtype==2 AND tagname GLOB 'sym-*'"
        "   AND tagname!='sym-'||%Q"
        " ORDER BY tagname",
        vid, p->zBranch);
1296
1297
1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308
1309
1310
1317
1318
1319
1320
1321
1322
1323

1324
1325
1326
1327
1328
1329
1330
1331







-
+







void commit_cmd(void){
  int hasChanges;        /* True if unsaved changes exist */
  int vid;               /* blob-id of parent version */
  int nrid;              /* blob-id of a modified file */
  int nvid;              /* Blob-id of the new check-in */
  Blob comment;          /* Check-in comment */
  const char *zComment;  /* Check-in comment */
  Stmt q;                /* Query to find files that have been modified */
  Stmt q;                /* Various queries */
  char *zUuid;           /* UUID of the new check-in */
  int noSign = 0;        /* True to omit signing the manifest using GPG */
  int isAMerge = 0;      /* True if checking in a merge */
  int noWarningFlag = 0; /* True if skipping all warnings */
  int forceFlag = 0;     /* Undocumented: Disables all checks */
  int forceDelta = 0;    /* Force a delta-manifest */
  int forceBaseline = 0; /* Force a baseline-manifest */
1449
1450
1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1465
1466



1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1470
1471
1472
1473
1474
1475
1476


1477
1478
1479
1480
1481
1482
1483



1484
1485
1486
1487
1488
1489

1490
1491
1492
1493
1494
1495
1496
1497







-
-
+






-
-
-
+
+
+



-
+








  /* Doing "fossil mv fileA fileB; fossil add fileA; fossil commit fileA"
  ** will generate a manifest that has two fileA entries, which is illegal.
  ** When you think about it, the sequence above makes no sense.  So detect
  ** it and disallow it.  Ticket [0ff64b0a5fc8].
  */
  if( g.aCommitFile ){
    Stmt qRename;
    db_prepare(&qRename,
    db_prepare(&q,
       "SELECT v1.pathname, v2.pathname"
       "  FROM vfile AS v1, vfile AS v2"
       " WHERE is_selected(v1.id)"
       "   AND v2.origname IS NOT NULL"
       "   AND v2.origname=v1.pathname"
       "   AND NOT is_selected(v2.id)");
    if( db_step(&qRename)==SQLITE_ROW ){
      const char *zFrom = db_column_text(&qRename, 0);
      const char *zTo = db_column_text(&qRename, 1);
    if( db_step(&q)==SQLITE_ROW ){
      const char *zFrom = db_column_text(&q, 0);
      const char *zTo = db_column_text(&q, 1);
      fossil_fatal("cannot do a partial commit of '%s' without '%s' because "
                   "'%s' was renamed to '%s'", zFrom, zTo, zFrom, zTo);
    }
    db_finalize(&qRename);
    db_finalize(&q);
  }

  user_select();
  /*
  ** Check that the user exists.
  */
  if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){
1524
1525
1526
1527
1528
1529
1530


1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542

1543
1544
1545
1546
1547






1548
1549
1550
1551
1552
1553
1554
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565





1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578







+
+












+
-
-
-
-
-
+
+
+
+
+
+







  if( zComment ){
    blob_zero(&comment);
    blob_append(&comment, zComment, -1);
  }else if( zComFile ){
    blob_zero(&comment);
    blob_read_from_file(&comment, zComFile);
    blob_to_utf8_no_bom(&comment, 1);
  }else if(dryRunFlag){
    blob_zero(&comment);
  }else{
    char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
    prepare_commit_comment(&comment, zInit, &sCiInfo, vid);
    if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
      blob_zero(&ans);
      prompt_user("unchanged check-in comment.  continue (y/N)? ", &ans);
      cReply = blob_str(&ans)[0];
      if( cReply!='y' && cReply!='Y' ) fossil_exit(1);;
    }
    free(zInit);
  }
  if( blob_size(&comment)==0 ){
    if( !dryRunFlag ){
    blob_zero(&ans);
    prompt_user("empty check-in comment.  continue (y/N)? ", &ans);
    cReply = blob_str(&ans)[0];
    if( cReply!='y' && cReply!='Y' ){
      fossil_exit(1);
      blob_zero(&ans);
      prompt_user("empty check-in comment.  continue (y/N)? ", &ans);
      cReply = blob_str(&ans)[0];
      if( cReply!='y' && cReply!='Y' ){
        fossil_exit(1);
      }
    }
  }else{
    db_multi_exec("REPLACE INTO vvar VALUES('ci-comment',%B)", &comment);
    db_end_transaction(0);
    db_begin_transaction();
  }

1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1637
1638
1639
1640
1641
1642
1643



1644
1645
1646
1647
1648
1649
1650







-
-
-







                 "use --allow-conflict to override");
  }else if( abortCommit ){
    fossil_fatal("one or more files were converted on your request; "
                 "please re-test before committing");
  }

  /* Create the new manifest */
  if( blob_size(&comment)==0 ){
    blob_append(&comment, "(no comment)", -1);
  }
  sCiInfo.pComment = &comment;
  sCiInfo.pCksum =  useCksum ? &cksum1 : 0;
  sCiInfo.verifyDate = !allowOlder && !forceFlag;
  if( forceDelta ){
    blob_zero(&manifest);
  }else{
    create_manifest(&manifest, 0, 0, vid, &sCiInfo, &szB);
1667
1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1688
1689
1690
1691
1692
1693
1694

1695
1696
1697
1698
1699
1700
1701
1702







-
+







      if( forceDelta || (szD*szD)<(szB*3-9) ){
        blob_reset(&manifest);
        manifest = delta;
      }else{
        blob_reset(&delta);
      }
    }else if( forceDelta ){
      fossil_panic("unable to find a baseline-manifest for the delta");
      fossil_fatal("unable to find a baseline-manifest for the delta");
    }
  }
  if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){
    blob_zero(&ans);
    prompt_user("unable to sign manifest.  continue (y/N)? ", &ans);
    cReply = blob_str(&ans)[0];
    if( cReply!='y' && cReply!='Y' ){
1695
1696
1697
1698
1699
1700
1701
1702

1703
1704
1705



1706
1707
1708
1709
1710
1711

1712
1713

1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735

1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734

1735


1736
1737





















1738
1739
1740
1741
1742



1743
1744
1745
1746
1747
1748
1749







-
+



+
+
+





-
+
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+




-
-
-







    blob_reset(&manifest);
    blob_read_from_file(&manifest, zManifestFile);
    free(zManifestFile);
  }

  nvid = content_put(&manifest);
  if( nvid==0 ){
    fossil_panic("trouble committing manifest: %s", g.zErrMsg);
    fossil_fatal("trouble committing manifest: %s", g.zErrMsg);
  }
  db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
  manifest_crosslink(nvid, &manifest);
  assert( blob_is_reset(&manifest) );
  content_deltify(vid, nvid, 0);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);

  db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
                 " WHERE id=-4");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zIntegrateUuid = db_column_text(&q, 0);
    int rid = db_column_int(&q, 1);
    if( is_a_leaf(db_column_int(&q, 1)) ){
    if( !is_a_leaf(rid) ){
      fossil_print("Not_Closed: %s (not a leaf any more)\n", zIntegrateUuid);
      fossil_print("Closed: %s\n", zIntegrateUuid);
    }else{
      if (!db_exists("SELECT 1 FROM tagxref "
                   " WHERE tagid=%d AND rid=%d AND tagtype>0",
                   TAG_CLOSED, rid)
      ){
        Blob ctrl;
        Blob cksum;
        char *zDate;
        int nrid;

        blob_zero(&ctrl);
        zDate = date_in_standard_format(sCiInfo.zDateOvrd ? sCiInfo.zDateOvrd : "now");
        blob_appendf(&ctrl, "D %s\n", zDate);
        blob_appendf(&ctrl, "T +closed %s\n", zIntegrateUuid);
        blob_appendf(&ctrl, "U %F\n", sCiInfo.zUserOvrd ? sCiInfo.zUserOvrd : g.zLogin);
        md5sum_blob(&ctrl, &cksum);
        blob_appendf(&ctrl, "Z %b\n", &cksum);
        nrid = content_put(&ctrl);
        manifest_crosslink(nrid, &ctrl);
        assert( blob_is_reset(&ctrl) );
      }
      fossil_print("Closed: %s\n", zIntegrateUuid);
      fossil_print("Not_Closed: %s (not a leaf any more)\n", zIntegrateUuid);
    }
  }
  db_finalize(&q);

  assert( blob_is_reset(&manifest) );
  content_deltify(vid, nvid, 0);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
  fossil_print("New_Version: %s\n", zUuid);
  if( outputManifest ){
    zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot);
    blob_zero(&muuid);
    blob_appendf(&muuid, "%s\n", zUuid);
    blob_write_to_file(&muuid, zManifestFile);
    free(zManifestFile);
Changes to src/checkout.c.
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







*/
int load_vfile(const char *zName){
  Blob uuid;
  int vid;

  blob_init(&uuid, zName, -1);
  if( name_to_uuid(&uuid, 1, "ci") ){
    fossil_panic(g.zErrMsg);
    fossil_fatal(g.zErrMsg);
  }
  vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
  if( vid==0 ){
    fossil_fatal("no such check-in: %s", g.argv[2]);
  }
  if( !is_a_version(vid) ){
    fossil_fatal("object [%.10s] is not a check-in", blob_str(&uuid));
Changes to src/clone.c.
83
84
85
86
87
88
89















90
91
92
93
94
95
96
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** COMMAND: clone
**
** Usage: %fossil clone ?OPTIONS? URL FILENAME
**
** Make a clone of a repository specified by URL in the local
** file named FILENAME.  
**
** URL must be in one of the following form: ([...] mean optional)
**   HTTP/HTTPS protocol:
**     http[s]://[userid[:password]@]host[:port][/path]
**
**   SSH protocol:
**     ssh://[userid[:password]@]host[:port]/path/to/repo.fossil
**
**   Filesystem:
**     [file://]path/to/repo.fossil
**
**   Note: For ssh and filesystem, path must have an extra leading 
**         '/' to use an absolute path.
**
**   Note: the userid for SSH is the SSH account, not the Fossil account.
**
** By default, your current login name is used to create the default
** admin user. This can be overridden using the -A|--admin-user
** parameter.
**
** Options:
**    --admin-user|-A USERNAME   Make USERNAME the administrator
**    --private                  Also clone private branches 
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140







-
+







  clone_ssh_find_options();
  url_proxy_options();
  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0);
  if( file_size(g.argv[3])>0 ){
    fossil_panic("file already exists: %s", g.argv[3]);
    fossil_fatal("file already exists: %s", g.argv[3]);
  }

  zDefaultUser = find_option("admin-user","A",1);

  url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
  if( g.urlIsFile ){
    file_copy(g.urlName, g.argv[3]);
155
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185







-

+







      blob_reset(&fn);
    }
    db_multi_exec(
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))), now());"
    );
    url_enable_proxy(0);
    url_get_password_if_needed();
    clone_ssh_db_set_options();
    url_get_password_if_needed();
    g.xlinkClusterOnly = 1;
    nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
    g.xlinkClusterOnly = 0;
    verify_cancel();
    db_end_transaction(0);
    db_close(1);
    if( nErr ){
Changes to src/content.c.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
25
26
27
28
29
30
31

32
33
34
35
36
37
38







-







** The artifact retrieval cache
*/
static struct {
  i64 szTotal;         /* Total size of all entries in the cache */
  int n;               /* Current number of cache entries */
  int nAlloc;          /* Number of slots allocated in a[] */
  int nextAge;         /* Age counter for implementing LRU */
  int skipCnt;         /* Used to limit entries expelled from cache */
  struct cacheLine {   /* One instance of this for each cache entry */
    int rid;                  /* Artifact id */
    int age;                  /* Age.  Newer is larger */
    Blob content;             /* Content of the artifact */
  } *a;                /* The positive cache */
  Bag inCache;         /* Set of artifacts currently in cache */

490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
489
490
491
492
493
494
495

496
497
498
499
500
501
502







-







  int markAsUnclustered = 0;
  int isDephantomize = 0;
  
  assert( g.repositoryOpen );
  assert( pBlob!=0 );
  assert( srcId==0 || zUuid!=0 );
  if( zUuid==0 ){
    assert( pBlob!=0 );
    assert( nBlob==0 );
    sha1sum_blob(pBlob, &hash);
  }else{
    blob_init(&hash, zUuid, -1);
  }
  if( nBlob ){
    size = nBlob;
825
826
827
828
829
830
831













832

833
834
835
836





837
838
839
840
841
842
843
844
845



846

847
848
849
850
851
852
853
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873







+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




+
+
+
+
+









+
+
+

+







void test_content_deltify_cmd(void){
  if( g.argc!=5 ) usage("RID SRCID FORCE");
  db_must_be_within_tree();
  content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
}

/*
** Return true if Blob p looks like it might be a parsable control artifact.
*/
static int looks_like_control_artifact(Blob *p){
  const char *z = blob_buffer(p);
  int n = blob_size(p);
  if( n<10 ) return 0;
  if( strncmp(z, "-----BEGIN PGP SIGNED MESSAGE-----", 34)==0 ) return 1;
  if( z[0]<'A' || z[0]>'Z' || z[1]!=' ' || z[0]=='I' ) return 0;
  if( z[n-1]!='\n' ) return 0;
  return 1;
}

/*
** COMMAND: test-integrity
** COMMAND: test-integrity ?OPTIONS?
**
** Verify that all content can be extracted from the BLOB table correctly.
** If the BLOB table is correct, then the repository can always be
** successfully reconstructed using "fossil rebuild".
**
** Options:
**
**    --parse            Parse all manifests, wikis, tickets, events, and
**                       so forth, reporting any errors found.
*/
void test_integrity(void){
  Stmt q;
  Blob content;
  Blob cksum;
  int n1 = 0;
  int n2 = 0;
  int nErr = 0;
  int total;
  int nCA = 0;
  int anCA[10];
  int bParse = find_option("parse",0,0)!=0;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);
  memset(anCA, 0, sizeof(anCA));

  /* Make sure no public artifact is a delta from a private artifact */
  db_prepare(&q,
    "SELECT "
    "   rid, (SELECT uuid FROM blob WHERE rid=delta.rid),"
    "   srcid, (SELECT uuid FROM blob WHERE rid=delta.srcid)"
    "  FROM delta"
887
888
889
890
891
892
893

























894
895





896
897
898
899
900









901
902
903
904
905
906
907
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938


939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+





+
+
+
+
+
+
+
+
+







    }
    sha1sum_blob(&content, &cksum);
    if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
      fossil_print("checksum mismatch on artifact %d: wanted %s but got %s\n",
                   rid, zUuid, blob_str(&cksum));
      nErr++;
    }
    if( bParse && looks_like_control_artifact(&content) ){
      Blob err;
      int i, n;
      char *z;
      Manifest *p;
      char zFirstLine[400];
      blob_zero(&err);

      z = blob_buffer(&content);
      n = blob_size(&content);
      for(i=0; i<n && z[i] && z[i]!='\n' && i<sizeof(zFirstLine)-1; i++){}
      memcpy(zFirstLine, z, i);
      zFirstLine[i] = 0;
      p = manifest_parse(&content, 0, &err);
      if( p==0 ){
        fossil_print("manifest_parse failed for %s:\n%s\n",
               blob_str(&cksum), blob_str(&err));
        if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
          fossil_print("\"%s\"\n", zFirstLine);
        }
      }else{
        anCA[p->type]++;
        manifest_destroy(p);
        nCA++;
      }
    blob_reset(&cksum);
    blob_reset(&content);
      blob_reset(&err);
    }else{
      blob_reset(&content);
    }
    blob_reset(&cksum);
    n2++;
  }
  db_finalize(&q);
  fossil_print("%d non-phantom blobs (out of %d total) checked:  %d errors\n",
               n2, n1, nErr);
  if( bParse ){
    const char *azType[] = { 0, "manifest", "cluster", "control", "wiki",
                             "ticket", "attachment", "event" };
    int i;
    fossil_print("%d total control artifacts\n", nCA);
    for(i=1; i<count(azType); i++){
      if( anCA[i] ) fossil_print("  %d %ss\n", anCA[i], azType[i]);
    }
  }
}

/*
** COMMAND: test-orphans
**
** Search the repository for orphaned artifacts
*/
Changes to src/db.c.
1398
1399
1400
1401
1402
1403
1404
1405
1406



1407
1408
1409
1410
1411
1412
1413
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415







-

+
+
+








  if( zInitialDate ){
    int rid;
    blob_zero(&manifest);
    blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n");
    zDate = date_in_standard_format(zInitialDate);
    blob_appendf(&manifest, "D %s\n", zDate);
    blob_appendf(&manifest, "P\n");
    md5sum_init();
    /* The R-card is necessary here because without it
     * fossil versions earlier than versions 1.27 would
     * interpret this artifact as a "control". */
    blob_appendf(&manifest, "R %s\n", md5sum_finish(0));
    blob_appendf(&manifest, "T *branch * trunk\n");
    blob_appendf(&manifest, "T *sym-trunk *\n");
    blob_appendf(&manifest, "U %F\n", g.zLogin);
    md5sum_blob(&manifest, &hash);
    blob_appendf(&manifest, "Z %b\n", &hash);
    blob_reset(&hash);
1990
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
2006







-
+







  url_proxy_options();
  keepFlag = find_option("keep",0,0)!=0;
  allowNested = find_option("nested",0,0)!=0;
  if( g.argc!=3 && g.argc!=4 ){
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local(0) ){
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
    fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
  }
  db_open_repository(g.argv[2]);
#if defined(_WIN32) || defined(__CYGWIN__)
# define LOCALDB_NAME "./_FOSSIL_"
#else
# define LOCALDB_NAME "./.fslckout"
#endif
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2135
2136
2137
2138
2139
2140
2141

2142
2143
2144
2145
2146
2147
2148







-







  { "pgp-command",   0,               40, 0, "gpg --clearsign -o " },
  { "proxy",         0,               32, 0, "off"                 },
  { "relative-paths",0,                0, 0, "on"                  },
  { "repo-cksum",    0,                0, 0, "on"                  },
  { "self-register", 0,                0, 0, "off"                 },
  { "ssh-command",   0,               40, 0, ""                    },
  { "ssh-fossil",    0,               40, 0, ""                    },
  { "ssh-fossil-user",  0,            40, 0, ""                    },
  { "ssl-ca-location",0,              40, 0, ""                    },
  { "ssl-identity",  0,               40, 0, ""                    },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",           0,                0, 0, "off"                 },
  { "tcl-setup",     0,               40, 0, ""                    },
#endif
  { "th1-setup",     0,               40, 0, ""                    },
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2308
2309
2310
2311
2312
2313
2314


2315
2316
2317
2318
2319
2320
2321







-
-







**                     users can not be deleted. Default: off.
**
**    ssh-command      Command used to talk to a remote machine with
**                     the "ssh://" protocol.
**
**    ssh-fossil       Remote fossil command to run with the "ssh://" protocol.
**
**    ssh-fossil-user  Fossil user to use instead of the URL user.
**
**    ssl-ca-location  The full pathname to a file containing PEM encoded
**                     CA root certificates, or a directory of certificates
**                     with filenames formed from the certificate hashes as
**                     required by OpenSSL.
**                     If set, this will override the OS default list of
**                     OpenSSL CAs. If unset, the default list will be used.
**                     Some platforms may add additional certificates.
Changes to src/deltacmd.c.
142
143
144
145
146
147
148
149

150
151
152
142
143
144
145
146
147
148

149
150
151
152







-
+



  blob_read_from_file(&f1, g.argv[2]);
  blob_read_from_file(&f2, g.argv[3]);
  blob_delta_create(&f1, &f2, &d12);
  blob_delta_create(&f2, &f1, &d21);
  blob_delta_apply(&f1, &d12, &a2);
  blob_delta_apply(&f2, &d21, &a1);
  if( blob_compare(&f1,&a1) || blob_compare(&f2, &a2) ){
    fossil_panic("delta test failed");
    fossil_fatal("delta test failed");
  }
  fossil_print("ok\n");
}
Changes to src/diff.c.
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1308
1309
1310
1311
1312
1313
1314

1315
1316
1317
1318
1319
1320
1321
1322







-
+







      sbsWriteMarker(&s, "   ", "");
      sbsWriteLineno(&s, b+j, SBS_LNB);
      sbsWriteText(&s, &B[b+j], SBS_TXTB);
    }
  }
  
  if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){
    blob_append(pOut, "<table class=\"sbsdiffcols\" width=\"90%\"><tr>\n", -1);
    blob_append(pOut, "<table class=\"sbsdiffcols\"><tr>\n", -1);
    for(i=SBS_LNA; i<=SBS_TXTB; i++){
      sbsWriteColumn(pOut, s.apCols[i], i);
      blob_reset(s.apCols[i]);
    }
    blob_append(pOut, "</tr></table>\n", -1);
  }
}
2044
2045
2046
2047
2048
2049
2050
2051

2052
2053
2054

2055
2056
2057
2058
2059
2060
2061
2044
2045
2046
2047
2048
2049
2050

2051
2052
2053

2054
2055
2056
2057
2058
2059
2060
2061







-
+


-
+







  Stmt q;              /* Query returning all ancestor versions */
  Stmt ins;            /* Inserts into the temporary VSEEN table */
  int cnt = 0;         /* Number of versions examined */

  /* Initialize the annotation */
  rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
  if( rid==0 ){
    fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid);
    fossil_fatal("file #%d is unchanged in manifest #%d", fnid, mid);
  }
  if( !content_get(rid, &toAnnotate) ){
    fossil_panic("unable to retrieve content of artifact #%d", rid);
    fossil_fatal("unable to retrieve content of artifact #%d", rid);
  }
  if( iLimit<=0 ) iLimit = 1000000000;
  annotation_start(p, &toAnnotate);
  db_begin_transaction();
  db_multi_exec(
     "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);"
     "DELETE FROM vseen;"
2148
2149
2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
2161
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162







+







  struct AnnVers *p;
  unsigned clr1, clr2, clr;

  /* Gather query parameters */
  showLog = atoi(PD("log","1"));
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( exclude_spiders("annotate") ) return;
  mid = name_to_typed_rid(PD("checkin","0"),"ci");
  zFilename = P("filename");
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
  iLimit = atoi(PD("limit","20"));
  if( P("filevers") ) annFlags |= ANN_FILE_VERS;
  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
2326
2327
2328
2329
2330
2331
2332
2333

2334
2335
2336
2337
2338
2339
2340
2327
2328
2329
2330
2331
2332
2333

2334
2335
2336
2337
2338
2339
2340
2341







-
+







  if( iLimit<=0 ) iLimit = 1000000000;
  compute_direct_ancestors(cid, 1000000);
  mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor "
          " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid"
          " ORDER BY ancestor.generation ASC LIMIT 1",
          fid, fnid);
  if( mid==0 ){
    fossil_panic("unable to find manifest");
    fossil_fatal("unable to find manifest");
  }
  annFlags |= ANN_FILE_ANCEST;
  annotate_file(&ann, fnid, mid, iLimit, annFlags);
  if( showLog ){
    struct AnnVers *p;
    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
      fossil_print("version %3d: %s %.10s file %.10s\n",
Changes to src/diffcmd.c.
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
615
616
617
618
619
620
621


622
623
624
625
626
627
628







-
-







@   RM_BG      #ffc0c0
@   HR_FG      #888888
@   HR_PAD_TOP 4
@   HR_PAD_BTM 8
@   FN_BG      #444444
@   FN_FG      #ffffff
@   FN_PAD     5
@   FONTS      {{DejaVu Sans Mono} Consolas Monaco}
@   FONT_SIZE  9
@   PADX       5
@   WIDTH      80
@   HEIGHT     45
@   LB_HEIGHT  25
@ }
@ 
@ if {![namespace exists ttk]} {
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881

882
883

884
885
886
887
888
889
890
864
865
866
867
868
869
870







871
872
873
874

875
876
877
878
879
880
881
882







-
-
-
-
-
-
-


+

-
+







@     $txt tag lower $tag
@   }
@   $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
@     -justify center
@ }
@ text .mkr
@ 
@ font create mono -family courier -size $CFG(FONT_SIZE)
@ foreach font $CFG(FONTS) {
@   if {[lsearch -exact [font families] $font] != -1} {
@      font config mono -family $font
@      break
@   }
@ }
@ foreach c [cols] {
@   set keyPrefix [string toupper [colType $c]]_COL_
@   if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}}
@   $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \
@     -font mono -padx $CFG(PADX) -yscroll sync-y
@     -padx $CFG(PADX) -yscroll sync-y
@   $c tag config hr -spacing1 $CFG(HR_PAD_TOP) -spacing3 $CFG(HR_PAD_BTM) \
@      -foreground $CFG(HR_FG)
@   $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD)
@   bindtags $c ". $c Text all"
@   bind $c <1> {focus %W}
@ }
@ 
Changes to src/event.c.
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127







-
+







  }
  verboseFlag = (zVerbose!=0) && !is_false(zVerbose);

  /* Extract the event content.
  */
  pEvent = manifest_get(rid, CFTYPE_EVENT);
  if( pEvent==0 ){
    fossil_panic("Object #%d is not an event", rid);
    fossil_fatal("Object #%d is not an event", rid);
  }
  blob_init(&fullbody, pEvent->zWiki, -1);
  if( wiki_find_title(&fullbody, &title, &tail) ){
    style_header(blob_str(&title));
  }else{
    style_header("Event %S", zEventId);
    tail = fullbody;
278
279
280
281
282
283
284
285

286
287
288




289


290
291
292
293
294
295
296
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301







-
+



+
+
+
+
-
+
+







      );
    }
  }
  zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime);
  if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){
    char *zDate;
    Blob cksum;
    int nrid;
    int nrid, n;
    blob_zero(&event);
    db_begin_transaction();
    login_verify_csrf_secret();
    while( fossil_isspace(zComment[0]) ) zComment++;
    n = strlen(zComment);
    while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
    if( n>0 ){
    blob_appendf(&event, "C %F\n", zComment);
      blob_appendf(&event, "C %#F\n", n, zComment);
    }
    zDate = date_in_standard_format("now");
    blob_appendf(&event, "D %s\n", zDate);
    free(zDate);
    zETime[10] = 'T';
    blob_appendf(&event, "E %s %s\n", zETime, zEventId);
    zETime[10] = ' ';
    if( rid ){
397
398
399
400
401
402
403
404

405
406
407
408
409
410
411
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416







-
+







  if( n<20 ) n = 20;
  if( n>40 ) n = 40;
  @ <form method="post" action="%s(g.zTop)/eventedit"><div>
  login_insert_csrf_secret();
  @ <input type="hidden" name="name" value="%h(zEventId)" />
  @ <table border="0" cellspacing="10">

  @ <tr><th align="right" valign="top">Event&nbsp;Time:</th>
  @ <tr><th align="right" valign="top">Event&nbsp;Time (UTC):</th>
  @ <td valign="top">
  @   <input type="text" name="t" size="25" value="%h(zETime)" />
  @ </td></tr>

  @ <tr><th align="right" valign="top">Timeline&nbsp;Comment:</th>
  @ <td valign="top">
  @ <textarea name="c" class="eventedit" cols="80" 
Changes to src/export.c.
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
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







-
+















-
+







  if( markfile_in!=0 ){
    Stmt qb,qc;
    char line[100];
    FILE *f;

    f = fossil_fopen(markfile_in, "r");
    if( f==0 ){
      fossil_panic("cannot open %s for reading", markfile_in);
      fossil_fatal("cannot open %s for reading", markfile_in);
    }
    db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
    db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
    while( fgets(line, sizeof(line), f)!=0 ){
      if( *line == 'b' ){
        db_bind_text(&qb, ":rid", line + 1);
        db_step(&qb);
        db_reset(&qb);
        bag_insert(&blobs, atoi(line + 1));
      }else if( *line == 'c' ){
        db_bind_text(&qc, ":rid", line + 1);
        db_step(&qc);
        db_reset(&qc);
        bag_insert(&vers, atoi(line + 1));
      }else{
        fossil_panic("bad input from %s: %s", markfile_in, line);
        fossil_fatal("bad input from %s: %s", markfile_in, line);
      }
    }
    db_finalize(&qb);
    db_finalize(&qc);
    fclose(f);
  }

333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
348
349
350
351
352
353

354
355
356
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347
348
349
350
351
352

353
354
355
356







-
+












-
+



  db_finalize(&q);
  bag_clear(&vers);

  if( markfile_out!=0 ){
    FILE *f;
    f = fossil_fopen(markfile_out, "w");
    if( f == 0 ){
      fossil_panic("cannot open %s for writing", markfile_out);
      fossil_fatal("cannot open %s for writing", markfile_out);
    }
    db_prepare(&q, "SELECT rid FROM oldblob");
    while( db_step(&q)==SQLITE_ROW ){
      fprintf(f, "b%d\n", db_column_int(&q, 0));
    }
    db_finalize(&q);
    db_prepare(&q, "SELECT rid FROM oldcommit");
    while( db_step(&q)==SQLITE_ROW ){
      fprintf(f, "c%d\n", db_column_int(&q, 0));
    }
    db_finalize(&q);
    if( ferror(f)!=0 || fclose(f)!=0 ) {
      fossil_panic("error while writing %s", markfile_out);
      fossil_fatal("error while writing %s", markfile_out);
    }
  }
}
Changes to src/finfo.c.
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76







-
+







    Blob line;
    Blob fname;
    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");
      fossil_fatal("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());
Changes to src/glob.c.
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
250
251
252
253
254
255
256

257
258
259
260
261
262
263
264







-
+







**
** Usage:  %fossil test-glob PATTERN STRING...
**
** PATTERN is a comma- and whitespace-separated list of optionally
** quoted glob patterns.  Show which of the STRINGs that follow match
** the PATTERN.
**
** If PATTERN begins with "@" the the rest of the pattern is understood
** If PATTERN begins with "@" the rest of the pattern is understood
** to be a setting name (such as binary-glob, crln-glob, or encoding-glob)
** and the value of that setting is used as the actually glob pattern.
*/
void glob_test_cmd(void){
  Glob *pGlob;
  int i;
  char *zPattern;
Changes to src/graph.c.
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210







-
+







  pRow->rid = rid;
  pRow->nParent = nParent;
  pRow->zBranch = persistBranchName(p, zBranch);
  if( zUuid==0 ) zUuid = "";
  sqlite3_snprintf(sizeof(pRow->zUuid), pRow->zUuid, "%s", zUuid);
  pRow->isLeaf = isLeaf;
  memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser));
  if( zBgClr==0 || zBgClr[0]==0 ) zBgClr = "white";
  if( zBgClr==0 ) zBgClr = "";
  pRow->zBgClr = persistBranchName(p, zBgClr);
  memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent);
  if( p->pFirst==0 ){
    p->pFirst = pRow;
  }else{
    p->pLast->pNext = pRow;
  }
Changes to src/http.c.
38
39
40
41
42
43
44
45


46
47
48
49
50
51
52
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53







-
+
+







  const char *zLogin;  /* The user login name */
  const char *zPw;     /* The user password */
  Blob pw;             /* The nonce with user password appended */
  Blob sig;            /* The signature field */

  zLogin = url_or_fossil_user();
  blob_zero(pLogin);
  if( zLogin==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
  if( zLogin==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ||
      ( g.urlIsSsh && ! url_ssh_use_http() ) ){
    return;  /* If no login card for users "nobody" and "anonymous" */
  }
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  if( g.urlPasswd ){
109
110
111
112
113
114
115

116
117
118
119
120
121
122
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124







+







    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
    fossil_free(zCredentials);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
  blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION 
                     " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
  if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
  if( g.fHttpTrace ){
    blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
  }else{
    blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
  }
  blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
}
214
215
216
217
218
219
220










221
222
223
224
225
226
227
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239







+
+
+
+
+
+
+
+
+
+







        goto write_err;
      }
      if( iHttpVersion==0 ){
        closeConnection = 1;
      }else{
        closeConnection = 0;
      }
    }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
      if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
      if( rc!=200 && rc!=302 ){
        int ii;
        for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
        while( zLine[ii]==' ' ) ii++;
        fossil_warning("server says: %s", &zLine[ii]);
        goto write_err;
      }
      closeConnection = 0;
    }else if( fossil_strnicmp(zLine, "content-length:", 15)==0 ){
      for(i=15; fossil_isspace(zLine[i]); i++){}
      iLength = atoi(&zLine[i]);
    }else if( fossil_strnicmp(zLine, "connection:", 11)==0 ){
      char c;
      for(i=11; fossil_isspace(zLine[i]); i++){}
      c = zLine[i];
292
293
294
295
296
297
298


299
300

301
302
303
304
305
306
307
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321







+
+

-
+








  /*
  ** Close the connection to the server if appropriate.
  **
  ** FIXME:  There is some bug in the lower layers that prevents the
  ** connection from remaining open.  The easiest fix for now is to
  ** simply close and restart the connection for each round-trip.
  **
  ** For SSH we will leave the connection open.
  */
  closeConnection = 1; /* FIX ME */
  if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */
  if( closeConnection ){
    transport_close();
  }else{
    transport_rewind();
  }
  return 0;

Changes to src/http_socket.c.
207
208
209
210
211
212
213

















207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    if( got<=0 ) break;
    total += (size_t)got;
    N -= (size_t)got;
    pContent = (void*)&((char*)pContent)[got];
  }
  return total;
}

/*
** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets
** populated. For hostnames with more than one IP (or if overridden in
** ~/.ssh/config) the rcvfrom may not match the host to which we connect.
*/
void socket_ssh_resolve_addr(void){
  struct hostent *pHost;        /* Used to make best effort for rcvfrom */
  struct sockaddr_in addr;

  memset(&addr, 0, sizeof(addr));
  pHost = gethostbyname(g.urlName);
  if( pHost!=0 ){
    memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
    g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
  }
}
Changes to src/http_transport.c.
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49







-
+







  i64 nSent;              /* Number of bytes sent */
  i64 nRcvd;              /* Number of bytes received */
  FILE *pFile;            /* File I/O for FILE: */
  char *zOutFile;         /* Name of outbound file for FILE: */
  char *zInFile;          /* Name of inbound file for FILE: */
  FILE *pLog;             /* Log output here */
} transport = {
  0, 0, 0, 0, 0, 0, 0
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

/*
** Information about the connection to the SSH subprocess when
** using the ssh:// sync method.
*/
static int sshPid;             /* Process id of ssh subprocess */
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
72
73
74
75
76
77
78















79
80
81
82
83
84
85







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  if( pnRcvd ) *pnRcvd = transport.nRcvd;
  if( resetFlag ){
    transport.nSent = 0;
    transport.nRcvd = 0;
  }
}

/*
** Read text from sshIn.  Zero-terminate and remove trailing
** whitespace.
*/
static void sshin_read(char *zBuf, int szBuf){
  int got;
  zBuf[0] = 0;
  got = read(sshIn, zBuf, szBuf-1);
  while( got>=0 ){
    zBuf[got] = 0;
    if( got==0 || !fossil_isspace(zBuf[got-1]) ) break;
    got--;
  }
}

/*
** Default SSH command
*/
#ifdef __MINGW32__
static char zDefaultSshCmd[] = "ssh -T";
#else
static char zDefaultSshCmd[] = "ssh -e none -T";
110
111
112
113
114
115
116

117
118
119
120
121
122
123
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109







+







  static int fPrintSshCmd = 1;  /* Print SSH command only once */
  const char *zSshFossilCmd;    /* Path to fossil on remote host */
  const char *zSsh;  /* The base SSH command */
  Blob zCmd;         /* The SSH command */
  char *zHost;       /* The host name to contact */
  int n;             /* Size of prefix string */

  socket_ssh_resolve_addr();
  zSsh = db_get("ssh-command", zDefaultSshCmd);
  zSshFossilCmd = db_get("ssh-fossil", "fossil");
  blob_init(&zCmd, zSsh, -1);
  if( g.urlPort!=g.urlDfltPort && g.urlPort ){
#ifdef __MINGW32__
    blob_appendf(&zCmd, " -P %d", g.urlPort);
#else
134
135
136
137
138
139
140

141




142
143
144
145
146
147
148
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
137
138







+
-
+
+
+
+







    zHost = mprintf("%s", g.urlName);
  }
  n = blob_size(&zCmd);
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, zHost);
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, mprintf("%s", zSshFossilCmd));
  if( url_ssh_use_http() ){
  blob_append(&zCmd, " http", 5);
    blob_append(&zCmd, " http", 5);
  }else{
    blob_append(&zCmd, " test-http", 10);
  }
  if( g.urlPath && g.urlPath[0] ){
    blob_append(&zCmd, " ", 1);
    shell_escape(&zCmd, mprintf("%s", g.urlPath));
  }
  if( fPrintSshCmd ){
    fossil_print("%s\n", blob_str(&zCmd)+n);  /* Show tail of SSH command */
    fPrintSshCmd = 0;
179
180
181
182
183
184
185
186

187
188

189
190
191
192
193
194
195
169
170
171
172
173
174
175

176
177

178
179
180
181
182
183
184
185







-
+

-
+







      #else
      socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
      rc = 1;
      #endif
    }else if( g.urlIsFile ){
      sqlite3_uint64 iRandId;
      sqlite3_randomness(sizeof(iRandId), &iRandId);
      transport.zOutFile = mprintf("%s-%llu-out.http", 
      transport.zOutFile = mprintf("%s-%llu-out.http",
                                       g.zRepositoryName, iRandId);
      transport.zInFile = mprintf("%s-%llu-in.http", 
      transport.zInFile = mprintf("%s-%llu-in.http",
                                       g.zRepositoryName, iRandId);
      transport.pFile = fossil_fopen(transport.zOutFile, "wb");
      if( transport.pFile==0 ){
        fossil_fatal("cannot output temporary file: %s", transport.zOutFile);
      }
      transport.isOpen = 1;
    }else{
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221







-
+







    if( g.urlIsSsh ){
      transport_ssh_close();
    }else if( g.urlIsHttps ){
      #ifdef FOSSIL_ENABLE_SSL
      ssl_close();
      #endif
    }else if( g.urlIsFile ){
      if( transport.pFile ){ 
      if( transport.pFile ){
        fclose(transport.pFile);
        transport.pFile = 0;
      }
      file_delete(transport.zInFile);
      file_delete(transport.zOutFile);
      free(transport.zInFile);
      free(transport.zOutFile);
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254







-
+







    #ifdef FOSSIL_ENABLE_SSL
    int sent;
    while( n>0 ){
      sent = ssl_send(0, z, n);
      /* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */
      if( sent<=0 ) break;
      n -= sent;
    }    
    }
    #endif
  }else if( g.urlIsFile ){
    fwrite(z, 1, n, transport.pFile);
  }else{
    int sent;
    while( n>0 ){
      sent = socket_send(0, z, n);
Changes to src/info.c.
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227







-
+







    }
    fossil_print("checkins:     %d\n",
                 db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
  }else{
    int rid;
    rid = name_to_rid(g.argv[2]);
    if( rid==0 ){
      fossil_panic("no such object: %s\n", g.argv[2]);
      fossil_fatal("no such object: %s\n", g.argv[2]);
    }
    show_common_info(rid, "uuid:", 1, 1);
  }
}

/*
** Show information about all tags on a given node.
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483







-
+







** If the /ci page is used (instead of /vinfo or /info) then the
** default behavior is to show unified diffs of all file changes.
** With /vinfo and /info, only a list of the changed files are
** shown, without diffs.  This behavior is inverted if the
** "show-version-diffs" setting is turned on.
*/
void ci_page(void){
  Stmt q;
  Stmt q1, q2, q3;
  int rid;
  int isLeaf;
  int verboseFlag;     /* True to show diffs */
  int sideBySide;      /* True for side-by-side diffs */
  u64 diffFlags;       /* Flag parameter for text_diff() */
  const char *zName;   /* Name of the checkin to be displayed */
  const char *zUuid;   /* UUID of zName */
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517


518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537




538
539
540
541
542
543
544
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514
515


516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533




534
535
536
537
538
539
540
541
542
543
544







-
+








-
-
+
+
















-
-
-
-
+
+
+
+







  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zParent = db_text(0,
    "SELECT uuid FROM plink, blob"
    " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
    rid
  );
  isLeaf = is_a_leaf(rid);
  db_prepare(&q,
  db_prepare(&q1,
     "SELECT uuid, datetime(mtime, 'localtime'), user, comment,"
     "       datetime(omtime, 'localtime'), mtime"
     "  FROM blob, event"
     " WHERE blob.rid=%d"
     "   AND event.objid=%d",
     rid, rid
  );
  sideBySide = !is_false(PD("sbs","1"));
  if( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
  if( db_step(&q1)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q1, 0);
    char *zTitle = mprintf("Check-in [%.10s]", zUuid);
    char *zEUser, *zEComment;
    const char *zUser;
    const char *zComment;
    const char *zDate;
    const char *zOrigDate;

    style_header(zTitle);
    login_anonymous_available();
    free(zTitle);
    zEUser = db_text(0,
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                    TAG_USER, rid);
    zEComment = db_text(0,
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_COMMENT, rid);
    zUser = db_column_text(&q, 2);
    zComment = db_column_text(&q, 3);
    zDate = db_column_text(&q,1);
    zOrigDate = db_column_text(&q, 4);
    zUser = db_column_text(&q1, 2);
    zComment = db_column_text(&q1, 3);
    zDate = db_column_text(&q1,1);
    zOrigDate = db_column_text(&q1, 4);
    @ <div class="section">Overview</div>
    @ <table class="label-value">
    @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
    if( g.perm.Setup ){
      @ (Record ID: %d(rid))
    }
    @ </td></tr>
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575
576




577
578
579
580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596

597
598
599
600
601


602
603
604

605
606
607
608
609
610
611
560
561
562
563
564
565
566

567
568
569
570
571
572




573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599


600
601
602
603

604
605
606
607
608
609
610
611







-
+





-
-
-
-
+
+
+
+




-
+














-
+



-
-
+
+


-
+







    if( zEComment ){
      @ <tr><th>Edited&nbsp;Comment:</th><td class="infoComment">%!w(zEComment)</td></tr>
      @ <tr><th>Original&nbsp;Comment:</th><td class="infoComment">%!w(zComment)</td></tr>
    }else{
      @ <tr><th>Comment:</th><td class="infoComment">%!w(zComment)</td></tr>
    }
    if( g.perm.Admin ){
      db_prepare(&q,
      db_prepare(&q2,
         "SELECT rcvfrom.ipaddr, user.login, datetime(rcvfrom.mtime)"
         "  FROM blob JOIN rcvfrom USING(rcvid) LEFT JOIN user USING(uid)"
         " WHERE blob.rid=%d",
         rid
      );
      if( db_step(&q)==SQLITE_ROW ){
        const char *zIpAddr = db_column_text(&q, 0);
        const char *zUser = db_column_text(&q, 1);
        const char *zDate = db_column_text(&q, 2);
      if( db_step(&q2)==SQLITE_ROW ){
        const char *zIpAddr = db_column_text(&q2, 0);
        const char *zUser = db_column_text(&q2, 1);
        const char *zDate = db_column_text(&q2, 2);
        if( zUser==0 || zUser[0]==0 ) zUser = "unknown";
        @ <tr><th>Received&nbsp;From:</th>
        @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
      }
      db_finalize(&q);
      db_finalize(&q2);
    }
    if( g.perm.Hyperlink ){
      const char *zProjName = db_get("project-name", "unnamed");
      @ <tr><th>Timelines:</th><td>
      @   %z(href("%R/timeline?f=%S",zUuid))family</a>
      if( zParent ){
        @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
      }
      if( !isLeaf ){
        @ | %z(href("%R/timeline?d=%S",zUuid))descendants</a>
      }
      if( zParent && !isLeaf ){
        @ | %z(href("%R/timeline?dp=%S",zUuid))both</a>
      }
      db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
      db_prepare(&q2,"SELECT substr(tag.tagname,5) FROM tagxref, tag "
                     " WHERE rid=%d AND tagtype>0 "
                     "   AND tag.tagid=tagxref.tagid "
                     "   AND +tag.tagname GLOB 'sym-*'", rid);
      while( db_step(&q)==SQLITE_ROW ){
        const char *zTagName = db_column_text(&q, 0);
      while( db_step(&q2)==SQLITE_ROW ){
        const char *zTagName = db_column_text(&q2, 0);
        @  | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a>
      }
      db_finalize(&q);
      db_finalize(&q2);


      /* The Download: line */
      if( g.perm.Zip ){
        char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
                             zProjName, zUuid, zUuid);
        @ </td></tr>
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642







-
+







      @ </tr>
    }
    @ </table>
  }else{
    style_header("Check-in Information");
    login_anonymous_available();
  }
  db_finalize(&q);
  db_finalize(&q1);
  showTags(rid, "");
  if( zParent ){
    @ <div class="section">Changes</div>
    @ <div class="sectionmenu">
    verboseFlag = g.zPath[0]!='c';
    if( db_get_boolean("show-version-diffs", 0)==0 ){
      verboseFlag = !verboseFlag;
675
676
677
678
679
680
681
682

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701






702
703
704

705
706
707
708
709
710
711
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689
690
691
692
693
694
695






696
697
698
699
700
701
702
703

704
705
706
707
708
709
710
711







-
+













-
-
-
-
-
-
+
+
+
+
+
+


-
+







    }
    @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
    @ patch</a></div>
    if( pRe ){
      @ <p><b>Only differences that match regular expression "%h(zRe)"
      @ are shown.</b></p>
    }
    db_prepare(&q,
    db_prepare(&q3,
       "SELECT name,"
       "       mperm,"
       "       (SELECT uuid FROM blob WHERE rid=mlink.pid),"
       "       (SELECT uuid FROM blob WHERE rid=mlink.fid),"
       "       (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
       "  FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
       " WHERE mlink.mid=%d"
       "   AND (mlink.fid>0"
              " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
       " ORDER BY name /*sort*/",
       rid, rid
    );
    diffFlags = construct_diff_flags(verboseFlag, sideBySide);
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q,0);
      int mperm = db_column_int(&q, 1);
      const char *zOld = db_column_text(&q,2);
      const char *zNew = db_column_text(&q,3);
      const char *zOldName = db_column_text(&q, 4);
    while( db_step(&q3)==SQLITE_ROW ){
      const char *zName = db_column_text(&q3,0);
      int mperm = db_column_int(&q3, 1);
      const char *zOld = db_column_text(&q3,2);
      const char *zNew = db_column_text(&q3,3);
      const char *zOldName = db_column_text(&q3, 4);
      append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm);
    }
    db_finalize(&q);
    db_finalize(&q3);
  }
  append_diff_javascript(sideBySide);
  style_footer();
}

/*
** WEBPAGE: winfo
Changes to src/json.c.
2002
2003
2004
2005
2006
2007
2008
2009

2010
2011
2012
2013
2014
2015
2016
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012
2013
2014
2015
2016







-
+







** Creates a comma-separated list of command names
** taken from zPages. zPages must be an array of objects
** whose final entry MUST have a NULL name value or results
** are undefined.
**
** The list is appended to pOut. The number of items (not bytes)
** appended are returned. If filterByMode is non-0 then the result
** list will contain only commands which are able to run in the the
** list will contain only commands which are able to run in the
** current run mode (CLI vs. HTTP).
*/
static int json_pagedefs_to_string(JsonPageDef const * zPages,
                                   Blob * pOut, int filterByMode){
  int i = 0;
  for( ; zPages->name; ++zPages, ++i ){
    if(filterByMode){
Changes to src/json_branch.c.
286
287
288
289
290
291
292
293

294
295
296
297

298
299
300
301
302
303
304
286
287
288
289
290
291
292

293
294
295
296

297
298
299
300
301
302
303
304







-
+



-
+







  
  blob_appendf(&branch, "U %F\n", g.zLogin);
  md5sum_blob(&branch, &mcksum);
  blob_appendf(&branch, "Z %b\n", &mcksum);

  brid = content_put(&branch);
  if( brid==0 ){
    fossil_panic("Problem committing manifest: %s", g.zErrMsg);
    fossil_fatal("Problem committing manifest: %s", g.zErrMsg);
  }
  db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
  if( manifest_crosslink(brid, &branch)==0 ){
    fossil_panic("unable to install new manifest");
    fossil_fatal("unable to install new manifest");
  }
  assert( blob_is_reset(&branch) );
  content_deltify(rootid, brid, 0);
  if( zNewRid ){
    *zNewRid = brid;
  }

Changes to src/json_status.c.
124
125
126
127
128
129
130




131
132
133
134
135
136
137
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141







+
+
+
+







        zStatus = "missing";
        ++nErr;
      }
    }else if( 2==isChnged ){
      zStatus = "updatedByMerge";
    }else if( 3==isChnged ){
      zStatus = "addedByMerge";
    }else if( 4==isChnged ){
      zStatus = "updatedByIntegrate";
    }else if( 5==isChnged ){
      zStatus = "addedByIntegrate";
    }else if( 1==isChnged ){
      if( file_contains_merge_marker(zFullName) ){
        zStatus = "conflict";
      }else{
        zStatus = "edited";
      }
    }
Changes to src/login.c.
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81







-
+








/*
** Return a path appropriate for setting a cookie.
**
** The path is g.zTop for single-repo cookies.  It is "/" for
** cookies of a login-group.
*/
static const char *login_cookie_path(void){
const char *login_cookie_path(void){
  if( login_group_name()==0 ){
    return g.zTop;
  }else{
    return "/";
  }
}

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
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







-
+

-
+







-
-
-
-
+
+
+
+







  int i;
  if( zAgent==0 ) return 0;  /* If no UserAgent, then probably a bot */
  for(i=0; zAgent[i]; i++){
    if( prefix_match("bot", zAgent+i) ) return 0;
    if( prefix_match("spider", zAgent+i) ) return 0;
    if( prefix_match("crawl", zAgent+i) ) return 0;
    /* If a URI appears in the User-Agent, it is probably a bot */
    if( memcmp("http", zAgent+i,4)==0 ) return 0;
    if( strncmp("http", zAgent+i,4)==0 ) return 0;
  }
  if( memcmp(zAgent, "Mozilla/", 8)==0 ){
  if( strncmp(zAgent, "Mozilla/", 8)==0 ){
    if( atoi(&zAgent[8])<4 ) return 0;  /* Many bots advertise as Mozilla/3 */
    if( strglob("*Firefox/[1-9]*", zAgent) ) return 1;
    if( strglob("*Chrome/[1-9]*", zAgent) ) return 1;
    if( strglob("*(compatible;?MSIE?[1789]*", zAgent) ) return 1;
    if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1;
    return 0;
  }
  if( memcmp(zAgent, "Opera/", 6)==0 ) return 1;
  if( memcmp(zAgent, "Safari/", 7)==0 ) return 1;
  if( memcmp(zAgent, "Lynx/", 5)==0 ) return 1;
  if( memcmp(zAgent, "NetSurf/", 8)==0 ) return 1;
  if( strncmp(zAgent, "Opera/", 6)==0 ) return 1;
  if( strncmp(zAgent, "Safari/", 7)==0 ) return 1;
  if( strncmp(zAgent, "Lynx/", 5)==0 ) return 1;
  if( strncmp(zAgent, "NetSurf/", 8)==0 ) return 1;
  return 0;
}

/*
** COMMAND: test-ishuman
**
** Read lines of text from standard input.  Interpret each line of text
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610







-
+







  @        onClick="chngAction(this.form)" /></td>
  @ </tr>
  @ </table>
  @ <script type="text/JavaScript">
  @   gebi('u').focus()
  @   function chngAction(form){
  if( g.sslNotAvailable==0
   && memcmp(g.zBaseURL,"https:",6)!=0
   && strncmp(g.zBaseURL,"https:",6)!=0
   && db_get_boolean("https-login",0)
  ){
     char *zSSL = mprintf("https:%s", &g.zBaseURL[5]);
     @  if( form.u.value!="anonymous" ){
     @     form.action = "%h(zSSL)/login";
     @  }
  }
761
762
763
764
765
766
767
768

769
770




771

772
773
774
775
776
777
778
761
762
763
764
765
766
767

768

769
770
771
772
773

774
775
776
777
778
779
780
781







-
+
-

+
+
+
+
-
+







  );
  return uid;
}

/*
** This routine examines the login cookie to see if it exists and
** is valid.  If the login cookie checks out, it then sets global
** variables appropriately.  Global variables set include g.userUid
** variables appropriately.
** and g.zLogin and the g.perm family of permission booleans.
**
**    g.userUid      Database USER.UID value.  Might be -1 for "nobody"
**    g.zLogin       Database USER.LOGIN value.  NULL for user "nobody"
**    g.perm         Permissions granted to this user
**    g.isHuman      True if the user is human, not a spider or robot
** If the 
**
*/
void login_check_credentials(void){
  int uid = 0;                  /* User id */
  const char *zCookie;          /* Text of the login cookie */
  const char *zIpAddr;          /* Raw IP address of the requestor */
  char *zRemoteAddr;            /* Abbreviated IP address of the requestor */
  const char *zCap = 0;         /* Capability string */
788
789
790
791
792
793
794
795


796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815







-
+
+








+







  ** local login is disabled and if we are using HTTP and not HTTPS, 
  ** then there is no need to check user credentials.
  **
  ** This feature allows the "fossil ui" command to give the user
  ** full access rights without having to log in.
  */
  zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
  if( fossil_strcmp(zIpAddr, "127.0.0.1")==0
  if( ( fossil_strcmp(zIpAddr, "127.0.0.1")==0 ||
        g.fSshClient & CGI_SSH_CLIENT )
   && g.useLocalauth
   && db_get_int("localauth",0)==0
   && P("HTTPS")==0
  ){
    uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
    g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
    zCap = "sx";
    g.noPswd = 1;
    g.isHuman = 1;
    sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "localhost");
  }

  /* Check the login cookie to see if it matches a known valid user.
  */
  if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
    /* Parse the cookie value up into HASH/ARG/USER */
905
906
907
908
909
910
911

912
913
914
915
916
917
918
919
920
921
922

923


924
925
926
927
928
929
930
931
932
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932

933
934
935
936
937
938
939







+











+
-
+
+

-







  /* Set the global variables recording the userid and login.  The
  ** "nobody" user is a special case in that g.zLogin==0.
  */
  g.userUid = uid;
  if( fossil_strcmp(g.zLogin,"nobody")==0 ){
    g.zLogin = 0;
  }
  g.isHuman = g.zLogin==0 ? isHuman(P("HTTP_USER_AGENT")) : 1;

  /* Set the capabilities */
  login_replace_capabilities(zCap, 0);
  login_set_anon_nobody_capabilities();

  /* The auto-hyperlink setting allows hyperlinks to be displayed for users
  ** who do not have the "h" permission as long as their UserAgent string
  ** makes it appear that they are human.  Check to see if auto-hyperlink is
  ** enabled for this repository and make appropriate adjustments to the
  ** permission flags if it is.
  */
  if( zCap[0]
  if( zCap[0] && !g.perm.Hyperlink
   && !g.perm.Hyperlink
   && g.isHuman
   && db_get_boolean("auto-hyperlink",1)
   && isHuman(P("HTTP_USER_AGENT"))
  ){
    g.perm.Hyperlink = 1;
    g.javascriptHyperlink = 1;
  }

  /* If the public-pages glob pattern is defined and REQUEST_URI matches
  ** one of the globs in public-pages, then also add in all default-perms
Changes to src/main.c.
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

139
140
141
142
143
144
145
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147







+




















+








/*
** All global variables are in this structure.
*/
struct Global {
  int argc; char **argv;  /* Command-line arguments to the program */
  char *nameOfExe;        /* Full path of executable. */
  const char *zErrlog;    /* Log errors to this file, if not NULL */
  int isConst;            /* True if the output is unchanging */
  sqlite3 *db;            /* The connection to the databases */
  sqlite3 *dbConfig;      /* Separate connection for global_config table */
  int useAttach;          /* True if global_config is attached to repository */
  const char *zConfigDbName;/* Path of the config database. NULL if not open */
  sqlite3_int64 now;      /* Seconds since 1970 */
  int repositoryOpen;     /* True if the main repository database is open */
  char *zRepositoryName;  /* Name of the repository database */
  const char *zMainDbType;/* "configdb", "localdb", or "repository" */
  const char *zConfigDbType;  /* "configdb", "localdb", or "repository" */
  int localOpen;          /* True if the local database is open */
  char *zLocalRoot;       /* The directory holding the  local database */
  int minPrefix;          /* Number of digits needed for a distinct UUID */
  int fSqlTrace;          /* True if --sqltrace flag is present */
  int fSqlStats;          /* True if --sqltrace or --sqlstats are present */
  int fSqlPrint;          /* True if -sqlprint flag is present */
  int fQuiet;             /* True if -quiet flag is present */
  int fHttpTrace;         /* Trace outbound HTTP requests */
  int fSystemTrace;       /* Trace calls to fossil_system(), --systemtrace */
  int fSshTrace;          /* Trace the SSH setup traffic */
  int fSshClient;         /* HTTP client flags for SSH client */
  char *zSshFossilCmd;    /* Path to remoe fossil command for SSH */
  char *zSshCmd;          /* SSH command string */
  char *zFossilUser;      /* Fossil user if different from URL user */
  int fNoSync;            /* Do not do an autosync ever.  --nosync */
  char *zPath;            /* Name of webpage being served */
  char *zExtra;           /* Extra path information past the webpage name */
  char *zBaseURL;         /* Full text of the URL being served */
183
184
185
186
187
188
189

190
191
192
193
194
195
196
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199







+








  const char *zLogin;     /* Login name.  "" if not logged in. */
  const char *zSSLIdentity;  /* Value of --ssl-identity option, filename of
                             ** SSL client identity */
  int useLocalauth;       /* No login required if from 127.0.0.1 */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */
  int isHuman;            /* True if access by a human, not a spider or bot */

  /* Information used to populate the RCVFROM table */
  int rcvid;              /* The rcvid.  0 if not yet defined. */
  char *zIpAddr;          /* The remote IP address */
  char *zNonce;           /* The nonce used for login */

  /* permissions used by the server */
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387







-
+







  Blob line = empty_blob;   /* One line of the file */
  unsigned int nLine;       /* Number of lines in the file*/
  unsigned int i, j, k;     /* Loop counters */
  int n;                    /* Number of bytes in one line */
  char *z;                  /* General use string pointer */
  char **newArgv;           /* New expanded g.argv under construction */
  char const * zFileName;   /* input file name */
  FILE * zInFile;           /* input FILE */
  FILE *inFile;             /* input FILE */
#if defined(_WIN32)
  wchar_t buf[MAX_PATH];
#endif

  g.argc = argc;
  g.argv = argv;
  sqlite3_initialize();
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
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







-
+


-
-
+
+

-
-
-
+
+
+

-
+







    if( z[0]=='-' ) z++;
    if( z[0]==0 ) return;   /* Stop searching at "--" */
    if( fossil_strcmp(z, "args")==0 ) break;
  }
  if( i>=g.argc-1 ) return;

  zFileName = g.argv[i+1];
  zInFile = (0==strcmp("-",zFileName))
  inFile = (0==strcmp("-",zFileName))
    ? stdin
    : fossil_fopen(zFileName,"rb");
  if(!zInFile){
    fossil_panic("Cannot open -args file [%s]", zFileName);
  if(!inFile){
    fossil_fatal("Cannot open -args file [%s]", zFileName);
  }else{
    blob_read_from_channel(&file, zInFile, -1);
    if(stdin != zInFile){
      fclose(zInFile);
    blob_read_from_channel(&file, inFile, -1);
    if(stdin != inFile){
      fclose(inFile);
    }
    zInFile = NULL;
    inFile = NULL;
  }
  blob_to_utf8_no_bom(&file, 1);
  z = blob_str(&file);
  for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
  newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
  for(j=0; j<i; j++) newArgv[j] = g.argv[j];

579
580
581
582
583
584
585

586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625







+








+



















+







    const char *zChdir = find_option("chdir",0,1);
    g.isHTTP = 0;
    g.fQuiet = find_option("quiet", 0, 0)!=0;
    g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
    g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
    g.fSshClient = 0;
    g.zSshFossilCmd = 0;
    g.zSshCmd = 0;
    g.zFossilUser = 0;
    if( g.fSqlTrace ) g.fSqlStats = 1;
    g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
    g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    g.zErrlog = find_option("errorlog", 0, 1);
    if( find_option("utc",0,0) ) g.fTimeFormat = 1;
    if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
    if( zChdir && file_chdir(zChdir, 0) ){
      fossil_fatal("unable to change directories to %s", zChdir);
    }
    if( find_option("help",0,0)!=0 ){
      /* --help anywhere on the command line is translated into
      ** "fossil help argv[1] argv[2]..." */
      int i;
      char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
      for(i=1; i<g.argc; i++) zNewArgv[i+1] = g.argv[i];
      zNewArgv[i+1] = 0;
      zNewArgv[0] = g.argv[0];
      zNewArgv[1] = "help";
      g.argc++;
      g.argv = zNewArgv;
    }
    zCmdName = g.argv[1];
  }
  if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
  rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
  if( rc==1 ){
    fossil_fatal("%s: unknown command: %s\n"
                 "%s: use \"help\" for more information\n",
                   g.argv[0], zCmdName, g.argv[0]);
  }else if( rc==2 ){
    int i, n;
792
793
794
795
796
797
798

799
800
801
802
803
804
805
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812







+







               MANIFEST_VERSION " " MANIFEST_DATE " UTC\n");
  if(!find_option("verbose","v",0)){
    return;
  }else{
    fossil_print("Compiled on %s %s using %s (%d-bit)\n",
                 __DATE__, __TIME__, COMPILER_NAME, sizeof(void*)*8);
    fossil_print("SQLite %s %.30s\n", SQLITE_VERSION, SQLITE_SOURCE_ID);
    fossil_print("Schema version %s\n", AUX_SCHEMA);
    fossil_print("zlib %s\n", ZLIB_VERSION);
#if defined(FOSSIL_ENABLE_SSL)
    fossil_print("SSL (%s)\n", OPENSSL_VERSION_TEXT);
#endif
#if defined(FOSSIL_ENABLE_TCL)
    fossil_print("TCL (Tcl %s)\n", TCL_PATCH_LEVEL);
#endif
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1135







-
+







    if( file_isdir(zDir)==1 ){
      if( file_chdir(zDir, 1) ){
        fossil_fatal("unable to chroot into %s", zDir);
      }
      zRepo = "/";
    }else{
      for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
      if( zDir[i]!='/' ) fossil_panic("bad repository name: %s", zRepo);
      if( zDir[i]!='/' ) fossil_fatal("bad repository name: %s", zRepo);
      if( i>0 ){
        zDir[i] = 0;
        if( file_chdir(zDir, 1) ){
          fossil_fatal("unable to chroot into %s", zDir);
        }
        zDir[i] = '/';
      }
1270
1271
1272
1273
1274
1275
1276

1277

1278
1279
1280
1281
1282
1283
1284
1277
1278
1279
1280
1281
1282
1283
1284

1285
1286
1287
1288
1289
1290
1291
1292







+
-
+







          zRepo, zPathInfo, zNewScript);
    }
  }

  /* Find the page that the user has requested, construct and deliver that
  ** page.
  */
  if( g.zContentType &&
  if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
      strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
    zPathInfo = "/xfer";
  }
  set_base_url(0);
  if( zPathInfo==0 || zPathInfo[0]==0
      || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
#ifdef FOSSIL_ENABLE_JSON
    if(g.json.isJsonMode){
1367
1368
1369
1370
1371
1372
1373
1374

1375
1376
1377
1378
1379
1380
1381
1375
1376
1377
1378
1379
1380
1381

1382
1383
1384
1385
1386
1387
1388
1389







-
+







    ** handling below, and by disabling it in JSON mode I can remove
    ** lots of special-case handling in several JSON handlers.
    */
#ifdef FOSSIL_ENABLE_JSON
    if(!g.json.isJsonMode){
#endif
      dehttpize(g.zExtra);
      cgi_set_parameter_nocopy("name", g.zExtra);
      cgi_set_parameter_nocopy("name", g.zExtra, 1);
#ifdef FOSSIL_ENABLE_JSON
    }
#endif
  }

  /* Locate the method specified by the path and execute the function
  ** that implements that method.
1504
1505
1506
1507
1508
1509
1510




1511
1512
1513
1514
1515
1516
1517
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529







+
+
+
+







  while( blob_line(&config, &line) ){
    if( !blob_token(&line, &key) ) continue;
    if( blob_buffer(&key)[0]=='#' ) continue;
    if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
      g.fDebug = fossil_fopen(blob_str(&value), "ab");
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){
      g.zErrlog = mprintf("%s", blob_str(&value));
      continue;
    }
    if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
      cgi_setenv("HOME", blob_str(&value));
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668

1669
1670
1671
1672
1673
1674
1675
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690







+









+
















+







**   --localauth      enable automatic login for local connections
**   --host NAME      specify hostname of the server
**   --https          signal a request coming in via https
**   --nossl          signal that no SSL connections are available
**   --notfound URL   use URL as "HTTP 404, object not found" page.
**   --files GLOB     comma-separate glob patterns for static file to serve
**   --baseurl URL    base URL (useful with reverse proxies)
**   --scgi           Interpret input as SCGI rather than HTTP
**
** See also: cgi, server, winsrv
*/
void cmd_http(void){
  const char *zIpAddr;
  const char *zNotFound;
  const char *zHost;
  const char *zAltBase;
  const char *zFileGlob;
  int useSCGI;

  /* The winhttp module passes the --files option as --files-urlenc with
  ** the argument being URL encoded, to avoid wildcard expansion in the
  ** shell.  This option is for internal use and is undocumented.
  */
  zFileGlob = find_option("files-urlenc",0,1);
  if( zFileGlob ){
    char *z = mprintf("%s", zFileGlob);
    dehttpize(z);
    zFileGlob = z;
  }else{
    zFileGlob = find_option("files",0,1);
  }
  zNotFound = find_option("notfound", 0, 1);
  g.useLocalauth = find_option("localauth", 0, 0)!=0;
  g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
  useSCGI = find_option("scgi", 0, 0)!=0;
  zAltBase = find_option("baseurl", 0, 1);
  if( zAltBase ) set_base_url(zAltBase);
  if( find_option("https",0,0)!=0 ) cgi_replace_parameter("HTTPS","on");
  zHost = find_option("host", 0, 1);
  if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
  g.cgiOutput = 1;
  if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
1683
1684
1685
1686
1687
1688
1689



1690
1691
1692





1693


1694
1695












1696
1697
1698
1699
1700
1701

1702
1703


1704
1705
1706
1707
1708
1709
1710
1711
1712






1713
1714



1715
1716
1717
1718
1719
1720
1721
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715

1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756


1757
1758
1759
1760
1761
1762
1763
1764
1765
1766







+
+
+



+
+
+
+
+
-
+
+


+
+
+
+
+
+
+
+
+
+
+
+






+


+
+



-





+
+
+
+
+
+
-
-
+
+
+







  }else{
    g.httpIn = stdin;
    g.httpOut = stdout;
    zIpAddr = 0;
  }
  if( zIpAddr==0 ){
    zIpAddr = cgi_ssh_remote_addr(0);
    if( zIpAddr && zIpAddr[0] ){
      g.fSshClient |= CGI_SSH_CLIENT;
    }
  }
  find_server_repository(0);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  if( useSCGI ){
    cgi_handle_scgi_request();
  }else if( g.fSshClient & CGI_SSH_CLIENT ){
    ssh_request_loop(zIpAddr, glob_create(zFileGlob));
  }else{
  cgi_handle_http_request(zIpAddr);
    cgi_handle_http_request(zIpAddr);
  }
  process_one_web_page(zNotFound, glob_create(zFileGlob));
}

/*
** Process all requests in a single SSH connection if possible.
*/
void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){
  do{
    cgi_handle_ssh_http_request(zIpAddr);
    process_one_web_page(0, FileGlob);
    blob_reset(&g.cgiIn);
  } while ( g.fSshClient & CGI_SSH_FOSSIL ||
          g.fSshClient & CGI_SSH_COMPAT );
}

/*
** Note that the following command is used by ssh:// processing.
**
** COMMAND: test-http
** Works like the http command but gives setup permission to all users.
**
*/
void cmd_test_http(void){
  const char *zIpAddr;    /* IP address of remote client */

  Th_InitTraceLog();
  login_set_capabilities("sx", 0);
  g.useLocalauth = 1;
  cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
  g.httpIn = stdin;
  g.httpOut = stdout;
  find_server_repository(0);
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  zIpAddr = cgi_ssh_remote_addr(0);
  if( zIpAddr && zIpAddr[0] ){
    g.fSshClient |= CGI_SSH_CLIENT;
    ssh_request_loop(zIpAddr, 0);
  }else{
    cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
  cgi_handle_http_request(0);
  process_one_web_page(0, 0);
    cgi_handle_http_request(0);
    process_one_web_page(0, 0);
  }
}

#if !defined(_WIN32)
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
/*
** Search for an executable on the PATH environment variable.
** Return true (1) if found and false (0) if not found.
1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792
1793
1794
1795
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841







+







**   --localauth         enable automatic login for requests from localhost
**   --localhost         listen on 127.0.0.1 only (always true for "ui")
**   -P|--port TCPPORT   listen to request on port TCPPORT
**   --th-trace          trace TH1 execution (for debugging purposes)
**   --baseurl URL       Use URL as the base (useful for reverse proxies)
**   --notfound URL      Redirect
**   --files GLOBLIST    Comma-separated list of glob patterns for static files
**   --scgi              Accept SCGI rather than HTTP
**
** See also: cgi, http, winsrv
*/
void cmd_webserver(void){
  int iPort, mxPort;        /* Range of TCP ports allowed */
  const char *zPort;        /* Value of the --port option */
  const char *zBrowser;     /* Name of web browser program */
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868







+








  zFileGlob = find_option("files", 0, 1);
  g.useLocalauth = find_option("localauth", 0, 0)!=0;
  Th_InitTraceLog();
  zPort = find_option("port", "P", 1);
  zNotFound = find_option("notfound", 0, 1);
  zAltBase = find_option("baseurl", 0, 1);
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  if ( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }
  if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
1842
1843
1844
1845
1846
1847
1848





1849

1850
1851
1852
1853
1854
1855
1856
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909







+
+
+
+
+

+







  if( isUiCmd ){
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
    zBrowser = db_get("web-browser", 0);
    if( zBrowser==0 ){
      static const char *const azBrowserProg[] =
          { "xdg-open", "gnome-open", "firefox", "google-chrome" };
      int i;
#if defined(__CYGWIN__)
      const char *path = fossil_getenv("PROGRAMFILES");
      path = fossil_utf8_to_filename(path);
      zBrowser = mprintf("\"%s/Internet Explorer/iexplore.exe\"", path);
#else
      zBrowser = "echo";
#endif
      for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
        if( binaryOnPath(azBrowserProg[i]) ){
          zBrowser = azBrowserProg[i];
          break;
        }
      }
    }
1872
1873
1874
1875
1876
1877
1878



1879


1880
1881
1882
1883
1884
1885
1886
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934

1935
1936
1937
1938
1939
1940
1941
1942
1943







+
+
+
-
+
+







  g.httpOut = stdout;
  if( g.fHttpTrace || g.fSqlTrace ){
    fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
  }
  g.cgiOutput = 1;
  find_server_repository(isUiCmd && zNotFound==0);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  if( flags & HTTP_SERVER_SCGI ){
    cgi_handle_scgi_request();
  }else{
  cgi_handle_http_request(0);
    cgi_handle_http_request(0);
  }
  process_one_web_page(zNotFound, glob_create(zFileGlob));
#else
  /* Win32 implementation */
  if( isUiCmd ){
    zBrowser = db_get("web-browser", "start");
    if( zIpAddr ){
      zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
Changes to src/manifest.c.
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







-
+







    char *zCPBase;      /* UUID of cherry-pick baseline. NULL for singletons */
  } *aCherrypick;
  int nCChild;          /* Number of cluster children */
  int nCChildAlloc;     /* Number of closts allocated in azCChild[] */
  char **azCChild;      /* UUIDs of referenced objects in a cluster. M cards */
  int nTag;             /* Number of T Cards */
  int nTagAlloc;        /* Slots allocated in aTag[] */
  struct { 
  struct TagType {
    char *zName;           /* Name of the tag */
    char *zUuid;           /* UUID that the tag is applied to */
    char *zValue;          /* Value if the tag is really a property */
  } *aTag;              /* One for each T card */
  int nField;           /* Number of J cards */
  int nFieldAlloc;      /* Slots allocated in aField[] */
  struct { 
351
352
353
354
355
356
357
358

359
360
361
362
363
364
365
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365







-
+







  ManifestText x;
  char cPrevType = 0;
  char cType;
  char *z;
  int n;
  char *zUuid;
  int sz = 0;
  int isRepeat;
  int isRepeat, hasSelfRefTag = 0;
  static Bag seen;
  const char *zErr = 0;

  if( rid==0 ){
    isRepeat = 1;
  }else if( bag_find(&seen, rid) ){
    isRepeat = 1;
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
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







-
+
-


-
-
-
-
-








+
+
+
+
+
+
+







  n = blob_size(pContent);
  if( n<=0 || z[n-1]!='\n' ){
    blob_reset(pContent);
    blob_appendf(pErr, n ? "not terminated with \\n" : "zero-length");
    return 0;
  }

  /* Strip off the PGP signature if there is one.  Then verify the
  /* Strip off the PGP signature if there is one.
  ** Z-card.
  */
  remove_pgp_signature(&z, &n);
  if( verify_z_card(z, n)==2 ){
    blob_reset(pContent);
    blob_appendf(pErr, "incorrect Z-card cksum");
    return 0;
  }

  /* Verify that the first few characters of the artifact look like
  ** a control artifact.
  */
  if( n<10 || z[0]<'A' || z[0]>'Z' || z[1]!=' ' ){
    blob_reset(pContent);
    blob_appendf(pErr, "line 1 not recognized");
    return 0;
  }
  /* Then verify the Z-card.
  */
  if( verify_z_card(z, n)==2 ){
    blob_reset(pContent);
    blob_appendf(pErr, "incorrect Z-card cksum");
    return 0;
  }

  /* Allocate a Manifest object to hold the parsed control artifact.
  */
  p = fossil_malloc( sizeof(*p) );
  memset(p, 0, sizeof(*p));
  memcpy(&p->content, pContent, sizeof(p->content));
658
659
660
661
662
663
664
665

666
667
668
669
670
671
672
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673







-
+







        defossilize(p->zMimetype);
        break;
      }

      /*
      **     P <uuid> ...
      **
      ** Specify one or more other artifacts where are the parents of
      ** Specify one or more other artifacts which are the parents of
      ** this artifact.  The first parent is the primary parent.  All
      ** others are parents by merge.
      */
      case 'P': {
        while( (zUuid = next_token(&x, &sz))!=0 ){
          if( sz!=UUID_SIZE ) SYNTAX("wrong size UUID on P-card");
          if( !validate16(zUuid, UUID_SIZE) )SYNTAX("invalid UUID on P-card");
714
715
716
717
718
719
720
721

722
723
724
725
726
727
728
715
716
717
718
719
720
721

722
723
724
725
726
727
728
729







-
+







      /*
      **     R <md5sum>
      **
      ** Specify the MD5 checksum over the name and content of all files
      ** in the manifest.
      */
      case 'R': {
        if( p->zRepoCksum!=0 ) SYNTAX("more than on R-card");
        if( p->zRepoCksum!=0 ) SYNTAX("more than one R-card");
        p->zRepoCksum = next_token(&x, &sz);
        if( sz!=32 ) SYNTAX("wrong size cksum on R-card");
        if( !validate16(p->zRepoCksum, 32) ) SYNTAX("malformed R-card cksum");
        break;
      }

      /*
746
747
748
749
750
751
752

753
754




755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773

774
775




776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780


781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804







+


+
+
+
+



















+
-
-
+
+
+
+












-
+







        if( zName==0 ) SYNTAX("missing name on T-card");
        zUuid = next_token(&x, &sz);
        if( zUuid==0 ) SYNTAX("missing UUID on T-card");
        zValue = next_token(&x, 0);
        if( zValue ) defossilize(zValue);
        if( sz==UUID_SIZE && validate16(zUuid, UUID_SIZE) ){
          /* A valid uuid */
          if( p->zEventId ) SYNTAX("non-self-referential T-card in event");
        }else if( sz==1 && zUuid[0]=='*' ){
          zUuid = 0;
          hasSelfRefTag = 1;
          if( p->zEventId && zName[0]!='+' ){
            SYNTAX("propagating T-card in event");
          }
        }else{
          SYNTAX("malformed UUID on T-card");
        }
        defossilize(zName);
        if( zName[0]!='-' && zName[0]!='+' && zName[0]!='*' ){
          SYNTAX("T-card name does not begin with '-', '+', or '*'");
        }
        if( validate16(&zName[1], strlen(&zName[1])) ){
          /* Do not allow tags whose names look like UUIDs */
          SYNTAX("T-card name looks like a UUID");
        }
        if( p->nTag>=p->nTagAlloc ){
          p->nTagAlloc = p->nTagAlloc*2 + 10;
          p->aTag = fossil_realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) );
        }
        i = p->nTag++;
        p->aTag[i].zName = zName;
        p->aTag[i].zUuid = zUuid;
        p->aTag[i].zValue = zValue;
        if( i>0 ){
        if( i>0 && fossil_strcmp(p->aTag[i-1].zName, zName)>=0 ){
          SYNTAX("T-card in the wrong order");
          int c = fossil_strcmp(p->aTag[i-1].zName, zName);
          if( c>0 || (c==0 && fossil_strcmp(p->aTag[i-1].zUuid, zUuid)>=0) ){
            SYNTAX("T-card in the wrong order");
          }
        }
        break;
      }

      /*
      **     U ?<login>?
      **
      ** Identify the user who created this control file by their
      ** login.  Only one U line is allowed.  Prohibited in clusters.
      ** If the user name is omitted, take that to be "anonymous".
      */
      case 'U': {
        if( p->zUser!=0 ) SYNTAX("more than on U-card");
        if( p->zUser!=0 ) SYNTAX("more than one U-card");
        p->zUser = next_token(&x, 0);
        if( p->zUser==0 ){
          p->zUser = "anonymous";
        }else{
          defossilize(p->zUser);
        }
        break;
847
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
863

864
865
866
867
868
869
870





871
872
873
874
875
876
877








878
879
880
881
882
883
884
885
886
887
888
889
890
891
892










893
894
895
896
897
898
899
900
901
902
903
904
905



















906
907
908
909
910






911
912
913
914


915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930


931
932
933
934
935
936
937
938
939
940





941
942
943
944
945
946
947
856
857
858
859
860
861
862


863








864







865
866
867
868
869
870
871





872
873
874
875
876
877
878
879
880
881
882
883
884










885
886
887
888
889
890
891
892
893
894













895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913





914
915
916
917
918
919

920


921
922
923
924
925









926



927
928

929
930
931






932
933
934
935
936
937
938
939
940
941
942
943







-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+


-
-
-
-
-
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-

-
-
+
+



-
-
-
-
-
-
-
-
-

-
-
-
+
+
-



-
-
-
-
-
-
+
+
+
+
+







      default: {
        SYNTAX("unrecognized card");
      }
    }
  }
  if( x.z<x.zEnd ) SYNTAX("extra characters at end of card");

  if( p->nFile>0 || p->zRepoCksum!=0 || p->zBaseline ){
    if( p->nCChild>0 ) SYNTAX("M-card in check-in");
  if( p->nCChild>0 ){
    if( p->rDate<=0.0 ) SYNTAX("missing date for check-in");
    if( p->nField>0 ) SYNTAX("J-card in check-in");
    if( p->zTicketUuid ) SYNTAX("K-card in check-in");
    if( p->zWiki ) SYNTAX("W-card in check-in");
    if( p->zWikiTitle ) SYNTAX("L-card in check-in");
    if( p->zEventId ) SYNTAX("E-card in check-in");
    if( p->zTicketUuid ) SYNTAX("K-card in check-in");
    if( p->zAttachName ) SYNTAX("A-card in check-in");
    if( p->zAttachName
    p->type = CFTYPE_MANIFEST;
  }else if( p->nCChild>0 ){
    if( p->rDate>0.0
     || p->zComment!=0
     || p->zUser!=0
     || p->nTag>0
     || p->nParent>0
     || p->zBaseline
     || p->zComment
     || p->rDate>0.0
     || p->zEventId
     || p->nFile>0
     || p->nField>0
     || p->zTicketUuid
     || p->zWiki
     || p->zWikiTitle
     || p->zEventId
     || p->zAttachName
     || p->zMimetype
     || p->zWikiTitle
     || p->zMimetype
     || p->nParent>0
     || p->nCherrypick>0
     || p->zRepoCksum
     || p->nTag>0
     || p->zUser
     || p->zWiki
    ){
      SYNTAX("cluster contains a card other than M- or Z-");
    }
    if( !seenZ ) SYNTAX("missing Z-card on cluster");
    p->type = CFTYPE_CLUSTER;
  }else if( p->nField>0 ){
    if( p->rDate<=0.0 ) SYNTAX("missing date for ticket");
    if( p->zWiki ) SYNTAX("W-card in ticket");
    if( p->zWikiTitle ) SYNTAX("L-card in ticket");
    if( p->zEventId ) SYNTAX("E-card in ticket");
    if( p->nCChild>0 ) SYNTAX("M-card in ticket");
    if( p->nTag>0 ) SYNTAX("T-card in ticket");
    if( p->zTicketUuid==0 ) SYNTAX("missing K-card in ticket");
    if( p->zUser==0 ) SYNTAX("missing U-card in ticket");
    if( p->zAttachName ) SYNTAX("A-card in ticket");
  }else if( p->zEventId ){
    if( p->rDate<=0.0 ) SYNTAX("missing date on event");
    if( p->nFile>0 ) SYNTAX("F-card in event");
    if( p->zRepoCksum ) SYNTAX("R-card in event");
    if( p->zBaseline ) SYNTAX("B-card in event");
    if( p->nField>0 ) SYNTAX("J-card in event");
    if( p->zTicketUuid ) SYNTAX("K-card in event");
    if( p->zWikiTitle!=0 ) SYNTAX("L-card in event");
    if( p->zWiki==0 ) SYNTAX("missing W-card on event");
    if( p->zAttachName ) SYNTAX("A-card in event");
    if( p->zMimetype) SYNTAX("N-card in ticket");
    if( !seenZ ) SYNTAX("missing Z-card in ticket");
    p->type = CFTYPE_TICKET;
  }else if( p->zEventId ){
    if( p->rDate<=0.0 ) SYNTAX("missing date for event");
    if( p->nCChild>0 ) SYNTAX("M-card in event");
    if( p->zTicketUuid!=0 ) SYNTAX("K-card in event");
    if( p->zWikiTitle!=0 ) SYNTAX("L-card in event");
    if( p->zWiki==0 ) SYNTAX("W-card in event");
    if( p->zAttachName ) SYNTAX("A-card in event");
    for(i=0; i<p->nTag; i++){
      if( p->aTag[i].zName[0]!='+' ) SYNTAX("propagating tag in event");
      if( p->aTag[i].zUuid!=0 ) SYNTAX("non-self-referential tag in event");
    if( !seenZ ) SYNTAX("missing Z-card on event");
    p->type = CFTYPE_EVENT;
  }else if( hasSelfRefTag || p->nFile>0 || p->zRepoCksum!=0 || p->zBaseline ){
    if( p->rDate<=0.0 ) SYNTAX("missing date on manifest");
    if( p->nField>0 ) SYNTAX("J-card in manifest");
    if( p->zTicketUuid ) SYNTAX("K-card in manifest");
    if( p->zWiki ) SYNTAX("W-card in manifest");
    if( p->zWikiTitle ) SYNTAX("L-card in manifest");
    if( p->zTicketUuid ) SYNTAX("K-card in manifest");
    if( p->zAttachName ) SYNTAX("A-card in manifest");
    p->type = CFTYPE_MANIFEST;
  }else if( p->nField>0 || p->zTicketUuid!=0 ){
    if( p->rDate<=0.0 ) SYNTAX("missing date on ticket");
    if( p->zWiki ) SYNTAX("W-card in ticket");
    if( p->zWikiTitle ) SYNTAX("L-card in ticket");
    if( p->nField==0 ) SYNTAX("missing J-card on ticket");
    if( p->nTag>0 ) SYNTAX("T-card in ticket");
    if( p->zTicketUuid==0 ) SYNTAX("missing K-card on ticket");
    if( p->zUser==0 ) SYNTAX("missing U-card on ticket");
    }
    if( !seenZ ) SYNTAX("Z-card missing in event");
    p->type = CFTYPE_EVENT;
  }else if( p->zWiki!=0 ){
    if( p->rDate<=0.0 ) SYNTAX("date missing on wiki");
    if( p->zAttachName ) SYNTAX("A-card in ticket");
    if( p->zMimetype) SYNTAX("N-card in ticket");
    if( !seenZ ) SYNTAX("missing Z-card on ticket");
    p->type = CFTYPE_TICKET;
  }else if( p->zWiki!=0 || p->zWikiTitle!=0 ){
    if( p->rDate<=0.0 ) SYNTAX("missing date on wiki");
    if( p->nCChild>0 ) SYNTAX("M-card in wiki");
    if( p->nTag>0 ) SYNTAX("T-card in wiki");
    if( p->zTicketUuid!=0 ) SYNTAX("K-card in wiki");
    if( p->zWikiTitle==0 ) SYNTAX("L-card in wiki");
    if( p->zWiki==0 ) SYNTAX("missing W-card on wiki");
    if( p->zWikiTitle==0 ) SYNTAX("missing L-card on wiki");
    if( p->zAttachName ) SYNTAX("A-card in wiki");
    if( !seenZ ) SYNTAX("missing Z-card on wiki");
    p->type = CFTYPE_WIKI;
  }else if( p->nTag>0 ){
    if( p->rDate<=0.0 ) SYNTAX("date missing on tag");
    if( p->nParent>0 ) SYNTAX("P-card on tag");
    if( p->zWikiTitle ) SYNTAX("L-card on tag");
    if( p->zTicketUuid ) SYNTAX("K-card in tag");
    if( p->zAttachName ) SYNTAX("A-card in tag");
    if( p->zMimetype ) SYNTAX("N-card in tag");
    if( !seenZ ) SYNTAX("missing Z-card on tag");
    p->type = CFTYPE_CONTROL;
  }else if( p->zAttachName ){
    if( p->nCChild>0 ) SYNTAX("M-card in attachment");
    if( p->rDate<=0.0 ) SYNTAX("missing date in attachment");
    if( p->zTicketUuid ) SYNTAX("K-card in attachment");
    if( p->rDate<=0.0 ) SYNTAX("missing date on attachment");
    if( p->nTag>0 ) SYNTAX("T-card in attachment");
    if( p->zWikiTitle ) SYNTAX("L-card in attachment");
    if( !seenZ ) SYNTAX("missing Z-card on attachment");
    p->type = CFTYPE_ATTACHMENT;
  }else{
    if( p->nCChild>0 ) SYNTAX("M-card in check-in");
    if( p->rDate<=0.0 ) SYNTAX("missing date in check-in");
    if( p->nField>0 ) SYNTAX("J-card in check-in");
    if( p->zTicketUuid ) SYNTAX("K-card in check-in");
    if( p->zWikiTitle ) SYNTAX("L-card in check-in");
    p->type = CFTYPE_MANIFEST;
    if( p->rDate<=0.0 ) SYNTAX("missing date on control");
    if( p->nParent>0 ) SYNTAX("P-card in control");
    if( p->zMimetype ) SYNTAX("N-card in control");
    if( !seenZ ) SYNTAX("missing Z-card on control");
    p->type = CFTYPE_CONTROL;
  }
  md5sum_init();
  if( !isRepeat ) g.parseCnt[p->type]++;
  return p;

manifest_syntax_error:
  if( zErr ){
1608
1609
1610
1611
1612
1613
1614














1615
1616
1617
1618
1619
1620
1621
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631







+
+
+
+
+
+
+
+
+
+
+
+
+
+







    "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
    tktTagId, pManifest->rDate, rid, pManifest->zUser,
    blob_str(&comment), blob_str(&brief)
  );
  blob_reset(&comment);
  blob_reset(&brief);
}

/*
** This is the comparison function used to sort the tag array.
*/
static int tag_compare(const void *a, const void *b){
  struct TagType *pA = (struct TagType*)a;
  struct TagType *pB = (struct TagType*)b;
  int c;
  c = fossil_strcmp(pA->zUuid, pB->zUuid);
  if( c==0 ){
    c = fossil_strcmp(pA->zName, pB->zName);
  }
  return c;
}

/*
** Scan artifact rid/pContent to see if it is a control artifact of
** any key:
**
**      *  Manifest
**      *  Control
1922
1923
1924
1925
1926
1927
1928





1929
1930

1931
1932
1933
1934

1935
1936
1937
1938
1939
1940
1941
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947

1948

1949
1950
1951
1952
1953
1954
1955
1956







+
+
+
+
+


+

-

-
+







    Blob comment;
    int i;
    const char *zName;
    const char *zValue;
    const char *zUuid;
    int branchMove = 0;
    blob_zero(&comment);
    if( p->zComment ){
      blob_appendf(&comment, " %s.", p->zComment);
    }
    /* Next loop expects tags to be sorted on UUID, so sort it. */
    qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
    for(i=0; i<p->nTag; i++){
      zUuid = p->aTag[i].zUuid;
      if( !zUuid ) continue;
      if( i==0 || fossil_strcmp(zUuid, p->aTag[i-1].zUuid)!=0 ){
        if( i>0 ) blob_append(&comment, " ", 1);
        blob_appendf(&comment,
           "Edit [%S]:",
           " Edit [%S]:",
           zUuid);
        branchMove = 0;
      }
      zName = p->aTag[i].zName;
      zValue = p->aTag[i].zValue;
      if( strcmp(zName, "*branch")==0 ){
        blob_appendf(&comment,
1963
1964
1965
1966
1967
1968
1969


1970



1971
1972





1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988

1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
1978
1979
1980
1981
1982
1983
1984
1985
1986

1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
2023







+
+
-
+
+
+

-
+
+
+
+
+
















+



-
+







          blob_appendf(&comment, " Add propagating tag \"%h\".", &zName[5]);
        }
      }else if( memcmp(zName, "+sym-",5)==0 ){
        blob_appendf(&comment, " Add tag \"%h\".", &zName[5]);
      }else if( memcmp(zName, "-sym-",5)==0 ){
        blob_appendf(&comment, " Cancel tag \"%h\".", &zName[5]);
      }else if( strcmp(zName, "+closed")==0 ){
        blob_append(&comment, " Marked \"Closed\"", -1);
        if( zValue && *zValue ){
        blob_appendf(&comment, " Marked \"Closed\".");
          blob_appendf(&comment, " with note \"%h\"", zValue);
        }
        blob_append(&comment, ".", 1);
      }else if( strcmp(zName, "-closed")==0 ){
        blob_appendf(&comment, " Removed the \"Closed\" mark.");
        blob_append(&comment, " Removed the \"Closed\" mark", -1);
        if( zValue && *zValue ){
          blob_appendf(&comment, " with note \"%h\"", zValue);
        }
        blob_append(&comment, ".", 1);
      }else {
        if( zName[0]=='-' ){
          blob_appendf(&comment, " Cancel \"%h\"", &zName[1]);
        }else if( zName[0]=='+' ){
          blob_appendf(&comment, " Add \"%h\"", &zName[1]);
        }else{
          blob_appendf(&comment, " Add propagating \"%h\"", &zName[1]);
        }
        if( zValue && zValue[0] ){
          blob_appendf(&comment, " with value \"%h\".", zValue);
        }else{
          blob_appendf(&comment, ".");
        }
      }
    }
    /*blob_appendf(&comment, " &#91;[/info/%S | details]&#93;");*/
    if( blob_size(&comment)==0 ) blob_append(&comment, " ", 1);
    db_multi_exec(
      "REPLACE INTO event(type,mtime,objid,user,comment)"
      "VALUES('g',%.17g,%d,%Q,%Q)",
      p->rDate, rid, p->zUser, blob_str(&comment)
      p->rDate, rid, p->zUser, blob_str(&comment)+1
    );
    blob_reset(&comment);
  }
  db_end_transaction(0);
  if( p->type==CFTYPE_MANIFEST ){
    manifest_cache_insert(p);
  }else{
Changes to src/merge.c.
256
257
258
259
260
261
262
263
264
265











266
267
268
269
270
271
272
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







-
-
-
+
+
+
+
+
+
+
+
+
+
+







    fossil_fatal("not a version: record #%d", pid);
  }
  if( !forceFlag && mid==pid ){
    fossil_print("Merge skipped because it is a no-op. "
                 " Use --force to override.\n");
    return;
  }
  if( integrateFlag && !is_a_leaf(mid) ){
    fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
    integrateFlag = 0;
  if( integrateFlag ){
    if( db_exists("SELECT 1 FROM vmerge WHERE id=-4")) {
      /* Fossil earlier than [55cacfcace] cannot handle this,
       * therefore disallow it. */
      fossil_fatal("Integration of another branch already in progress."
        "  Commit or Undo needed first", g.argv[2]);
    }
    if( !is_a_leaf(mid) ){
      fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
      integrateFlag = 0;
    }
  }
  if( verboseFlag ){
    print_checkin_description(mid, 12, integrateFlag?"integrate:":"merge-from:");
    print_checkin_description(pid, 12, "baseline:");
  }
  vfile_check_signature(vid, CKSIG_ENOTFILE);
  db_begin_transaction();
Changes to src/name.c.
246
247
248
249
250
251
252


253
254
255
256
257
258
259
260
261
262











263
264
265
266
267
268
269
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







+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







    "   AND event.objid=tagxref.rid "
    "   AND event.type GLOB '%q'",
    zTag, zType
  );
  if( rid>0 ) return rid;

  /* Undocumented:  numeric tags get translated directly into the RID */
  if( memcmp(zTag, "rid:", 4)==0 ){
    zTag += 4;
  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);
    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;
}


/*
Changes to src/pivot.c.
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94







-
+







  Stmt q1, q2, u1, i1;
  int rid = 0;
  
  /* aqueue must contain at least one primary and one other.  Otherwise
  ** we abort early
  */
  if( db_int(0, "SELECT count(distinct src) FROM aqueue")<2 ){
    fossil_panic("lack both primary and secondary files");
    fossil_fatal("lack both primary and secondary files");
  }

  /* Prepare queries we will be needing
  **
  ** The first query finds the oldest pending version on the aqueue.  This
  ** will be next one searched.
  */
Changes to src/popen.c.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33



34
35
36
37
38
39
40
15
16
17
18
19
20
21


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41







-
-










+
+
+







**
*******************************************************************************
**
** This file contains an implementation of a bi-directional popen().
*/
#include "config.h"
#include "popen.h"
#include <signal.h>
#include <sys/wait.h>

#ifdef _WIN32
#include <windows.h>
#include <fcntl.h>
/*
** Print a fatal error and quit.
*/
static void win32_fatal_error(const char *zMsg){
  fossil_fatal("%s", zMsg);
}
#else
#include <signal.h>
#include <sys/wait.h>
#endif

/*
** The following macros are used to cast pointers to integers and
** integers to pointers.  The way you do this varies from one compiler
** to the next, so we have developed the following set of #if statements
** to generate appropriate macros for a wide range of compilers.
Changes to src/printf.c.
20
21
22
23
24
25
26

27
28
29
30
31
32
33
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34







+







*/
#include "config.h"
#include "printf.h"
#if defined(_WIN32)
#   include <io.h>
#   include <fcntl.h>
#endif
#include <time.h>

/*
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
#define etRADIX       1 /* Integer types.  %d, %x, %o, and so forth */
#define etFLOAT       2 /* Floating point.  %f */
904
905
906
907
908
909
910

































911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926

927




928

929
930

931

932
933
934
935
936
937
938
939
940
941
942

943
944
945
946
947
948



949
950
951
952
953

954
955
956
957
958
959
960
961
962
963

964
965
966
967
968
969
970
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

958
959
960

961
962
963
964
965
966
967

968
969
970
971
972
973
974
975
976
977
978
979
980

981

982
983
984
985

986
987
988
989
990



991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













-


+
-
+
+
+
+

+

-
+

+










-
+
-




-
+
+
+


-
-
-
+










+







  b = empty_blob;
  vxprintf(&b, zFormat, ap);
  fossil_puts(blob_str(&b), 1);
  blob_reset(&b);
  va_end(ap);
}

/*
** Write a message to the error log, if the error log filename is
** defined.
*/
static void fossil_errorlog(const char *zFormat, ...){
  struct tm *pNow;
  time_t now;
  FILE *out;
  const char *z;
  int i;
  va_list ap;
  static const char *azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT",
      "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
      "REQUEST_URI", "SCRIPT_NAME" };
  if( g.zErrlog==0 ) return;
  out = fopen(g.zErrlog, "a");
  if( out==0 ) return;
  now = time(0);
  pNow = gmtime(&now);
  fprintf(out, "------------- %04d-%02d-%02d %02d:%02d:%02d UTC ------------\n",
          pNow->tm_year+1900, pNow->tm_mon+1, pNow->tm_mday+1,
          pNow->tm_hour, pNow->tm_min, pNow->tm_sec);
  va_start(ap, zFormat);
  vfprintf(out, zFormat, ap);
  fprintf(out, "\n");
  va_end(ap);
  for(i=0; i<sizeof(azEnv)/sizeof(azEnv[0]); i++){
    if( (z = getenv(azEnv[i]))!=0 || (z = P(azEnv[i]))!=0 ){
      fprintf(out, "%s=%s\n", azEnv[i], z);
    }
  }
  fclose(out);
}

/*
** The following variable becomes true while processing a fatal error
** or a panic.  If additional "recursive-fatal" errors occur while
** shutting down, the recursive errors are silently ignored.
*/
static int mainInFatalError = 0;

/*
** Print an error message, rollback all databases, and quit.  These
** routines never return.
*/
NORETURN void fossil_panic(const char *zFormat, ...){
  char *z;
  va_list ap;
  int rc = 1;
  char z[1000];
  static int once = 1;
  static int once = 0;

  if( once ) exit(1);
  once = 1;
  mainInFatalError = 1;
  db_force_rollback();
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  sqlite3_vsnprintf(sizeof(z),z,zFormat, ap);
  va_end(ap);
  fossil_errorlog("panic: %s", z);
#ifdef FOSSIL_ENABLE_JSON
  if( g.json.isJsonMode ){
    json_err( 0, z, 1 );
    if( g.isHTTP ){
      rc = 0 /* avoid HTTP 500 */;
    }
  }
  else
#endif
  {
    if( g.cgiOutput && once ){
    if( g.cgiOutput ){
      once = 0;
      cgi_printf("<p class=\"generalError\">%h</p>", z);
      cgi_reply();
    }else if( !g.fQuiet ){
      fossil_force_newline();
      fossil_trace("Fossil internal error: %s\n", z);
      fossil_puts("Fossil internal error: ", 1);
      fossil_puts(z, 1);
      fossil_puts("\n", 1);
    }
  }
  free(z);
  db_force_rollback();
  fossil_exit(rc);
  exit(rc);
}

NORETURN void fossil_fatal(const char *zFormat, ...){
  char *z;
  int rc = 1;
  va_list ap;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  fossil_errorlog("fatal: %s", z);
#ifdef FOSSIL_ENABLE_JSON
  if( g.json.isJsonMode ){
    json_err( g.json.resultCode, z, 1 );
    if( g.isHTTP ){
      rc = 0 /* avoid HTTP 500 */;
    }
  }
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052







+







  va_list ap;
  int rc = 1;
  if( mainInFatalError ) return;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  fossil_errorlog("fatal: %s", z);
#ifdef FOSSIL_ENABLE_JSON
  if( g.json.isJsonMode ){
    json_err( g.json.resultCode, z, 1 );
    if( g.isHTTP ){
      rc = 0 /* avoid HTTP 500 */;
    }
  } else
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038
1039
1040
1041
1042
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083







+







/* Print a warning message */
void fossil_warning(const char *zFormat, ...){
  char *z;
  va_list ap;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  fossil_errorlog("warning: %s", z);
#ifdef FOSSIL_ENABLE_JSON
  if(g.json.isJsonMode){
    json_warn( FSL_JSON_W_UNKNOWN, z );
  }else
#endif
  {
    if( g.cgiOutput ){
Changes to src/rebuild.c.
860
861
862
863
864
865
866
867

868
869
870
871
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
875
876
877
878

879
880
881
882
883
884
885
886







-
+











-
+







      fossil_filename_free(zUtf8Name);
      if( file_isdir(zSubpath)==1 ){
        recon_read_dir(zSubpath);
      }
      blob_init(&path, 0, 0);
      blob_appendf(&path, "%s", zSubpath);
      if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){
        fossil_panic("some unknown error occurred while reading \"%s\"", 
        fossil_fatal("some unknown error occurred while reading \"%s\"", 
                     blob_str(&path));
      }
      content_put(&aContent);
      blob_reset(&path);
      blob_reset(&aContent);
      free(zSubpath);
      fossil_print("\r%d", ++nFileRead);
      fflush(stdout);
    }
    closedir(d);
  }else {
    fossil_panic("encountered error %d while trying to open \"%s\".",
    fossil_fatal("encountered error %d while trying to open \"%s\".",
                  errno, g.argv[3]);
  }
  fossil_filename_free(zUnicodePath);
}

/*
** COMMAND: reconstruct*
Changes to src/report.c.
76
77
78
79
80
81
82

83
84
85
86
87
88
89
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90







+







    }
    if( g.perm.TktFmt ){
      blob_appendf(&ril, "[%zsql</a>]",
                         href("%R/rptsql?rn=%d", rn));
    }
    blob_appendf(&ril, "</li>\n");
  }
  db_finalize(&q);

  Th_Store("report_items", blob_str(&ril));
  
  Th_Render(zScript);
  
  blob_reset(&ril);
  if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1);
Changes to src/shell.c.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
49
50
51
52
53
54
55

56
57
58
59
60
61
62







-







# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include <readline/readline.h>
# include <readline/history.h>
#endif
#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
# define readline(p) local_getline(p,stdin,0)
# define add_history(X)
# define read_history(X)
# define write_history(X)
# define stifle_history(X)
#endif

#if defined(_WIN32) || defined(WIN32)
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
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







-
-
+
+

-
+
-
-
-
+
+
-

-
-
-
-
-
-
-
-














-
+
-
-
-
-
+






-






-
-
+
+
+
+
+
+
+
+
+
+

-
+



-
+
-
-
-

-
+
-
-

+
+
-
+
+
+
+
+

+








/*
** This routine reads a line of text from FILE in, stores
** the text in memory obtained from malloc() and returns a pointer
** to the text.  NULL is returned at end of file, or if malloc()
** fails.
**
** The interface is like "readline" but no command-line editing
** is done.
** If zLine is not NULL then it is a malloced buffer returned from
** a previous call to this routine that may be reused.
*/
static char *local_getline(char *zPrompt, FILE *in, int csvFlag){
static char *local_getline(char *zLine, FILE *in){
  char *zLine;
  int nLine;
  int n;
  int nLine = zLine==0 ? 0 : 100;
  int n = 0;
  int inQuote = 0;

  if( zPrompt && *zPrompt ){
    printf("%s",zPrompt);
    fflush(stdout);
  }
  nLine = 100;
  zLine = malloc( nLine );
  if( zLine==0 ) return 0;
  n = 0;
  while( 1 ){
    if( n+100>nLine ){
      nLine = nLine*2 + 100;
      zLine = realloc(zLine, nLine);
      if( zLine==0 ) return 0;
    }
    if( fgets(&zLine[n], nLine - n, in)==0 ){
      if( n==0 ){
        free(zLine);
        return 0;
      }
      zLine[n] = 0;
      break;
    }
    while( zLine[n] ){
    while( zLine[n] ) n++;
      if( zLine[n]=='"' ) inQuote = !inQuote;
      n++;
    }
    if( n>0 && zLine[n-1]=='\n' && (!inQuote || !csvFlag) ){
    if( n>0 && zLine[n-1]=='\n' ){
      n--;
      if( n>0 && zLine[n-1]=='\r' ) n--;
      zLine[n] = 0;
      break;
    }
  }
  zLine = realloc( zLine, n+1 );
  return zLine;
}

/*
** Retrieve a single line of input text.
**
** zPrior is a string of prior text retrieved.  If not the empty
** string, then issue a continuation prompt.
** If in==0 then read from standard input and prompt before each line.
** If isContinuation is true, then a continuation prompt is appropriate.
** If isContinuation is zero, then the main prompt should be used.
**
** If zPrior is not NULL then it is a buffer from a prior call to this
** routine that can be reused.
**
** The result is stored in space obtained from malloc() and must either
** be freed by the caller or else passed back into this routine via the
** zPrior argument for reuse.
*/
static char *one_input_line(const char *zPrior, FILE *in){
static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
  char *zPrompt;
  char *zResult;
  if( in!=0 ){
    return local_getline(0, in, 0);
    zResult = local_getline(zPrior, in);
  }
  if( zPrior && zPrior[0] ){
    zPrompt = continuePrompt;
  }else{
    zPrompt = mainPrompt;
    zPrompt = isContinuation ? continuePrompt : mainPrompt;
  }
  zResult = readline(zPrompt);
#if defined(HAVE_READLINE) && HAVE_READLINE==1
    free(zPrior);
    zResult = readline(zPrompt);
  if( zResult && *zResult ) add_history(zResult);
    if( zResult && *zResult ) add_history(zResult);
#else
    printf("%s", zPrompt);
    fflush(stdout);
    zResult = local_getline(zPrior, stdin);
#endif
  }
  return zResult;
}

struct previous_mode_data {
  int valid;        /* Is there legit data in here? */
  int mode;
  int showHeader;
1718
1719
1720
1721
1722
1723
1724
1725

1726
1727
1728
1729
1730
1731
1732
1713
1714
1715
1716
1717
1718
1719

1720
1721
1722
1723
1724
1725
1726
1727







-
+







        if( pc==cQuote ){
          pc = 0;
          continue;
        }
      }
      if( (c==cSep && pc==cQuote)
       || (c=='\n' && pc==cQuote)
       || (c=='\n' && pc=='\r' && p->n>2 && p->z[p->n-2]==cQuote)
       || (c=='\n' && pc=='\r' && p->n>=2 && p->z[p->n-2]==cQuote)
       || (c==EOF && pc==cQuote)
      ){
        do{ p->n--; }while( p->z[p->n]!=cQuote );
        p->cTerm = c;
        break;
      }
      if( pc==cQuote && c!='\r' ){
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000







+







  if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){
    char *zTable = azArg[2];    /* Insert data into this table */
    char *zFile = azArg[1];     /* Name of file to extra content from */
    sqlite3_stmt *pStmt = NULL; /* A statement */
    int nCol;                   /* Number of columns in the table */
    int nByte;                  /* Number of bytes in an SQL string */
    int i, j;                   /* Loop counters */
    int needCommit;             /* True to COMMIT or ROLLBACK at end */
    int nSep;                   /* Number of bytes in p->separator[] */
    char *zSql;                 /* An SQL statement */
    CSVReader sCsv;             /* Reader context */
    int (*xCloser)(FILE*);      /* Procedure to close th3 connection */

    seenInterrupt = 0;
    memset(&sCsv, 0, sizeof(sCsv));
2092
2093
2094
2095
2096
2097
2098


2099
2100
2101
2102
2103
2104
2105
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103







+
+







    sqlite3_free(zSql);
    if( rc ){
      fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
      if (pStmt) sqlite3_finalize(pStmt);
      xCloser(sCsv.in);
      return 1;
    }
    needCommit = sqlite3_get_autocommit(db);
    if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
    do{
      int startLine = sCsv.nLine;
      for(i=0; i<nCol; i++){
        char *z = csv_read_one_field(&sCsv);
        if( z==0 && i==0 ) break;
        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
        if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){
2128
2129
2130
2131
2132
2133
2134
2135

2136
2137
2138
2139
2140
2141
2142
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138
2139
2140







-
+







        }
      }
    }while( sCsv.cTerm!=EOF );

    xCloser(sCsv.in);
    sqlite3_free(sCsv.z);
    sqlite3_finalize(pStmt);
    sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
    if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
  }else

  if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
    struct callback_data data;
    char *zErrMsg = 0;
    open_db(p);
    memcpy(&data, p, sizeof(data));
2777
2778
2779
2780
2781
2782
2783
2784

2785
2786
2787
2788
2789
2790
2791
2775
2776
2777
2778
2779
2780
2781

2782
2783
2784
2785
2786
2787
2788
2789







-
+







  return rc;
}

/*
** Return TRUE if a semicolon occurs anywhere in the first N characters
** of string z[].
*/
static int _contains_semicolon(const char *z, int N){
static int line_contains_semicolon(const char *z, int N){
  int i;
  for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }
  return 0;
}

/*
** Test to see if a line consists entirely of whitespace.
2812
2813
2814
2815
2816
2817
2818
2819

2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835

2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863











2864
2865
2866
2867
2868

2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879

2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890

2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
















2906

2907
2908
2909
2910
2911
2912
2913
2914
2915
2916


2917
2918

2919
2920
2921
2922
2923
2924
2925
2810
2811
2812
2813
2814
2815
2816

2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832

2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852









2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866


2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877

2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888

2889
2890
2891













2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907

2908
2909






2910


2911
2912
2913

2914
2915
2916
2917
2918
2919
2920
2921







-
+















-
+



















-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+



-
-
+










-
+










-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

-
-
-
-
-
-

-
-
+
+

-
+







}

/*
** Return TRUE if the line typed in is an SQL command terminator other
** than a semi-colon.  The SQL Server style "go" command is understood
** as is the Oracle "/".
*/
static int _is_command_terminator(const char *zLine){
static int line_is_command_terminator(const char *zLine){
  while( IsSpace(zLine[0]) ){ zLine++; };
  if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
    return 1;  /* Oracle */
  }
  if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
         && _all_whitespace(&zLine[2]) ){
    return 1;  /* SQL Server */
  }
  return 0;
}

/*
** Return true if zSql is a complete SQL statement.  Return false if it
** ends in the middle of a string literal or C-style comment.
*/
static int _is_complete(char *zSql, int nSql){
static int line_is_complete(char *zSql, int nSql){
  int rc;
  if( zSql==0 ) return 1;
  zSql[nSql] = ';';
  zSql[nSql+1] = 0;
  rc = sqlite3_complete(zSql);
  zSql[nSql] = 0;
  return rc;
}

/*
** Read input from *in and process it.  If *in==0 then input
** is interactive - the user is typing it it.  Otherwise, input
** is coming from a file or device.  A prompt is issued and history
** is saved only if input is interactive.  An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
**
** Return the number of errors.
*/
static int process_input(struct callback_data *p, FILE *in){
  char *zLine = 0;
  char *zSql = 0;
  int nSql = 0;
  int nSqlPrior = 0;
  char *zErrMsg;
  int rc;
  int errCnt = 0;
  int lineno = 0;
  int startline = 0;
  char *zLine = 0;          /* A single input line */
  char *zSql = 0;           /* Accumulated SQL text */
  int nLine;                /* Length of current line */
  int nSql = 0;             /* Bytes of zSql[] used */
  int nAlloc = 0;           /* Allocated zSql[] space */
  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
  char *zErrMsg;            /* Error message returned */
  int rc;                   /* Error code */
  int errCnt = 0;           /* Number of errors seen */
  int lineno = 0;           /* Current line number */
  int startline = 0;        /* Line number for start of current input */

  while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
    fflush(p->out);
    free(zLine);
    zLine = one_input_line(zSql, in);
    zLine = one_input_line(in, zLine, nSql>0);
    if( zLine==0 ){
      /* End of input */
      if( stdin_is_interactive ) printf("\n");
      break;
    }
    if( seenInterrupt ){
      if( in!=0 ) break;
      seenInterrupt = 0;
    }
    lineno++;
    if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
    if( nSql==0 && _all_whitespace(zLine) ) continue;
    if( zLine && zLine[0]=='.' && nSql==0 ){
      if( p->echoOn ) printf("%s\n", zLine);
      rc = do_meta_command(zLine, p);
      if( rc==2 ){ /* exit requested */
        break;
      }else if( rc ){
        errCnt++;
      }
      continue;
    }
    if( _is_command_terminator(zLine) && _is_complete(zSql, nSql) ){
    if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
      memcpy(zLine,";",2);
    }
    nSqlPrior = nSql;
    if( zSql==0 ){
      int i;
      for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
      if( zLine[i]!=0 ){
        nSql = strlen30(zLine);
        zSql = malloc( nSql+3 );
        if( zSql==0 ){
          fprintf(stderr, "Error: out of memory\n");
          exit(1);
        }
        memcpy(zSql, zLine, nSql+1);
        startline = lineno;
    nLine = strlen30(zLine);
    if( nSql+nLine+2>=nAlloc ){
      nAlloc = nSql+nLine+100;
      zSql = realloc(zSql, nAlloc);
      if( zSql==0 ){
        fprintf(stderr, "Error: out of memory\n");
        exit(1);
      }
    }
    nSqlPrior = nSql;
    if( nSql==0 ){
      int i;
      for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
      assert( nAlloc>0 && zSql!=0 );
      memcpy(zSql, zLine+i, nLine+1-i);
      startline = lineno;
      }
      nSql = nLine-i;
    }else{
      int len = strlen30(zLine);
      zSql = realloc( zSql, nSql + len + 4 );
      if( zSql==0 ){
        fprintf(stderr,"Error: out of memory\n");
        exit(1);
      }
      zSql[nSql++] = '\n';
      memcpy(&zSql[nSql], zLine, len+1);
      nSql += len;
      memcpy(zSql+nSql, zLine, nLine+1);
      nSql += nLine;
    }
    if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
    if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
                && sqlite3_complete(zSql) ){
      p->cnt = 0;
      open_db(p);
      BEGIN_TIMER;
      rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
      END_TIMER;
      if( rc || zErrMsg ){
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949
2950
2951

2952
2953
2954
2955
2956
2957
2958
2931
2932
2933
2934
2935
2936
2937


2938

2939


2940
2941
2942

2943
2944
2945
2946
2947
2948
2949
2950







-
-

-
+
-
-



-
+







          sqlite3_free(zErrMsg);
          zErrMsg = 0;
        }else{
          fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
        }
        errCnt++;
      }
      free(zSql);
      zSql = 0;
      nSql = 0;
    }else if( zSql && _all_whitespace(zSql) ){
    }else if( nSql && _all_whitespace(zSql) ){
      free(zSql);
      zSql = 0;
      nSql = 0;
    }
  }
  if( zSql ){
  if( nSql ){
    if( !_all_whitespace(zSql) ){
      fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
    }
    free(zSql);
  }
  free(zLine);
  return errCnt>0;
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3184
3185
3186
3187
3188
3189
3190

3191
3192
3193
3194
3195
3196
3197







-







      /* Need to check for batch mode here to so we can avoid printing
      ** informational messages (like from process_sqliterc) before 
      ** we do the actual processing of arguments later in a second pass.
      */
      stdin_is_interactive = 0;
    }else if( strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      int j, c;
      const char *zSize;
      sqlite3_int64 szHeap;

      zSize = cmdline_option_value(argc, argv, ++i);
      szHeap = integerValue(zSize);
      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
Changes to src/sqlite3.c.
1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.8.0.  By combining all the individual C code files into this 
** version 3.8.1.  By combining all the individual C code files into this 
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other
652
653
654
655
656
657
658
659
660
661



662
663
664
665
666
667
668
652
653
654
655
656
657
658



659
660
661
662
663
664
665
666
667
668







-
-
-
+
+
+







** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.0"
#define SQLITE_VERSION_NUMBER 3008000
#define SQLITE_SOURCE_ID      "2013-08-06 07:45:08 924f7e4d7a8fa2fe9100836663f3733b6e1a9084"
#define SQLITE_VERSION        "3.8.1"
#define SQLITE_VERSION_NUMBER 3008001
#define SQLITE_SOURCE_ID      "2013-08-30 06:20:23 d9c018f8155ab48df8e0e02519bba50588fe49fc"

/*
** 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
7778
7779
7780
7781
7782
7783
7784
7785

7786
7787
7788
7789
7790
7791
7792
7778
7779
7780
7781
7782
7783
7784

7785
7786
7787
7788
7789
7790
7791
7792







-
+







#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#if 0
}  /* End of the 'extern "C"' block */
#endif
#endif
#endif /* _SQLITE3_H_ */

/*
** 2010 August 30
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
8366
8367
8368
8369
8370
8371
8372














8373
8374
8375
8376
8377
8378
8379
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393







+
+
+
+
+
+
+
+
+
+
+
+
+
+







# define SQLITE_DEFAULT_MMAP_SIZE_xc 1  /* Exclude from ctime.c */
#endif
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
# undef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
#endif

/*
** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
** Priority is given to SQLITE_ENABLE_STAT4.  If either are defined, also
** define SQLITE_ENABLE_STAT3_OR_STAT4
*/
#ifdef SQLITE_ENABLE_STAT4
# undef SQLITE_ENABLE_STAT3
# define SQLITE_ENABLE_STAT3_OR_STAT4 1
#elif SQLITE_ENABLE_STAT3
# define SQLITE_ENABLE_STAT3_OR_STAT4 1
#elif SQLITE_ENABLE_STAT3_OR_STAT4
# undef SQLITE_ENABLE_STAT3_OR_STAT4
#endif

/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle. 
**
** The sqlite.busyHandler member of the sqlite struct contains the busy
** callback for the database handle. Each pager opened via the sqlite
** handle is passed a pointer to sqlite.busyHandler. The busy-handler
8585
8586
8587
8588
8589
8590
8591
8592

8593
8594
8595
8596
8597
8598
8599
8599
8600
8601
8602
8603
8604
8605

8606
8607
8608
8609
8610
8611
8612
8613







-
+







#define BTREE_MEMORY        2  /* This is an in-memory DB */
#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */

SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
9286
9287
9288
9289
9290
9291
9292
9293
9294














9295
9296
9297
9298
9299
9300
9301
9300
9301
9302
9303
9304
9305
9306


9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327







-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#define PAGER_JOURNALMODE_TRUNCATE    3   /* Commit by truncating journal */
#define PAGER_JOURNALMODE_MEMORY      4   /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL         5   /* Use write-ahead logging */

/*
** Flags that make up the mask passed to sqlite3PagerAcquire().
*/
#define PAGER_ACQUIRE_NOCONTENT     0x01  /* Do not load data from disk */
#define PAGER_ACQUIRE_READONLY      0x02  /* Read-only page is acceptable */
#define PAGER_GET_NOCONTENT     0x01  /* Do not load data from disk */
#define PAGER_GET_READONLY      0x02  /* Read-only page is acceptable */

/*
** Flags for sqlite3PagerSetFlags()
*/
#define PAGER_SYNCHRONOUS_OFF       0x01  /* PRAGMA synchronous=OFF */
#define PAGER_SYNCHRONOUS_NORMAL    0x02  /* PRAGMA synchronous=NORMAL */
#define PAGER_SYNCHRONOUS_FULL      0x03  /* PRAGMA synchronous=FULL */
#define PAGER_SYNCHRONOUS_MASK      0x03  /* Mask for three values above */
#define PAGER_FULLFSYNC             0x04  /* PRAGMA fullfsync=ON */
#define PAGER_CKPT_FULLFSYNC        0x08  /* PRAGMA checkpoint_fullfsync=ON */
#define PAGER_CACHESPILL            0x10  /* PRAGMA cache_spill=ON */
#define PAGER_FLAGS_MASK            0x1c  /* All above except SYNCHRONOUS */

/*
** The remainder of this file contains the declarations of the functions
** that make up the Pager sub-system API. See source code comments for 
** a detailed description of each routine.
*/

9315
9316
9317
9318
9319
9320
9321
9322

9323
9324
9325
9326
9327
9328
9329
9341
9342
9343
9344
9345
9346
9347

9348
9349
9350
9351
9352
9353
9354
9355







-
+







/* Functions used to configure a Pager object. */
SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned);
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*);
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*);

10178
10179
10180
10181
10182
10183
10184



10185
10186
10187



10188
10189
10190

10191
10192
10193
10194
10195
10196
10197
10198







10199
10200
10201
10202
10203
10204
10205
10206
10207
10208
10209
10210










10211
10212
10213
10214
10215
10216
10217
10204
10205
10206
10207
10208
10209
10210
10211
10212
10213



10214
10215
10216
10217
10218

10219
10220







10221
10222
10223
10224
10225
10226
10227












10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244







+
+
+
-
-
-
+
+
+


-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+







#define ENC(db) ((db)->aDb[0].pSchema->enc)

/*
** Possible values for the sqlite3.flags.
*/
#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
#define SQLITE_InternChanges  0x00000002  /* Uncommitted Hash table changes */
#define SQLITE_FullFSync      0x00000004  /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync  0x00000008  /* Use full fsync for checkpoint */
#define SQLITE_CacheSpill     0x00000010  /* OK to spill pager cache */
#define SQLITE_FullColNames   0x00000004  /* Show full column names on SELECT */
#define SQLITE_ShortColNames  0x00000008  /* Show short columns names */
#define SQLITE_CountRows      0x00000010  /* Count rows changed by INSERT, */
#define SQLITE_FullColNames   0x00000020  /* Show full column names on SELECT */
#define SQLITE_ShortColNames  0x00000040  /* Show short columns names */
#define SQLITE_CountRows      0x00000080  /* Count rows changed by INSERT, */
                                          /*   DELETE, or UPDATE and return */
                                          /*   the count using a callback. */
#define SQLITE_NullCallback   0x00000020  /* Invoke the callback once if the */
#define SQLITE_NullCallback   0x00000100  /* Invoke the callback once if the */
                                          /*   result set is empty */
#define SQLITE_SqlTrace       0x00000040  /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    0x00000080  /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema    0x00000100  /* OK to update SQLITE_MASTER */
#define SQLITE_VdbeAddopTrace 0x00000200  /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_IgnoreChecks   0x00000400  /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0000800  /* For shared-cache mode */
#define SQLITE_LegacyFileFmt  0x00001000  /* Create new databases in format 1 */
#define SQLITE_SqlTrace       0x00000200  /* Debug print SQL as it executes */
#define SQLITE_VdbeListing    0x00000400  /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema    0x00000800  /* OK to update SQLITE_MASTER */
#define SQLITE_VdbeAddopTrace 0x00001000  /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_IgnoreChecks   0x00002000  /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0004000  /* For shared-cache mode */
#define SQLITE_LegacyFileFmt  0x00008000  /* Create new databases in format 1 */
#define SQLITE_FullFSync      0x00002000  /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync  0x00004000  /* Use full fsync for checkpoint */
#define SQLITE_RecoveryMode   0x00008000  /* Ignore schema errors */
#define SQLITE_ReverseOrder   0x00010000  /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers    0x00020000  /* Enable recursive triggers */
#define SQLITE_ForeignKeys    0x00040000  /* Enforce foreign key constraints  */
#define SQLITE_AutoIndex      0x00080000  /* Enable automatic indexes */
#define SQLITE_PreferBuiltin  0x00100000  /* Preference to built-in funcs */
#define SQLITE_LoadExtension  0x00200000  /* Enable load_extension */
#define SQLITE_EnableTrigger  0x00400000  /* True to enable triggers */
#define SQLITE_DeferFKs       0x00800000  /* Defer all FK constraints */
#define SQLITE_QueryOnly      0x01000000  /* Disable database changes */
#define SQLITE_RecoveryMode   0x00010000  /* Ignore schema errors */
#define SQLITE_ReverseOrder   0x00020000  /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers    0x00040000  /* Enable recursive triggers */
#define SQLITE_ForeignKeys    0x00080000  /* Enforce foreign key constraints  */
#define SQLITE_AutoIndex      0x00100000  /* Enable automatic indexes */
#define SQLITE_PreferBuiltin  0x00200000  /* Preference to built-in funcs */
#define SQLITE_LoadExtension  0x00400000  /* Enable load_extension */
#define SQLITE_EnableTrigger  0x00800000  /* True to enable triggers */
#define SQLITE_DeferFKs       0x01000000  /* Defer all FK constraints */
#define SQLITE_QueryOnly      0x02000000  /* Disable database changes */


/*
** Bits of the sqlite3.dbOptFlags field that are used by the
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
*/
10755
10756
10757
10758
10759
10760
10761
10762

10763

10764

10765
10766
10767
10768
10769
10770
10771
10772
10773
10774
10775
10776
10777
10778

10779
10780

10781
10782
10783
10784



10785
10786
10787
10788
10789
10790
10791
10782
10783
10784
10785
10786
10787
10788

10789
10790
10791

10792
10793
10794
10795
10796
10797
10798
10799
10800
10801
10802




10803


10804




10805
10806
10807
10808
10809
10810
10811
10812
10813
10814







-
+

+
-
+










-
-
-
-
+
-
-
+
-
-
-
-
+
+
+







  Expr *pPartIdxWhere;     /* WHERE clause for partial indices */
  int tnum;                /* DB Page containing root of this index */
  u16 nColumn;             /* Number of columns in table used by this index */
  u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  unsigned autoIndex:2;    /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
  unsigned uniqNotNull:1;  /* True if UNIQUE and NOT NULL for all columns */
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int nSample;             /* Number of elements in aSample[] */
  int nSampleCol;          /* Size of IndexSample.anEq[] and so on */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  tRowcnt *aAvgEq;         /* Average nEq values for keys not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};

/*
** Each sample stored in the sqlite_stat3 table is represented in memory 
** using a structure of this type.  See documentation at the top of the
** analyze.c source file for additional information.
*/
struct IndexSample {
  union {
    char *z;        /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
    double r;       /* Value if eType is SQLITE_FLOAT */
    i64 i;          /* Value if eType is SQLITE_INTEGER */
  void *p;          /* Pointer to sampled record */
  } u;
  u8 eType;         /* SQLITE_NULL, SQLITE_INTEGER ... etc. */
  int n;            /* Size of record in bytes */
  int nByte;        /* Size in byte of text or blob. */
  tRowcnt nEq;      /* Est. number of rows where the key equals this sample */
  tRowcnt nLt;      /* Est. number of rows where key is less than this sample */
  tRowcnt nDLt;     /* Est. number of distinct keys less than this sample */
  tRowcnt *anEq;    /* Est. number of rows where the key equals this sample */
  tRowcnt *anLt;    /* Est. number of rows where key is less than this sample */
  tRowcnt *anDLt;   /* Est. number of distinct keys less than this sample */
};

/*
** Each token coming out of the lexer is an instance of
** this structure.  Tokens are also used as part of an expression.
**
** Note if Token.z==0 then Token.dyn and Token.n are undefined and
11212
11213
11214
11215
11216
11217
11218
11219

11220
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236

11237
11238
11239
11240
11241
11242
11243
11235
11236
11237
11238
11239
11240
11241

11242
11243
11244
11245
11246
11247
11248
11249
11250
11251
11252
11253
11254
11255
11256



11257
11258
11259
11260
11261
11262
11263
11264







-
+














-
-
-
+







** NameContext in the parent query.  Thus the process of scanning the
** NameContext list corresponds to searching through successively outer
** subqueries looking for a match.
*/
struct NameContext {
  Parse *pParse;       /* The parser */
  SrcList *pSrcList;   /* One or more tables used to resolve names */
  ExprList *pEList;    /* Optional list of named expressions */
  ExprList *pEList;    /* Optional list of result-set columns */
  AggInfo *pAggInfo;   /* Information about aggregates at this level */
  NameContext *pNext;  /* Next outer name context.  NULL for outermost */
  int nRef;            /* Number of names resolved by this context */
  int nErr;            /* Number of errors encountered while resolving names */
  u8 ncFlags;          /* Zero or more NC_* flags defined below */
};

/*
** Allowed values for the NameContext, ncFlags field.
*/
#define NC_AllowAgg  0x01    /* Aggregate functions are allowed here */
#define NC_HasAgg    0x02    /* One or more aggregate functions seen */
#define NC_IsCheck   0x04    /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x08    /* True if analyzing arguments to an agg func */
#define NC_AsMaybe   0x10    /* Resolve to AS terms of the result set only
                             ** if no other resolution is available */
#define NC_PartIdx   0x20    /* True if resolving a partial index WHERE */
#define NC_PartIdx   0x10    /* True if resolving a partial index WHERE */

/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641

11642


11643
11644
11645
11646
11647
11648
11649
11653
11654
11655
11656
11657
11658
11659

11660

11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671







-

-
+

+
+







struct StrAccum {
  sqlite3 *db;         /* Optional database for lookaside.  Can be NULL */
  char *zBase;         /* A base allocation.  Not from malloc. */
  char *zText;         /* The string collected so far */
  int  nChar;          /* Length of the string so far */
  int  nAlloc;         /* Amount of space allocated in zText */
  int  mxAlloc;        /* Maximum allowed string length */
  u8   mallocFailed;   /* Becomes true if any memory allocation fails */
  u8   useMalloc;      /* 0: none,  1: sqlite3DbMalloc,  2: sqlite3_malloc */
  u8   tooBig;         /* Becomes true if string size exceeds limits */
  u8   accError;       /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
};
#define STRACCUM_NOMEM   1
#define STRACCUM_TOOBIG  2

/*
** A pointer to this structure is used to communicate information
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12272
12273
12274
12275
12276
12277
12278



12279
12280
12281
12282
12283
12284
12285







-
-
-







SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, 
                        void(*)(void*));
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
#ifdef SQLITE_ENABLE_STAT3
SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
#endif
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
SQLITE_PRIVATE const Token sqlite3IntTokens[];
12319
12320
12321
12322
12323
12324
12325






12326
12327
12328
12329
12330
12331
12332
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357







+
+
+
+
+
+







SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*);
SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int);
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);

SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *);
SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void);
SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*);
SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*);
#endif

/*
** The interface to the LEMON-generated parser
*/
SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(size_t));
SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
12360
12361
12362
12363
12364
12365
12366
12367

12368
12369
12370
12371
12372
12373

12374
12375
12376
12377
12378
12379
12380
12385
12386
12387
12388
12389
12390
12391

12392
12393
12394
12395
12396
12397
12398
12399
12400
12401
12402
12403
12404
12405
12406







-
+






+







#  define sqlite3VtabUnlock(X)
#  define sqlite3VtabUnlockList(X)
#  define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
#  define sqlite3GetVTable(X,Y)  ((VTable*)0)
#else
SQLITE_PRIVATE    void sqlite3VtabClear(sqlite3 *db, Table*);
SQLITE_PRIVATE    void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
SQLITE_PRIVATE    int sqlite3VtabSync(sqlite3 *db, char **);
SQLITE_PRIVATE    int sqlite3VtabSync(sqlite3 *db, Vdbe*);
SQLITE_PRIVATE    int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE    int sqlite3VtabCommit(sqlite3 *db);
SQLITE_PRIVATE    void sqlite3VtabLock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE    int sqlite3VtabSavepoint(sqlite3 *, int, int);
SQLITE_PRIVATE    void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
SQLITE_PRIVATE    VTable *sqlite3GetVTable(sqlite3*, Table*);
#  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*);
12901
12902
12903
12904
12905
12906
12907


12908

12909
12910
12911
12912
12913
12914
12915
12927
12928
12929
12930
12931
12932
12933
12934
12935

12936
12937
12938
12939
12940
12941
12942
12943







+
+
-
+







#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#ifdef SQLITE_ENABLE_RTREE
  "ENABLE_RTREE",
#endif
#if defined(SQLITE_ENABLE_STAT4)
  "ENABLE_STAT4",
#ifdef SQLITE_ENABLE_STAT3
#elif defined(SQLITE_ENABLE_STAT3)
  "ENABLE_STAT3",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  "ENABLE_UNLOCK_NOTIFY",
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
  "ENABLE_UPDATE_DELETE_LIMIT",
13473
13474
13475
13476
13477
13478
13479


13480
13481
13482


13483
13484
13485
13486
13487
13488
13489
13490
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510


13511
13512

13513
13514
13515
13516
13517
13518
13519







+
+

-
-
+
+
-







** (Mem) which are only defined there.
*/
struct sqlite3_context {
  FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
  Mem s;                /* The return value is stored here */
  Mem *pMem;            /* Memory cell used to store aggregate context */
  CollSeq *pColl;       /* Collating sequence */
  Vdbe *pVdbe;          /* The VM that owns this context */
  int iOp;              /* Instruction number of OP_Function */
  int isError;          /* Error code returned by the function. */
  int skipFlag;         /* Skip skip accumulator loading if true */
  int iOp;              /* Instruction number of OP_Function */
  u8 skipFlag;          /* Skip skip accumulator loading if true */
  u8 fErrorOrAux;       /* isError!=0 or pVdbe->pAuxData modified */
  Vdbe *pVdbe;          /* The VM that owns this context */
};

/*
** An Explain object accumulates indented output which is helpful
** in describing recursive data structures.
*/
struct Explain {
13552
13553
13554
13555
13556
13557
13558
13559

13560
13561
13562
13563
13564
13565
13566
13581
13582
13583
13584
13585
13586
13587

13588
13589
13590
13591
13592
13593
13594
13595







-
+







  bft bIsReader:1;        /* True for statements that read */
  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
  bft doingRerun:1;       /* True if rerunning after an auto-reprepare */
  int nChange;            /* Number of db changes made since last reset */
  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
  int iStatement;         /* Statement number (or 0 if has not opened stmt) */
  int aCounter[4];        /* Counters used by sqlite3_stmt_status() */
  u32 aCounter[5];        /* Counters used by sqlite3_stmt_status() */
#ifndef SQLITE_OMIT_TRACE
  i64 startTime;          /* Time when query started - used for profiling */
#endif
  i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
  i64 nStmtDefCons;       /* Number of def. constraints when stmt started */
  i64 nStmtDefImmCons;    /* Number of def. imm constraints when stmt started */
  char *zSql;             /* Text of the SQL statement that generated this */
16059
16060
16061
16062
16063
16064
16065
16066

16067
16068
16069
16070
16071
16072
16073
16088
16089
16090
16091
16092
16093
16094

16095
16096
16097
16098
16099
16100
16101
16102







-
+







*/
static int sqlite3MemSize(void *p){
  struct MemBlockHdr *pHdr;
  if( !p ){
    return 0;
  }
  pHdr = sqlite3MemsysGetHeader(p);
  return pHdr->iSize;
  return (int)pHdr->iSize;
}

/*
** Initialize the memory allocation subsystem.
*/
static int sqlite3MemInit(void *NotUsed){
  UNUSED_PARAMETER(NotUsed);
16101
16102
16103
16104
16105
16106
16107
16108

16109
16110
16111
16112
16113
16114
16115
16116

16117
16118
16119
16120
16121
16122
16123
16130
16131
16132
16133
16134
16135
16136

16137
16138
16139
16140
16141
16142
16143
16144

16145
16146
16147
16148
16149
16150
16151
16152







-
+







-
+







** to clear the content of a freed allocation to unpredictable values.
*/
static void randomFill(char *pBuf, int nByte){
  unsigned int x, y, r;
  x = SQLITE_PTR_TO_INT(pBuf);
  y = nByte | 1;
  while( nByte >= 4 ){
    x = (x>>1) ^ (-(x&1) & 0xd0000001);
    x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
    y = y*1103515245 + 12345;
    r = x ^ y;
    *(int*)pBuf = r;
    pBuf += 4;
    nByte -= 4;
  }
  while( nByte-- > 0 ){
    x = (x>>1) ^ (-(x&1) & 0xd0000001);
    x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
    y = y*1103515245 + 12345;
    r = x ^ y;
    *(pBuf++) = r & 0xff;
  }
}

/*
16204
16205
16206
16207
16208
16209
16210
16211

16212
16213

16214
16215
16216
16217
16218
16219
16220
16233
16234
16235
16236
16237
16238
16239

16240
16241

16242
16243
16244
16245
16246
16247
16248
16249







-
+

-
+







    pHdr->pNext->pPrev = pHdr->pPrev;
  }else{
    assert( mem.pLast==pHdr );
    mem.pLast = pHdr->pPrev;
  }
  z = (char*)pBt;
  z -= pHdr->nTitle;
  adjustStats(pHdr->iSize, -1);
  adjustStats((int)pHdr->iSize, -1);
  randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
                pHdr->iSize + sizeof(int) + pHdr->nTitle);
                (int)pHdr->iSize + sizeof(int) + pHdr->nTitle);
  free(z);
  sqlite3_mutex_leave(mem.mutex);  
}

/*
** Change the size of an existing memory allocation.
**
16230
16231
16232
16233
16234
16235
16236
16237

16238
16239
16240
16241
16242
16243
16244
16259
16260
16261
16262
16263
16264
16265

16266
16267
16268
16269
16270
16271
16272
16273







-
+







  assert( mem.disallow==0 );
  assert( (nByte & 7)==0 );     /* EV: R-46199-30249 */
  pOldHdr = sqlite3MemsysGetHeader(pPrior);
  pNew = sqlite3MemMalloc(nByte);
  if( pNew ){
    memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
    if( nByte>pOldHdr->iSize ){
      randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
      randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize);
    }
    sqlite3MemFree(pPrior);
  }
  return pNew;
}

/*
16345
16346
16347
16348
16349
16350
16351
16352

16353
16354
16355
16356
16357
16358
16359
16374
16375
16376
16377
16378
16379
16380

16381
16382
16383
16384
16385
16386
16387
16388







-
+







}

SQLITE_PRIVATE void sqlite3MemdebugSync(){
  struct MemBlockHdr *pHdr;
  for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
    void **pBt = (void**)pHdr;
    pBt -= pHdr->nBacktraceSlots;
    mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
    mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
  }
}

/*
** Open the file indicated and write a log of all unfreed memory 
** allocations into that log.
*/
17229
17230
17231
17232
17233
17234
17235
17236

17237
17238
17239
17240
17241
17242

17243
17244
17245
17246
17247
17248
17249
17258
17259
17260
17261
17262
17263
17264

17265
17266
17267
17268
17269
17270

17271
17272
17273
17274
17275
17276
17277
17278







-
+





-
+







  ** of each block.  One byte per block.
  */
  u8 *aCtrl;

} mem5;

/*
** Access the static variable through a macro for SQLITE_OMIT_WSD
** Access the static variable through a macro for SQLITE_OMIT_WSD.
*/
#define mem5 GLOBAL(struct Mem5Global, mem5)

/*
** Assuming mem5.zPool is divided up into an array of Mem5Link
** structures, return a pointer to the idx-th such lik.
** structures, return a pointer to the idx-th such link.
*/
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))

/*
** Unlink the chunk at mem5.aPool[i] from list it is currently
** on.  It should be found on mem5.aiFreelist[iLogsize].
*/
17331
17332
17333
17334
17335
17336
17337
17338

17339
17340
17341
17342
17343
17344
17345
17360
17361
17362
17363
17364
17365
17366

17367
17368
17369
17370
17371
17372
17373
17374







-
+







  return iFirst;
}

/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable.  Return NULL if nBytes==0.
**
** The caller guarantees that nByte positive.
** The caller guarantees that nByte is positive.
**
** The caller has obtained a mutex prior to invoking this
** routine so there is never any chance that two or more
** threads can be in this routine at the same time.
*/
static void *memsys5MallocUnsafe(int nByte){
  int i;           /* Index of a mem5.aPool[] slot */
17453
17454
17455
17456
17457
17458
17459
17460

17461
17462
17463
17464
17465
17466
17467
17482
17483
17484
17485
17486
17487
17488

17489
17490
17491
17492
17493
17494
17495
17496







-
+







    }
    size *= 2;
  }
  memsys5Link(iBlock, iLogsize);
}

/*
** Allocate nBytes of memory
** Allocate nBytes of memory.
*/
static void *memsys5Malloc(int nBytes){
  sqlite3_int64 *p = 0;
  if( nBytes>0 ){
    memsys5Enter();
    p = memsys5MallocUnsafe(nBytes);
    memsys5Leave();
18467
18468
18469
18470
18471
18472
18473
18474

18475
18476
18477
18478
18479
18480
18481
18496
18497
18498
18499
18500
18501
18502

18503
18504
18505
18506
18507
18508
18509
18510







-
+







      OSVERSIONINFO sInfo;
      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
      GetVersionEx(&sInfo);
      osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return osType==2;
  }
#endif /* SQLITE_OS_WINCE */
#endif /* SQLITE_OS_WINCE || SQLITE_OS_WINRT */
#endif

#ifdef SQLITE_DEBUG
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use only inside assert() statements.
*/
18505
18506
18507
18508
18509
18510
18511
18512

18513
18514
18515
18516
18517
18518
18519
18534
18535
18536
18537
18538
18539
18540

18541
18542
18543
18544
18545
18546
18547
18548







-
+







};
static int winMutex_isInit = 0;
/* As winMutexInit() and winMutexEnd() are called as part
** of the sqlite3_initialize and sqlite3_shutdown()
** processing, the "interlocked" magic is probably not
** strictly necessary.
*/
static long winMutex_lock = 0;
static LONG winMutex_lock = 0;

SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */

static int winMutexInit(void){ 
  /* The first to increment to 1 does actual initialization */
  if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
    int i;
19885
19886
19887
19888
19889
19890
19891
19892

19893
19894
19895
19896
19897
19898
19899
19914
19915
19916
19917
19918
19919
19920

19921
19922
19923
19924
19925
19926
19927
19928







-
+







        if( precision<etBUFSIZE-10 ){
          nOut = etBUFSIZE;
          zOut = buf;
        }else{
          nOut = precision + 10;
          zOut = zExtra = sqlite3Malloc( nOut );
          if( zOut==0 ){
            pAccum->mallocFailed = 1;
            pAccum->accError = STRACCUM_NOMEM;
            return;
          }
        }
        bufpt = &zOut[nOut-1];
        if( xtype==etORDINAL ){
          static const char zOrd[] = "thstndrd";
          int x = (int)(longvalue % 10);
19997
19998
19999
20000
20001
20002
20003
20004

20005
20006
20007
20008
20009
20010
20011
20026
20027
20028
20029
20030
20031
20032

20033
20034
20035
20036
20037
20038
20039
20040







-
+







          e2 = 0;
        }else{
          e2 = exp;
        }
        if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
          bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
          if( bufpt==0 ){
            pAccum->mallocFailed = 1;
            pAccum->accError = STRACCUM_NOMEM;
            return;
          }
        }
        zOut = bufpt;
        nsd = 16 + flag_altform2*10;
        flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
        /* The sign in front of the number */
20132
20133
20134
20135
20136
20137
20138
20139

20140
20141
20142
20143
20144
20145
20146
20161
20162
20163
20164
20165
20166
20167

20168
20169
20170
20171
20172
20173
20174
20175







-
+







          if( ch==q )  n++;
        }
        needQuote = !isnull && xtype==etSQLESCAPE2;
        n += i + 1 + needQuote*2;
        if( n>etBUFSIZE ){
          bufpt = zExtra = sqlite3Malloc( n );
          if( bufpt==0 ){
            pAccum->mallocFailed = 1;
            pAccum->accError = STRACCUM_NOMEM;
            return;
          }
        }else{
          bufpt = buf;
        }
        j = 0;
        if( needQuote ) bufpt[j++] = q;
20210
20211
20212
20213
20214
20215
20216
20217
20218
20219



20220
20221
20222
20223


20224
20225
20226
20227
20228
20229
20230
20231
20232

20233
20234
20235
20236
20237
20238
20239
20240
20241
20242
20243

20244
20245
20246
20247
20248
20249
20250
20251
20252
20253
20254
20255
20256
20257

20258
20259
20260
20261
20262
20263
20264
20239
20240
20241
20242
20243
20244
20245



20246
20247
20248
20249
20250
20251

20252
20253
20254
20255



20256
20257
20258

20259
20260
20261
20262
20263
20264
20265
20266
20267
20268
20269

20270
20271
20272
20273
20274
20275
20276
20277
20278
20279
20280
20281
20282
20283

20284
20285
20286
20287
20288
20289
20290
20291







-
-
-
+
+
+



-
+
+


-
-
-



-
+










-
+













-
+







} /* End of function */

/*
** Append N bytes of text from z to the StrAccum object.
*/
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
  assert( z!=0 || N==0 );
  if( p->tooBig | p->mallocFailed ){
    testcase(p->tooBig);
    testcase(p->mallocFailed);
  if( p->accError ){
    testcase(p->accError==STRACCUM_TOOBIG);
    testcase(p->accError==STRACCUM_NOMEM);
    return;
  }
  assert( p->zText!=0 || p->nChar==0 );
  if( N<0 ){
  if( N<=0 ){
    if( N==0 || z[0]==0 ) return;
    N = sqlite3Strlen30(z);
  }
  if( N==0 || NEVER(z==0) ){
    return;
  }
  if( p->nChar+N >= p->nAlloc ){
    char *zNew;
    if( !p->useMalloc ){
      p->tooBig = 1;
      p->accError = STRACCUM_TOOBIG;
      N = p->nAlloc - p->nChar - 1;
      if( N<=0 ){
        return;
      }
    }else{
      char *zOld = (p->zText==p->zBase ? 0 : p->zText);
      i64 szNew = p->nChar;
      szNew += N + 1;
      if( szNew > p->mxAlloc ){
        sqlite3StrAccumReset(p);
        p->tooBig = 1;
        p->accError = STRACCUM_TOOBIG;
        return;
      }else{
        p->nAlloc = (int)szNew;
      }
      if( p->useMalloc==1 ){
        zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
      }else{
        zNew = sqlite3_realloc(zOld, p->nAlloc);
      }
      if( zNew ){
        if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
        p->zText = zNew;
      }else{
        p->mallocFailed = 1;
        p->accError = STRACCUM_NOMEM;
        sqlite3StrAccumReset(p);
        return;
      }
    }
  }
  assert( p->zText );
  memcpy(&p->zText[p->nChar], z, N);
20278
20279
20280
20281
20282
20283
20284
20285

20286
20287
20288
20289
20290
20291
20292
20305
20306
20307
20308
20309
20310
20311

20312
20313
20314
20315
20316
20317
20318
20319







-
+







        p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
      }else{
        p->zText = sqlite3_malloc(p->nChar+1);
      }
      if( p->zText ){
        memcpy(p->zText, p->zBase, p->nChar+1);
      }else{
        p->mallocFailed = 1;
        p->accError = STRACCUM_NOMEM;
      }
    }
  }
  return p->zText;
}

/*
20309
20310
20311
20312
20313
20314
20315
20316

20317
20318
20319
20320
20321
20322
20323
20324
20325
20326
20327
20328
20329
20330
20331
20332
20333
20334

20335
20336
20337
20338
20339
20340
20341
20336
20337
20338
20339
20340
20341
20342

20343

20344
20345
20346
20347
20348
20349
20350
20351
20352
20353
20354
20355
20356
20357
20358
20359

20360
20361
20362
20363
20364
20365
20366
20367







-
+
-
















-
+







SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
  p->zText = p->zBase = zBase;
  p->db = 0;
  p->nChar = 0;
  p->nAlloc = n;
  p->mxAlloc = mx;
  p->useMalloc = 1;
  p->tooBig = 0;
  p->accError = 0;
  p->mallocFailed = 0;
}

/*
** Print into memory obtained from sqliteMalloc().  Use the internal
** %-conversion extensions.
*/
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
  char *z;
  char zBase[SQLITE_PRINT_BUF_SIZE];
  StrAccum acc;
  assert( db!=0 );
  sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
                      db->aLimit[SQLITE_LIMIT_LENGTH]);
  acc.db = db;
  sqlite3VXPrintf(&acc, 1, zFormat, ap);
  z = sqlite3StrAccumFinish(&acc);
  if( acc.mallocFailed ){
  if( acc.accError==STRACCUM_NOMEM ){
    db->mallocFailed = 1;
  }
  return z;
}

/*
** Print into memory obtained from sqliteMalloc().  Use the internal
20524
20525
20526
20527
20528
20529
20530
20531
20532
20533

20534
20535
20536
20537
20538
20539
20540
20541
20542
20543
20544
20545
20546

20547
20548

20549
20550
20551
20552
20553
20554
20555
20556
20557
20558
20559
20560
20561
20562




20563
20564
20565
20566
20567
20568
20569
20550
20551
20552
20553
20554
20555
20556



20557











20558

20559
20560

20561
20562
20563
20564
20565
20566
20567
20568
20569
20570
20571
20572
20573
20574
20575
20576
20577
20578
20579
20580
20581
20582
20583
20584
20585
20586







-
-
-
+
-
-
-
-
-
-
-
-
-
-
-

-
+

-
+














+
+
+
+







static SQLITE_WSD struct sqlite3PrngType {
  unsigned char isInit;          /* True if initialized */
  unsigned char i, j;            /* State variables */
  unsigned char s[256];          /* State variables */
} sqlite3Prng;

/*
** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
** must be held while executing this routine.
**
** Return N random bytes.
** Why not just use a library random generator like lrand48() for this?
** Because the OP_NewRowid opcode in the VDBE depends on having a very
** good source of random numbers.  The lrand48() library function may
** well be good enough.  But maybe not.  Or maybe lrand48() has some
** subtle problems on some systems that could cause problems.  It is hard
** to know.  To minimize the risk of problems due to bad lrand48()
** implementations, SQLite uses this random number generator based
** on RC4, which we know works very well.
**
** (Later):  Actually, OP_NewRowid does not depend on a good source of
** randomness any more.  But we will leave this code in all the same.
*/
static u8 randomByte(void){
SQLITE_API void sqlite3_randomness(int N, void *pBuf){
  unsigned char t;

  unsigned char *zBuf = pBuf;

  /* The "wsdPrng" macro will resolve to the pseudo-random number generator
  ** state vector.  If writable static data is unsupported on the target,
  ** we have to locate the state vector at run-time.  In the more common
  ** case where writable static data is supported, wsdPrng can refer directly
  ** to the "sqlite3Prng" state vector declared above.
  */
#ifdef SQLITE_OMIT_WSD
  struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
# define wsdPrng p[0]
#else
# define wsdPrng sqlite3Prng
#endif

#if SQLITE_THREADSAFE
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
  sqlite3_mutex_enter(mutex);
#endif

  /* Initialize the state of the random number generator once,
  ** the first time this routine is called.  The seed value does
  ** not need to contain a lot of randomness since we are not
  ** trying to do secure encryption or anything like that...
  **
  ** Nothing in this file or anywhere else in SQLite does any kind of
20584
20585
20586
20587
20588
20589
20590
20591

20592
20593
20594
20595
20596
20597
20598
20599







20600
20601
20602
20603
20604
20605
20606
20607
20608
20609
20610
20611
20612
20613
20614
20615
20616
20617
20618
20619
20601
20602
20603
20604
20605
20606
20607

20608








20609
20610
20611
20612
20613
20614
20615













20616
20617
20618
20619
20620
20621
20622







-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-







      t = wsdPrng.s[wsdPrng.j];
      wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
      wsdPrng.s[i] = t;
    }
    wsdPrng.isInit = 1;
  }

  /* Generate and return single random byte
  while( N-- ){
  */
  wsdPrng.i++;
  t = wsdPrng.s[wsdPrng.i];
  wsdPrng.j += t;
  wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
  wsdPrng.s[wsdPrng.j] = t;
  t += wsdPrng.s[wsdPrng.i];
  return wsdPrng.s[t];
    wsdPrng.i++;
    t = wsdPrng.s[wsdPrng.i];
    wsdPrng.j += t;
    wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
    wsdPrng.s[wsdPrng.j] = t;
    t += wsdPrng.s[wsdPrng.i];
    *(zBuf++) = wsdPrng.s[t];
}

/*
** Return N random bytes.
*/
SQLITE_API void sqlite3_randomness(int N, void *pBuf){
  unsigned char *zBuf = pBuf;
#if SQLITE_THREADSAFE
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
#endif
  sqlite3_mutex_enter(mutex);
  while( N-- ){
    *(zBuf++) = randomByte();
  }
  sqlite3_mutex_leave(mutex);
}

#ifndef SQLITE_OMIT_BUILTIN_TEST
/*
** For testing purposes, we sometimes want to preserve the state of
21092
21093
21094
21095
21096
21097
21098
21099
21100
21101
21102
21103
21104
21105
21106
21107
21108
21109
21110
21111
21112
21113
21114
21115
21116
21117
21118
21119
21120
21121
21122
21123
21124
21125
21126
21127
21128
21129
21130
21131
21095
21096
21097
21098
21099
21100
21101


























21102
21103
21104
21105
21106
21107
21108







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
  assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
  assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
  assert( m.z || db->mallocFailed );
  return m.z;
}

/*
** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
** enc. A pointer to the new string is returned, and the value of *pnOut
** is set to the length of the returned string in bytes. The call should
** arrange to call sqlite3DbFree() on the returned pointer when it is
** no longer required.
** 
** If a malloc failure occurs, NULL is returned and the db.mallocFailed
** flag set.
*/
#ifdef SQLITE_ENABLE_STAT3
SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
  Mem m;
  memset(&m, 0, sizeof(m));
  m.db = db;
  sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
  if( sqlite3VdbeMemTranslate(&m, enc) ){
    assert( db->mallocFailed );
    return 0;
  }
  assert( m.z==m.zMalloc );
  *pnOut = m.n;
  return m.z;
}
#endif

/*
** zIn is a UTF-16 encoded unicode string at least nChar characters long.
** Return the number of bytes in the first nChar unicode characters
** in pZ.  nChar must be non-negative.
*/
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
  int c;
23074
23075
23076
23077
23078
23079
23080

23081
23082
23083
23084
23085

23086
23087
23088
23089
23090
23091
23092
23051
23052
23053
23054
23055
23056
23057
23058
23059
23060
23061
23062
23063
23064
23065
23066
23067
23068
23069
23070
23071







+





+







  unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_MAX_MMAP_SIZE>0
  int nFetchOut;                      /* Number of outstanding xFetch refs */
  sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
  sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
  sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
  void *pMapRegion;                   /* Memory mapped region */
#endif
#ifdef __QNXNTO__
  int sectorSize;                     /* Device sector size */
  int deviceCharacteristics;          /* Precomputed device characteristics */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
  int openFlags;                      /* The flags specified at open() */
#endif
23513
23514
23515
23516
23517
23518
23519

23520
23521
23522
23523
23524
23525
23526
23527
23528
23529
23530
23531

23532
23533
23534
23535
23536
23537
23538
23492
23493
23494
23495
23496
23497
23498
23499
23500
23501
23502
23503
23504
23505
23506
23507
23508
23509
23510
23511
23512
23513
23514
23515
23516
23517
23518
23519







+












+








  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)

  { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)

#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
  { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)

  { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)

#if HAVE_MREMAP
  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
#else
  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
#endif
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
#endif

}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
23631
23632
23633
23634
23635
23636
23637
23638

23639
23640
23641
23642
23643

23644










23645
23646
23647
23648
23649
23650
23651
23612
23613
23614
23615
23616
23617
23618

23619
23620
23621
23622
23623
23624
23625

23626
23627
23628
23629
23630
23631
23632
23633
23634
23635
23636
23637
23638
23639
23640
23641
23642







-
+





+
-
+
+
+
+
+
+
+
+
+
+







** transaction crashes and leaves behind hot journals, then any
** process that is able to write to the database will also be able to
** recover the hot journals.
*/
static int robust_open(const char *z, int f, mode_t m){
  int fd;
  mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
  do{
  while(1){
#if defined(O_CLOEXEC)
    fd = osOpen(z,f|O_CLOEXEC,m2);
#else
    fd = osOpen(z,f,m2);
#endif
    if( fd<0 ){
  }while( fd<0 && errno==EINTR );
      if( errno==EINTR ) continue;
      break;
    }
    if( fd>2 ) break;
    osClose(fd);
    sqlite3_log(SQLITE_WARNING, 
                "attempt to open \"%s\" as file descriptor %d", z, fd);
    fd = -1;
    if( osOpen("/dev/null", f, m)<0 ) break;
  }
  if( fd>=0 ){
    if( m!=0 ){
      struct stat statbuf;
      if( osFstat(fd, &statbuf)==0 
       && statbuf.st_size==0
       && (statbuf.st_mode&0777)!=m 
      ){
24935
24936
24937
24938
24939
24940
24941

24942
24943

24944
24945
24946
24947
24948
24949
24950
24951
24952
24953
24954
24955
24956

24957

24958
24959
24960
24961
24962
24963
24964
24926
24927
24928
24929
24930
24931
24932
24933
24934
24935
24936
24937
24938
24939
24940
24941
24942
24943
24944
24945
24946
24947
24948
24949
24950
24951
24952
24953
24954
24955
24956
24957
24958
24959







+


+













+

+







** the requested locking level, this routine is a no-op.
*/
static int unixUnlock(sqlite3_file *id, int eFileLock){
  assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
  return posixUnlock(id, eFileLock, 0);
}

#if SQLITE_MAX_MMAP_SIZE>0
static int unixMapfile(unixFile *pFd, i64 nByte);
static void unixUnmapfile(unixFile *pFd);
#endif

/*
** This function performs the parts of the "close file" operation 
** common to all locking schemes. It closes the directory and file
** handles, if they are valid, and sets all fields of the unixFile
** structure to 0.
**
** It is *not* necessary to hold the mutex when this routine is called,
** even on VxWorks.  A mutex will be acquired on VxWorks by the
** vxworksReleaseFileId() routine.
*/
static int closeUnixFile(sqlite3_file *id){
  unixFile *pFile = (unixFile*)id;
#if SQLITE_MAX_MMAP_SIZE>0
  unixUnmapfile(pFile);
#endif
  if( pFile->h>=0 ){
    robust_close(pFile, pFile->h, __LINE__);
    pFile->h = -1;
  }
#if OS_VXWORKS
  if( pFile->pId ){
    if( pFile->ctrlFlags & UNIXFILE_DELETE ){
26155
26156
26157
26158
26159
26160
26161

26162
26163
26164
26165
26166
26167
26168
26150
26151
26152
26153
26154
26155
26156
26157
26158
26159
26160
26161
26162
26163
26164







+







  int got;
  int prior = 0;
#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
  i64 newOffset;
#endif
  TIMER_START;
  assert( cnt==(cnt&0x1ffff) );
  assert( id->h>2 );
  cnt &= 0x1ffff;
  do{
#if defined(USE_PREAD)
    got = osPread(id->h, pBuf, cnt, offset);
    SimulateIOError( got = -1 );
#elif defined(USE_PREAD64)
    got = osPread64(id->h, pBuf, cnt, offset);
26269
26270
26271
26272
26273
26274
26275

26276
26277
26278
26279
26280
26281
26282
26265
26266
26267
26268
26269
26270
26271
26272
26273
26274
26275
26276
26277
26278
26279







+







  const void *pBuf,               /* Copy data from this buffer to the file */
  int nBuf,                       /* Size of buffer pBuf in bytes */
  int *piErrno                    /* OUT: Error number if error occurs */
){
  int rc = 0;                     /* Value returned by system call */

  assert( nBuf==(nBuf&0x1ffff) );
  assert( fd>2 );
  nBuf &= 0x1ffff;
  TIMER_START;

#if defined(USE_PREAD)
  do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
#elif defined(USE_PREAD64)
  do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
26654
26655
26656
26657
26658
26659
26660

26661
26662
26663
26664
26665
26666
26667

26668
26669
26670
26671
26672
26673
26674
26651
26652
26653
26654
26655
26656
26657
26658
26659
26660
26661
26662
26663
26664
26665
26666
26667
26668
26669
26670
26671
26672
26673







+







+







    ** source.
    */
    if( pFile->inNormalWrite && nByte==0 ){
      pFile->transCntrChng = 1;
    }
#endif

#if SQLITE_MAX_MMAP_SIZE>0
    /* If the file was just truncated to a size smaller than the currently
    ** mapped region, reduce the effective mapping size as well. SQLite will
    ** use read() and write() to access data beyond this point from now on.  
    */
    if( nByte<pFile->mmapSize ){
      pFile->mmapSize = nByte;
    }
#endif

    return SQLITE_OK;
  }
}

/*
** Determine the current size of a file in bytes
26750
26751
26752
26753
26754
26755
26756

26757
26758
26759
26760
26761
26762
26763
26764
26765
26766
26767
26768

26769
26770
26771
26772
26773
26774
26775
26749
26750
26751
26752
26753
26754
26755
26756
26757
26758
26759
26760
26761
26762
26763
26764
26765
26766
26767
26768
26769
26770
26771
26772
26773
26774
26775
26776







+












+







        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
        iWrite += nBlk;
      }
#endif
    }
  }

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
    int rc;
    if( pFile->szChunk<=0 ){
      if( robust_ftruncate(pFile->h, nByte) ){
        pFile->lastErrno = errno;
        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
      }
    }

    rc = unixMapfile(pFile, nByte);
    return rc;
  }
#endif

  return SQLITE_OK;
}

/*
** If *pArg is inititially negative then this is a query.  Set *pArg to
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
26830
26831
26832
26833
26834
26835
26836

26837
26838
26839
26840
26841
26842
26843
26844
26845
26846
26847
26848
26849
26850
26851
26852

26853
26854
26855
26856
26857
26858
26859
26831
26832
26833
26834
26835
26836
26837
26838
26839
26840
26841
26842
26843
26844
26845
26846
26847
26848
26849
26850
26851
26852
26853
26854
26855
26856
26857
26858
26859
26860
26861
26862







+
















+







      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
      if( zTFile ){
        unixGetTempname(pFile->pVfs->mxPathname, zTFile);
        *(char**)pArg = zTFile;
      }
      return SQLITE_OK;
    }
#if SQLITE_MAX_MMAP_SIZE>0
    case SQLITE_FCNTL_MMAP_SIZE: {
      i64 newLimit = *(i64*)pArg;
      int rc = SQLITE_OK;
      if( newLimit>sqlite3GlobalConfig.mxMmap ){
        newLimit = sqlite3GlobalConfig.mxMmap;
      }
      *(i64*)pArg = pFile->mmapSizeMax;
      if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
        pFile->mmapSizeMax = newLimit;
        if( pFile->mmapSize>0 ){
          unixUnmapfile(pFile);
          rc = unixMapfile(pFile, -1);
        }
      }
      return rc;
    }
#endif
#ifdef SQLITE_DEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
    case SQLITE_FCNTL_DB_UNCHANGED: {
27656
27657
27658
27659
27660
27661
27662

27663
27664
27665
27666
27667
27668
27669
27670
27671
27672
27673
27674
27675
27676
27677
27678
27679
27680
27681
27682
27683
27684
27685
27686
27687
27688
27689
27690
27691
27692
27693
27694
27695
27696
27697
27698
27699
27700
27659
27660
27661
27662
27663
27664
27665
27666
27667
27668
27669
27670
27671

27672
27673
27674
27675
27676
27677

27678
27679

27680
27681
27682
27683
27684
27685
27686
27687
27688
27689
27690
27691

27692

27693
27694
27695
27696
27697
27698
27699







+





-






-


-












-

-







#else
# define unixShmMap     0
# define unixShmLock    0
# define unixShmBarrier 0
# define unixShmUnmap   0
#endif /* #ifndef SQLITE_OMIT_WAL */

#if SQLITE_MAX_MMAP_SIZE>0
/*
** If it is currently memory mapped, unmap file pFd.
*/
static void unixUnmapfile(unixFile *pFd){
  assert( pFd->nFetchOut==0 );
#if SQLITE_MAX_MMAP_SIZE>0
  if( pFd->pMapRegion ){
    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
    pFd->pMapRegion = 0;
    pFd->mmapSize = 0;
    pFd->mmapSizeActual = 0;
  }
#endif
}

#if SQLITE_MAX_MMAP_SIZE>0
/*
** Return the system page size.
*/
static int unixGetPagesize(void){
#if HAVE_MREMAP
  return 512;
#elif defined(_BSD_SOURCE)
  return getpagesize();
#else
  return (int)sysconf(_SC_PAGESIZE);
#endif
}
#endif /* SQLITE_MAX_MMAP_SIZE>0 */

#if SQLITE_MAX_MMAP_SIZE>0
/*
** Attempt to set the size of the memory mapping maintained by file 
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
**
** If successful, this function sets the following variables:
**
**       unixFile.pMapRegion
27771
27772
27773
27774
27775
27776
27777
27778
27779
27780
27781
27782
27783
27784
27785
27786
27787
27788
27789
27790
27791
27792
27793
27794
27795
27796
27797
27798
27799
27800
27801
27802
27803
27804
27770
27771
27772
27773
27774
27775
27776

27777
27778
27779
27780
27781
27782
27783
27784
27785
27786
27787
27788
27789
27790
27791
27792
27793
27794

27795
27796
27797
27798
27799
27800
27801







-


















-







    ** will probably fail too. Fall back to using xRead/xWrite exclusively
    ** in this case.  */
    pFd->mmapSizeMax = 0;
  }
  pFd->pMapRegion = (void *)pNew;
  pFd->mmapSize = pFd->mmapSizeActual = nNew;
}
#endif

/*
** Memory map or remap the file opened by file-descriptor pFd (if the file
** is already mapped, the existing mapping is replaced by the new). Or, if 
** there already exists a mapping for this file, and there are still 
** outstanding xFetch() references to it, this function is a no-op.
**
** If parameter nByte is non-negative, then it is the requested size of 
** the mapping to create. Otherwise, if nByte is less than zero, then the 
** requested size is the size of the file on disk. The actual size of the
** created mapping is either the requested size or the value configured 
** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
**
** SQLITE_OK is returned if no error occurs (even if the mapping is not
** recreated as a result of outstanding references) or an SQLite error
** code otherwise.
*/
static int unixMapfile(unixFile *pFd, i64 nByte){
#if SQLITE_MAX_MMAP_SIZE>0
  i64 nMap = nByte;
  int rc;

  assert( nMap>=0 || pFd->nFetchOut==0 );
  if( pFd->nFetchOut>0 ) return SQLITE_OK;

  if( nMap<0 ){
27816
27817
27818
27819
27820
27821
27822
27823
27824
27825
27826

27827
27828
27829
27830
27831
27832
27833
27813
27814
27815
27816
27817
27818
27819

27820
27821
27822
27823
27824
27825
27826
27827
27828
27829
27830







-



+







  if( nMap!=pFd->mmapSize ){
    if( nMap>0 ){
      unixRemapfile(pFd, nMap);
    }else{
      unixUnmapfile(pFd);
    }
  }
#endif

  return SQLITE_OK;
}
#endif /* SQLITE_MAX_MMAP_SIZE>0 */

/*
** If possible, return a pointer to a mapping of file fd starting at offset
** iOff. The mapping must be valid for at least nAmt bytes.
**
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
27868
27869
27870
27871
27872
27873
27874

27875
27876
27877
27878
27879
27880
27881
27882
27883
27884
27885
27886
27887
27888
27889

27890
27891
27892
27893
27894
27895
27896
27865
27866
27867
27868
27869
27870
27871
27872
27873
27874
27875
27876
27877
27878
27879
27880
27881
27882
27883
27884
27885
27886
27887
27888
27889
27890
27891
27892
27893
27894
27895







+















+







** to inform the VFS layer that, according to POSIX, any existing mapping 
** may now be invalid and should be unmapped.
*/
static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
  UNUSED_PARAMETER(iOff);

#if SQLITE_MAX_MMAP_SIZE>0
  /* If p==0 (unmap the entire file) then there must be no outstanding 
  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
  ** then there must be at least one outstanding.  */
  assert( (p==0)==(pFd->nFetchOut==0) );

  /* If p!=0, it must match the iOff value. */
  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );

  if( p ){
    pFd->nFetchOut--;
  }else{
    unixUnmapfile(pFd);
  }

  assert( pFd->nFetchOut>=0 );
#endif
  return SQLITE_OK;
}

/*
** Here ends the implementation of all sqlite3_file methods.
**
********************** End sqlite3_file Methods *******************************
28214
28215
28216
28217
28218
28219
28220

28221

28222
28223
28224
28225
28226
28227
28228
28213
28214
28215
28216
28217
28218
28219
28220
28221
28222
28223
28224
28225
28226
28227
28228
28229







+

+







  assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );

  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
  pNew->ctrlFlags = (u8)ctrlFlags;
#if SQLITE_MAX_MMAP_SIZE>0
  pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pNew->ctrlFlags |= UNIXFILE_PSOW;
  }
  if( strcmp(pVfs->zName,"unix-excl")==0 ){
    pNew->ctrlFlags |= UNIXFILE_EXCL;
  }
30715
30716
30717
30718
30719
30720
30721
30722

30723
30724
30725
30726
30727
30728
30729
30730
30731
30732
30733
30734
30735
30736
30737
30738
30739
30740
30741




























































30742
30743
30744
30745
30746
30747
30748
30716
30717
30718
30719
30720
30721
30722

30723
30724
30725
30726
30727
30728
30729
30730
30731
30732
30733
30734
30735
30736
30737
30738
30739
30740
30741
30742
30743
30744
30745
30746
30747
30748
30749
30750
30751
30752
30753
30754
30755
30756
30757
30758
30759
30760
30761
30762
30763
30764
30765
30766
30767
30768
30769
30770
30771
30772
30773
30774
30775
30776
30777
30778
30779
30780
30781
30782
30783
30784
30785
30786
30787
30788
30789
30790
30791
30792
30793
30794
30795
30796
30797
30798
30799
30800
30801
30802
30803
30804
30805
30806
30807
30808
30809







-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/************** Continuing where we left off in os_win.c *********************/

/*
** Compiling and using WAL mode requires several APIs that are only
** 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\
#  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

/*
** Maximum pathname length (in chars) for Win32.  This should normally be
** MAX_PATH.
*/
#ifndef SQLITE_WIN32_MAX_PATH_CHARS
#  define SQLITE_WIN32_MAX_PATH_CHARS   (MAX_PATH)
#endif

/*
** Maximum pathname length (in chars) for WinNT.  This should normally be
** 32767.
*/
#ifndef SQLITE_WINNT_MAX_PATH_CHARS
#  define SQLITE_WINNT_MAX_PATH_CHARS   (32767)
#endif

/*
** Maximum pathname length (in bytes) for Win32.  The MAX_PATH macro is in
** characters, so we allocate 3 bytes per character assuming worst-case of
** 4-bytes-per-character for UTF8.
*/
#ifndef SQLITE_WIN32_MAX_PATH_BYTES
#  define SQLITE_WIN32_MAX_PATH_BYTES   (SQLITE_WIN32_MAX_PATH_CHARS*4)
#endif

/*
** Maximum pathname length (in bytes) for WinNT.  This should normally be
** 32767 * sizeof(WCHAR).
*/
#ifndef SQLITE_WINNT_MAX_PATH_BYTES
#  define SQLITE_WINNT_MAX_PATH_BYTES   \
                            (sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS)
#endif

/*
** Maximum error message length (in chars) for WinRT.
*/
#ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS
#  define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024)
#endif

/*
** Returns non-zero if the character should be treated as a directory
** separator.
*/
#ifndef winIsDirSep
#  define winIsDirSep(a)                (((a) == '/') || ((a) == '\\'))
#endif

/*
** Returns the string that should be used as the directory separator.
*/
#ifndef winGetDirDep
#  ifdef __CYGWIN__
#    define winGetDirDep()              "/"
#  else
#    define winGetDirDep()              "\\"
#  endif
#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)
/*
31742
31743
31744
31745
31746
31747
31748
31749

31750
31751

31752
31753

31754
31755
31756
31757
31758
31759
31760
31803
31804
31805
31806
31807
31808
31809

31810
31811

31812
31813

31814
31815
31816
31817
31818
31819
31820
31821







-
+

-
+

-
+







** the LockFileEx() API.  But we can still statically link against that
** API as long as we don't call it when running Win95/98/ME.  A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
# define isNT()  (1)
# define osIsNT()  (1)
#elif !defined(SQLITE_WIN32_HAS_WIDE)
# define isNT()  (0)
# define osIsNT()  (0)
#else
  static int isNT(void){
  static int osIsNT(void){
    if( sqlite3_os_type==0 ){
      OSVERSIONINFOA sInfo;
      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
      osGetVersionExA(&sInfo);
      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return sqlite3_os_type==2;
31957
31958
31959
31960
31961
31962
31963
31964

31965
31966
31967
31968
31969
31970
31971
32018
32019
32020
32021
32022
32023
32024

32025
32026
32027
32028
32029
32030
32031
32032







-
+







#endif /* SQLITE_WIN32_MALLOC */

/*
** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). 
**
** Space to hold the returned string is obtained from malloc.
*/
static LPWSTR utf8ToUnicode(const char *zFilename){
static LPWSTR winUtf8ToUnicode(const char *zFilename){
  int nChar;
  LPWSTR zWideFilename;

  nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
  if( nChar==0 ){
    return 0;
  }
31982
31983
31984
31985
31986
31987
31988
31989

31990
31991
31992
31993
31994
31995
31996
32043
32044
32045
32046
32047
32048
32049

32050
32051
32052
32053
32054
32055
32056
32057







-
+







  return zWideFilename;
}

/*
** Convert Microsoft Unicode to UTF-8.  Space to hold the returned string is
** obtained from sqlite3_malloc().
*/
static char *unicodeToUtf8(LPCWSTR zWideFilename){
static char *winUnicodeToUtf8(LPCWSTR zWideFilename){
  int nByte;
  char *zFilename;

  nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
  if( nByte == 0 ){
    return 0;
  }
32010
32011
32012
32013
32014
32015
32016
32017

32018
32019
32020
32021
32022
32023
32024
32071
32072
32073
32074
32075
32076
32077

32078
32079
32080
32081
32082
32083
32084
32085







-
+







/*
** Convert an ANSI string to Microsoft Unicode, based on the
** current codepage settings for file apis.
** 
** Space to hold the returned string is obtained
** from sqlite3_malloc.
*/
static LPWSTR mbcsToUnicode(const char *zFilename){
static LPWSTR winMbcsToUnicode(const char *zFilename){
  int nByte;
  LPWSTR zMbcsFilename;
  int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;

  nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
                                0)*sizeof(WCHAR);
  if( nByte==0 ){
32040
32041
32042
32043
32044
32045
32046
32047

32048
32049
32050
32051
32052
32053
32054
32101
32102
32103
32104
32105
32106
32107

32108
32109
32110
32111
32112
32113
32114
32115







-
+







/*
** Convert Microsoft Unicode to multi-byte character string, based on the
** user's ANSI codepage.
**
** Space to hold the returned string is obtained from
** sqlite3_malloc().
*/
static char *unicodeToMbcs(LPCWSTR zWideFilename){
static char *winUnicodeToMbcs(LPCWSTR zWideFilename){
  int nByte;
  char *zFilename;
  int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;

  nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
  if( nByte == 0 ){
    return 0;
32070
32071
32072
32073
32074
32075
32076
32077

32078
32079
32080
32081

32082
32083
32084
32085
32086
32087
32088
32089
32090
32091
32092
32093
32094

32095
32096
32097
32098

32099
32100
32101
32102
32103
32104
32105
32131
32132
32133
32134
32135
32136
32137

32138
32139
32140
32141

32142
32143
32144
32145
32146
32147
32148
32149
32150
32151
32152
32153
32154

32155
32156
32157
32158

32159
32160
32161
32162
32163
32164
32165
32166







-
+



-
+












-
+



-
+







** Convert multibyte character string to UTF-8.  Space to hold the
** returned string is obtained from sqlite3_malloc().
*/
SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
  char *zFilenameUtf8;
  LPWSTR zTmpWide;

  zTmpWide = mbcsToUnicode(zFilename);
  zTmpWide = winMbcsToUnicode(zFilename);
  if( zTmpWide==0 ){
    return 0;
  }
  zFilenameUtf8 = unicodeToUtf8(zTmpWide);
  zFilenameUtf8 = winUnicodeToUtf8(zTmpWide);
  sqlite3_free(zTmpWide);
  return zFilenameUtf8;
}

/*
** Convert UTF-8 to multibyte character string.  Space to hold the 
** returned string is obtained from sqlite3_malloc().
*/
SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
  char *zFilenameMbcs;
  LPWSTR zTmpWide;

  zTmpWide = utf8ToUnicode(zFilename);
  zTmpWide = winUtf8ToUnicode(zFilename);
  if( zTmpWide==0 ){
    return 0;
  }
  zFilenameMbcs = unicodeToMbcs(zTmpWide);
  zFilenameMbcs = winUnicodeToMbcs(zTmpWide);
  sqlite3_free(zTmpWide);
  return zFilenameMbcs;
}

/*
** This function sets the data directory or the temporary directory based on
** the provided arguments.  The type argument must be 1 in order to set the
32121
32122
32123
32124
32125
32126
32127
32128

32129
32130
32131
32132
32133
32134
32135
32136
32137
32138
32139
32140
32141

32142
32143
32144
32145

32146
32147
32148
32149
32150
32151
32152
32153

32154
32155

32156
32157
32158
32159
32160
32161
32162

32163
32164
32165
32166
32167
32168
32169
32170
32171
32172
32173
32174
32175
32176
32177
32178
32179

32180
32181
32182
32183
32184
32185
32186
32182
32183
32184
32185
32186
32187
32188

32189
32190
32191
32192
32193
32194
32195
32196
32197
32198
32199
32200
32201

32202
32203
32204
32205

32206
32207
32208
32209
32210
32211
32212
32213

32214
32215

32216
32217
32218
32219
32220
32221
32222

32223
32224
32225
32226
32227
32228
32229
32230
32231
32232
32233
32234
32235
32236
32237
32238
32239

32240
32241
32242
32243
32244
32245
32246
32247







-
+












-
+



-
+







-
+

-
+






-
+
















-
+







  assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
          || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
  );
  assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
  if( ppDirectory ){
    char *zValueUtf8 = 0;
    if( zValue && zValue[0] ){
      zValueUtf8 = unicodeToUtf8(zValue);
      zValueUtf8 = winUnicodeToUtf8(zValue);
      if ( zValueUtf8==0 ){
        return SQLITE_NOMEM;
      }
    }
    sqlite3_free(*ppDirectory);
    *ppDirectory = zValueUtf8;
    return SQLITE_OK;
  }
  return SQLITE_ERROR;
}

/*
** The return value of getLastErrorMsg
** The return value of winGetLastErrorMsg
** is zero if the error message fits in the buffer, or non-zero
** otherwise (if the message was truncated).
*/
static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
  /* FormatMessage returns 0 on failure.  Otherwise it
  ** returns the number of TCHARs written to the output
  ** buffer, excluding the terminating null char.
  */
  DWORD dwLen = 0;
  char *zOut = 0;

  if( isNT() ){
  if( osIsNT() ){
#if SQLITE_OS_WINRT
    WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
    WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1];
    dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
                             FORMAT_MESSAGE_IGNORE_INSERTS,
                             NULL,
                             lastErrno,
                             0,
                             zTempWide,
                             MAX_PATH,
                             SQLITE_WIN32_MAX_ERRMSG_CHARS,
                             0);
#else
    LPWSTR zTempWide = NULL;
    dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                             FORMAT_MESSAGE_FROM_SYSTEM |
                             FORMAT_MESSAGE_IGNORE_INSERTS,
                             NULL,
                             lastErrno,
                             0,
                             (LPWSTR) &zTempWide,
                             0,
                             0);
#endif
    if( dwLen > 0 ){
      /* allocate a buffer and convert to UTF8 */
      sqlite3BeginBenignMalloc();
      zOut = unicodeToUtf8(zTempWide);
      zOut = winUnicodeToUtf8(zTempWide);
      sqlite3EndBenignMalloc();
#if !SQLITE_OS_WINRT
      /* free the system buffer allocated by FormatMessage */
      osLocalFree(zTempWide);
#endif
    }
  }
32240
32241
32242
32243
32244
32245
32246
32247

32248
32249
32250
32251
32252
32253
32254
32301
32302
32303
32304
32305
32306
32307

32308
32309
32310
32311
32312
32313
32314
32315







-
+







  const char *zPath,              /* File path associated with error */
  int iLine                       /* Source line number where error occurred */
){
  char zMsg[500];                 /* Human readable error text */
  int i;                          /* Loop counter */

  zMsg[0] = 0;
  getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
  winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
  assert( errcode!=SQLITE_OK );
  if( zPath==0 ) zPath = "";
  for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
  zMsg[i] = 0;
  sqlite3_log(errcode,
      "os_win.c:%d: (%lu) %s(%s) - %s",
      iLine, lastErrno, zFunc, zPath, zMsg
32265
32266
32267
32268
32269
32270
32271
32272
32273


32274
32275
32276
32277
32278
32279
32280

32281
32282

32283
32284
32285
32286
32287
32288
32289
32290
32291

32292
32293
32294
32295
32296
32297
32298
32299
32300
32301
32302
32303
32304

32305
32306
32307
32308

32309
32310
32311
32312
32313
32314
32315
32326
32327
32328
32329
32330
32331
32332


32333
32334
32335
32336
32337
32338
32339
32340

32341
32342

32343
32344
32345
32346
32347
32348
32349
32350
32351

32352
32353
32354
32355
32356
32357
32358
32359
32360
32361
32362
32363
32364

32365
32366
32367
32368

32369
32370
32371
32372
32373
32374
32375
32376







-
-
+
+






-
+

-
+








-
+












-
+



-
+







*/
#ifndef SQLITE_WIN32_IOERR_RETRY
# define SQLITE_WIN32_IOERR_RETRY 10
#endif
#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
#endif
static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;

/*
** If a ReadFile() or WriteFile() error occurs, invoke this routine
** to see if it should be retried.  Return TRUE to retry.  Return FALSE
** to give up with an error.
*/
static int retryIoerr(int *pnRetry, DWORD *pError){
static int winRetryIoerr(int *pnRetry, DWORD *pError){
  DWORD e = osGetLastError();
  if( *pnRetry>=win32IoerrRetry ){
  if( *pnRetry>=winIoerrRetry ){
    if( pError ){
      *pError = e;
    }
    return 0;
  }
  if( e==ERROR_ACCESS_DENIED ||
      e==ERROR_LOCK_VIOLATION ||
      e==ERROR_SHARING_VIOLATION ){
    sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
    sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
    ++*pnRetry;
    return 1;
  }
  if( pError ){
    *pError = e;
  }
  return 0;
}

/*
** Log a I/O error retry episode.
*/
static void logIoerr(int nRetry){
static void winLogIoerr(int nRetry){
  if( nRetry ){
    sqlite3_log(SQLITE_IOERR, 
      "delayed %dms for lock/sharing conflict",
      win32IoerrRetryDelay*nRetry*(nRetry+1)/2
      winIoerrRetryDelay*nRetry*(nRetry+1)/2
    );
  }
}

#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
32366
32367
32368
32369
32370
32371
32372
32373

32374
32375
32376
32377
32378
32379
32380
32427
32428
32429
32430
32431
32432
32433

32434
32435
32436
32437
32438
32439
32440
32441







-
+







static int winceCreateLock(const char *zFilename, winFile *pFile){
  LPWSTR zTok;
  LPWSTR zName;
  DWORD lastErrno;
  BOOL bLogged = FALSE;
  BOOL bInit = TRUE;

  zName = utf8ToUnicode(zFilename);
  zName = winUtf8ToUnicode(zFilename);
  if( zName==0 ){
    /* out of memory */
    return SQLITE_IOERR_NOMEM;
  }

  /* Initialize the local lockdata */
  memset(&pFile->local, 0, sizeof(pFile->local));
32639
32640
32641
32642
32643
32644
32645
32646

32647
32648
32649
32650
32651
32652
32653
32700
32701
32702
32703
32704
32705
32706

32707
32708
32709
32710
32711
32712
32713
32714







-
+







  /*
  ** NOTE: Windows CE is handled differently here due its lack of the Win32
  **       API LockFile.
  */
  return winceLockFile(phFile, offsetLow, offsetHigh,
                       numBytesLow, numBytesHigh);
#else
  if( isNT() ){
  if( osIsNT() ){
    OVERLAPPED ovlp;
    memset(&ovlp, 0, sizeof(OVERLAPPED));
    ovlp.Offset = offsetLow;
    ovlp.OffsetHigh = offsetHigh;
    return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
  }else{
    return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
32670
32671
32672
32673
32674
32675
32676
32677

32678
32679
32680
32681
32682
32683
32684
32731
32732
32733
32734
32735
32736
32737

32738
32739
32740
32741
32742
32743
32744
32745







-
+







  /*
  ** NOTE: Windows CE is handled differently here due its lack of the Win32
  **       API UnlockFile.
  */
  return winceUnlockFile(phFile, offsetLow, offsetHigh,
                         numBytesLow, numBytesHigh);
#else
  if( isNT() ){
  if( osIsNT() ){
    OVERLAPPED ovlp;
    memset(&ovlp, 0, sizeof(OVERLAPPED));
    ovlp.Offset = offsetLow;
    ovlp.OffsetHigh = offsetHigh;
    return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
  }else{
    return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
32700
32701
32702
32703
32704
32705
32706
32707

32708
32709
32710
32711
32712
32713
32714
32761
32762
32763
32764
32765
32766
32767

32768
32769
32770
32771
32772
32773
32774
32775







-
+







#endif

/*
** Move the current position of the file handle passed as the first 
** argument to offset iOffset within the file. If successful, return 0. 
** Otherwise, set pFile->lastErrno and return non-zero.
*/
static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
#if !SQLITE_OS_WINRT
  LONG upperBits;                 /* Most sig. 32 bits of new offset */
  LONG lowerBits;                 /* Least sig. 32 bits of new offset */
  DWORD dwRet;                    /* Value returned by SetFilePointer() */
  DWORD lastErrno;                /* Value returned by GetLastError() */

  OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
32725
32726
32727
32728
32729
32730
32731
32732

32733
32734
32735
32736
32737
32738
32739
32740
32741
32742
32743
32744
32745
32746
32747
32748
32749
32750
32751
32752
32753

32754
32755
32756
32757
32758
32759
32760
32786
32787
32788
32789
32790
32791
32792

32793
32794
32795
32796
32797
32798
32799
32800
32801
32802
32803
32804
32805
32806
32807
32808
32809
32810
32811
32812
32813

32814
32815
32816
32817
32818
32819
32820
32821







-
+




















-
+







  */
  dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);

  if( (dwRet==INVALID_SET_FILE_POINTER
      && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
    pFile->lastErrno = lastErrno;
    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
             "seekWinFile", pFile->zPath);
             "winSeekFile", pFile->zPath);
    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
    return 1;
  }

  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
  return 0;
#else
  /*
  ** Same as above, except that this implementation works for WinRT.
  */

  LARGE_INTEGER x;                /* The new offset */
  BOOL bRet;                      /* Value returned by SetFilePointerEx() */

  x.QuadPart = iOffset;
  bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);

  if(!bRet){
    pFile->lastErrno = osGetLastError();
    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
             "seekWinFile", pFile->zPath);
             "winSeekFile", pFile->zPath);
    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
    return 1;
  }

  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
  return 0;
#endif
32861
32862
32863
32864
32865
32866
32867
32868

32869
32870
32871
32872
32873
32874
32875
32876
32877
32878
32879
32880
32881

32882
32883
32884
32885
32886
32887

32888
32889
32890
32891
32892
32893
32894
32922
32923
32924
32925
32926
32927
32928

32929
32930
32931
32932
32933
32934
32935
32936
32937
32938
32939
32940
32941

32942
32943
32944
32945
32946
32947

32948
32949
32950
32951
32952
32953
32954
32955







-
+












-
+





-
+







      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE
  if( seekWinFile(pFile, offset) ){
  if( winSeekFile(pFile, offset) ){
    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
    return SQLITE_FULL;
  }
  while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
#else
  memset(&overlapped, 0, sizeof(OVERLAPPED));
  overlapped.Offset = (LONG)(offset & 0xffffffff);
  overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
  while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
         osGetLastError()!=ERROR_HANDLE_EOF ){
#endif
    DWORD lastErrno;
    if( retryIoerr(&nRetry, &lastErrno) ) continue;
    if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
    pFile->lastErrno = lastErrno;
    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
    return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
             "winRead", pFile->zPath);
  }
  logIoerr(nRetry);
  winLogIoerr(nRetry);
  if( nRead<(DWORD)amt ){
    /* Unread parts of the buffer must be zero-filled */
    memset(&((char*)pBuf)[nRead], 0, amt-nRead);
    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
    return SQLITE_IOERR_SHORT_READ;
  }

32933
32934
32935
32936
32937
32938
32939
32940

32941
32942
32943
32944
32945
32946
32947
32994
32995
32996
32997
32998
32999
33000

33001
33002
33003
33004
33005
33006
33007
33008







-
+







      amt -= nCopy;
      offset += nCopy;
    }
  }
#endif

#if SQLITE_OS_WINCE
  rc = seekWinFile(pFile, offset);
  rc = winSeekFile(pFile, offset);
  if( rc==0 ){
#else
  {
#endif
#if !SQLITE_OS_WINCE
    OVERLAPPED overlapped;        /* The offset for WriteFile. */
#endif
32958
32959
32960
32961
32962
32963
32964
32965

32966
32967
32968
32969
32970
32971
32972
33019
33020
33021
33022
33023
33024
33025

33026
33027
33028
33029
33030
33031
33032
33033







-
+








    while( nRem>0 ){
#if SQLITE_OS_WINCE
      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
#else
      if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
#endif
        if( retryIoerr(&nRetry, &lastErrno) ) continue;
        if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
        break;
      }
      assert( nWrite==0 || nWrite<=(DWORD)nRem );
      if( nWrite==0 || nWrite>(DWORD)nRem ){
        lastErrno = osGetLastError();
        break;
      }
32990
32991
32992
32993
32994
32995
32996
32997

32998
32999
33000
33001
33002
33003
33004
33051
33052
33053
33054
33055
33056
33057

33058
33059
33060
33061
33062
33063
33064
33065







-
+







      OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
      return SQLITE_FULL;
    }
    OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
    return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
             "winWrite", pFile->zPath);
  }else{
    logIoerr(nRetry);
    winLogIoerr(nRetry);
  }
  OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
  return SQLITE_OK;
}

/*
** Truncate an open file to a specified size
33019
33020
33021
33022
33023
33024
33025
33026

33027
33028
33029
33030
33031
33032
33033
33080
33081
33082
33083
33084
33085
33086

33087
33088
33089
33090
33091
33092
33093
33094







-
+







  ** size).
  */
  if( pFile->szChunk>0 ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }

  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( seekWinFile(pFile, nByte) ){
  if( winSeekFile(pFile, nByte) ){
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate1", pFile->zPath);
  }else if( 0==osSetEndOfFile(pFile->h) &&
            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
    pFile->lastErrno = lastErrno;
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate2", pFile->zPath);
33100
33101
33102
33103
33104
33105
33106

33107
33108
33109
33110
33111
33112
33113
33161
33162
33163
33164
33165
33166
33167
33168
33169
33170
33171
33172
33173
33174
33175







+







  sqlite3_sync_count++;
#endif

  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
  ** no-op
  */
#ifdef SQLITE_NO_SYNC
  OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h));
  return SQLITE_OK;
#else
  rc = osFlushFileBuffers(pFile->h);
  SimulateIOError( rc=FALSE );
  if( rc ){
    OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
    return SQLITE_OK;
33197
33198
33199
33200
33201
33202
33203
33204

33205
33206
33207

33208
33209
33210
33211
33212
33213
33214
33259
33260
33261
33262
33263
33264
33265

33266
33267
33268

33269
33270
33271
33272
33273
33274
33275
33276







-
+


-
+







#endif

/*
** Acquire a reader lock.
** Different API routines are called depending on whether or not this
** is Win9x or WinNT.
*/
static int getReadLock(winFile *pFile){
static int winGetReadLock(winFile *pFile){
  int res;
  OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
  if( isNT() ){
  if( osIsNT() ){
#if SQLITE_OS_WINCE
    /*
    ** NOTE: Windows CE is handled differently here due its lack of the Win32
    **       API LockFileEx.
    */
    res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
#else
33232
33233
33234
33235
33236
33237
33238
33239

33240
33241
33242
33243

33244
33245
33246
33247
33248
33249
33250
33251
33252
33253
33254

33255
33256
33257
33258
33259
33260
33261
33294
33295
33296
33297
33298
33299
33300

33301
33302
33303
33304

33305
33306
33307
33308
33309
33310
33311
33312
33313
33314
33315

33316
33317
33318
33319
33320
33321
33322
33323







-
+



-
+










-
+







  OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
  return res;
}

/*
** Undo a readlock
*/
static int unlockReadLock(winFile *pFile){
static int winUnlockReadLock(winFile *pFile){
  int res;
  DWORD lastErrno;
  OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
  if( isNT() ){
  if( osIsNT() ){
    res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
    res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
  }
#endif
  if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
    pFile->lastErrno = lastErrno;
    winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
             "unlockReadLock", pFile->zPath);
             "winUnlockReadLock", pFile->zPath);
  }
  OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
  return res;
}

/*
** Lock the file with the lock specified by parameter locktype - one
33338
33339
33340
33341
33342
33343
33344
33345

33346
33347
33348
33349
33350
33351
33352
33400
33401
33402
33403
33404
33405
33406

33407
33408
33409
33410
33411
33412
33413
33414







-
+







    }
  }

  /* Acquire a shared lock
  */
  if( locktype==SHARED_LOCK && res ){
    assert( pFile->locktype==NO_LOCK );
    res = getReadLock(pFile);
    res = winGetReadLock(pFile);
    if( res ){
      newLocktype = SHARED_LOCK;
    }else{
      lastErrno = osGetLastError();
    }
  }

33369
33370
33371
33372
33373
33374
33375
33376

33377
33378
33379
33380
33381
33382
33383

33384
33385
33386
33387
33388
33389
33390
33391
33392
33393
33394
33395
33396
33397
33398
33399
33400
33401
33402
33403


33404
33405
33406
33407
33408
33409
33410
33431
33432
33433
33434
33435
33436
33437

33438
33439
33440
33441
33442
33443
33444

33445
33446
33447
33448
33449
33450
33451
33452
33453
33454
33455
33456
33457
33458
33459
33460
33461


33462
33463
33464
33465
33466
33467
33468
33469
33470
33471
33472







-
+






-
+
















-
-


+
+







    gotPendingLock = 0;
  }

  /* Acquire an EXCLUSIVE lock
  */
  if( locktype==EXCLUSIVE_LOCK && res ){
    assert( pFile->locktype>=SHARED_LOCK );
    res = unlockReadLock(pFile);
    res = winUnlockReadLock(pFile);
    res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
                      SHARED_SIZE, 0);
    if( res ){
      newLocktype = EXCLUSIVE_LOCK;
    }else{
      lastErrno = osGetLastError();
      getReadLock(pFile);
      winGetReadLock(pFile);
    }
  }

  /* If we are holding a PENDING lock that ought to be released, then
  ** release it now.
  */
  if( gotPendingLock && locktype==SHARED_LOCK ){
    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
  }

  /* Update the state of the lock has held in the file descriptor then
  ** return the appropriate result code.
  */
  if( res ){
    rc = SQLITE_OK;
  }else{
    OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
             pFile->h, locktype, newLocktype));
    pFile->lastErrno = lastErrno;
    rc = SQLITE_BUSY;
    OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
             pFile->h, locktype, newLocktype));
  }
  pFile->locktype = (u8)newLocktype;
  OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
  return rc;
}

33456
33457
33458
33459
33460
33461
33462
33463

33464
33465
33466
33467
33468
33469
33470
33471
33472
33473
33474

33475
33476
33477
33478
33479
33480
33481
33518
33519
33520
33521
33522
33523
33524

33525
33526
33527
33528
33529
33530
33531
33532
33533
33534
33535

33536
33537
33538
33539
33540
33541
33542
33543







-
+










-
+







  assert( pFile!=0 );
  assert( locktype<=SHARED_LOCK );
  OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
           pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
  type = pFile->locktype;
  if( type>=EXCLUSIVE_LOCK ){
    winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
    if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
    if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
      /* This should never happen.  We should always be able to
      ** reacquire the read lock */
      rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
               "winUnlock", pFile->zPath);
    }
  }
  if( type>=RESERVED_LOCK ){
    winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
  }
  if( locktype==NO_LOCK && type>=SHARED_LOCK ){
    unlockReadLock(pFile);
    winUnlockReadLock(pFile);
  }
  if( type>=PENDING_LOCK ){
    winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
  }
  pFile->locktype = (u8)locktype;
  OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
           pFile->h, pFile->locktype, sqlite3ErrName(rc)));
33495
33496
33497
33498
33499
33500
33501
33502

33503
33504
33505
33506
33507
33508
33509
33557
33558
33559
33560
33561
33562
33563

33564
33565
33566
33567
33568
33569
33570
33571







-
+







    pFile->ctrlFlags &= ~mask;
  }else{
    pFile->ctrlFlags |= mask;
  }
}

/* Forward declaration */
static int getTempname(int nBuf, char *zBuf);
static int winGetTempname(sqlite3_vfs *, char **);
#if SQLITE_MAX_MMAP_SIZE>0
static int winMapfile(winFile*, sqlite3_int64);
#endif

/*
** Control and query of the open file handle.
*/
33558
33559
33560
33561
33562
33563
33564
33565

33566
33567

33568
33569
33570

33571
33572

33573
33574
33575
33576
33577
33578

33579
33580


33581
33582
33583
33584


33585
33586
33587
33588
33589
33590
33591
33620
33621
33622
33623
33624
33625
33626

33627
33628

33629
33630
33631

33632
33633

33634
33635
33636
33637
33638
33639

33640


33641
33642
33643
33644


33645
33646
33647
33648
33649
33650
33651
33652
33653







-
+

-
+


-
+

-
+





-
+
-
-
+
+


-
-
+
+







      *(char**)pArg = sqlite3_mprintf("win32");
      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_WIN32_AV_RETRY: {
      int *a = (int*)pArg;
      if( a[0]>0 ){
        win32IoerrRetry = a[0];
        winIoerrRetry = a[0];
      }else{
        a[0] = win32IoerrRetry;
        a[0] = winIoerrRetry;
      }
      if( a[1]>0 ){
        win32IoerrRetryDelay = a[1];
        winIoerrRetryDelay = a[1];
      }else{
        a[1] = win32IoerrRetryDelay;
        a[1] = winIoerrRetryDelay;
      }
      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
      char *zTFile = 0;
      if( zTFile ){
        getTempname(pFile->pVfs->mxPathname, zTFile);
      int rc = winGetTempname(pFile->pVfs, &zTFile);
      if( rc==SQLITE_OK ){
        *(char**)pArg = zTFile;
      }
      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
      return SQLITE_OK;
      OSTRACE(("FCNTL file=%p, rc=%d\n", pFile->h, rc));
      return rc;
    }
#if SQLITE_MAX_MMAP_SIZE>0
    case SQLITE_FCNTL_MMAP_SIZE: {
      i64 newLimit = *(i64*)pArg;
      int rc = SQLITE_OK;
      if( newLimit>sqlite3GlobalConfig.mxMmap ){
        newLimit = sqlite3GlobalConfig.mxMmap;
34539
34540
34541
34542
34543
34544
34545
34546

34547
34548
34549


34550
34551
34552
34553
34554
34555
34556
34557
34558
34559
34560
34561
34562


34563
34564

34565
34566
34567
34568







34569
34570

34571

34572
34573

34574
34575
34576
34577
34578
34579
34580


34581
34582
34583
34584
34585
34586
34587















34588
34589
34590



34591
34592
34593

34594

34595
34596








34597
34598
34599
34600

34601
34602

34603

34604


34605
34606
34607
34608
34609
34610
34611

34612
34613







34614
34615
34616
34617
34618
34619

34620
34621

34622
34623
34624
34625
34626
34627
34628
34629
34630
34631
34632
34633
34634
34635
34636
34637
34638
34639
34640
34641
34642
34643
34644
34645
34646
34647
34648

34649
34650


34651
34652
34653
34654
34655

34656
34657
34658
34659
34660
34661
34662
34663
34664
34665
34666
34667

34668
34669
34670
34671
34672
34673
34674
34675
34676
34677
34678
34679
34680
34681
34682
34683

34684
34685
34686
34687
34688
34689

34690
34691
34692
34693
34694
34695
34696
34697
34698
34699
34700
34701
34702
34703
34704
34705
34706

34707
34708
34709
34710
34711
34712
34713
34601
34602
34603
34604
34605
34606
34607

34608
34609


34610
34611
34612
34613
34614
34615
34616
34617
34618
34619
34620
34621
34622


34623
34624

34625
34626




34627
34628
34629
34630
34631
34632
34633
34634

34635

34636
34637

34638
34639
34640
34641
34642
34643


34644
34645
34646
34647
34648
34649
34650
34651
34652
34653
34654
34655
34656
34657
34658
34659
34660
34661
34662
34663
34664
34665
34666
34667
34668


34669
34670
34671
34672
34673

34674
34675
34676


34677
34678
34679
34680
34681
34682
34683
34684
34685
34686
34687

34688
34689

34690
34691
34692
34693
34694
34695
34696
34697
34698
34699
34700
34701
34702
34703


34704
34705
34706
34707
34708
34709
34710
34711
34712
34713
34714
34715

34716
34717
34718
34719
34720
34721
34722
34723








34724








34725
34726
34727
34728
34729

34730
34731

34732
34733
34734
34735
34736
34737

34738

34739



34740
34741
34742
34743
34744
34745
34746
34747
34748
34749
34750
34751
34752
34753
34754
34755
34756
34757
34758
34759
34760
34761
34762

34763
34764
34765
34766
34767
34768

34769
34770
34771
34772
34773
34774
34775
34776
34777
34778
34779
34780
34781
34782
34783
34784
34785

34786
34787
34788
34789
34790
34791
34792
34793







-
+

-
-
+
+











-
-
+
+
-

+
-
-
-
-
+
+
+
+
+
+
+

-
+
-
+

-
+





-
-
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+


-
+

+
-
-
+
+
+
+
+
+
+
+



-
+

-
+

+

+
+







+
-
-
+
+
+
+
+
+
+





-
+


+




-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-





-
+

-
+
+




-
+
-

-
-
-







+















-
+





-
+
















-
+








/*
** Convert a UTF-8 filename into whatever form the underlying
** operating system wants filenames in.  Space to hold the result
** is obtained from malloc and must be freed by the calling
** function.
*/
static void *convertUtf8Filename(const char *zFilename){
static void *winConvertUtf8Filename(const char *zFilename){
  void *zConverted = 0;
  if( isNT() ){
    zConverted = utf8ToUnicode(zFilename);
  if( osIsNT() ){
    zConverted = winUtf8ToUnicode(zFilename);
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
    zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
  }
#endif
  /* caller will handle out of memory */
  return zConverted;
}

/*
** Maximum pathname length (in bytes) for windows.  The MAX_PATH macro is
** in characters, so we allocate 3 bytes per character assuming worst-case
** This function returns non-zero if the specified UTF-8 string buffer
** ends with a directory separator character.
** 3-bytes-per-character UTF8.
*/
static int winEndsInDirSep(char *zBuf){
#ifndef SQLITE_WIN32_MAX_PATH
#  define SQLITE_WIN32_MAX_PATH   (MAX_PATH*3)
#endif

  if( zBuf ){
    int nLen = sqlite3Strlen30(zBuf);
    return nLen>0 && winIsDirSep(zBuf[nLen-1]);
  }
  return 0;
}

/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** Create a temporary file name and store the resulting pointer into pzBuf.
** hold at pVfs->mxPathname characters.
** The pointer returned in pzBuf must be freed via sqlite3_free().
*/
static int getTempname(int nBuf, char *zBuf){
static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  size_t i, j;
  int nTempPath;
  char zTempPath[SQLITE_WIN32_MAX_PATH+2];
  int nBuf, nLen;
  char *zBuf;

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. 
  */
  SimulateIOError( return SQLITE_IOERR );

  /* Allocate a temporary buffer to store the fully qualified file
  ** name for the temporary file.  If this fails, we cannot continue.
  */
  nBuf = pVfs->mxPathname;
  zBuf = sqlite3MallocZero( nBuf+2 );
  if( !zBuf ){
    OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
    return SQLITE_IOERR_NOMEM;
  }

  /* Figure out the effective temporary directory.  First, check if one
  ** has been explicitly set by the application; otherwise, use the one
  ** configured by the operating system.
  */
  assert( nBuf>30 );
  if( sqlite3_temp_directory ){
    sqlite3_snprintf(SQLITE_WIN32_MAX_PATH-30, zTempPath, "%s",
                     sqlite3_temp_directory);
    sqlite3_snprintf(nBuf-30, zBuf, "%s%s", sqlite3_temp_directory,
                     winEndsInDirSep(sqlite3_temp_directory) ? "" :
                     winGetDirDep());
  }
#if !SQLITE_OS_WINRT
  else if( isNT() ){
  else if( osIsNT() ){
    char *zMulti;
    LPWSTR zWidePath = sqlite3MallocZero( nBuf*sizeof(WCHAR) );
    WCHAR zWidePath[MAX_PATH];
    if( osGetTempPathW(MAX_PATH-30, zWidePath)==0 ){
    if( !zWidePath ){
      sqlite3_free(zBuf);
      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
      return SQLITE_IOERR_NOMEM;
    }
    if( osGetTempPathW(nBuf, zWidePath)==0 ){
      sqlite3_free(zWidePath);
      sqlite3_free(zBuf);
      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
      return SQLITE_IOERR_GETTEMPPATH;
    }
    zMulti = unicodeToUtf8(zWidePath);
    zMulti = winUnicodeToUtf8(zWidePath);
    if( zMulti ){
      sqlite3_snprintf(SQLITE_WIN32_MAX_PATH-30, zTempPath, "%s", zMulti);
      sqlite3_snprintf(nBuf-30, zBuf, "%s", zMulti);
      sqlite3_free(zMulti);
      sqlite3_free(zWidePath);
    }else{
      sqlite3_free(zWidePath);
      sqlite3_free(zBuf);
      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
      return SQLITE_IOERR_NOMEM;
    }
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
    char *zUtf8;
    char *zMbcsPath = sqlite3MallocZero( nBuf );
    char zMbcsPath[SQLITE_WIN32_MAX_PATH];
    if( osGetTempPathA(SQLITE_WIN32_MAX_PATH-30, zMbcsPath)==0 ){
    if( !zMbcsPath ){
      sqlite3_free(zBuf);
      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
      return SQLITE_IOERR_NOMEM;
    }
    if( osGetTempPathA(nBuf, zMbcsPath)==0 ){
      sqlite3_free(zBuf);
      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
      return SQLITE_IOERR_GETTEMPPATH;
    }
    zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
    if( zUtf8 ){
      sqlite3_snprintf(SQLITE_WIN32_MAX_PATH-30, zTempPath, "%s", zUtf8);
      sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8);
      sqlite3_free(zUtf8);
    }else{
      sqlite3_free(zBuf);
      OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
      return SQLITE_IOERR_NOMEM;
    }
  }
#else
  else{
    /*
    ** Compiled without ANSI support and the current operating system
    ** is not Windows NT; therefore, just zero the temporary buffer.
    */
    memset(zTempPath, 0, SQLITE_WIN32_MAX_PATH+2);
  }
#endif /* SQLITE_WIN32_HAS_ANSI */
#else
  else{
    /*
    ** Compiled for WinRT and the sqlite3_temp_directory is not set;
    ** therefore, just zero the temporary buffer.
    */
    memset(zTempPath, 0, SQLITE_WIN32_MAX_PATH+2);
  }
#endif /* !SQLITE_OS_WINRT */

  /* Check that the output buffer is large enough for the temporary file 
  ** name. If it is not, return SQLITE_ERROR.
  */
  nTempPath = sqlite3Strlen30(zTempPath);
  nLen = sqlite3Strlen30(zBuf);

  if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
  if( (nLen + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
    sqlite3_free(zBuf);
    OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
    return SQLITE_ERROR;
  }

  for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
  sqlite3_snprintf(nBuf-18-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX);
  zTempPath[i] = 0;

  sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
                       "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
                   zTempPath);
  j = sqlite3Strlen30(zBuf);
  sqlite3_randomness(15, &zBuf[j]);
  for(i=0; i<15; i++, j++){
    zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  }
  zBuf[j] = 0;
  zBuf[j+1] = 0;
  *pzBuf = zBuf;

  OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
  return SQLITE_OK;
}

/*
** Return TRUE if the named file is really a directory.  Return false if
** it is something other than a directory, or if there is any kind of memory
** allocation failure.
*/
static int winIsDir(const void *zConverted){
  DWORD attr;
  int rc = 0;
  DWORD lastErrno;

  if( isNT() ){
  if( osIsNT() ){
    int cnt = 0;
    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
    memset(&sAttrData, 0, sizeof(sAttrData));
    while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
                             GetFileExInfoStandard,
                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
                             &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
    if( !rc ){
      return 0; /* Invalid name? */
    }
    attr = sAttrData.dwFileAttributes;
#if SQLITE_OS_WINCE==0
  }else{
    attr = osGetFileAttributesA((char*)zConverted);
#endif
  }
  return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
}

/*
** Open a file.
*/
static int winOpen(
  sqlite3_vfs *pVfs,        /* Not used */
  sqlite3_vfs *pVfs,        /* Used to get maximum path name length */
  const char *zName,        /* Name of the file (UTF-8) */
  sqlite3_file *id,         /* Write the SQLite file handle here */
  int flags,                /* Open mode flags */
  int *pOutFlags            /* Status return flags */
){
  HANDLE h;
  DWORD lastErrno;
34722
34723
34724
34725
34726
34727
34728
34729

34730
34731
34732
34733
34734
34735
34736
34802
34803
34804
34805
34806
34807
34808

34809
34810
34811
34812
34813
34814
34815
34816







-
+







  void *zConverted;              /* Filename in OS encoding */
  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
  int cnt = 0;

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[SQLITE_WIN32_MAX_PATH+2];     /* Buffer used to create temp filename */
  char *zTmpname = 0; /* For temporary filename, if necessary. */

  int rc = SQLITE_OK;            /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
#endif

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
34777
34778
34779
34780
34781
34782
34783
34784

34785
34786
34787
34788
34789
34790
34791
34792
34793
34794
34795


34796
34797
34798
34799
34800
34801
34802
34803
34804
34805
34806
34807
34808

34809
34810
34811

34812

34813
34814
34815
34816
34817
34818

34819
34820
34821
34822
34823
34824
34825
34857
34858
34859
34860
34861
34862
34863

34864
34865
34866
34867
34868
34869
34870
34871
34872
34873


34874
34875
34876
34877
34878
34879
34880
34881
34882
34883
34884
34885
34886
34887

34888
34889
34890

34891
34892
34893
34894
34895
34896
34897
34898
34899
34900
34901
34902
34903
34904
34905
34906
34907







-
+









-
-
+
+












-
+


-
+

+






+







  );

  assert( pFile!=0 );
  memset(pFile, 0, sizeof(winFile));
  pFile->h = INVALID_HANDLE_VALUE;

#if SQLITE_OS_WINRT
  if( !sqlite3_temp_directory ){
  if( !zUtf8Name && !sqlite3_temp_directory ){
    sqlite3_log(SQLITE_ERROR,
        "sqlite3_temp_directory variable should be set for WinRT");
  }
#endif

  /* If the second argument to this function is NULL, generate a 
  ** temporary file name to use 
  */
  if( !zUtf8Name ){
    assert(isDelete && !isOpenJournal);
    rc = getTempname(SQLITE_WIN32_MAX_PATH+2, zTmpname);
    assert( isDelete && !isOpenJournal );
    rc = winGetTempname(pVfs, &zTmpname);
    if( rc!=SQLITE_OK ){
      OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
      return rc;
    }
    zUtf8Name = zTmpname;
  }

  /* Database filenames are double-zero terminated if they are not
  ** URIs with parameters.  Hence, they can always be passed into
  ** sqlite3_uri_parameter().
  */
  assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
        zUtf8Name[strlen(zUtf8Name)+1]==0 );
       zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 );

  /* Convert the filename to the system encoding. */
  zConverted = convertUtf8Filename(zUtf8Name);
  zConverted = winConvertUtf8Filename(zUtf8Name);
  if( zConverted==0 ){
    sqlite3_free(zTmpname);
    OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
    return SQLITE_IOERR_NOMEM;
  }

  if( winIsDir(zConverted) ){
    sqlite3_free(zConverted);
    sqlite3_free(zTmpname);
    OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
    return SQLITE_CANTOPEN_ISDIR;
  }

  if( isReadWrite ){
    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  }else{
34858
34859
34860
34861
34862
34863
34864
34865

34866
34867
34868
34869
34870
34871
34872
34873
34874
34875
34876
34877
34878
34879
34880

34881
34882
34883
34884
34885
34886
34887
34888
34889
34890

34891
34892
34893
34894
34895
34896
34897
34898
34899
34900
34901
34902
34903

34904
34905
34906
34907
34908

34909
34910
34911
34912
34913
34914
34915
34916

34917
34918
34919
34920
34921
34922
34923
34940
34941
34942
34943
34944
34945
34946

34947
34948
34949
34950
34951
34952
34953
34954
34955
34956
34957
34958
34959
34960
34961

34962
34963
34964
34965
34966
34967
34968
34969
34970
34971

34972
34973
34974
34975
34976
34977
34978
34979
34980
34981
34982
34983
34984

34985
34986
34987
34988
34989

34990
34991
34992
34993
34994
34995
34996
34997
34998
34999
35000
35001
35002
35003
35004
35005
35006







-
+














-
+









-
+












-
+




-
+








+







  }
  /* Reports from the internet are that performance is always
  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
#if SQLITE_OS_WINCE
  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
#endif

  if( isNT() ){
  if( osIsNT() ){
#if SQLITE_OS_WINRT
    CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
    extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
    extendedParameters.dwFileAttributes =
            dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
    extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
    extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
    extendedParameters.lpSecurityAttributes = NULL;
    extendedParameters.hTemplateFile = NULL;
    while( (h = osCreateFile2((LPCWSTR)zConverted,
                              dwDesiredAccess,
                              dwShareMode,
                              dwCreationDisposition,
                              &extendedParameters))==INVALID_HANDLE_VALUE &&
                              retryIoerr(&cnt, &lastErrno) ){
                              winRetryIoerr(&cnt, &lastErrno) ){
               /* Noop */
    }
#else
    while( (h = osCreateFileW((LPCWSTR)zConverted,
                              dwDesiredAccess,
                              dwShareMode, NULL,
                              dwCreationDisposition,
                              dwFlagsAndAttributes,
                              NULL))==INVALID_HANDLE_VALUE &&
                              retryIoerr(&cnt, &lastErrno) ){
                              winRetryIoerr(&cnt, &lastErrno) ){
               /* Noop */
    }
#endif
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
    while( (h = osCreateFileA((LPCSTR)zConverted,
                              dwDesiredAccess,
                              dwShareMode, NULL,
                              dwCreationDisposition,
                              dwFlagsAndAttributes,
                              NULL))==INVALID_HANDLE_VALUE &&
                              retryIoerr(&cnt, &lastErrno) ){
                              winRetryIoerr(&cnt, &lastErrno) ){
               /* Noop */
    }
  }
#endif
  logIoerr(cnt);
  winLogIoerr(cnt);

  OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
           dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));

  if( h==INVALID_HANDLE_VALUE ){
    pFile->lastErrno = lastErrno;
    winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
    sqlite3_free(zConverted);
    sqlite3_free(zTmpname);
    if( isReadWrite && !isExclusive ){
      return winOpen(pVfs, zName, id, 
         ((flags|SQLITE_OPEN_READONLY) &
                     ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
         pOutFlags);
    }else{
      return SQLITE_CANTOPEN_BKPT;
34938
34939
34940
34941
34942
34943
34944

34945
34946
34947
34948
34949
34950
34951
34952
34953

34954
34955
34956
34957
34958
34959
34960
35021
35022
35023
35024
35025
35026
35027
35028
35029
35030
35031
35032
35033
35034
35035
35036
35037
35038
35039
35040
35041
35042
35043
35044
35045







+









+








#if SQLITE_OS_WINCE
  if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
       && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
  ){
    osCloseHandle(h);
    sqlite3_free(zConverted);
    sqlite3_free(zTmpname);
    OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
    return rc;
  }
  if( isTemp ){
    pFile->zDeleteOnClose = zConverted;
  }else
#endif
  {
    sqlite3_free(zConverted);
    sqlite3_free(zTmpname);
  }

  pFile->pMethod = &winIoMethod;
  pFile->pVfs = pVfs;
  pFile->h = h;
  if( isReadonly ){
    pFile->ctrlFlags |= WINFILE_RDONLY;
35000
35001
35002
35003
35004
35005
35006
35007

35008

35009
35010
35011

35012
35013
35014
35015
35016
35017
35018
35085
35086
35087
35088
35089
35090
35091

35092
35093
35094
35095
35096

35097
35098
35099
35100
35101
35102
35103
35104







-
+

+


-
+







  void *zConverted;
  UNUSED_PARAMETER(pVfs);
  UNUSED_PARAMETER(syncDir);

  SimulateIOError(return SQLITE_IOERR_DELETE);
  OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));

  zConverted = convertUtf8Filename(zFilename);
  zConverted = winConvertUtf8Filename(zFilename);
  if( zConverted==0 ){
    OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
    return SQLITE_IOERR_NOMEM;
  }
  if( isNT() ){
  if( osIsNT() ){
    do {
#if SQLITE_OS_WINRT
      WIN32_FILE_ATTRIBUTE_DATA sAttrData;
      memset(&sAttrData, 0, sizeof(sAttrData));
      if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
                                  &sAttrData) ){
        attr = sAttrData.dwFileAttributes;
35043
35044
35045
35046
35047
35048
35049
35050

35051
35052
35053
35054
35055
35056
35057
35129
35130
35131
35132
35133
35134
35135

35136
35137
35138
35139
35140
35141
35142
35143







-
+







        rc = SQLITE_ERROR; /* Files only. */
        break;
      }
      if ( osDeleteFileW(zConverted) ){
        rc = SQLITE_OK; /* Deleted OK. */
        break;
      }
      if ( !retryIoerr(&cnt, &lastErrno) ){
      if ( !winRetryIoerr(&cnt, &lastErrno) ){
        rc = SQLITE_ERROR; /* No more retries. */
        break;
      }
    } while(1);
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
35071
35072
35073
35074
35075
35076
35077
35078

35079
35080
35081
35082
35083
35084
35085
35086
35087
35088
35089

35090
35091
35092
35093
35094
35095
35096
35157
35158
35159
35160
35161
35162
35163

35164
35165
35166
35167
35168
35169
35170
35171
35172
35173
35174

35175
35176
35177
35178
35179
35180
35181
35182







-
+










-
+







        rc = SQLITE_ERROR; /* Files only. */
        break;
      }
      if ( osDeleteFileA(zConverted) ){
        rc = SQLITE_OK; /* Deleted OK. */
        break;
      }
      if ( !retryIoerr(&cnt, &lastErrno) ){
      if ( !winRetryIoerr(&cnt, &lastErrno) ){
        rc = SQLITE_ERROR; /* No more retries. */
        break;
      }
    } while(1);
  }
#endif
  if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
             "winDelete", zFilename);
  }else{
    logIoerr(cnt);
    winLogIoerr(cnt);
  }
  sqlite3_free(zConverted);
  OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
  return rc;
}

/*
35108
35109
35110
35111
35112
35113
35114
35115

35116
35117
35118
35119
35120

35121
35122
35123
35124
35125
35126

35127
35128
35129
35130
35131
35132
35133
35134
35135
35136
35137
35138
35139

35140
35141
35142
35143
35144
35145
35146
35194
35195
35196
35197
35198
35199
35200

35201
35202
35203
35204
35205

35206
35207
35208
35209
35210
35211

35212
35213
35214
35215
35216
35217
35218
35219
35220
35221
35222
35223
35224

35225
35226
35227
35228
35229
35230
35231
35232







-
+




-
+





-
+












-
+







  void *zConverted;
  UNUSED_PARAMETER(pVfs);

  SimulateIOError( return SQLITE_IOERR_ACCESS; );
  OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
           zFilename, flags, pResOut));

  zConverted = convertUtf8Filename(zFilename);
  zConverted = winConvertUtf8Filename(zFilename);
  if( zConverted==0 ){
    OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
    return SQLITE_IOERR_NOMEM;
  }
  if( isNT() ){
  if( osIsNT() ){
    int cnt = 0;
    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
    memset(&sAttrData, 0, sizeof(sAttrData));
    while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
                             GetFileExInfoStandard, 
                             &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
                             &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
    if( rc ){
      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
      ** as if it does not exist.
      */
      if(    flags==SQLITE_ACCESS_EXISTS
          && sAttrData.nFileSizeHigh==0 
          && sAttrData.nFileSizeLow==0 ){
        attr = INVALID_FILE_ATTRIBUTES;
      }else{
        attr = sAttrData.dwFileAttributes;
      }
    }else{
      logIoerr(cnt);
      winLogIoerr(cnt);
      if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
        winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
        sqlite3_free(zConverted);
        return SQLITE_IOERR_ACCESS;
      }else{
        attr = INVALID_FILE_ATTRIBUTES;
      }
35183
35184
35185
35186
35187
35188
35189
35190

35191
35192
35193
35194
35195
35196
35197
35269
35270
35271
35272
35273
35274
35275

35276
35277
35278
35279
35280
35281
35282
35283







-
+







  /*
  ** If the path name starts with a forward slash or a backslash, it is either
  ** a legal UNC name, a volume relative path, or an absolute path name in the
  ** "Unix" format on Windows.  There is no easy way to differentiate between
  ** the final two cases; therefore, we return the safer return value of TRUE
  ** so that callers of this function will simply use it verbatim.
  */
  if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
  if ( winIsDirSep(zPathname[0]) ){
    return TRUE;
  }

  /*
  ** If the path name starts with a letter and a colon it is either a volume
  ** relative path or an absolute path.  Callers of this function must not
  ** attempt to treat it as a relative path name (i.e. they should simply use
35219
35220
35221
35222
35223
35224
35225
35226
35227
35228
35229
35230
35231
35232
35233
35234



35235


35236
35237

35238
35239

35240
35241
35242
35243



35244
35245
35246
35247
35248
35249
35250
35305
35306
35307
35308
35309
35310
35311

35312
35313
35314
35315
35316
35317
35318
35319
35320
35321
35322

35323
35324
35325

35326
35327
35328
35329
35330
35331


35332
35333
35334
35335
35336
35337
35338
35339
35340
35341







-








+
+
+
-
+
+

-
+


+


-
-
+
+
+







  int nFull,                    /* Size of output buffer in bytes */
  char *zFull                   /* Output buffer */
){
  
#if defined(__CYGWIN__)
  SimulateIOError( return SQLITE_ERROR );
  UNUSED_PARAMETER(nFull);
  assert( pVfs->mxPathname>=SQLITE_WIN32_MAX_PATH );
  assert( nFull>=pVfs->mxPathname );
  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
    /*
    ** NOTE: We are dealing with a relative path name and the data
    **       directory has been set.  Therefore, use it as the basis
    **       for converting the relative path name to an absolute
    **       one by prepending the data directory and a slash.
    */
    char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
    if( !zOut ){
      winLogError(SQLITE_IOERR_NOMEM, 0, "winFullPathname", zRelative);
    char zOut[SQLITE_WIN32_MAX_PATH+1];
      return SQLITE_IOERR_NOMEM;
    }
    if( cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
                         SQLITE_WIN32_MAX_PATH+1)<0 ){
                         pVfs->mxPathname+1)<0 ){
      winLogError(SQLITE_CANTOPEN_FULLPATH, (DWORD)errno, "cygwin_conv_path",
                  zRelative);
      sqlite3_free(zOut);
      return SQLITE_CANTOPEN_FULLPATH;
    }
    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
                     sqlite3_data_directory, zOut);
    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%s%s",
                     sqlite3_data_directory, winGetDirDep(), zOut);
    sqlite3_free(zOut);
  }else{
    if( cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull)<0 ){
      winLogError(SQLITE_CANTOPEN_FULLPATH, (DWORD)errno, "cygwin_conv_path",
                  zRelative);
      return SQLITE_CANTOPEN_FULLPATH;
    }
  }
35258
35259
35260
35261
35262
35263
35264
35265
35266


35267
35268
35269
35270
35271
35272
35273
35349
35350
35351
35352
35353
35354
35355


35356
35357
35358
35359
35360
35361
35362
35363
35364







-
-
+
+







  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
    /*
    ** NOTE: We are dealing with a relative path name and the data
    **       directory has been set.  Therefore, use it as the basis
    **       for converting the relative path name to an absolute
    **       one by prepending the data directory and a backslash.
    */
    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
                     sqlite3_data_directory, zRelative);
    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%s%s",
                     sqlite3_data_directory, winGetDirDep(), zRelative);
  }else{
    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
  }
  return SQLITE_OK;
#endif

#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
35291
35292
35293
35294
35295
35296
35297
35298
35299


35300
35301
35302

35303
35304
35305
35306

35307
35308
35309
35310
35311
35312
35313
35382
35383
35384
35385
35386
35387
35388


35389
35390
35391
35392

35393
35394
35395
35396

35397
35398
35399
35400
35401
35402
35403
35404







-
-
+
+


-
+



-
+







  if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
    /*
    ** NOTE: We are dealing with a relative path name and the data
    **       directory has been set.  Therefore, use it as the basis
    **       for converting the relative path name to an absolute
    **       one by prepending the data directory and a backslash.
    */
    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
                     sqlite3_data_directory, zRelative);
    sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%s%s",
                     sqlite3_data_directory, winGetDirDep(), zRelative);
    return SQLITE_OK;
  }
  zConverted = convertUtf8Filename(zRelative);
  zConverted = winConvertUtf8Filename(zRelative);
  if( zConverted==0 ){
    return SQLITE_IOERR_NOMEM;
  }
  if( isNT() ){
  if( osIsNT() ){
    LPWSTR zTemp;
    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
    if( nByte==0 ){
      winLogError(SQLITE_ERROR, osGetLastError(),
                  "GetFullPathNameW1", zConverted);
      sqlite3_free(zConverted);
      return SQLITE_CANTOPEN_FULLPATH;
35323
35324
35325
35326
35327
35328
35329
35330

35331
35332
35333
35334
35335
35336
35337
35414
35415
35416
35417
35418
35419
35420

35421
35422
35423
35424
35425
35426
35427
35428







-
+







      winLogError(SQLITE_ERROR, osGetLastError(),
                  "GetFullPathNameW2", zConverted);
      sqlite3_free(zConverted);
      sqlite3_free(zTemp);
      return SQLITE_CANTOPEN_FULLPATH;
    }
    sqlite3_free(zConverted);
    zOut = unicodeToUtf8(zTemp);
    zOut = winUnicodeToUtf8(zTemp);
    sqlite3_free(zTemp);
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
    char *zTemp;
    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
    if( nByte==0 ){
35376
35377
35378
35379
35380
35381
35382
35383

35384
35385
35386
35387
35388

35389
35390
35391
35392
35393
35394
35395
35396
35397
35398
35399
35400
35401
35402
35403
35404
35405

35406
35407
35408
35409
35410
35411
35412
35467
35468
35469
35470
35471
35472
35473

35474
35475
35476
35477
35478

35479
35480
35481
35482
35483
35484
35485
35486
35487
35488
35489
35490
35491
35492
35493
35494
35495

35496
35497
35498
35499
35500
35501
35502
35503







-
+




-
+
















-
+







*/
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
  HANDLE h;
  void *zConverted = convertUtf8Filename(zFilename);
  void *zConverted = winConvertUtf8Filename(zFilename);
  UNUSED_PARAMETER(pVfs);
  if( zConverted==0 ){
    return 0;
  }
  if( isNT() ){
  if( osIsNT() ){
#if SQLITE_OS_WINRT
    h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
#else
    h = osLoadLibraryW((LPCWSTR)zConverted);
#endif
  }
#ifdef SQLITE_WIN32_HAS_ANSI
  else{
    h = osLoadLibraryA((char*)zConverted);
  }
#endif
  sqlite3_free(zConverted);
  return (void*)h;
}
static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
  UNUSED_PARAMETER(pVfs);
  getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
  winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
}
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
  UNUSED_PARAMETER(pVfs);
  return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
}
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
  UNUSED_PARAMETER(pVfs);
35574
35575
35576
35577
35578
35579
35580
35581

35582
35583
35584
35585
35586
35587
35588
35589
35590
35591

35592
35593
35594
35595
35596
35597
35598
35599
35600
35601
35602
35603
35604
35605
35606
35607
35608
35609
35610
35611


























35612
35613
35614
35615
35616
35617
35618
35619
35620
35621
35622
35623
35624
35625
35626
35627





35628
35629
35630
35631
35632
35633
35634
35665
35666
35667
35668
35669
35670
35671

35672
35673
35674
35675
35676
35677
35678
35679
35680
35681

35682
35683
35684
35685
35686
35687
35688
35689
35690
35691
35692
35693
35694
35695
35696
35697
35698
35699
35700
35701
35702
35703
35704
35705
35706
35707
35708
35709
35710
35711
35712
35713
35714
35715
35716
35717
35718
35719
35720
35721
35722
35723
35724
35725
35726
35727
35728
35729
35730
35731
35732
35733
35734
35735
35736
35737
35738
35739
35740
35741
35742
35743
35744
35745
35746
35747
35748
35749
35750
35751
35752
35753
35754
35755
35756







-
+









-
+




















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















+
+
+
+
+







**
** However if an error message is supplied, it will be incorporated
** by sqlite into the error message available to the user using
** sqlite3_errmsg(), possibly making IO errors easier to debug.
*/
static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
  UNUSED_PARAMETER(pVfs);
  return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
  return winGetLastErrorMsg(osGetLastError(), nBuf, zBuf);
}

/*
** Initialize and deinitialize the operating system interface.
*/
SQLITE_API int sqlite3_os_init(void){
  static sqlite3_vfs winVfs = {
    3,                   /* iVersion */
    sizeof(winFile),     /* szOsFile */
    SQLITE_WIN32_MAX_PATH, /* mxPathname */
    SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
    0,                   /* pNext */
    "win32",             /* zName */
    0,                   /* pAppData */
    winOpen,             /* xOpen */
    winDelete,           /* xDelete */
    winAccess,           /* xAccess */
    winFullPathname,     /* xFullPathname */
    winDlOpen,           /* xDlOpen */
    winDlError,          /* xDlError */
    winDlSym,            /* xDlSym */
    winDlClose,          /* xDlClose */
    winRandomness,       /* xRandomness */
    winSleep,            /* xSleep */
    winCurrentTime,      /* xCurrentTime */
    winGetLastError,     /* xGetLastError */
    winCurrentTimeInt64, /* xCurrentTimeInt64 */
    winSetSystemCall,    /* xSetSystemCall */
    winGetSystemCall,    /* xGetSystemCall */
    winNextSystemCall,   /* xNextSystemCall */
  };
#if defined(SQLITE_WIN32_HAS_WIDE)
  static sqlite3_vfs winLongPathVfs = {
    3,                   /* iVersion */
    sizeof(winFile),     /* szOsFile */
    SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
    0,                   /* pNext */
    "win32-longpath",    /* zName */
    0,                   /* pAppData */
    winOpen,             /* xOpen */
    winDelete,           /* xDelete */
    winAccess,           /* xAccess */
    winFullPathname,     /* xFullPathname */
    winDlOpen,           /* xDlOpen */
    winDlError,          /* xDlError */
    winDlSym,            /* xDlSym */
    winDlClose,          /* xDlClose */
    winRandomness,       /* xRandomness */
    winSleep,            /* xSleep */
    winCurrentTime,      /* xCurrentTime */
    winGetLastError,     /* xGetLastError */
    winCurrentTimeInt64, /* xCurrentTimeInt64 */
    winSetSystemCall,    /* xSetSystemCall */
    winGetSystemCall,    /* xGetSystemCall */
    winNextSystemCall,   /* xNextSystemCall */
  };
#endif

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==74 );

  /* get memory map allocation granularity */
  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
#if SQLITE_OS_WINRT
  osGetNativeSystemInfo(&winSysInfo);
#else
  osGetSystemInfo(&winSysInfo);
#endif
  assert( winSysInfo.dwAllocationGranularity>0 );
  assert( winSysInfo.dwPageSize>0 );

  sqlite3_vfs_register(&winVfs, 1);

#if defined(SQLITE_WIN32_HAS_WIDE)
  sqlite3_vfs_register(&winLongPathVfs, 0);
#endif

  return SQLITE_OK; 
}

SQLITE_API int sqlite3_os_end(void){ 
#if SQLITE_OS_WINRT
  if( sleepObj!=NULL ){
    osCloseHandle(sleepObj);
37434
37435
37436
37437
37438
37439
37440

37441
37442
37443
37444
37445
37446
37447
37556
37557
37558
37559
37560
37561
37562
37563
37564
37565
37566
37567
37568
37569
37570







+







  )){
    goto fetch_out;
  }

  if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
    goto fetch_out;
  }
  assert( pCache->nHash>0 && pCache->apHash );

  /* Step 4. Try to recycle a page. */
  if( pCache->bPurgeable && pGroup->pLruTail && (
         (pCache->nPage+1>=pCache->nMax)
      || pGroup->nCurrentPage>=pGroup->nMaxPage
      || pcache1UnderMemoryPressure(pCache)
  )){
38794
38795
38796
38797
38798
38799
38800







38801
38802
38803
38804
38805
38806
38807
38917
38918
38919
38920
38921
38922
38923
38924
38925
38926
38927
38928
38929
38930
38931
38932
38933
38934
38935
38936
38937







+
+
+
+
+
+
+







  Pgno nOrig;                  /* Original number of pages in file */
  Pgno iSubRec;                /* Index of first record in sub-journal */
#ifndef SQLITE_OMIT_WAL
  u32 aWalData[WAL_SAVEPOINT_NDATA];        /* WAL savepoint context */
#endif
};

/*
** Bits of the Pager.doNotSpill flag.  See further description below.
*/
#define SPILLFLAG_OFF         0x01      /* Never spill cache.  Set via pragma */
#define SPILLFLAG_ROLLBACK    0x02      /* Current rolling back, so do not spill */
#define SPILLFLAG_NOSYNC      0x04      /* Spill is ok, but do not sync */

/*
** A open page cache is an instance of struct Pager. A description of
** some of the more important member variables follows:
**
** eState
**
**   The current 'state' of the pager object. See the comment and state
38860
38861
38862
38863
38864
38865
38866
38867

38868
38869
38870
38871



38872

38873
38874


38875
38876
38877


38878
38879

38880
38881
38882
38883
38884
38885
38886
38990
38991
38992
38993
38994
38995
38996

38997
38998



38999
39000
39001
39002
39003


39004
39005
39006
39007

39008
39009
39010

39011
39012
39013
39014
39015
39016
39017
39018







-
+

-
-
-
+
+
+

+
-
-
+
+


-
+
+

-
+







**   subsequently interrupted transaction that reuses the journal file.
**
**   The flag is cleared as soon as the journal file is finalized (either
**   by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
**   journal file from being successfully finalized, the setMaster flag
**   is cleared anyway (and the pager will move to ERROR state).
**
** doNotSpill, doNotSyncSpill
** doNotSpill
**
**   These two boolean variables control the behavior of cache-spills
**   (calls made by the pcache module to the pagerStress() routine to
**   write cached data to the file-system in order to free up memory).
**   This variables control the behavior of cache-spills  (calls made by
**   the pcache module to the pagerStress() routine to write cached data
**   to the file-system in order to free up memory).
**
**   When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set,
**   When doNotSpill is non-zero, writing to the database from pagerStress()
**   is disabled altogether. This is done in a very obscure case that
**   writing to the database from pagerStress() is disabled altogether.
**   The SPILLFLAG_ROLLBACK case is done in a very obscure case that
**   comes up during savepoint rollback that requires the pcache module
**   to allocate a new page to prevent the journal file from being written
**   while it is being traversed by code in pager_playback().
**   while it is being traversed by code in pager_playback().  The SPILLFLAG_OFF
**   case is a user preference.
** 
**   If doNotSyncSpill is non-zero, writing to the database from pagerStress()
**   If the SPILLFLAG_NOSYNC bit is set, writing to the database from pagerStress()
**   is permitted, but syncing the journal file is not. This flag is set
**   by sqlite3PagerWrite() when the file-system sector-size is larger than
**   the database page-size in order to prevent a journal sync from happening 
**   in between the journalling of two pages on the same sector. 
**
** subjInMemory
**
38976
38977
38978
38979
38980
38981
38982
38983
38984
38985
38986
38987
38988
38989
38990
39108
39109
39110
39111
39112
39113
39114

39115
39116
39117
39118
39119
39120
39121







-







  ** "configuration" of the pager.
  */
  u8 eState;                  /* Pager state (OPEN, READER, WRITER_LOCKED..) */
  u8 eLock;                   /* Current lock held on database file */
  u8 changeCountDone;         /* Set after incrementing the change-counter */
  u8 setMaster;               /* True if a m-j name has been written to jrnl */
  u8 doNotSpill;              /* Do not spill the cache when non-zero */
  u8 doNotSyncSpill;          /* Do not do a spill that requires jrnl sync */
  u8 subjInMemory;            /* True to use in-memory sub-journals */
  Pgno dbSize;                /* Number of pages in the database */
  Pgno dbOrigSize;            /* dbSize before the current transaction */
  Pgno dbFileSize;            /* Number of pages in the database file */
  Pgno dbHintSize;            /* Value passed to FCNTL_SIZE_HINT call */
  int errCode;                /* One of several kinds of errors */
  int nRec;                   /* Pages journalled since last j-header written */
39355
39356
39357
39358
39359
39360
39361
39362
39363


39364


39365
39366
39367
39368





39369
39370
39371
39372
39373
39374
39375
39486
39487
39488
39489
39490
39491
39492

39493
39494
39495
39496
39497
39498




39499
39500
39501
39502
39503
39504
39505
39506
39507
39508
39509
39510







-

+
+

+
+
-
-
-
-
+
+
+
+
+







** or more open savepoints for which:
**
**   * The page-number is less than or equal to PagerSavepoint.nOrig, and
**   * The bit corresponding to the page-number is not set in
**     PagerSavepoint.pInSavepoint.
*/
static int subjRequiresPage(PgHdr *pPg){
  Pgno pgno = pPg->pgno;
  Pager *pPager = pPg->pPager;
  PagerSavepoint *p;
  Pgno pgno;
  int i;
  if( pPager->nSavepoint ){
    pgno = pPg->pgno;
  for(i=0; i<pPager->nSavepoint; i++){
    PagerSavepoint *p = &pPager->aSavepoint[i];
    if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
      return 1;
    for(i=0; i<pPager->nSavepoint; i++){
      p = &pPager->aSavepoint[i];
      if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
        return 1;
      }
    }
  }
  return 0;
}

/*
** Return true if the page is already in the journal file.
40636
40637
40638
40639
40640
40641
40642
40643
40644


40645
40646
40647


40648
40649
40650
40651
40652
40653
40654
40771
40772
40773
40774
40775
40776
40777


40778
40779
40780


40781
40782
40783
40784
40785
40786
40787
40788
40789







-
-
+
+

-
-
+
+







    **
    ** The solution is to add an in-memory page to the cache containing
    ** the data just read from the sub-journal. Mark the page as dirty 
    ** and if the pager requires a journal-sync, then mark the page as 
    ** requiring a journal-sync before it is written.
    */
    assert( isSavepnt );
    assert( pPager->doNotSpill==0 );
    pPager->doNotSpill++;
    assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
    pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
    rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
    assert( pPager->doNotSpill==1 );
    pPager->doNotSpill--;
    assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
    pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
    if( rc!=SQLITE_OK ) return rc;
    pPg->flags &= ~PGHDR_NEED_READ;
    sqlite3PcacheMakeDirty(pPg);
  }
  if( pPg ){
    /* No page should ever be explicitly rolled back that is in use, except
    ** for page 1 which is held in use in order to keep the lock on the
41207
41208
41209
41210
41211
41212
41213
41214
41215
41216
41217
41218
41219
41220
41221
41222
41223
41224
41225
41226
41342
41343
41344
41345
41346
41347
41348






41349
41350
41351
41352
41353
41354
41355







-
-
-
-
-
-







  Pgno pgno = pPg->pgno;       /* Page number to read */
  int rc = SQLITE_OK;          /* Return code */
  int pgsz = pPager->pageSize; /* Number of bytes to read */

  assert( pPager->eState>=PAGER_READER && !MEMDB );
  assert( isOpen(pPager->fd) );

  if( NEVER(!isOpen(pPager->fd)) ){
    assert( pPager->tempFile );
    memset(pPg->pData, 0, pPager->pageSize);
    return SQLITE_OK;
  }

#ifndef SQLITE_OMIT_WAL
  if( iFrame ){
    /* Try to pull the page from the write-ahead log. */
    rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
  }else
#endif
  {
41745
41746
41747
41748
41749
41750
41751



41752
41753
41754



41755
41756
41757
41758
41759
41760
41761
41874
41875
41876
41877
41878
41879
41880
41881
41882
41883



41884
41885
41886
41887
41888
41889
41890
41891
41892
41893







+
+
+
-
-
-
+
+
+







** Free as much memory as possible from the pager.
*/
SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
  sqlite3PcacheShrink(pPager->pPCache);
}

/*
** Adjust settings of the pager to those specified in the pgFlags parameter.
**
** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
** Adjust the robustness of the database to damage due to OS crashes
** or power failures by changing the number of syncs()s when writing
** the rollback journal.  There are three levels:
** of the database to damage due to OS crashes or power failures by
** changing the number of syncs()s when writing the journals.
** There are three levels:
**
**    OFF       sqlite3OsSync() is never called.  This is the default
**              for temporary and transient files.
**
**    NORMAL    The journal is synced once before writes begin on the
**              database.  This is normally adequate protection, but
**              it is theoretically possible, though very unlikely,
41788
41789
41790
41791
41792
41793
41794
41795

41796
41797
41798

41799
41800

41801
41802
41803
41804
41805
41806
41807

41808
41809
41810

41811
41812
41813
41814
41815
41816
41817
41818
41819
41820





41821
41822
41823
41824
41825
41826
41827
41920
41921
41922
41923
41924
41925
41926

41927
41928


41929

41930
41931
41932
41933
41934
41935
41936
41937

41938
41939
41940

41941
41942
41943
41944
41945
41946
41947
41948
41949
41950
41951
41952
41953
41954
41955
41956
41957
41958
41959
41960
41961
41962
41963







-
+

-
-
+
-

+






-
+


-
+










+
+
+
+
+







** synchronous=FULL versus synchronous=NORMAL setting determines when
** the xSync primitive is called and is relevant to all platforms.
**
** Numeric values associated with these states are OFF==1, NORMAL=2,
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
SQLITE_PRIVATE void sqlite3PagerSetFlags(
  Pager *pPager,        /* The pager to set safety level for */
  int level,            /* PRAGMA synchronous.  1=OFF, 2=NORMAL, 3=FULL */  
  int bFullFsync,       /* PRAGMA fullfsync */
  unsigned pgFlags      /* Various flags */
  int bCkptFullFsync    /* PRAGMA checkpoint_fullfsync */
){
  unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
  assert( level>=1 && level<=3 );
  pPager->noSync =  (level==1 || pPager->tempFile) ?1:0;
  pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
  if( pPager->noSync ){
    pPager->syncFlags = 0;
    pPager->ckptSyncFlags = 0;
  }else if( bFullFsync ){
  }else if( pgFlags & PAGER_FULLFSYNC ){
    pPager->syncFlags = SQLITE_SYNC_FULL;
    pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
  }else if( bCkptFullFsync ){
  }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
    pPager->syncFlags = SQLITE_SYNC_NORMAL;
    pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
  }else{
    pPager->syncFlags = SQLITE_SYNC_NORMAL;
    pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
  }
  pPager->walSyncFlags = pPager->syncFlags;
  if( pPager->fullSync ){
    pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
  }
  if( pgFlags & PAGER_CACHESPILL ){
    pPager->doNotSpill &= ~SPILLFLAG_OFF;
  }else{
    pPager->doNotSpill |= SPILLFLAG_OFF;
  }
}
#endif

/*
** The following global variable is incremented whenever the library
** attempts to open a temporary file.  This information is used for
** testing and analysis only.  
42714
42715
42716
42717
42718
42719
42720
42721

42722
42723
42724
42725
42726
42727



42728
42729
42730
42731
42732
42733
42734
42735
42736



42737
42738




42739
42740
42741
42742
42743
42744
42745
42850
42851
42852
42853
42854
42855
42856

42857
42858
42859
42860
42861


42862
42863
42864
42865
42866
42867
42868
42869
42870
42871
42872
42873
42874
42875
42876


42877
42878
42879
42880
42881
42882
42883
42884
42885
42886
42887







-
+




-
-
+
+
+









+
+
+
-
-
+
+
+
+







static int pagerStress(void *p, PgHdr *pPg){
  Pager *pPager = (Pager *)p;
  int rc = SQLITE_OK;

  assert( pPg->pPager==pPager );
  assert( pPg->flags&PGHDR_DIRTY );

  /* The doNotSyncSpill flag is set during times when doing a sync of
  /* The doNotSpill NOSYNC bit is set during times when doing a sync of
  ** journal (and adding a new header) is not allowed.  This occurs
  ** during calls to sqlite3PagerWrite() while trying to journal multiple
  ** pages belonging to the same sector.
  **
  ** The doNotSpill flag inhibits all cache spilling regardless of whether
  ** or not a sync is required.  This is set during a rollback.
  ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling
  ** regardless of whether or not a sync is required.  This is set during
  ** a rollback or by user request, respectively.
  **
  ** Spilling is also prohibited when in an error state since that could
  ** lead to database corruption.   In the current implementaton it 
  ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
  ** while in the error state, hence it is impossible for this routine to
  ** be called in the error state.  Nevertheless, we include a NEVER()
  ** test for the error state as a safeguard against future changes.
  */
  if( NEVER(pPager->errCode) ) return SQLITE_OK;
  testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK );
  testcase( pPager->doNotSpill & SPILLFLAG_OFF );
  testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC );
  if( pPager->doNotSpill ) return SQLITE_OK;
  if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
  if( pPager->doNotSpill
   && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
      || (pPg->flags & PGHDR_NEED_SYNC)!=0)
  ){
    return SQLITE_OK;
  }

  pPg->pDirty = 0;
  if( pagerUseWal(pPager) ){
    /* Write a single frame for this page to the log. */
    if( subjRequiresPage(pPg) ){ 
43553
43554
43555
43556
43557
43558
43559
43560

43561
43562
43563
43564
43565

43566
43567
43568
43569
43570
43571
43572

43573
43574
43575
43576
43577
43578
43579
43695
43696
43697
43698
43699
43700
43701

43702
43703
43704
43705
43706

43707
43708
43709
43710
43711
43712
43713

43714
43715
43716
43717
43718
43719
43720
43721







-
+




-
+






-
+







** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
SQLITE_PRIVATE int sqlite3PagerAcquire(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int flags           /* PAGER_ACQUIRE_XXX flags */
  int flags           /* PAGER_GET_XXX flags */
){
  int rc = SQLITE_OK;
  PgHdr *pPg = 0;
  u32 iFrame = 0;                 /* Frame to read from WAL file */
  const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
  const int noContent = (flags & PAGER_GET_NOCONTENT);

  /* It is acceptable to use a read-only (mmap) page for any page except
  ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
  ** flag was specified by the caller. And so long as the db is not a 
  ** temporary or in-memory database.  */
  const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
   && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
   && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
#ifdef SQLITE_HAS_CODEC
   && pPager->xCodec==0
#endif
  );

  assert( pPager->eState>=PAGER_READER );
  assert( assert_pager_state(pPager) );
44085
44086
44087
44088
44089
44090
44091
44092

44093
44094
44095
44096
44097
44098


44099
44100
44101
44102
44103
44104
44105
44227
44228
44229
44230
44231
44232
44233

44234
44235
44236
44237
44238


44239
44240
44241
44242
44243
44244
44245
44246
44247







-
+




-
-
+
+







  if( nPagePerSector>1 ){
    Pgno nPageCount;          /* Total number of pages in database file */
    Pgno pg1;                 /* First page of the sector pPg is located on. */
    int nPage = 0;            /* Number of pages starting at pg1 to journal */
    int ii;                   /* Loop counter */
    int needSync = 0;         /* True if any page has PGHDR_NEED_SYNC */

    /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
    /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
    ** a journal header to be written between the pages journaled by
    ** this function.
    */
    assert( !MEMDB );
    assert( pPager->doNotSyncSpill==0 );
    pPager->doNotSyncSpill++;
    assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
    pPager->doNotSpill |= SPILLFLAG_NOSYNC;

    /* This trick assumes that both the page-size and sector-size are
    ** an integer power of 2. It sets variable pg1 to the identifier
    ** of the first page of the sector pPg is located on.
    */
    pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;

44150
44151
44152
44153
44154
44155
44156
44157
44158


44159
44160
44161
44162
44163
44164
44165
44292
44293
44294
44295
44296
44297
44298


44299
44300
44301
44302
44303
44304
44305
44306
44307







-
-
+
+







        if( pPage ){
          pPage->flags |= PGHDR_NEED_SYNC;
          sqlite3PagerUnref(pPage);
        }
      }
    }

    assert( pPager->doNotSyncSpill==1 );
    pPager->doNotSyncSpill--;
    assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
    pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
  }else{
    rc = pager_write(pDbPage);
  }
  return rc;
}

/*
49147
49148
49149
49150
49151
49152
49153
49154
49155
49156
49157
49158
49159
49160
49161








49162
49163
49164
49165
49166
49167
49168
49169
49170
49171
49172
49173
49174
49175
49176
49177

49178
49179


49180
49181
49182
49183
49184
49185
49186
49289
49290
49291
49292
49293
49294
49295



49296
49297
49298
49299
49300
49301
49302
49303
49304
49305
49306
49307
49308
49309
49310
49311
49312
49313
49314
49315
49316
49317
49318
49319
49320
49321
49322
49323
49324
49325


49326
49327
49328
49329
49330
49331
49332
49333
49334







-
-
-





+
+
+
+
+
+
+
+
















+
-
-
+
+







  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
};

/*
** Potential values for BtCursor.eState.
**
** CURSOR_VALID:
**   Cursor points to a valid entry. getPayload() etc. may be called.
**
** CURSOR_INVALID:
**   Cursor does not point to a valid entry. This can happen (for example) 
**   because the table is empty or because BtreeCursorFirst() has not been
**   called.
**
** CURSOR_VALID:
**   Cursor points to a valid entry. getPayload() etc. may be called.
**
** CURSOR_SKIPNEXT:
**   Cursor is valid except that the Cursor.skipNext field is non-zero
**   indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
**   operation should be a no-op.
**
** CURSOR_REQUIRESEEK:
**   The table that this cursor was opened on still exists, but has been 
**   modified since the cursor was last used. The cursor position is saved
**   in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in 
**   this state, restoreCursorPosition() can be called to attempt to
**   seek the cursor to the saved position.
**
** CURSOR_FAULT:
**   A unrecoverable error (an I/O error or a malloc failure) has occurred
**   on a different connection that shares the BtShared cache with this
**   cursor.  The error has left the cache in an inconsistent state.
**   Do nothing else with this cursor.  Any attempt to use the cursor
**   should return the error code stored in BtCursor.skip
*/
#define CURSOR_INVALID           0
#define CURSOR_VALID             1
#define CURSOR_SKIPNEXT          2
#define CURSOR_REQUIRESEEK       2
#define CURSOR_FAULT             3
#define CURSOR_REQUIRESEEK       3
#define CURSOR_FAULT             4

/* 
** The database page the PENDING_BYTE occupies. This page is never used.
*/
# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)

/*
50286
50287
50288
50289
50290
50291
50292



50293
50294
50295
50296
50297
50298
50299
50434
50435
50436
50437
50438
50439
50440
50441
50442
50443
50444
50445
50446
50447
50448
50449
50450







+
+
+







  }
  pCur->eState = CURSOR_INVALID;
  rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext);
  if( rc==SQLITE_OK ){
    sqlite3_free(pCur->pKey);
    pCur->pKey = 0;
    assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
    if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
      pCur->eState = CURSOR_SKIPNEXT;
    }
  }
  return rc;
}

#define restoreCursorPosition(p) \
  (p->eState>=CURSOR_REQUIRESEEK ? \
         btreeRestoreCursorPosition(p) : \
50311
50312
50313
50314
50315
50316
50317
50318

50319
50320
50321
50322
50323
50324
50325
50462
50463
50464
50465
50466
50467
50468

50469
50470
50471
50472
50473
50474
50475
50476







-
+







  int rc;

  rc = restoreCursorPosition(pCur);
  if( rc ){
    *pHasMoved = 1;
    return rc;
  }
  if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){
  if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
    *pHasMoved = 1;
  }else{
    *pHasMoved = 0;
  }
  return SQLITE_OK;
}

50499
50500
50501
50502
50503
50504
50505

50506

50507
50508
50509
50510
50511
50512
50513
50650
50651
50652
50653
50654
50655
50656
50657

50658
50659
50660
50661
50662
50663
50664
50665







+
-
+








  pInfo->pCell = pCell;
  assert( pPage->leaf==0 || pPage->leaf==1 );
  n = pPage->childPtrSize;
  assert( n==4-4*pPage->leaf );
  if( pPage->intKey ){
    if( pPage->hasData ){
      assert( n==0 );
      n += getVarint32(&pCell[n], nPayload);
      n = getVarint32(pCell, nPayload);
    }else{
      nPayload = 0;
    }
    n += getVarint(&pCell[n], (u64*)&pInfo->nKey);
    pInfo->nData = nPayload;
  }else{
    pInfo->nData = 0;
51143
51144
51145
51146
51147
51148
51149
51150

51151
51152
51153
51154
51155
51156
51157
51158

51159
51160
51161
51162
51163
51164
51165
51295
51296
51297
51298
51299
51300
51301

51302

51303
51304
51305


51306

51307
51308
51309
51310
51311
51312
51313
51314







-
+
-



-
-

-
+







** means we have started to be concerned about content and the disk
** read should occur at that point.
*/
static int btreeGetPage(
  BtShared *pBt,       /* The btree */
  Pgno pgno,           /* Number of the page to fetch */
  MemPage **ppPage,    /* Return the page in this parameter */
  int noContent,       /* Do not load page content if true */
  int flags            /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
  int bReadonly        /* True if a read-only (mmap) page is ok */
){
  int rc;
  DbPage *pDbPage;
  int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0) 
            | (bReadonly ? PAGER_ACQUIRE_READONLY : 0);

  assert( noContent==0 || bReadonly==0 );
  assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY );
  assert( sqlite3_mutex_held(pBt->mutex) );
  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
  if( rc ) return rc;
  *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
  return SQLITE_OK;
}

51199
51200
51201
51202
51203
51204
51205
51206

51207
51208
51209

51210
51211
51212
51213
51214

51215
51216
51217
51218
51219
51220
51221
51348
51349
51350
51351
51352
51353
51354

51355
51356
51357
51358
51359
51360
51361
51362
51363

51364
51365
51366
51367
51368
51369
51370
51371







-
+



+




-
+







** If an error occurs, then the value *ppPage is set to is undefined. It
** may remain unchanged, or it may be set to an invalid value.
*/
static int getAndInitPage(
  BtShared *pBt,                  /* The database file */
  Pgno pgno,                      /* Number of the page to get */
  MemPage **ppPage,               /* Write the page pointer here */
  int bReadonly                   /* True if a read-only (mmap) page is ok */
  int bReadonly                   /* PAGER_GET_READONLY or 0 */
){
  int rc;
  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( bReadonly==PAGER_GET_READONLY || bReadonly==0 );

  if( pgno>btreePagecount(pBt) ){
    rc = SQLITE_CORRUPT_BKPT;
  }else{
    rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly);
    rc = btreeGetPage(pBt, pgno, ppPage, bReadonly);
    if( rc==SQLITE_OK ){
      rc = btreeInitPage(*ppPage);
      if( rc!=SQLITE_OK ){
        releasePage(*ppPage);
      }
    }
  }
51727
51728
51729
51730
51731
51732
51733
51734

51735
51736
51737
51738

51739
51740
51741
51742
51743
51744

51745
51746
51747
51748
51749
51750
51751
51877
51878
51879
51880
51881
51882
51883

51884
51885



51886
51887
51888
51889

51890

51891
51892
51893
51894
51895
51896
51897
51898







-
+

-
-
-
+



-

-
+







** how well the database resists damage due to OS crashes and power
** failures.  Level 1 is the same as asynchronous (no syncs() occur and
** there is a high probability of damage)  Level 2 is the default.  There
** is a very low but non-zero probability of damage.  Level 3 reduces the
** probability of damage to near zero but with a write performance reduction.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(
SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(
  Btree *p,              /* The btree to set the safety level on */
  int level,             /* PRAGMA synchronous.  1=OFF, 2=NORMAL, 3=FULL */
  int fullSync,          /* PRAGMA fullfsync. */
  int ckptFullSync       /* PRAGMA checkpoint_fullfync */
  unsigned pgFlags       /* Various PAGER_* flags */
){
  BtShared *pBt = p->pBt;
  assert( sqlite3_mutex_held(p->db->mutex) );
  assert( level>=1 && level<=3 );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync);
  sqlite3PagerSetFlags(pBt->pPager, pgFlags);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}
#endif

/*
** Return TRUE if the given btree is set to safety level 1.  In other
51943
51944
51945
51946
51947
51948
51949
51950

51951
51952
51953
51954
51955
51956
51957
52090
52091
52092
52093
52094
52095
52096

52097
52098
52099
52100
52101
52102
52103
52104







-
+







  int nPageFile = 0;   /* Number of pages in the database file */
  int nPageHeader;     /* Number of pages in the database according to hdr */

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( pBt->pPage1==0 );
  rc = sqlite3PagerSharedLock(pBt->pPager);
  if( rc!=SQLITE_OK ) return rc;
  rc = btreeGetPage(pBt, 1, &pPage1, 0, 0);
  rc = btreeGetPage(pBt, 1, &pPage1, 0);
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */
  nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
  sqlite3PagerPagecount(pBt->pPager, &nPageFile);
52071
52072
52073
52074
52075
52076
52077

52078
52079
52080
52081
52082
52083
52084
52218
52219
52220
52221
52222
52223
52224
52225
52226
52227
52228
52229
52230
52231
52232







+







    pBt->max1bytePayload = 127;
  }else{
    pBt->max1bytePayload = (u8)pBt->maxLocal;
  }
  assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
  pBt->pPage1 = pPage1;
  pBt->nPage = nPage;
assert( pPage1->leaf==0 || pPage1->leaf==1 );
  return SQLITE_OK;

page1_init_failed:
  releasePage(pPage1);
  pBt->pPage1 = 0;
  return rc;
}
52525
52526
52527
52528
52529
52530
52531
52532

52533
52534
52535
52536
52537
52538
52539
52673
52674
52675
52676
52677
52678
52679

52680
52681
52682
52683
52684
52685
52686
52687







-
+







  }

  /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
  ** that it points at iFreePage. Also fix the pointer map entry for
  ** iPtrPage.
  */
  if( eType!=PTRMAP_ROOTPAGE ){
    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0);
    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    rc = sqlite3PagerWrite(pPtrPage->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(pPtrPage);
      return rc;
52609
52610
52611
52612
52613
52614
52615
52616

52617
52618
52619
52620
52621
52622
52623
52757
52758
52759
52760
52761
52762
52763

52764
52765
52766
52767
52768
52769
52770
52771







-
+







      }
    } else {
      Pgno iFreePg;             /* Index of free page to move pLastPg to */
      MemPage *pLastPg;
      u8 eMode = BTALLOC_ANY;   /* Mode parameter for allocateBtreePage() */
      Pgno iNear = 0;           /* nearby parameter for allocateBtreePage() */

      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0);
      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }

      /* If bCommit is zero, this loop runs exactly once and page pLastPg
      ** is swapped with the first free page pulled off the free list.
      **
53008
53009
53010
53011
53012
53013
53014
53015

53016
53017
53018
53019
53020
53021
53022
53156
53157
53158
53159
53160
53161
53162

53163
53164
53165
53166
53167
53168
53169
53170







-
+







    if( rc2!=SQLITE_OK ){
      rc = rc2;
    }

    /* The rollback may have destroyed the pPage1->aData value.  So
    ** call btreeGetPage() on page 1 again to make
    ** sure pPage1->aData is set correctly. */
    if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){
    if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
      int nPage = get4byte(28+(u8*)pPage1->aData);
      testcase( nPage==0 );
      if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
      testcase( pBt->nPage!=nPage );
      pBt->nPage = nPage;
      releasePage(pPage1);
    }
53443
53444
53445
53446
53447
53448
53449
53450

53451
53452
53453
53454
53455
53456
53457
53591
53592
53593
53594
53595
53596
53597

53598
53599
53600
53601
53602
53603
53604
53605







-
+







      }
    }
  }
#endif

  assert( next==0 || rc==SQLITE_DONE );
  if( rc==SQLITE_OK ){
    rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0));
    rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0);
    assert( rc==SQLITE_OK || pPage==0 );
    if( rc==SQLITE_OK ){
      next = get4byte(pPage->aData);
    }
  }

  *pPgnoNext = next;
53665
53666
53667
53668
53669
53670
53671
53672

53673
53674
53675
53676
53677
53678
53679
53813
53814
53815
53816
53817
53818
53819

53820
53821
53822
53823
53824
53825
53826
53827







-
+







          memcpy(aWrite, aSave, 4);
        }else
#endif

        {
          DbPage *pDbPage;
          rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
              (eOp==0 ? PAGER_ACQUIRE_READONLY : 0)
              (eOp==0 ? PAGER_GET_READONLY : 0)
          );
          if( rc==SQLITE_OK ){
            aPayload = sqlite3PagerGetData(pDbPage);
            nextPage = get4byte(aPayload);
            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
            sqlite3PagerUnref(pDbPage);
            offset = 0;
53849
53850
53851
53852
53853
53854
53855
53856


53857
53858
53859
53860
53861
53862
53863
53997
53998
53999
54000
54001
54002
54003

54004
54005
54006
54007
54008
54009
54010
54011
54012







-
+
+







  assert( cursorHoldsMutex(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
  assert( pCur->iPage>=0 );
  if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
    return SQLITE_CORRUPT_BKPT;
  }
  rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0));
  rc = getAndInitPage(pBt, newPgno, &pNewPage,
               pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
  if( rc ) return rc;
  pCur->apPage[i+1] = pNewPage;
  pCur->aiIdx[i+1] = 0;
  pCur->iPage++;

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
53966
53967
53968
53969
53970
53971
53972
53973


53974
53975
53976
53977
53978
53979
53980
54115
54116
54117
54118
54119
54120
54121

54122
54123
54124
54125
54126
54127
54128
54129
54130







-
+
+







      releasePage(pCur->apPage[i]);
    }
    pCur->iPage = 0;
  }else if( pCur->pgnoRoot==0 ){
    pCur->eState = CURSOR_INVALID;
    return SQLITE_OK;
  }else{
    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0);
    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0],
                        pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    pCur->iPage = 0;

    /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
54361
54362
54363
54364
54365
54366
54367



54368
54369
54370
54371





54372
54373
54374
54375
54376
54377
54378
54379
54380
54381
54382















54383
54384
54385
54386
54387
54388
54389
54390
54391
54392
54393
54394
54395
54396
54397
54398
54399
54400




54401
54402
54403
54404
54405
54406
54407
54511
54512
54513
54514
54515
54516
54517
54518
54519
54520




54521
54522
54523
54524
54525











54526
54527
54528
54529
54530
54531
54532
54533
54534
54535
54536
54537
54538
54539
54540
54541
54542
54543
54544
54545
54546
54547
54548
54549
54550
54551
54552
54553
54554
54555
54556
54557

54558
54559
54560
54561
54562
54563
54564
54565
54566
54567
54568







+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
+
+
+
+







*/
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
  int rc;
  int idx;
  MemPage *pPage;

  assert( cursorHoldsMutex(pCur) );
  assert( pRes!=0 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  if( pCur->eState!=CURSOR_VALID ){
  rc = restoreCursorPosition(pCur);
  if( rc!=SQLITE_OK ){
    return rc;
  }
    rc = restoreCursorPosition(pCur);
    if( rc!=SQLITE_OK ){
      *pRes = 0;
      return rc;
    }
  assert( pRes!=0 );
  if( CURSOR_INVALID==pCur->eState ){
    *pRes = 1;
    return SQLITE_OK;
  }
  if( pCur->skipNext>0 ){
    pCur->skipNext = 0;
    *pRes = 0;
    return SQLITE_OK;
  }
  pCur->skipNext = 0;
    if( CURSOR_INVALID==pCur->eState ){
      *pRes = 1;
      return SQLITE_OK;
    }
    if( pCur->skipNext ){
      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
      pCur->eState = CURSOR_VALID;
      if( pCur->skipNext>0 ){
        pCur->skipNext = 0;
        *pRes = 0;
        return SQLITE_OK;
      }
      pCur->skipNext = 0;
    }
  }

  pPage = pCur->apPage[pCur->iPage];
  idx = ++pCur->aiIdx[pCur->iPage];
  assert( pPage->isInit );

  /* If the database file is corrupt, it is possible for the value of idx 
  ** to be invalid here. This can only occur if a second cursor modifies
  ** the page while cursor pCur is holding a reference to it. Which can
  ** only happen if the database is corrupt in such a way as to link the
  ** page into more than one b-tree structure. */
  testcase( idx>pPage->nCell );

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
  if( idx>=pPage->nCell ){
    if( !pPage->leaf ){
      rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
      if( rc ) return rc;
      if( rc ){
        *pRes = 0;
        return rc;
      }
      rc = moveToLeftmost(pCur);
      *pRes = 0;
      return rc;
    }
    do{
      if( pCur->iPage==0 ){
        *pRes = 1;
54435
54436
54437
54438
54439
54440
54441





54442
54443
54444
54445





54446
54447
54448
54449
54450
54451
54452
54453
54454
54455
54456
















54457
54458
54459
54460
54461
54462
54463

54464
54465
54466
54467
54468
54469
54470
54596
54597
54598
54599
54600
54601
54602
54603
54604
54605
54606
54607




54608
54609
54610
54611
54612











54613
54614
54615
54616
54617
54618
54619
54620
54621
54622
54623
54624
54625
54626
54627
54628
54629
54630
54631
54632
54633
54634
54635
54636
54637
54638
54639
54640
54641
54642
54643







+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+







** this routine was called, then set *pRes=1.
*/
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
  int rc;
  MemPage *pPage;

  assert( cursorHoldsMutex(pCur) );
  assert( pRes!=0 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  pCur->atLast = 0;
  if( pCur->eState!=CURSOR_VALID ){
    if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
  rc = restoreCursorPosition(pCur);
  if( rc!=SQLITE_OK ){
    return rc;
  }
      rc = btreeRestoreCursorPosition(pCur);
      if( rc!=SQLITE_OK ){
        *pRes = 0;
        return rc;
      }
  pCur->atLast = 0;
  if( CURSOR_INVALID==pCur->eState ){
    *pRes = 1;
    return SQLITE_OK;
  }
  if( pCur->skipNext<0 ){
    pCur->skipNext = 0;
    *pRes = 0;
    return SQLITE_OK;
  }
  pCur->skipNext = 0;
    }
    if( CURSOR_INVALID==pCur->eState ){
      *pRes = 1;
      return SQLITE_OK;
    }
    if( pCur->skipNext ){
      assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
      pCur->eState = CURSOR_VALID;
      if( pCur->skipNext<0 ){
        pCur->skipNext = 0;
        *pRes = 0;
        return SQLITE_OK;
      }
      pCur->skipNext = 0;
    }
  }

  pPage = pCur->apPage[pCur->iPage];
  assert( pPage->isInit );
  if( !pPage->leaf ){
    int idx = pCur->aiIdx[pCur->iPage];
    rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
    if( rc ){
      *pRes = 0;
      return rc;
    }
    rc = moveToRightmost(pCur);
  }else{
    while( pCur->aiIdx[pCur->iPage]==0 ){
      if( pCur->iPage==0 ){
        pCur->eState = CURSOR_INVALID;
54580
54581
54582
54583
54584
54585
54586
54587

54588
54589
54590
54591
54592
54593
54594
54753
54754
54755
54756
54757
54758
54759

54760
54761
54762
54763
54764
54765
54766
54767







-
+







      }else{
        iTrunk = get4byte(&pPage1->aData[32]);
      }
      testcase( iTrunk==mxPage );
      if( iTrunk>mxPage ){
        rc = SQLITE_CORRUPT_BKPT;
      }else{
        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
      }
      if( rc ){
        pTrunk = 0;
        goto end_allocate_page;
      }
      assert( pTrunk!=0 );
      assert( pTrunk->aData!=0 );
54644
54645
54646
54647
54648
54649
54650
54651

54652
54653
54654
54655
54656
54657
54658
54817
54818
54819
54820
54821
54822
54823

54824
54825
54826
54827
54828
54829
54830
54831







-
+







          MemPage *pNewTrunk;
          Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
          if( iNewTrunk>mxPage ){ 
            rc = SQLITE_CORRUPT_BKPT;
            goto end_allocate_page;
          }
          testcase( iNewTrunk==mxPage );
          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0);
          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
          if( rc!=SQLITE_OK ){
            goto end_allocate_page;
          }
          rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
          if( rc!=SQLITE_OK ){
            releasePage(pNewTrunk);
            goto end_allocate_page;
54723
54724
54725
54726
54727
54728
54729
54730
54731


54732
54733
54734
54735
54736
54737
54738
54896
54897
54898
54899
54900
54901
54902


54903
54904
54905
54906
54907
54908
54909
54910
54911







-
-
+
+







                 *pPgno, closest+1, k, pTrunk->pgno, n-1));
          rc = sqlite3PagerWrite(pTrunk->pDbPage);
          if( rc ) goto end_allocate_page;
          if( closest<k-1 ){
            memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
          }
          put4byte(&aData[4], k-1);
          noContent = !btreeGetHasContent(pBt, *pPgno);
          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent, 0);
          noContent = !btreeGetHasContent(pBt, *pPgno) ? PAGER_GET_NOCONTENT : 0;
          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
          if( rc==SQLITE_OK ){
            rc = sqlite3PagerWrite((*ppPage)->pDbPage);
            if( rc!=SQLITE_OK ){
              releasePage(*ppPage);
            }
          }
          searchList = 0;
54756
54757
54758
54759
54760
54761
54762
54763

54764
54765
54766
54767
54768
54769
54770
54771
54772
54773
54774
54775
54776
54777
54778
54779

54780
54781
54782
54783
54784
54785
54786
54787
54788
54789
54790
54791
54792
54793

54794
54795
54796
54797
54798
54799
54800
54929
54930
54931
54932
54933
54934
54935

54936
54937
54938
54939
54940
54941
54942
54943
54944
54945
54946
54947
54948
54949
54950
54951

54952
54953
54954
54955
54956
54957
54958
54959
54960
54961
54962
54963
54964
54965

54966
54967
54968
54969
54970
54971
54972
54973







-
+















-
+













-
+







    **
    ** Note that the pager will not actually attempt to load or journal 
    ** content for any page that really does lie past the end of the database
    ** file on disk. So the effects of disabling the no-content optimization
    ** here are confined to those pages that lie between the end of the
    ** database image and the end of the database file.
    */
    int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate));
    int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate)) ? PAGER_GET_NOCONTENT : 0;

    rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
    if( rc ) return rc;
    pBt->nPage++;
    if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;

#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){
      /* If *pPgno refers to a pointer-map page, allocate two new pages
      ** at the end of the file instead of one. The first allocated page
      ** becomes a new pointer-map page, the second is used by the caller.
      */
      MemPage *pPg = 0;
      TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
      assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0);
      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
      if( rc==SQLITE_OK ){
        rc = sqlite3PagerWrite(pPg->pDbPage);
        releasePage(pPg);
      }
      if( rc ) return rc;
      pBt->nPage++;
      if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
    }
#endif
    put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
    *pPgno = pBt->nPage;

    assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0);
    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
    if( rc ) return rc;
    rc = sqlite3PagerWrite((*ppPage)->pDbPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
    }
    TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  }
54854
54855
54856
54857
54858
54859
54860
54861

54862
54863
54864
54865
54866
54867
54868
55027
55028
55029
55030
55031
55032
55033

55034
55035
55036
55037
55038
55039
55040
55041







-
+







  nFree = get4byte(&pPage1->aData[36]);
  put4byte(&pPage1->aData[36], nFree+1);

  if( pBt->btsFlags & BTS_SECURE_DELETE ){
    /* If the secure_delete option is enabled, then
    ** always fully overwrite deleted information with zeros.
    */
    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) )
    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
     ||            ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
    ){
      goto freepage_out;
    }
    memset(pPage->aData, 0, pPage->pBt->pageSize);
  }

54881
54882
54883
54884
54885
54886
54887
54888

54889
54890
54891
54892
54893
54894
54895
55054
55055
55056
55057
55058
55059
55060

55061
55062
55063
55064
55065
55066
55067
55068







-
+







  ** first trunk page in the current free-list. This block tests if it
  ** is possible to add the page as a new free-list leaf.
  */
  if( nFree!=0 ){
    u32 nLeaf;                /* Initial number of leaf cells on trunk page */

    iTrunk = get4byte(&pPage1->aData[32]);
    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
    if( rc!=SQLITE_OK ){
      goto freepage_out;
    }

    nLeaf = get4byte(&pTrunk->aData[4]);
    assert( pBt->usableSize>32 );
    if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
54927
54928
54929
54930
54931
54932
54933
54934

54935
54936
54937
54938
54939
54940
54941
55100
55101
55102
55103
55104
55105
55106

55107
55108
55109
55110
55111
55112
55113
55114







-
+








  /* If control flows to this point, then it was not possible to add the
  ** the page being freed as a leaf page of the first trunk in the free-list.
  ** Possibly because the free-list is empty, or possibly because the 
  ** first trunk in the free-list is full. Either way, the page being freed
  ** will become the new first trunk page in the free-list.
  */
  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){
  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
    goto freepage_out;
  }
  rc = sqlite3PagerWrite(pPage->pDbPage);
  if( rc!=SQLITE_OK ){
    goto freepage_out;
  }
  put4byte(pPage->aData, iTrunk);
56826
56827
56828
56829
56830
56831
56832
56833

56834
56835
56836
56837
56838
56839
56840
56841
56842
56843
56844
56845
56846
56847
56848
56849
56850
56851
56852
56853
56854

56855
56856
56857
56858
56859
56860
56861
56999
57000
57001
57002
57003
57004
57005

57006
57007
57008
57009
57010
57011
57012
57013
57014
57015
57016
57017
57018
57019
57020
57021
57022
57023
57024
57025
57026

57027
57028
57029
57030
57031
57032
57033
57034







-
+




















-
+







      rc = saveAllCursors(pBt, 0, 0);
      releasePage(pPageMove);
      if( rc!=SQLITE_OK ){
        return rc;
      }

      /* Move the page currently at pgnoRoot to pgnoMove. */
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
      if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
        rc = SQLITE_CORRUPT_BKPT;
      }
      if( rc!=SQLITE_OK ){
        releasePage(pRoot);
        return rc;
      }
      assert( eType!=PTRMAP_ROOTPAGE );
      assert( eType!=PTRMAP_FREEPAGE );
      rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
      releasePage(pRoot);

      /* Obtain the page at pgnoRoot */
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      rc = sqlite3PagerWrite(pRoot->pDbPage);
      if( rc!=SQLITE_OK ){
        releasePage(pRoot);
        return rc;
57025
57026
57027
57028
57029
57030
57031
57032

57033
57034
57035
57036
57037
57038
57039
57198
57199
57200
57201
57202
57203
57204

57205
57206
57207
57208
57209
57210
57211
57212







-
+







  ** This error is caught long before control reaches this point.
  */
  if( NEVER(pBt->pCursor) ){
    sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
    return SQLITE_LOCKED_SHAREDCACHE;
  }

  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0);
  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
  if( rc ) return rc;
  rc = sqlite3BtreeClearTable(p, iTable, 0);
  if( rc ){
    releasePage(pPage);
    return rc;
  }

57060
57061
57062
57063
57064
57065
57066
57067

57068
57069
57070
57071
57072
57073
57074
57075
57076
57077

57078
57079
57080
57081
57082
57083
57084
57233
57234
57235
57236
57237
57238
57239

57240
57241
57242
57243
57244
57245
57246
57247
57248
57249

57250
57251
57252
57253
57254
57255
57256
57257







-
+









-
+







      }else{
        /* The table being dropped does not have the largest root-page
        ** number in the database. So move the page that does into the 
        ** gap left by the deleted root-page.
        */
        MemPage *pMove;
        releasePage(pPage);
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
        releasePage(pMove);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        pMove = 0;
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
        freePage(pMove, &rc);
        releasePage(pMove);
        if( rc!=SQLITE_OK ){
          return rc;
        }
        *piMoved = maxRootPgno;
      }
57285
57286
57287
57288
57289
57290
57291
57292

57293
57294
57295
57296
57297
57298
57299
57458
57459
57460
57461
57462
57463
57464

57465
57466
57467
57468
57469
57470
57471
57472







-
+







    sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
  }
  if( zMsg1 ){
    sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1);
  }
  sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
  va_end(ap);
  if( pCheck->errMsg.mallocFailed ){
  if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
    pCheck->mallocFailed = 1;
  }
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK

57482
57483
57484
57485
57486
57487
57488
57489

57490
57491
57492
57493
57494
57495
57496
57655
57656
57657
57658
57659
57660
57661

57662
57663
57664
57665
57666
57667
57668
57669







-
+








  /* Check that the page exists
  */
  pBt = pCheck->pBt;
  usableSize = pBt->usableSize;
  if( iPage==0 ) return 0;
  if( checkRef(pCheck, iPage, zParentContext) ) return 0;
  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){
  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
    checkAppendMsg(pCheck, zContext,
       "unable to get the page. error code=%d", rc);
    return 0;
  }

  /* Clear MemPage.isInit to make sure the corruption detection code in
  ** btreeInitPage() is executed.  */
58441
58442
58443
58444
58445
58446
58447
58448

58449
58450
58451
58452
58453
58454
58455
58614
58615
58616
58617
58618
58619
58620

58621
58622
58623
58624
58625
58626
58627
58628







-
+







    nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
    assert( nSrcPage>=0 );
    for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
      const Pgno iSrcPg = p->iNext;                 /* Source page number */
      if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
        DbPage *pSrcPg;                             /* Source page object */
        rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
                                 PAGER_ACQUIRE_READONLY);
                                 PAGER_GET_READONLY);
        if( rc==SQLITE_OK ){
          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
          sqlite3PagerUnref(pSrcPg);
        }
      }
      p->iNext++;
    }
59596
59597
59598
59599
59600
59601
59602

59603
59604


59605
59606
59607


59608
59609
59610
59611
59612
59613
59614
59615
59616
59617
59618












59619
59620
59621
59622
59623





59624
59625
59626
59627
59628
59629
59630
59631
59632
59633
59634
59635
59636
59637
59769
59770
59771
59772
59773
59774
59775
59776


59777
59778



59779
59780
59781










59782
59783
59784
59785
59786
59787
59788
59789
59790
59791
59792
59793





59794
59795
59796
59797
59798







59799
59800
59801
59802
59803
59804
59805







+
-
-
+
+
-
-
-
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-







  }

  /* If one value is a number and the other is not, the number is less.
  ** If both are numbers, compare as reals if one is a real, or as integers
  ** if both values are integers.
  */
  if( combined_flags&(MEM_Int|MEM_Real) ){
    double r1, r2;
    if( !(f1&(MEM_Int|MEM_Real)) ){
      return 1;
    if( (f1 & f2 & MEM_Int)!=0 ){
      if( pMem1->u.i < pMem2->u.i ) return -1;
    }
    if( !(f2&(MEM_Int|MEM_Real)) ){
      return -1;
      if( pMem1->u.i > pMem2->u.i ) return 1;
      return 0;
    }
    if( (f1 & f2 & MEM_Int)==0 ){
      double r1, r2;
      if( (f1&MEM_Real)==0 ){
        r1 = (double)pMem1->u.i;
      }else{
        r1 = pMem1->r;
      }
      if( (f2&MEM_Real)==0 ){
        r2 = (double)pMem2->u.i;
      }else{
    if( (f1&MEM_Real)!=0 ){
      r1 = pMem1->r;
    }else if( (f1&MEM_Int)!=0 ){
      r1 = (double)pMem1->u.i;
    }else{
      return 1;
    }
    if( (f2&MEM_Real)!=0 ){
      r2 = pMem2->r;
    }else if( (f2&MEM_Int)!=0 ){
      r2 = (double)pMem2->u.i;
    }else{
        r2 = pMem2->r;
      }
      if( r1<r2 ) return -1;
      if( r1>r2 ) return 1;
      return 0;
      return -1;
    }
    if( r1<r2 ) return -1;
    if( r1>r2 ) return 1;
    return 0;
    }else{
      assert( f1&MEM_Int );
      assert( f2&MEM_Int );
      if( pMem1->u.i < pMem2->u.i ) return -1;
      if( pMem1->u.i > pMem2->u.i ) return 1;
      return 0;
    }
  }

  /* If one value is a string and the other is a blob, the string is less.
  ** If both are strings, compare using the collating functions.
  */
  if( combined_flags&MEM_Str ){
    if( (f1 & MEM_Str)==0 ){
59803
59804
59805
59806
59807
59808
59809









59810





59811










59812
59813
59814
59815
59816
59817














































59818
59819
59820
59821
59822
59823
59824







59825
59826
59827
59828
59829
59830

59831
59832
59833
59834
59835
59836
59837
59838

59839
59840

59841
59842

59843
59844
59845
59846
59847
59848
59849
59850
59851
59852
59853
59854
59855
59856
59857
59858
59859
59860

59861
59862
59863
59864
59865
59866
59867
59868
59869
59870
59871
59872
59873
59874
59875
59876
59877

59878
59879
59880
59881



59882
59883
59884
59885
59886
59887
59888
59889
59890
59891
59892
59893
59894

59895
59896
59897
59898
59899
59900
59901
59902

59903
59904
59905
59906
59907
59908
59909
59910
59911
59912
59913
59914
59915
59916

59917
59918
59919
59920


59921
59922




59923
59924
59925



















































































































































































59926
59927
59928
59929
59930
59931
59932
59971
59972
59973
59974
59975
59976
59977
59978
59979
59980
59981
59982
59983
59984
59985
59986

59987
59988
59989
59990
59991
59992
59993
59994
59995
59996
59997
59998
59999
60000
60001
60002






60003
60004
60005
60006
60007
60008
60009
60010
60011
60012
60013
60014
60015
60016
60017
60018
60019
60020
60021
60022
60023
60024
60025
60026
60027
60028
60029
60030
60031
60032
60033
60034
60035
60036
60037
60038
60039
60040
60041
60042
60043
60044
60045
60046
60047
60048
60049






60050
60051
60052
60053
60054
60055
60056
60057
60058
60059
60060
60061
60062
60063
60064
60065
60066
60067
60068
60069
60070

60071
60072

60073
60074

60075
60076
60077
60078
60079
60080
60081
60082
60083
60084
60085
60086
60087
60088
60089
60090
60091
60092

60093
60094
60095
60096
60097
60098
60099
60100
60101
60102
60103
60104
60105
60106
60107
60108
60109

60110
60111
60112
60113

60114
60115
60116
60117
60118
60119
60120
60121
60122
60123
60124
60125
60126
60127
60128

60129
60130
60131
60132
60133
60134
60135
60136

60137
60138
60139
60140
60141
60142
60143
60144
60145
60146
60147
60148
60149
60150

60151
60152
60153
60154
60155
60156
60157


60158
60159
60160
60161
60162
60163
60164
60165
60166
60167
60168
60169
60170
60171
60172
60173
60174
60175
60176
60177
60178
60179
60180
60181
60182
60183
60184
60185
60186
60187
60188
60189
60190
60191
60192
60193
60194
60195
60196
60197
60198
60199
60200
60201
60202
60203
60204
60205
60206
60207
60208
60209
60210
60211
60212
60213
60214
60215
60216
60217
60218
60219
60220
60221
60222
60223
60224
60225
60226
60227
60228
60229
60230
60231
60232
60233
60234
60235
60236
60237
60238
60239
60240
60241
60242
60243
60244
60245
60246
60247
60248
60249
60250
60251
60252
60253
60254
60255
60256
60257
60258
60259
60260
60261
60262
60263
60264
60265
60266
60267
60268
60269
60270
60271
60272
60273
60274
60275
60276
60277
60278
60279
60280
60281
60282
60283
60284
60285
60286
60287
60288
60289
60290
60291
60292
60293
60294
60295
60296
60297
60298
60299
60300
60301
60302
60303
60304
60305
60306
60307
60308
60309
60310
60311
60312
60313
60314
60315
60316
60317
60318
60319
60320
60321
60322
60323
60324
60325
60326
60327
60328
60329
60330
60331
60332
60333
60334
60335
60336
60337
60338
60339
60340
60341
60342
60343
60344
60345
60346
60347
60348
60349
60350







+
+
+
+
+
+
+
+
+
-
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+






+







-
+

-
+

-
+

















-
+
















-
+



-
+
+
+












-
+







-
+













-
+




+
+
-
-
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    p->type = SQLITE_NULL;
    p->db = db;
  }
  return p;
}

/*
** Context object passed by sqlite3Stat4ProbeSetValue() through to 
** valueNew(). See comments above valueNew() for details.
*/
struct ValueNewStat4Ctx {
  Parse *pParse;
  Index *pIdx;
  UnpackedRecord **ppRec;
  int iVal;
};
** Create a new sqlite3_value object, containing the value of pExpr.

/*
** Allocate and return a pointer to a new sqlite3_value object. If
** the second argument to this function is NULL, the object is allocated
** by calling sqlite3ValueNew().
**
** Otherwise, if the second argument is non-zero, then this function is 
** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
** already been allocated, allocate the UnpackedRecord structure that 
** that function will return to its caller here. Then return a pointer 
** an sqlite3_value within the UnpackedRecord.a[] array.
*/
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  if( p ){
    UnpackedRecord *pRec = p->ppRec[0];
** This only works for very simple expressions that consist of one constant
** token (i.e. "5", "5.1", "'a string'"). If the expression can
** be converted directly into a value, then the value is allocated and
** a pointer written to *ppVal. The caller is responsible for deallocating
** the value by passing it to sqlite3ValueFree() later on. If the expression
** cannot be converted to a value, then *ppVal is set to NULL.

    if( pRec==0 ){
      Index *pIdx = p->pIdx;      /* Index being probed */
      int nByte;                  /* Bytes of space to allocate */
      int i;                      /* Counter variable */
      int nCol = pIdx->nColumn+1; /* Number of index columns including rowid */
  
      nByte = sizeof(Mem) * nCol + sizeof(UnpackedRecord);
      pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
      if( pRec ){
        pRec->pKeyInfo = sqlite3IndexKeyinfo(p->pParse, pIdx);
        if( pRec->pKeyInfo ){
          assert( pRec->pKeyInfo->nField+1==nCol );
          pRec->pKeyInfo->enc = ENC(db);
          pRec->flags = UNPACKED_PREFIX_MATCH;
          pRec->aMem = (Mem *)&pRec[1];
          for(i=0; i<nCol; i++){
            pRec->aMem[i].flags = MEM_Null;
            pRec->aMem[i].type = SQLITE_NULL;
            pRec->aMem[i].db = db;
          }
        }else{
          sqlite3DbFree(db, pRec);
          pRec = 0;
        }
      }
      if( pRec==0 ) return 0;
      p->ppRec[0] = pRec;
    }
  
    pRec->nField = p->iVal+1;
    return &pRec->aMem[p->iVal];
  }
#endif
  return sqlite3ValueNew(db);
}

/*
** Extract a value from the supplied expression in the manner described
** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
** using valueNew().
**
** If pCtx is NULL and an error occurs after the sqlite3_value object
** has been allocated, it is freed before returning. Or, if pCtx is not
** NULL, it is assumed that the caller will free any allocated object
** in all cases.
*/
SQLITE_PRIVATE int sqlite3ValueFromExpr(
  sqlite3 *db,              /* The database connection */
  Expr *pExpr,              /* The expression to evaluate */
  u8 enc,                   /* Encoding to use */
  u8 affinity,              /* Affinity to use */
  sqlite3_value **ppVal     /* Write the new value here */
int valueFromExpr(
  sqlite3 *db,                    /* The database connection */
  Expr *pExpr,                    /* The expression to evaluate */
  u8 enc,                         /* Encoding to use */
  u8 affinity,                    /* Affinity to use */
  sqlite3_value **ppVal,          /* Write the new value here */
  struct ValueNewStat4Ctx *pCtx   /* Second argument for valueNew() */
){
  int op;
  char *zVal = 0;
  sqlite3_value *pVal = 0;
  int negInt = 1;
  const char *zNeg = "";
  int rc = SQLITE_OK;

  if( !pExpr ){
    *ppVal = 0;
    return SQLITE_OK;
  }
  op = pExpr->op;

  /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3.
  /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT4.
  ** The ifdef here is to enable us to achieve 100% branch test coverage even
  ** when SQLITE_ENABLE_STAT3 is omitted.
  ** when SQLITE_ENABLE_STAT4 is omitted.
  */
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  if( op==TK_REGISTER ) op = pExpr->op2;
#else
  if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
#endif

  /* Handle negative integers in a single step.  This is needed in the
  ** case when the value is -9223372036854775808.
  */
  if( op==TK_UMINUS
   && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
    pExpr = pExpr->pLeft;
    op = pExpr->op;
    negInt = -1;
    zNeg = "-";
  }

  if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
    pVal = sqlite3ValueNew(db);
    pVal = valueNew(db, pCtx);
    if( pVal==0 ) goto no_mem;
    if( ExprHasProperty(pExpr, EP_IntValue) ){
      sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
    }else{
      zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
      if( zVal==0 ) goto no_mem;
      sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
      if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
    }
    if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
      sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
    }else{
      sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
    }
    if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
    if( enc!=SQLITE_UTF8 ){
      sqlite3VdbeChangeEncoding(pVal, enc);
      rc = sqlite3VdbeChangeEncoding(pVal, enc);
    }
  }else if( op==TK_UMINUS ) {
    /* This branch happens for multiple negative signs.  Ex: -(-5) */
    if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
    if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) 
     && pVal!=0
    ){
      sqlite3VdbeMemNumerify(pVal);
      if( pVal->u.i==SMALLEST_INT64 ){
        pVal->flags &= MEM_Int;
        pVal->flags |= MEM_Real;
        pVal->r = (double)LARGEST_INT64;
      }else{
        pVal->u.i = -pVal->u.i;
      }
      pVal->r = -pVal->r;
      sqlite3ValueApplyAffinity(pVal, affinity, enc);
    }
  }else if( op==TK_NULL ){
    pVal = sqlite3ValueNew(db);
    pVal = valueNew(db, pCtx);
    if( pVal==0 ) goto no_mem;
  }
#ifndef SQLITE_OMIT_BLOB_LITERAL
  else if( op==TK_BLOB ){
    int nVal;
    assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
    assert( pExpr->u.zToken[1]=='\'' );
    pVal = sqlite3ValueNew(db);
    pVal = valueNew(db, pCtx);
    if( !pVal ) goto no_mem;
    zVal = &pExpr->u.zToken[2];
    nVal = sqlite3Strlen30(zVal)-1;
    assert( zVal[nVal]=='\'' );
    sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
                         0, SQLITE_DYNAMIC);
  }
#endif

  if( pVal ){
    sqlite3VdbeMemStoreType(pVal);
  }
  *ppVal = pVal;
  return SQLITE_OK;
  return rc;

no_mem:
  db->mallocFailed = 1;
  sqlite3DbFree(db, zVal);
  assert( *ppVal==0 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  sqlite3ValueFree(pVal);
  *ppVal = 0;
  if( pCtx==0 ) sqlite3ValueFree(pVal);
#else
  assert( pCtx==0 ); sqlite3ValueFree(pVal);
#endif
  return SQLITE_NOMEM;
}

/*
** Create a new sqlite3_value object, containing the value of pExpr.
**
** This only works for very simple expressions that consist of one constant
** token (i.e. "5", "5.1", "'a string'"). If the expression can
** be converted directly into a value, then the value is allocated and
** a pointer written to *ppVal. The caller is responsible for deallocating
** the value by passing it to sqlite3ValueFree() later on. If the expression
** cannot be converted to a value, then *ppVal is set to NULL.
*/
SQLITE_PRIVATE int sqlite3ValueFromExpr(
  sqlite3 *db,              /* The database connection */
  Expr *pExpr,              /* The expression to evaluate */
  u8 enc,                   /* Encoding to use */
  u8 affinity,              /* Affinity to use */
  sqlite3_value **ppVal     /* Write the new value here */
){
  return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0);
}

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** The implementation of the sqlite_record() function. This function accepts
** a single argument of any type. The return value is a formatted database 
** record (a blob) containing the argument value.
**
** This is used to convert the value stored in the 'sample' column of the
** sqlite_stat3 table to the record format SQLite uses internally.
*/
static void recordFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const int file_format = 1;
  int iSerial;                    /* Serial type */
  int nSerial;                    /* Bytes of space for iSerial as varint */
  int nVal;                       /* Bytes of space required for argv[0] */
  int nRet;
  sqlite3 *db;
  u8 *aRet;

  iSerial = sqlite3VdbeSerialType(argv[0], file_format);
  nSerial = sqlite3VarintLen(iSerial);
  nVal = sqlite3VdbeSerialTypeLen(iSerial);
  db = sqlite3_context_db_handle(context);

  nRet = 1 + nSerial + nVal;
  aRet = sqlite3DbMallocRaw(db, nRet);
  if( aRet==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    aRet[0] = nSerial+1;
    sqlite3PutVarint(&aRet[1], iSerial);
    sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format);
    sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
    sqlite3DbFree(db, aRet);
  }
}

/*
** Register built-in functions used to help read ANALYZE data.
*/
SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){
  static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = {
    FUNCTION(sqlite_record,   1, 0, 0, recordFunc),
  };
  int i;
  FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
  FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
  for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
    sqlite3FuncDefInsert(pHash, &aFunc[i]);
  }
}

/*
** This function is used to allocate and populate UnpackedRecord 
** structures intended to be compared against sample index keys stored 
** in the sqlite_stat4 table.
**
** A single call to this function attempts to populates field iVal (leftmost 
** is 0 etc.) of the unpacked record with a value extracted from expression
** pExpr. Extraction of values is possible if:
**
**  * (pExpr==0). In this case the value is assumed to be an SQL NULL,
**
**  * The expression is a bound variable, and this is a reprepare, or
**
**  * The sqlite3ValueFromExpr() function is able to extract a value 
**    from the expression (i.e. the expression is a literal value).
**
** If a value can be extracted, the affinity passed as the 5th argument
** is applied to it before it is copied into the UnpackedRecord. Output
** parameter *pbOk is set to true if a value is extracted, or false 
** otherwise.
**
** When this function is called, *ppRec must either point to an object
** allocated by an earlier call to this function, or must be NULL. If it
** is NULL and a value can be successfully extracted, a new UnpackedRecord
** is allocated (and *ppRec set to point to it) before returning.
**
** Unless an error is encountered, SQLITE_OK is returned. It is not an
** error if a value cannot be extracted from pExpr. If an error does
** occur, an SQLite error code is returned.
*/
SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
  Parse *pParse,                  /* Parse context */
  Index *pIdx,                    /* Index being probed */
  UnpackedRecord **ppRec,         /* IN/OUT: Probe record */
  Expr *pExpr,                    /* The expression to extract a value from */
  u8 affinity,                    /* Affinity to use */
  int iVal,                       /* Array element to populate */
  int *pbOk                       /* OUT: True if value was extracted */
){
  int rc = SQLITE_OK;
  sqlite3_value *pVal = 0;

  struct ValueNewStat4Ctx alloc;
  alloc.pParse = pParse;
  alloc.pIdx = pIdx;
  alloc.ppRec = ppRec;
  alloc.iVal = iVal;

  if( !pExpr ){
    pVal = valueNew(pParse->db, &alloc);
    if( pVal ){
      sqlite3VdbeMemSetNull((Mem*)pVal);
      *pbOk = 1;
    }
  }else if( pExpr->op==TK_VARIABLE
        || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
  ){
    Vdbe *v;
    int iBindVar = pExpr->iColumn;
    sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
    if( (v = pParse->pReprepare)!=0 ){
      pVal = valueNew(pParse->db, &alloc);
      if( pVal ){
        rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
        if( rc==SQLITE_OK ){
          sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
        }
        pVal->db = pParse->db;
        *pbOk = 1;
        sqlite3VdbeMemStoreType((Mem*)pVal);
      }
    }else{
      *pbOk = 0;
    }
  }else{
    sqlite3 *db = pParse->db;
    rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc);
    *pbOk = (pVal!=0);
  }

  assert( pVal==0 || pVal->db==pParse->db );
  return rc;
}

/*
** Unless it is NULL, the argument must be an UnpackedRecord object returned
** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes
** the object.
*/
SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
  if( pRec ){
    int i;
    int nCol = pRec->pKeyInfo->nField+1;
    Mem *aMem = pRec->aMem;
    sqlite3 *db = aMem[0].db;
    for(i=0; i<nCol; i++){
      sqlite3DbFree(db, aMem[i].zMalloc);
    }
    sqlite3DbFree(db, pRec->pKeyInfo);
    sqlite3DbFree(db, pRec);
  }
}
#endif /* ifdef SQLITE_ENABLE_STAT4 */

/*
** Change the string value of an sqlite3_value object
*/
SQLITE_PRIVATE void sqlite3ValueSetStr(
  sqlite3_value *v,     /* Value to be set */
  int n,                /* Length of string z */
  const void *z,        /* Text of the new string */
61724
61725
61726
61727
61728
61729
61730
61731

61732
61733
61734
61735
61736
61737
61738
62142
62143
62144
62145
62146
62147
62148

62149
62150
62151
62152
62153
62154
62155
62156







-
+








  /* Before doing anything else, call the xSync() callback for any
  ** virtual module tables written in this transaction. This has to
  ** be done before determining whether a master journal file is 
  ** required, as an xSync() callback may add an attached database
  ** to the transaction.
  */
  rc = sqlite3VtabSync(db, &p->zErrMsg);
  rc = sqlite3VtabSync(db, p);

  /* This loop determines (a) if the commit hook should be invoked and
  ** (b) how many database files have open write transactions, not 
  ** including the temp database. (b) is important because if more than 
  ** one database file has an open write transaction, a master journal
  ** file is required for an atomic commit.
  */ 
63264
63265
63266
63267
63268
63269
63270















63271
63272
63273
63274
63275
63276
63277
63682
63683
63684
63685
63686
63687
63688
63689
63690
63691
63692
63693
63694
63695
63696
63697
63698
63699
63700
63701
63702
63703
63704
63705
63706
63707
63708
63709
63710







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  if( iVar>32 ){
    v->expmask = 0xffffffff;
  }else{
    v->expmask |= ((u32)1 << (iVar-1));
  }
}

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
  sqlite3 *db = p->db;
  sqlite3DbFree(db, p->zErrMsg);
  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = 0;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

/************** End of vdbeaux.c *********************************************/
/************** Begin file vdbeapi.c *****************************************/
/*
** 2004 May 26
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
63477
63478
63479
63480
63481
63482
63483

63484
63485
63486
63487
63488
63489

63490
63491
63492
63493
63494
63495
63496
63910
63911
63912
63913
63914
63915
63916
63917
63918
63919
63920
63921
63922
63923
63924
63925
63926
63927
63928
63929
63930
63931







+






+







SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
  assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
  sqlite3VdbeMemSetDouble(&pCtx->s, rVal);
}
SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
  assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
  pCtx->isError = SQLITE_ERROR;
  pCtx->fErrorOrAux = 1;
  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
  assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
  pCtx->isError = SQLITE_ERROR;
  pCtx->fErrorOrAux = 1;
  sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
  assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
  sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal);
}
63546
63547
63548
63549
63550
63551
63552

63553
63554
63555
63556
63557
63558
63559
63560
63561
63562

63563
63564
63565
63566
63567
63568
63569
63570
63571

63572
63573
63574
63575
63576
63577
63578
63981
63982
63983
63984
63985
63986
63987
63988
63989
63990
63991
63992
63993
63994
63995
63996
63997
63998
63999
64000
64001
64002
64003
64004
64005
64006
64007
64008
64009
64010
64011
64012
64013
64014
64015
64016







+










+









+







}
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
  assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
  sqlite3VdbeMemSetZeroBlob(&pCtx->s, n);
}
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
  pCtx->isError = errCode;
  pCtx->fErrorOrAux = 1;
  if( pCtx->s.flags & MEM_Null ){
    sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1, 
                         SQLITE_UTF8, SQLITE_STATIC);
  }
}

/* Force an SQLITE_TOOBIG error. */
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
  assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
  pCtx->isError = SQLITE_TOOBIG;
  pCtx->fErrorOrAux = 1;
  sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, 
                       SQLITE_UTF8, SQLITE_STATIC);
}

/* An SQLITE_NOMEM error. */
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
  assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
  sqlite3VdbeMemSetNull(&pCtx->s);
  pCtx->isError = SQLITE_NOMEM;
  pCtx->fErrorOrAux = 1;
  pCtx->s.db->mallocFailed = 1;
}

/*
** This function is called after a transaction has been committed. It 
** invokes callbacks registered with sqlite3_wal_hook() as required.
*/
63887
63888
63889
63890
63891
63892
63893




63894
63895
63896
63897
63898
63899
63900
64325
64326
64327
64328
64329
64330
64331
64332
64333
64334
64335
64336
64337
64338
64339
64340
64341
64342







+
+
+
+







  if( pAuxData==0 ){
    pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
    if( !pAuxData ) goto failed;
    pAuxData->iOp = pCtx->iOp;
    pAuxData->iArg = iArg;
    pAuxData->pNext = pVdbe->pAuxData;
    pVdbe->pAuxData = pAuxData;
    if( pCtx->fErrorOrAux==0 ){
      pCtx->isError = 0;
      pCtx->fErrorOrAux = 1;
    }
  }else if( pAuxData->xDelete ){
    pAuxData->xDelete(pAuxData->pAux);
  }

  pAuxData->pAux = pAux;
  pAuxData->xDelete = xDelete;
  return;
64555
64556
64557
64558
64559
64560
64561
64562
64563
64564



64565
64566
64567
64568
64569
64570
64571
64997
64998
64999
65000
65001
65002
65003



65004
65005
65006
65007
65008
65009
65010
65011
65012
65013







-
-
-
+
+
+







}

/*
** Return the value of a status counter for a prepared statement
*/
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
  Vdbe *pVdbe = (Vdbe*)pStmt;
  int v = pVdbe->aCounter[op-1];
  if( resetFlag ) pVdbe->aCounter[op-1] = 0;
  return v;
  u32 v = pVdbe->aCounter[op];
  if( resetFlag ) pVdbe->aCounter[op] = 0;
  return (int)v;
}

/************** End of vdbeapi.c *********************************************/
/************** Begin file vdbetrace.c ***************************************/
/*
** 2009 November 25
**
65444
65445
65446
65447
65448
65449
65450
65451
65452
65453
65454
65455
65456
65457
65458
65459
65460
65461
65462
65463
65464
65465
65466
65467
65468
65469
65470
65886
65887
65888
65889
65890
65891
65892













65893
65894
65895
65896
65897
65898
65899







-
-
-
-
-
-
-
-
-
-
-
-
-







  Savepoint *p;
  for(p=db->pSavepoint; p; p=p->pNext) n++;
  assert( n==(db->nSavepoint + db->isTransactionSavepoint) );
  return 1;
}
#endif

/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
  sqlite3 *db = p->db;
  sqlite3DbFree(db, p->zErrMsg);
  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
  sqlite3_free(pVtab->zErrMsg);
  pVtab->zErrMsg = 0;
}


/*
** Execute as much of a VDBE program as we can then return.
**
** sqlite3VdbeMakeReady() must be called before this routine in order to
** close the program with a final OP_Halt and to set up the callbacks
** and the error message pointer.
65964
65965
65966
65967
65968
65969
65970
65971

65972
65973
65974
65975
65976
65977
65978
66393
66394
66395
66396
66397
66398
66399

66400
66401
66402
66403
66404
66405
66406
66407







-
+







  p->pResultSet = 0;
  db->busyHandler.nBusy = 0;
  CHECK_FOR_INTERRUPT;
  sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( db->xProgress ){
    assert( 0 < db->nProgressOps );
    nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP-1];
    nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
    if( nProgressLimit==0 ){
      nProgressLimit = db->nProgressOps;
    }else{
      nProgressLimit %= (unsigned)db->nProgressOps;
    }
  }
#endif
66027
66028
66029
66030
66031
66032
66033
66034

66035
66036
66037
66038
66039
66040
66041
66042
66043
66044
66045

66046
66047
66048
66049
66050
66051

66052
66053
66054
66055
66056
66057

66058
66059
66060
66061
66062
66063

66064
66065
66066
66067
66068

66069
66070
66071
66072
66073
66074
66075
66456
66457
66458
66459
66460
66461
66462

66463
66464
66465
66466
66467
66468
66469
66470
66471
66472
66473

66474
66475
66476
66477
66478
66479

66480
66481
66482
66483
66484
66485

66486
66487
66488
66489
66490
66491

66492
66493
66494
66495
66496

66497
66498
66499
66500
66501
66502
66503
66504







-
+










-
+





-
+





-
+





-
+




-
+







    ** external allocations out of mem[p2] and set mem[p2] to be
    ** an undefined integer.  Opcodes will either fill in the integer
    ** value or convert mem[p2] to a different type.
    */
    assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
    if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      assert( pOp->p2<=(p->nMem-p->nCursor) );
      pOut = &aMem[pOp->p2];
      memAboutToChange(p, pOut);
      VdbeMemRelease(pOut);
      pOut->flags = MEM_Int;
    }

    /* Sanity checking on other operands */
#ifdef SQLITE_DEBUG
    if( (pOp->opflags & OPFLG_IN1)!=0 ){
      assert( pOp->p1>0 );
      assert( pOp->p1<=p->nMem );
      assert( pOp->p1<=(p->nMem-p->nCursor) );
      assert( memIsValid(&aMem[pOp->p1]) );
      REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
    }
    if( (pOp->opflags & OPFLG_IN2)!=0 ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      assert( pOp->p2<=(p->nMem-p->nCursor) );
      assert( memIsValid(&aMem[pOp->p2]) );
      REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
    }
    if( (pOp->opflags & OPFLG_IN3)!=0 ){
      assert( pOp->p3>0 );
      assert( pOp->p3<=p->nMem );
      assert( pOp->p3<=(p->nMem-p->nCursor) );
      assert( memIsValid(&aMem[pOp->p3]) );
      REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
    }
    if( (pOp->opflags & OPFLG_OUT2)!=0 ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      assert( pOp->p2<=(p->nMem-p->nCursor) );
      memAboutToChange(p, &aMem[pOp->p2]);
    }
    if( (pOp->opflags & OPFLG_OUT3)!=0 ){
      assert( pOp->p3>0 );
      assert( pOp->p3<=p->nMem );
      assert( pOp->p3<=(p->nMem-p->nCursor) );
      memAboutToChange(p, &aMem[pOp->p3]);
    }
#endif
  
    switch( pOp->opcode ){

/*****************************************************************************
66154
66155
66156
66157
66158
66159
66160
66161

66162
66163
66164
66165
66166
66167
66168
66583
66584
66585
66586
66587
66588
66589

66590
66591
66592
66593
66594
66595
66596
66597







-
+








/* Opcode:  Gosub P1 P2 * * *
**
** Write the current address onto register P1
** and then jump to address P2.
*/
case OP_Gosub: {            /* jump */
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
  pIn1 = &aMem[pOp->p1];
  assert( (pIn1->flags & MEM_Dyn)==0 );
  memAboutToChange(p, pIn1);
  pIn1->flags = MEM_Int;
  pIn1->u.i = pc;
  REGISTER_TRACE(pOp->p1, pIn1);
  pc = pOp->p2 - 1;
66370
66371
66372
66373
66374
66375
66376
66377

66378
66379
66380
66381
66382
66383
66384
66799
66800
66801
66802
66803
66804
66805

66806
66807
66808
66809
66810
66811
66812
66813







-
+







*/
case OP_Null: {           /* out2-prerelease */
#if 0  /* local variables moved into u.ab */
  int cnt;
  u16 nullFlag;
#endif /* local variables moved into u.ab */
  u.ab.cnt = pOp->p3-pOp->p2;
  assert( pOp->p3<=p->nMem );
  assert( pOp->p3<=(p->nMem-p->nCursor) );
  pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
  while( u.ab.cnt>0 ){
    pOut++;
    memAboutToChange(p, pOut);
    VdbeMemRelease(pOut);
    pOut->flags = u.ab.nullFlag;
    u.ab.cnt--;
66443
66444
66445
66446
66447
66448
66449
66450
66451


66452
66453
66454
66455
66456
66457
66458
66872
66873
66874
66875
66876
66877
66878


66879
66880
66881
66882
66883
66884
66885
66886
66887







-
-
+
+







  u.ad.p2 = pOp->p2;
  assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
  assert( u.ad.p1+u.ad.n<=u.ad.p2 || u.ad.p2+u.ad.n<=u.ad.p1 );

  pIn1 = &aMem[u.ad.p1];
  pOut = &aMem[u.ad.p2];
  while( u.ad.n-- ){
    assert( pOut<=&aMem[p->nMem] );
    assert( pIn1<=&aMem[p->nMem] );
    assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
    assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
    assert( memIsValid(pIn1) );
    memAboutToChange(p, pOut);
    u.ad.zMalloc = pOut->zMalloc;
    pOut->zMalloc = 0;
    sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
    if( pOut->pScopyFrom>=&aMem[u.ad.p1] && pOut->pScopyFrom<&aMem[u.ad.p1+pOp->p3] ){
66532
66533
66534
66535
66536
66537
66538
66539

66540
66541
66542
66543
66544
66545
66546
66961
66962
66963
66964
66965
66966
66967

66968
66969
66970
66971
66972
66973
66974
66975







-
+







case OP_ResultRow: {
#if 0  /* local variables moved into u.af */
  Mem *pMem;
  int i;
#endif /* local variables moved into u.af */
  assert( p->nResColumn==pOp->p2 );
  assert( pOp->p1>0 );
  assert( pOp->p1+pOp->p2<=p->nMem+1 );
  assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 );

  /* If this statement has violated immediate foreign key constraints, do
  ** not return the number of rows modified. And do not RELEASE the statement
  ** transaction. It needs to be rolled back.  */
  if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
    assert( db->flags&SQLITE_CountRows );
    assert( p->usesStmtJournal );
66812
66813
66814
66815
66816
66817
66818
66819

66820
66821
66822
66823

66824
66825
66826
66827
66828
66829
66830
67241
67242
67243
67244
67245
67246
67247

67248
67249
67250
67251

67252
67253
67254
67255
67256
67257
67258
67259







-
+



-
+







  sqlite3_value **apVal;
  int n;
#endif /* local variables moved into u.ai */

  u.ai.n = pOp->p5;
  u.ai.apVal = p->apArg;
  assert( u.ai.apVal || u.ai.n==0 );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  pOut = &aMem[pOp->p3];
  memAboutToChange(p, pOut);

  assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) );
  assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=(p->nMem-p->nCursor)+1) );
  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ai.n );
  u.ai.pArg = &aMem[pOp->p2];
  for(u.ai.i=0; u.ai.i<u.ai.n; u.ai.i++, u.ai.pArg++){
    assert( memIsValid(u.ai.pArg) );
    u.ai.apVal[u.ai.i] = u.ai.pArg;
    Deephemeralize(u.ai.pArg);
    sqlite3VdbeMemStoreType(u.ai.pArg);
66843
66844
66845
66846
66847
66848
66849
66850

66851
66852
66853
66854
66855
66856
66857
66858
66859
66860
66861
66862
66863
66864
66865
66866
66867
66868
66869
66870
66871
66872
66873
66874
66875
66876

66877
66878
66879





66880
66881
66882
66883
66884
66885
66886
67272
67273
67274
67275
67276
67277
67278

67279
67280
67281
67282
67283
67284
67285
67286
67287
67288
67289





67290
67291
67292
67293
67294
67295
67296
67297
67298
67299
67300
67301



67302
67303
67304
67305
67306
67307
67308
67309
67310
67311
67312
67313







-
+










-
-
-
-
-











+
-
-
-
+
+
+
+
+







  /* The output cell may already have a buffer allocated. Move
  ** the pointer to u.ai.ctx.s so in case the user-function can use
  ** the already allocated buffer instead of allocating a new one.
  */
  sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
  MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);

  u.ai.ctx.isError = 0;
  u.ai.ctx.fErrorOrAux = 0;
  if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
    assert( pOp>aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    u.ai.ctx.pColl = pOp[-1].p4.pColl;
  }
  db->lastRowid = lastRowid;
  (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
  lastRowid = db->lastRowid;

  /* If any auxiliary data functions have been called by this user function,
  ** immediately call the destructor for any non-static values.
  */
  sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);

  if( db->mallocFailed ){
    /* Even though a malloc() has failed, the implementation of the
    ** user function may have called an sqlite3_result_XXX() function
    ** to return a value. The following call releases any resources
    ** associated with such a value.
    */
    sqlite3VdbeMemRelease(&u.ai.ctx.s);
    goto no_mem;
  }

  /* If the function returned an error, throw an exception */
  if( u.ai.ctx.fErrorOrAux ){
  if( u.ai.ctx.isError ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
    rc = u.ai.ctx.isError;
    if( u.ai.ctx.isError ){
      sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
      rc = u.ai.ctx.isError;
    }
    sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
  }

  /* Copy the result of the function into register P3 */
  sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding);
  sqlite3VdbeMemMove(pOut, &u.ai.ctx.s);
  if( sqlite3VdbeMemTooBig(pOut) ){
    goto too_big;
67248
67249
67250
67251
67252
67253
67254
67255



67256
67257
67258
67259
67260
67261
67262
67263
67264
67265
67266
67267
67675
67676
67677
67678
67679
67680
67681

67682
67683
67684
67685
67686
67687


67688
67689
67690
67691
67692
67693
67694







-
+
+
+



-
-







        u.ak.res = 1;  /* Results are not equal */
      }
    }else{
      /* SQLITE_NULLEQ is clear and at least one operand is NULL,
      ** then the result is always NULL.
      ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
      */
      if( pOp->p5 & SQLITE_STOREP2 ){
      if( pOp->p5 & SQLITE_JUMPIFNULL ){
        pc = pOp->p2-1;
      }else if( pOp->p5 & SQLITE_STOREP2 ){
        pOut = &aMem[pOp->p2];
        MemSetTypeFlag(pOut, MEM_Null);
        REGISTER_TRACE(pOp->p2, pOut);
      }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
        pc = pOp->p2-1;
      }
      break;
    }
  }else{
    /* Neither operand is NULL.  Do a comparison. */
    u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK;
    if( u.ak.affinity ){
67354
67355
67356
67357
67358
67359
67360
67361
67362


67363
67364
67365


67366
67367
67368
67369
67370
67371
67372
67781
67782
67783
67784
67785
67786
67787


67788
67789
67790


67791
67792
67793
67794
67795
67796
67797
67798
67799







-
-
+
+

-
-
+
+







  assert( u.al.pKeyInfo!=0 );
  u.al.p1 = pOp->p1;
  u.al.p2 = pOp->p2;
#if SQLITE_DEBUG
  if( aPermute ){
    int k, mx = 0;
    for(k=0; k<u.al.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
    assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 );
    assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 );
    assert( u.al.p1>0 && u.al.p1+mx<=(p->nMem-p->nCursor)+1 );
    assert( u.al.p2>0 && u.al.p2+mx<=(p->nMem-p->nCursor)+1 );
  }else{
    assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 );
    assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 );
    assert( u.al.p1>0 && u.al.p1+u.al.n<=(p->nMem-p->nCursor)+1 );
    assert( u.al.p2>0 && u.al.p2+u.al.n<=(p->nMem-p->nCursor)+1 );
  }
#endif /* SQLITE_DEBUG */
  for(u.al.i=0; u.al.i<u.al.n; u.al.i++){
    u.al.idx = aPermute ? aPermute[u.al.i] : u.al.i;
    assert( memIsValid(&aMem[u.al.p1+u.al.idx]) );
    assert( memIsValid(&aMem[u.al.p2+u.al.idx]) );
    REGISTER_TRACE(u.al.p1+u.al.idx, &aMem[u.al.p1+u.al.idx]);
67615
67616
67617
67618
67619
67620
67621
67622

67623
67624
67625
67626
67627
67628
67629
68042
68043
68044
68045
68046
68047
68048

68049
68050
68051
68052
68053
68054
68055
68056







-
+









  u.ao.p1 = pOp->p1;
  u.ao.p2 = pOp->p2;
  u.ao.pC = 0;
  memset(&u.ao.sMem, 0, sizeof(u.ao.sMem));
  assert( u.ao.p1<p->nCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  u.ao.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.ao.pDest);
  u.ao.zRec = 0;

  /* This block sets the variable u.ao.payloadSize to be the total number of
  ** bytes in the record.
  **
67915
67916
67917
67918
67919
67920
67921
67922

67923
67924
67925
67926
67927
67928
67929
68342
68343
68344
68345
68346
68347
68348

68349
68350
68351
68352
68353
68354
68355
68356







-
+







#endif /* local variables moved into u.ap */

  u.ap.zAffinity = pOp->p4.z;
  assert( u.ap.zAffinity!=0 );
  assert( u.ap.zAffinity[pOp->p2]==0 );
  pIn1 = &aMem[pOp->p1];
  while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){
    assert( pIn1 <= &p->aMem[p->nMem] );
    assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] );
    assert( memIsValid(pIn1) );
    ExpandBlob(pIn1);
    applyAffinity(pIn1, u.ap.cAff, encoding);
    pIn1++;
  }
  break;
}
67978
67979
67980
67981
67982
67983
67984
67985

67986
67987
67988
67989
67990
67991
67992
68405
68406
68407
68408
68409
68410
68411

68412
68413
68414
68415
68416
68417
68418
68419







-
+







  ** of the record to data0.
  */
  u.aq.nData = 0;         /* Number of bytes of data space */
  u.aq.nHdr = 0;          /* Number of bytes of header space */
  u.aq.nZero = 0;         /* Number of zero bytes at the end of the record */
  u.aq.nField = pOp->p1;
  u.aq.zAffinity = pOp->p4.z;
  assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 );
  assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=(p->nMem-p->nCursor)+1 );
  u.aq.pData0 = &aMem[u.aq.nField];
  u.aq.nField = pOp->p2;
  u.aq.pLast = &u.aq.pData0[u.aq.nField-1];
  u.aq.file_format = p->minWriteFileFormat;

  /* Identify the output register */
  assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
68044
68045
68046
68047
68048
68049
68050
68051

68052
68053
68054
68055
68056
68057
68058
68471
68472
68473
68474
68475
68476
68477

68478
68479
68480
68481
68482
68483
68484
68485







-
+







    u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.serial_type);      /* serial type */
  }
  for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){  /* serial data */
    u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), u.aq.pRec,u.aq.file_format);
  }
  assert( u.aq.i==u.aq.nByte );

  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  pOut->n = (int)u.aq.nByte;
  pOut->flags = MEM_Blob | MEM_Dyn;
  pOut->xDel = 0;
  if( u.aq.nZero ){
    pOut->u.nZero = u.aq.nZero;
    pOut->flags |= MEM_Zero;
  }
68640
68641
68642
68643
68644
68645
68646
68647

68648
68649
68650
68651
68652
68653
68654
69067
69068
69069
69070
69071
69072
69073

69074
69075
69076
69077
69078
69079
69080
69081







-
+







      p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
    }
  }else{
    u.ay.wrFlag = 0;
  }
  if( pOp->p5 & OPFLAG_P2ISREG ){
    assert( u.ay.p2>0 );
    assert( u.ay.p2<=p->nMem );
    assert( u.ay.p2<=(p->nMem-p->nCursor) );
    pIn2 = &aMem[u.ay.p2];
    assert( memIsValid(pIn2) );
    assert( (pIn2->flags & MEM_Int)!=0 );
    sqlite3VdbeMemIntegerify(pIn2);
    u.ay.p2 = (int)pIn2->u.i;
    /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and
    ** that opcode will always set the u.ay.p2 value to 2 or more or else fail.
69191
69192
69193
69194
69195
69196
69197
69198

69199
69200
69201
69202
69203
69204
69205
69618
69619
69620
69621
69622
69623
69624

69625
69626
69627
69628
69629
69630
69631
69632







-
+







  i64 R;                             /* Rowid stored in register P3 */
#endif /* local variables moved into u.bf */

  pIn3 = &aMem[pOp->p3];
  u.bf.aMx = &aMem[pOp->p4.i];
  /* Assert that the values of parameters P1 and P4 are in range. */
  assert( pOp->p4type==P4_INT32 );
  assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
  assert( pOp->p4.i>0 && pOp->p4.i<=(p->nMem-p->nCursor) );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );

  /* Find the index cursor. */
  u.bf.pCx = p->apCsr[pOp->p1];
  assert( u.bf.pCx->deferredMoveto==0 );
  u.bf.pCx->seekResult = 0;
  u.bf.pCx->cacheStatus = CACHE_STALE;
69398
69399
69400
69401
69402
69403
69404
69405

69406
69407
69408
69409
69410
69411
69412
69825
69826
69827
69828
69829
69830
69831

69832
69833
69834
69835
69836
69837
69838
69839







-
+







        if( p->pFrame ){
          for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent);
          /* Assert that P3 is a valid memory cell. */
          assert( pOp->p3<=u.bh.pFrame->nMem );
          u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
        }else{
          /* Assert that P3 is a valid memory cell. */
          assert( pOp->p3<=p->nMem );
          assert( pOp->p3<=(p->nMem-p->nCursor) );
          u.bh.pMem = &aMem[pOp->p3];
          memAboutToChange(p, u.bh.pMem);
        }
        assert( memIsValid(u.bh.pMem) );

        REGISTER_TRACE(pOp->p3, u.bh.pMem);
        sqlite3VdbeMemIntegerify(u.bh.pMem);
69808
69809
69810
69811
69812
69813
69814
69815

69816
69817
69818
69819
69820
69821
69822
70235
70236
70237
70238
70239
70240
70241

70242
70243
70244
70245
70246
70247
70248
70249







-
+







    u.bn.v = u.bn.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  }else if( u.bn.pC->pVtabCursor ){
    u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab;
    u.bn.pModule = u.bn.pVtab->pModule;
    assert( u.bn.pModule->xRowid );
    rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
    importVtabErrMsg(p, u.bn.pVtab);
    sqlite3VtabImportErrmsg(p, u.bn.pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
  }else{
    assert( u.bn.pC->pCursor!=0 );
    rc = sqlite3VdbeCursorMoveto(u.bn.pC);
    if( rc ) goto abort_due_to_error;
    if( u.bn.pC->rowidIsValid ){
      u.bn.v = u.bn.pC->lastRowid;
69900
69901
69902
69903
69904
69905
69906
69907

69908
69909
69910
69911
69912
69913
69914
70327
70328
70329
70330
70331
70332
70333

70334
70335
70336
70337
70338
70339
70340
70341







-
+







*/
case OP_SorterSort:    /* jump */
case OP_Sort: {        /* jump */
#ifdef SQLITE_TEST
  sqlite3_sort_count++;
  sqlite3_search_count--;
#endif
  p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
  p->aCounter[SQLITE_STMTSTATUS_SORT]++;
  /* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
69983
69984
69985
69986
69987
69988
69989
69990

69991
69992
69993
69994
69995
69996
69997
69998
69999
70000

70001
70002
70003
70004
70005
70006
70007
70008
70009
70010
70011

70012
70013
70014
70015
70016
70017
70018
70410
70411
70412
70413
70414
70415
70416

70417
70418
70419
70420
70421
70422
70423
70424
70425
70426

70427
70428
70429
70430
70431
70432
70433
70434
70435
70436
70437

70438
70439
70440
70441
70442
70443
70444
70445







-
+









-
+










-
+







case OP_Next: {        /* jump */
#if 0  /* local variables moved into u.br */
  VdbeCursor *pC;
  int res;
#endif /* local variables moved into u.br */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5<=ArraySize(p->aCounter) );
  assert( pOp->p5<ArraySize(p->aCounter) );
  u.br.pC = p->apCsr[pOp->p1];
  if( u.br.pC==0 ){
    break;  /* See ticket #2273 */
  }
  assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
  if( isSorter(u.br.pC) ){
    assert( pOp->opcode==OP_SorterNext );
    rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
  }else{
    u.br.res = 1;
    /* u.br.res = 1; // Always initialized by the xAdvance() call */
    assert( u.br.pC->deferredMoveto==0 );
    assert( u.br.pC->pCursor );
    assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
    assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
    rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
  }
  u.br.pC->nullRow = (u8)u.br.res;
  u.br.pC->cacheStatus = CACHE_STALE;
  if( u.br.res==0 ){
    pc = pOp->p2 - 1;
    if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
    p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
    sqlite3_search_count++;
#endif
  }
  u.br.pC->rowidIsValid = 0;
  goto check_for_interrupt;
}
70076
70077
70078
70079
70080
70081
70082
70083

70084
70085
70086
70087
70088
70089
70090
70503
70504
70505
70506
70507
70508
70509

70510
70511
70512
70513
70514
70515
70516
70517







-
+







  VdbeCursor *pC;
  BtCursor *pCrsr;
  int res;
  UnpackedRecord r;
#endif /* local variables moved into u.bt */

  assert( pOp->p3>0 );
  assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
  assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 );
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bt.pC = p->apCsr[pOp->p1];
  assert( u.bt.pC!=0 );
  u.bt.pCrsr = u.bt.pC->pCursor;
  if( ALWAYS(u.bt.pCrsr!=0) ){
    u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
    u.bt.r.nField = (u16)pOp->p3;
70292
70293
70294
70295
70296
70297
70298

70299
70300
70301
70302
70303
70304
70305
70719
70720
70721
70722
70723
70724
70725
70726
70727
70728
70729
70730
70731
70732
70733







+







case OP_Clear: {
#if 0  /* local variables moved into u.bx */
  int nChange;
#endif /* local variables moved into u.bx */

  u.bx.nChange = 0;
  assert( p->readOnly==0 );
  assert( pOp->p1!=1 );
  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
  rc = sqlite3BtreeClearTable(
      db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
  );
  if( pOp->p3 ){
    p->nChange += u.bx.nChange;
    if( pOp->p3>0 ){
70498
70499
70500
70501
70502
70503
70504
70505

70506
70507
70508
70509
70510
70511
70512
70926
70927
70928
70929
70930
70931
70932

70933
70934
70935
70936
70937
70938
70939
70940







-
+







#endif /* local variables moved into u.ca */

  assert( p->bIsReader );
  u.ca.nRoot = pOp->p2;
  assert( u.ca.nRoot>0 );
  u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
  if( u.ca.aRoot==0 ) goto no_mem;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  u.ca.pnErr = &aMem[pOp->p3];
  assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
  assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
  pIn1 = &aMem[pOp->p1];
  for(u.ca.j=0; u.ca.j<u.ca.nRoot; u.ca.j++){
    u.ca.aRoot[u.ca.j] = (int)sqlite3VdbeIntValue(&pIn1[u.ca.j]);
  }
70934
70935
70936
70937
70938
70939
70940
70941

70942
70943
70944
70945
70946
70947
70948
71362
71363
71364
71365
71366
71367
71368

71369
71370
71371
71372
71373
71374
71375
71376







-
+







  for(u.cg.i=0; u.cg.i<u.cg.n; u.cg.i++, u.cg.pRec++){
    assert( memIsValid(u.cg.pRec) );
    u.cg.apVal[u.cg.i] = u.cg.pRec;
    memAboutToChange(p, u.cg.pRec);
    sqlite3VdbeMemStoreType(u.cg.pRec);
  }
  u.cg.ctx.pFunc = pOp->p4.pFunc;
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3];
  u.cg.pMem->n++;
  u.cg.ctx.s.flags = MEM_Null;
  u.cg.ctx.s.z = 0;
  u.cg.ctx.s.zMalloc = 0;
  u.cg.ctx.s.xDel = 0;
  u.cg.ctx.s.db = db;
70983
70984
70985
70986
70987
70988
70989
70990

70991
70992
70993
70994
70995
70996
70997
71411
71412
71413
71414
71415
71416
71417

71418
71419
71420
71421
71422
71423
71424
71425







-
+







** P4 argument is only needed for the degenerate case where
** the step function was not previously called.
*/
case OP_AggFinal: {
#if 0  /* local variables moved into u.ch */
  Mem *pMem;
#endif /* local variables moved into u.ch */
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
  u.ch.pMem = &aMem[pOp->p1];
  assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
  rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc);
  if( rc ){
    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem));
  }
  sqlite3VdbeChangeEncoding(u.ch.pMem, encoding);
71249
71250
71251
71252
71253
71254
71255
71256

71257
71258
71259
71260
71261
71262
71263
71677
71678
71679
71680
71681
71682
71683

71684
71685
71686
71687
71688
71689
71690
71691







-
+







*/
case OP_VBegin: {
#if 0  /* local variables moved into u.cl */
  VTable *pVTab;
#endif /* local variables moved into u.cl */
  u.cl.pVTab = pOp->p4.pVtab;
  rc = sqlite3VtabBegin(db, u.cl.pVTab);
  if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
  if( u.cl.pVTab ) sqlite3VtabImportErrmsg(p, u.cl.pVTab->pVtab);
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 * * P4 *
**
71302
71303
71304
71305
71306
71307
71308
71309

71310
71311
71312
71313
71314
71315
71316
71730
71731
71732
71733
71734
71735
71736

71737
71738
71739
71740
71741
71742
71743
71744







-
+







  assert( p->bIsReader );
  u.cm.pCur = 0;
  u.cm.pVtabCursor = 0;
  u.cm.pVtab = pOp->p4.pVtab->pVtab;
  u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
  assert(u.cm.pVtab && u.cm.pModule);
  rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
  importVtabErrMsg(p, u.cm.pVtab);
  sqlite3VtabImportErrmsg(p, u.cm.pVtab);
  if( SQLITE_OK==rc ){
    /* Initialize sqlite3_vtab_cursor base class */
    u.cm.pVtabCursor->pVtab = u.cm.pVtab;

    /* Initialize vdbe cursor object */
    u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
    if( u.cm.pCur ){
71382
71383
71384
71385
71386
71387
71388
71389

71390
71391
71392
71393
71394
71395
71396
71810
71811
71812
71813
71814
71815
71816

71817
71818
71819
71820
71821
71822
71823
71824







-
+







      u.cn.apArg[u.cn.i] = &u.cn.pArgc[u.cn.i+1];
      sqlite3VdbeMemStoreType(u.cn.apArg[u.cn.i]);
    }

    p->inVtabMethod = 1;
    rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
    p->inVtabMethod = 0;
    importVtabErrMsg(p, u.cn.pVtab);
    sqlite3VtabImportErrmsg(p, u.cn.pVtab);
    if( rc==SQLITE_OK ){
      u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
    }

    if( u.cn.res ){
      pc = pOp->p2 - 1;
    }
71414
71415
71416
71417
71418
71419
71420
71421

71422
71423
71424
71425
71426
71427
71428
71429
71430
71431
71432
71433
71434
71435
71436
71437
71438
71439
71440
71441
71442

71443
71444
71445
71446
71447
71448
71449
71842
71843
71844
71845
71846
71847
71848

71849
71850
71851
71852
71853
71854
71855
71856
71857
71858
71859
71860
71861
71862
71863
71864
71865
71866
71867
71868
71869

71870
71871
71872
71873
71874
71875
71876
71877







-
+




















-
+







  const sqlite3_module *pModule;
  Mem *pDest;
  sqlite3_context sContext;
#endif /* local variables moved into u.co */

  VdbeCursor *pCur = p->apCsr[pOp->p1];
  assert( pCur->pVtabCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  u.co.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.co.pDest);
  if( pCur->nullRow ){
    sqlite3VdbeMemSetNull(u.co.pDest);
    break;
  }
  u.co.pVtab = pCur->pVtabCursor->pVtab;
  u.co.pModule = u.co.pVtab->pModule;
  assert( u.co.pModule->xColumn );
  memset(&u.co.sContext, 0, sizeof(u.co.sContext));

  /* The output cell may already have a buffer allocated. Move
  ** the current contents to u.co.sContext.s so in case the user-function
  ** can use the already allocated buffer instead of allocating a
  ** new one.
  */
  sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest);
  MemSetTypeFlag(&u.co.sContext.s, MEM_Null);

  rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
  importVtabErrMsg(p, u.co.pVtab);
  sqlite3VtabImportErrmsg(p, u.co.pVtab);
  if( u.co.sContext.isError ){
    rc = u.co.sContext.isError;
  }

  /* Copy the result of the function to the P3 register. We
  ** do this regardless of whether or not an error occurred to ensure any
  ** dynamic allocation in u.co.sContext.s (a Mem struct) is  released.
71490
71491
71492
71493
71494
71495
71496
71497

71498
71499
71500
71501
71502
71503
71504
71918
71919
71920
71921
71922
71923
71924

71925
71926
71927
71928
71929
71930
71931
71932







-
+







  ** xNext(). Instead, if an error occurs, true is returned (indicating that
  ** data is available) and the error code returned when xColumn or
  ** some other method is next invoked on the save virtual table cursor.
  */
  p->inVtabMethod = 1;
  rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
  p->inVtabMethod = 0;
  importVtabErrMsg(p, u.cp.pVtab);
  sqlite3VtabImportErrmsg(p, u.cp.pVtab);
  if( rc==SQLITE_OK ){
    u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
  }

  if( !u.cp.res ){
    /* If there is data, jump to P2 */
    pc = pOp->p2 - 1;
71529
71530
71531
71532
71533
71534
71535
71536

71537
71538
71539
71540
71541
71542
71543
71957
71958
71959
71960
71961
71962
71963

71964
71965
71966
71967
71968
71969
71970
71971







-
+







  assert( u.cq.pName->flags & MEM_Str );
  testcase( u.cq.pName->enc==SQLITE_UTF8 );
  testcase( u.cq.pName->enc==SQLITE_UTF16BE );
  testcase( u.cq.pName->enc==SQLITE_UTF16LE );
  rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
  if( rc==SQLITE_OK ){
    rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
    importVtabErrMsg(p, u.cq.pVtab);
    sqlite3VtabImportErrmsg(p, u.cq.pVtab);
    p->expired = 0;
  }
  break;
}
#endif

#ifndef SQLITE_OMIT_VIRTUALTABLE
71593
71594
71595
71596
71597
71598
71599
71600

71601
71602
71603
71604
71605
71606
71607
72021
72022
72023
72024
72025
72026
72027

72028
72029
72030
72031
72032
72033
72034
72035







-
+







      sqlite3VdbeMemStoreType(u.cr.pX);
      u.cr.apArg[u.cr.i] = u.cr.pX;
      u.cr.pX++;
    }
    db->vtabOnConflict = pOp->p5;
    rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, u.cr.pVtab);
    sqlite3VtabImportErrmsg(p, u.cr.pVtab);
    if( rc==SQLITE_OK && pOp->p1 ){
      assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
      db->lastRowid = lastRowid = u.cr.rowid;
    }
    if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
        rc = SQLITE_OK;
71760
71761
71762
71763
71764
71765
71766

71767

71768
71769
71770
71771
71772
71773
71774
72188
72189
72190
72191
72192
72193
72194
72195

72196
72197
72198
72199
72200
72201
72202
72203







+
-
+







  }

  /* This is the only way out of this procedure.  We have to
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:
  db->lastRowid = lastRowid;
  testcase( nVmStep>0 );
  p->aCounter[SQLITE_STMTSTATUS_VM_STEP-1] += (int)nVmStep;
  p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
  sqlite3VdbeLeave(p);
  return rc;

  /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
  ** is encountered.
  */
too_big:
74039
74040
74041
74042
74043
74044
74045
74046

74047
74048
74049
74050
74051
74052
74053
74054
74055
74056
74057



74058
74059
74060
74061
74062
74063
74064
74468
74469
74470
74471
74472
74473
74474

74475
74476
74477
74478
74479
74480
74481
74482
74483
74484


74485
74486
74487
74488
74489
74490
74491
74492
74493
74494







-
+









-
-
+
+
+







** TK_AS operator.  The TK_AS operator causes the expression to be
** evaluated just once and then reused for each alias.
**
** The reason for suppressing the TK_AS term when the expression is a simple
** column reference is so that the column reference will be recognized as
** usable by indices within the WHERE clause processing logic. 
**
** Hack:  The TK_AS operator is inhibited if zType[0]=='G'.  This means
** The TK_AS operator is inhibited if zType[0]=='G'.  This means
** that in a GROUP BY clause, the expression is evaluated twice.  Hence:
**
**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
**
** Is equivalent to:
**
**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
**
** The result of random()%5 in the GROUP BY clause is probably different
** from the result in the result-set.  We might fix this someday.  Or
** then again, we might not...
** from the result in the result-set.  On the other hand Standard SQL does
** not allow the GROUP BY clause to contain references to result-set columns.
** So this should never come up in well-formed queries.
**
** If the reference is followed by a COLLATE operator, then make sure
** the COLLATE operator is preserved.  For example:
**
**     SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
**
** Should be transformed into:
74380
74381
74382
74383
74384
74385
74386






74387
74388
74389
74390

74391
74392
74393
74394
74395
74396
74397
74810
74811
74812
74813
74814
74815
74816
74817
74818
74819
74820
74821
74822
74823
74824
74825

74826
74827
74828
74829
74830
74831
74832
74833







+
+
+
+
+
+



-
+







    **
    **     SELECT a+b AS x FROM table WHERE x<10;
    **
    ** In cases like this, replace pExpr with a copy of the expression that
    ** forms the result set entry ("a+b" in the example) and return immediately.
    ** Note that the expression in the result set should have already been
    ** resolved by the time the WHERE clause is resolved.
    **
    ** The ability to use an output result-set column in the WHERE, GROUP BY,
    ** or HAVING clauses, or as part of a larger expression in the ORDRE BY
    ** clause is not standard SQL.  This is a (goofy) SQLite extension, that
    ** is supported for backwards compatibility only.  TO DO: Issue a warning
    ** on sqlite3_log() whenever the capability is used.
    */
    if( (pEList = pNC->pEList)!=0
     && zTab==0
     && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
     && cnt==0
    ){
      for(j=0; j<pEList->nExpr; j++){
        char *zAs = pEList->a[j].zName;
        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
          Expr *pOrig;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->x.pList==0 );
74945
74946
74947
74948
74949
74950
74951
74952

74953
74954
74955
74956
74957
74958
74959
75381
75382
75383
75384
75385
75386
75387

75388
75389
75390
75391
75392
75393
75394
75395







-
+







  }
  return 0;
}

/*
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
** the SELECT statement pSelect.  If any term is reference to a
** result set expression (as determined by the ExprList.a.iCol field)
** result set expression (as determined by the ExprList.a.iOrderByCol field)
** then convert that term into a copy of the corresponding result set
** column.
**
** If any errors are detected, add an error message to pParse and
** return non-zero.  Return zero if no errors are seen.
*/
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
74993
74994
74995
74996
74997
74998
74999
75000

75001
75002
75003
75004
75005
75006
75007
75429
75430
75431
75432
75433
75434
75435

75436
75437
75438
75439
75440
75441
75442
75443







-
+







** The Name context of the SELECT statement is pNC.  zType is either
** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
**
** This routine resolves each term of the clause into an expression.
** If the order-by term is an integer I between 1 and N (where N is the
** number of columns in the result set of the SELECT) then the expression
** in the resolution is a copy of the I-th result-set expression.  If
** the order-by term is an identify that corresponds to the AS-name of
** the order-by term is an identifier that corresponds to the AS-name of
** a result-set expression, then the term resolves to a copy of the
** result-set expression.  Otherwise, the expression is resolved in
** the usual way - using sqlite3ResolveExprNames().
**
** This routine returns the number of errors.  If errors occur, then
** an appropriate error message might be left in pParse.  (OOM errors
** excepted.)
75019
75020
75021
75022
75023
75024
75025


75026
75027
75028
75029
75030
75031
75032
75033
75034
75035











75036
75037
75038
75039
75040
75041
75042
75455
75456
75457
75458
75459
75460
75461
75462
75463










75464
75465
75466
75467
75468
75469
75470
75471
75472
75473
75474
75475
75476
75477
75478
75479
75480
75481







+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







  int nResult;                   /* Number of terms in the result set */

  if( pOrderBy==0 ) return 0;
  nResult = pSelect->pEList->nExpr;
  pParse = pNC->pParse;
  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
    Expr *pE = pItem->pExpr;
    Expr *pE2 = sqlite3ExprSkipCollate(pE);
    if( zType[0]!='G' ){
    iCol = resolveAsName(pParse, pSelect->pEList, pE);
    if( iCol>0 ){
      /* If an AS-name match is found, mark this ORDER BY column as being
      ** a copy of the iCol-th result-set column.  The subsequent call to
      ** sqlite3ResolveOrderGroupBy() will convert the expression to a
      ** copy of the iCol-th result-set expression. */
      pItem->iOrderByCol = (u16)iCol;
      continue;
    }
    if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
      iCol = resolveAsName(pParse, pSelect->pEList, pE2);
      if( iCol>0 ){
        /* If an AS-name match is found, mark this ORDER BY column as being
        ** a copy of the iCol-th result-set column.  The subsequent call to
        ** sqlite3ResolveOrderGroupBy() will convert the expression to a
        ** copy of the iCol-th result-set expression. */
        pItem->iOrderByCol = (u16)iCol;
        continue;
      }
    }
    if( sqlite3ExprIsInteger(pE2, &iCol) ){
      /* The ORDER BY term is an integer constant.  Again, set the column
      ** number so that sqlite3ResolveOrderGroupBy() will convert the
      ** order-by term to a copy of the result-set expression */
      if( iCol<1 || iCol>0xffff ){
        resolveOutOfRangeError(pParse, zType, i+1, nResult);
        return 1;
      }
75171
75172
75173
75174
75175
75176
75177
75178

75179
75180
75181
75182
75183
75184
75185
75186
75187
75188
75189
75190
75191
75192
75193
75194
75195
75196
75197
75610
75611
75612
75613
75614
75615
75616

75617
75618
75619
75620
75621
75622
75623
75624
75625

75626
75627

75628
75629
75630
75631
75632
75633
75634







-
+








-


-







    /* If a HAVING clause is present, then there must be a GROUP BY clause.
    */
    if( p->pHaving && !pGroupBy ){
      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
      return WRC_Abort;
    }
  
    /* Add the expression list to the name-context before parsing the
    /* Add the output column list to the name-context before parsing the
    ** other expressions in the SELECT statement. This is so that
    ** expressions in the WHERE clause (etc.) can refer to expressions by
    ** aliases in the result set.
    **
    ** Minor point: If this is the case, then the expression will be
    ** re-evaluated for each reference to it.
    */
    sNC.pEList = p->pEList;
    sNC.ncFlags |= NC_AsMaybe;
    if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
    sNC.ncFlags &= ~NC_AsMaybe;

    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.ncFlags |= NC_AllowAgg;

75512
75513
75514
75515
75516
75517
75518
75519
75520

75521
75522
75523
75524
75525
75526
75527
75949
75950
75951
75952
75953
75954
75955


75956
75957
75958
75959
75960
75961
75962
75963







-
-
+







  Expr *p = pExpr;
  while( p ){
    int op = p->op;
    if( op==TK_CAST || op==TK_UPLUS ){
      p = p->pLeft;
      continue;
    }
    assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
    if( op==TK_COLLATE ){
    if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
      pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
      break;
    }
    if( p->pTab!=0
     && (op==TK_AGG_COLUMN || op==TK_COLUMN
          || op==TK_REGISTER || op==TK_TRIGGER)
    ){
76677
76678
76679
76680
76681
76682
76683

76684
76685
76686
76687
76688
76689
76690
77113
77114
77115
77116
77117
77118
77119
77120
77121
77122
77123
77124
77125
77126
77127







+







    case TK_UPLUS: {
      rc = sqlite3ExprIsInteger(p->pLeft, pValue);
      break;
    }
    case TK_UMINUS: {
      int v;
      if( sqlite3ExprIsInteger(p->pLeft, &v) ){
        assert( v!=(-2147483647-1) );
        *pValue = -v;
        rc = 1;
      }
      break;
    }
    default: break;
  }
77132
77133
77134
77135
77136
77137
77138

77139
77140
77141
77142
77143


77144
77145
77146



77147
77148
77149
77150
77151
77152
77153
77154
77569
77570
77571
77572
77573
77574
77575
77576
77577
77578
77579
77580
77581
77582
77583



77584
77585
77586

77587
77588
77589
77590
77591
77592
77593







+





+
+
-
-
-
+
+
+
-







        ExprList *pEList;

        assert( !isRowid );
        sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
        dest.affSdst = (u8)affinity;
        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
        pExpr->x.pSelect->iLimit = 0;
        testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
        if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
          sqlite3DbFree(pParse->db, pKeyInfo);
          return 0;
        }
        pEList = pExpr->x.pSelect->pEList;
        assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
        assert( pEList!=0 );
        if( pKeyInfo && ALWAYS(pEList!=0 && pEList->nExpr>0) ){ 
          pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
              pEList->a[0].pExpr);
        assert( pEList->nExpr>0 );
        pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
                                                         pEList->a[0].pExpr);
        }
      }else if( ALWAYS(pExpr->x.pList!=0) ){
        /* Case 2:     expr IN (exprlist)
        **
        ** For each expression, build an index key from the evaluation and
        ** store it in the temporary table. If <expr> is a column, then use
        ** that columns affinity when building index keys. If <expr> is not
        ** a column, use numeric affinity.
78900
78901
78902
78903
78904
78905
78906

78907
78908
78909
78910
78911
78912
78913
79339
79340
79341
79342
79343
79344
79345
79346
79347
79348
79349
79350
79351
79352
79353







+







  compLeft.op = TK_GE;
  compLeft.pLeft = &exprX;
  compLeft.pRight = pExpr->x.pList->a[0].pExpr;
  compRight.op = TK_LE;
  compRight.pLeft = &exprX;
  compRight.pRight = pExpr->x.pList->a[1].pExpr;
  exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
  exprX.op2 = exprX.op;
  exprX.op = TK_REGISTER;
  if( jumpIfTrue ){
    sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
  }else{
    sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
  }
  sqlite3ReleaseTempReg(pParse, regFree1);
80333
80334
80335
80336
80337
80338
80339
80340

80341
80342
80343
80344
80345
80346
80347
80773
80774
80775
80776
80777
80778
80779

80780
80781
80782
80783
80784
80785
80786
80787







-
+







    return;
  }

  /* Ensure the default expression is something that sqlite3ValueFromExpr()
  ** can handle (i.e. not CURRENT_TIME etc.)
  */
  if( pDflt ){
    sqlite3_value *pVal;
    sqlite3_value *pVal = 0;
    if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
      db->mallocFailed = 1;
      return;
    }
    if( !pVal ){
      sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
      return;
80474
80475
80476
80477
80478
80479
80480
80481

80482
80483
80484
80485
80486
80487
80488
80489
80490
80491
80492
80493
80494
80495
80496
80497
80498
80499
80500
80501

80502
80503
80504
80505
80506
80507
80508
80509
80510









80511
80512
80513
80514
80515
80516
80517
80518


80519
80520
80521
80522
80523
80524
80525
80914
80915
80916
80917
80918
80919
80920

80921
80922
80923
80924
80925
80926
80927
80928
80929
80930
80931
80932
80933
80934
80935
80936
80937
80938
80939
80940
80941
80942
80943
80944
80945
80946
80947
80948
80949


80950
80951
80952
80953
80954
80955
80956
80957
80958
80959
80960
80961
80962
80963
80964
80965

80966
80967
80968
80969
80970
80971
80972
80973
80974







-
+




















+







-
-
+
+
+
+
+
+
+
+
+







-
+
+







  return;
}
#endif  /* SQLITE_ALTER_TABLE */

/************** End of alter.c ***********************************************/
/************** Begin file analyze.c *****************************************/
/*
** 2005 July 8
** 2005-07-08
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
** The ANALYZE command gather statistics about the content of tables
** and indices.  These statistics are made available to the query planner
** to help it make better decisions about how to perform queries.
**
** The following system tables are or have been supported:
**
**    CREATE TABLE sqlite_stat1(tbl, idx, stat);
**    CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample);
**    CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
**    CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample);
**
** Additional tables might be added in future releases of SQLite.
** The sqlite_stat2 table is not created or used unless the SQLite version
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
** with SQLITE_ENABLE_STAT2.  The sqlite_stat2 table is deprecated.
** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
** created and used by SQLite versions 3.7.9 and later and with
** SQLITE_ENABLE_STAT3 defined.  The fucntionality of sqlite_stat3
** is a superset of sqlite_stat2.  
** SQLITE_ENABLE_STAT3 defined.  The functionality of sqlite_stat3
** is a superset of sqlite_stat2.  The sqlite_stat4 is an enhanced
** version of sqlite_stat3 and is only available when compiled with
** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later.  It is
** not possible to enable both STAT3 and STAT4 at the same time.  If they
** are both enabled, then STAT4 is precedence.
**
** For most applications, sqlite_stat1 provides all the statisics required
** for the query planner to make good choices.
**
** Format of sqlite_stat1:
**
** There is normally one row per index, with the index identified by the
** name in the idx column.  The tbl column is the name of the table to
** which the index belongs.  In each such row, the stat column will be
** a string consisting of a list of integers.  The first integer in this
** list is the number of rows in the index and in the table.  The second
** list is the number of rows in the index.  (This is the same as the
** number of rows in the table, except for partial indices.)  The second
** integer is the average number of rows in the index that have the same
** value in the first column of the index.  The third integer is the average
** number of rows in the index that have the same value for the first two
** columns.  The N-th integer (for N>1) is the average number of rows in 
** the index which have the same value for the first N-1 columns.  For
** a K-column index, there will be K+1 integers in the stat column.  If
** the index is unique, then the last integer will be 1.
80558
80559
80560
80561
80562
80563
80564
80565
80566



80567
80568
80569








80570
80571
80572
80573
80574
80575
80576
80577
80578
















80579
80580
80581
80582
80583
80584
80585
80586
80587
80588
80589
80590


80591
80592
80593











80594
80595
80596














80597
80598

80599
80600
80601



80602
80603

80604
80605
80606
80607
80608
80609
80610
80611


80612
80613
80614
80615
80616
80617
80618
80619
80620
80621
80622
80623
80624



80625

80626




80627
80628
80629
80630
80631
80632
80633
80634
80635
80636



80637
80638
80639
80640
80641
80642
80643
80644
80645
80646
80647
80648

80649
80650
80651
80652
80653
80654
80655
80656
80657










80658
80659
80660
80661
80662

80663
80664
80665
80666


80667
80668
80669

80670
80671
80672
80673
80674
80675
80676



80677
80678
80679
80680
80681
80682
80683
80684

80685
80686
80687


80688
80689
80690
80691

80692
80693
80694
80695
80696














80697
80698
80699

80700
80701

80702
80703
80704
80705
80706


80707
80708
80709
80710



80711
80712
80713
80714
80715
80716


80717

80718
80719

80720
80721


80722
80723

80724
80725
80726
80727
80728
80729
80730
80731







80732

80733
80734
80735
80736
80737















80738
80739
80740
80741
80742
80743
80744
80745
80746



































80747
80748
80749
80750
80751
80752
80753
80754
80755
80756
80757
80758
80759
80760












80761
80762










80763









80764
80765
80766
80767
80768

80769
80770
80771
80772

80773
80774
80775
80776
80777
80778
80779
80780
80781
80782
80783
80784




80785
80786
80787




80788






80789
80790
80791
80792






80793
80794
80795
80796
80797
80798
80799
80800
80801
80802
80803
80804
80805

































80806
80807
80808




80809
80810
80811
80812



80813
80814

80815
80816
80817
80818
80819





80820
80821

80822
80823
80824
80825
80826
80827
80828
80829
80830
80831





















80832
80833
80834
80835
80836
80837
80838

80839
80840
80841

80842
80843
80844
80845
80846
80847
80848
80849
80850
80851
80852
80853
80854




















































































80855





























































80856
80857
80858


80859
80860

80861



80862

80863
80864
80865
80866
80867

80868
80869
80870
80871



80872
80873
80874
80875
80876





























































80877
80878
80879
80880
80881
80882
80883
80884
















80885
80886
80887
80888
80889
80890

80891
80892
80893
80894

80895
80896
80897
80898
80899
80900












































80901
80902
80903
80904
80905
80906
80907
80908
80909
80910
80911


80912
80913
80914
80915

80916
80917
80918
80919
80920
80921
80922
80923
80924
80925
80926




80927
80928
80929
80930
80931
80932
80933
80934
80935

80936
80937
80938
80939
80940
80941
80942
80943
80944
80945




80946

80947
80948
80949
80950
80951
80952
80953
81007
81008
81009
81010
81011
81012
81013


81014
81015
81016
81017


81018
81019
81020
81021
81022
81023
81024
81025
81026
81027







81028
81029
81030
81031
81032
81033
81034
81035
81036
81037
81038
81039
81040
81041
81042
81043
81044











81045
81046
81047
81048

81049
81050
81051
81052
81053
81054
81055
81056
81057
81058
81059
81060
81061
81062
81063
81064
81065
81066
81067
81068
81069
81070
81071
81072
81073
81074
81075
81076
81077

81078



81079
81080
81081
81082

81083


81084
81085
81086



81087
81088
81089
81090
81091
81092
81093
81094
81095
81096
81097
81098
81099
81100
81101
81102
81103
81104

81105
81106
81107
81108
81109
81110
81111
81112




81113
81114
81115
81116
81117
81118
81119
81120
81121
81122
81123
81124
81125
81126
81127
81128
81129
81130
81131
81132









81133
81134
81135
81136
81137
81138
81139
81140
81141
81142
81143
81144
81145
81146
81147
81148
81149
81150
81151

81152
81153
81154
81155

81156
81157
81158
81159
81160
81161


81162
81163
81164
81165
81166
81167
81168
81169
81170
81171

81172
81173


81174
81175
81176
81177
81178

81179
81180
81181
81182


81183
81184
81185
81186
81187
81188
81189
81190
81191
81192
81193
81194
81195
81196
81197
81198

81199
81200

81201
81202




81203
81204




81205
81206
81207
81208
81209

81210


81211
81212

81213
81214

81215


81216
81217
81218

81219
81220
81221
81222
81223




81224
81225
81226
81227
81228
81229
81230
81231
81232
81233




81234
81235
81236
81237
81238
81239
81240
81241
81242
81243
81244
81245
81246
81247
81248
81249
81250
81251
81252





81253
81254
81255
81256
81257
81258
81259
81260
81261
81262
81263
81264
81265
81266
81267
81268
81269
81270
81271
81272
81273
81274
81275
81276
81277
81278
81279
81280
81281
81282
81283
81284
81285
81286
81287
81288
81289












81290
81291
81292
81293
81294
81295
81296
81297
81298
81299
81300
81301
81302
81303
81304
81305
81306
81307
81308
81309
81310
81311
81312
81313
81314
81315
81316
81317
81318
81319
81320
81321
81322
81323
81324




81325


81326

81327












81328
81329
81330
81331



81332
81333
81334
81335
81336
81337
81338
81339
81340
81341
81342




81343
81344
81345
81346
81347
81348













81349
81350
81351
81352
81353
81354
81355
81356
81357
81358
81359
81360
81361
81362
81363
81364
81365
81366
81367
81368
81369
81370
81371
81372
81373
81374
81375
81376
81377
81378
81379
81380
81381
81382


81383
81384
81385
81386
81387



81388
81389
81390


81391





81392
81393
81394
81395
81396


81397










81398
81399
81400
81401
81402
81403
81404
81405
81406
81407
81408
81409
81410
81411
81412
81413
81414
81415
81416
81417
81418


81419


81420
81421
81422
81423
81424
81425
81426













81427
81428
81429
81430
81431
81432
81433
81434
81435
81436
81437
81438
81439
81440
81441
81442
81443
81444
81445
81446
81447
81448
81449
81450
81451
81452
81453
81454
81455
81456
81457
81458
81459
81460
81461
81462
81463
81464
81465
81466
81467
81468
81469
81470
81471
81472
81473
81474
81475
81476
81477
81478
81479
81480
81481
81482
81483
81484
81485
81486
81487
81488
81489
81490
81491
81492
81493
81494
81495
81496
81497
81498
81499
81500
81501
81502
81503
81504
81505
81506
81507
81508
81509
81510
81511
81512
81513
81514
81515
81516
81517
81518
81519
81520
81521
81522
81523
81524
81525
81526
81527
81528
81529
81530
81531
81532
81533
81534
81535
81536
81537
81538
81539
81540
81541
81542
81543
81544
81545
81546
81547
81548
81549
81550
81551
81552
81553
81554
81555
81556
81557
81558
81559
81560
81561
81562
81563
81564
81565
81566
81567
81568
81569
81570
81571
81572
81573


81574
81575


81576
81577
81578
81579
81580

81581



81582

81583
81584
81585
81586
81587
81588
81589
81590





81591
81592
81593
81594
81595
81596
81597
81598
81599
81600
81601
81602
81603
81604
81605
81606
81607
81608
81609
81610
81611
81612
81613
81614
81615
81616
81617
81618
81619
81620
81621
81622
81623
81624
81625
81626
81627
81628
81629
81630
81631
81632
81633
81634
81635
81636
81637
81638
81639
81640
81641
81642
81643
81644
81645
81646
81647
81648
81649
81650
81651








81652
81653
81654
81655
81656
81657
81658
81659
81660
81661
81662
81663
81664
81665
81666
81667






81668




81669






81670
81671
81672
81673
81674
81675
81676
81677
81678
81679
81680
81681
81682
81683
81684
81685
81686
81687
81688
81689
81690
81691
81692
81693
81694
81695
81696
81697
81698
81699
81700
81701
81702
81703
81704
81705
81706
81707
81708
81709
81710
81711
81712
81713
81714
81715
81716
81717
81718
81719
81720
81721
81722
81723

81724
81725
81726
81727
81728
81729
81730
81731
81732


81733
81734
81735




81736
81737
81738
81739









81740




81741


81742


81743
81744
81745
81746
81747
81748
81749
81750
81751
81752
81753
81754
81755







-
-
+
+
+

-
-
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+


-
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
+
+
+

-
+
-
-



-
-
-
+
+













+
+
+
-
+

+
+
+
+


-
-
-
-




+
+
+












+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+





+



-
+
+


-
+





-
-
+
+
+







-
+

-
-
+
+



-
+



-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

-
+

-
-
-
-
+
+
-
-
-
-
+
+
+


-

-
-
+
+
-
+

-
+
-
-
+
+

-
+




-
-
-
-
+
+
+
+
+
+
+

+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

-
-
-
-
+
-
-

-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+

+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
+

-
-
-
+
+
+
-
-
+
-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-

-
-


+



+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-
-
+

+
+
+
-
+
-
-
-

-
+




+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+
+




+


-
-



-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-

-
-

-
-
+
+
+
+

+







** The format for sqlite_stat2 is recorded here for legacy reference.  This
** version of SQLite does not support sqlite_stat2.  It neither reads nor
** writes the sqlite_stat2 table.  This version of SQLite only supports
** sqlite_stat3.
**
** Format for sqlite_stat3:
**
** The sqlite_stat3 is an enhancement to sqlite_stat2.  A new name is
** used to avoid compatibility problems.  
** The sqlite_stat3 format is a subset of sqlite_stat4.  Hence, the
** sqlite_stat4 format will be described first.  Further information
** about sqlite_stat3 follows the sqlite_stat4 description.
**
** The format of the sqlite_stat3 table is similar to the format of
** the sqlite_stat2 table.  There are multiple entries for each index.
** Format for sqlite_stat4:
**
** As with sqlite_stat2, the sqlite_stat4 table contains histogram data
** to aid the query planner in choosing good indices based on the values
** that indexed columns are compared against in the WHERE clauses of
** queries.
**
** The sqlite_stat4 table contains multiple entries for each index.
** The idx column names the index and the tbl column is the table of the
** index.  If the idx and tbl columns are the same, then the sample is
** of the INTEGER PRIMARY KEY.  The sample column is a value taken from
** the left-most column of the index.  The nEq column is the approximate
** number of entires in the index whose left-most column exactly matches
** the sample.  nLt is the approximate number of entires whose left-most
** column is less than the sample.  The nDLt column is the approximate
** number of distinct left-most entries in the index that are less than
** the sample.
** of the INTEGER PRIMARY KEY.  The sample column is a blob which is the
** binary encoding of a key from the index, with the trailing rowid
** omitted.  The nEq column is a list of integers.  The first integer
** is the approximate number of entries in the index whose left-most 
** column exactly matches the left-most column of the sample.  The second
** integer in nEq is the approximate number of entries in the index where
** the first two columns match the first two columns of the sample.
** And so forth.  nLt is another list of integers that show the approximate
** number of entries that are strictly less than the sample.  The first
** integer in nLt contains the number of entries in the index where the
** left-most column is less than the left-most column of the sample.
** The K-th integer in the nLt entry is the number of index entries 
** where the first K columns are less than the first K columns of the
** sample.  The nDLt column is like nLt except that it contains the 
** number of distinct entries in the index that are less than the
** sample.
**
** Future versions of SQLite might change to store a string containing
** multiple integers values in the nDLt column of sqlite_stat3.  The first
** integer will be the number of prior index entires that are distinct in
** the left-most column.  The second integer will be the number of prior index
** entries that are distinct in the first two columns.  The third integer
** will be the number of prior index entries that are distinct in the first
** three columns.  And so forth.  With that extension, the nDLt field is
** similar in function to the sqlite_stat1.stat field.
**
** There can be an arbitrary number of sqlite_stat3 entries per index.
** The ANALYZE command will typically generate sqlite_stat3 tables
** There can be an arbitrary number of sqlite_stat4 entries per index.
** The ANALYZE command will typically generate sqlite_stat4 tables
** that contain between 10 and 40 samples which are distributed across
** the key space, though not uniformly, and which include samples with
** largest possible nEq values.
** large nEq values.
**
** Format for sqlite_stat3 redux:
**
** The sqlite_stat3 table is like sqlite_stat4 except that it only
** looks at the left-most column of the index.  The sqlite_stat3.sample
** column contains the actual value of the left-most column instead
** of a blob encoding of the complete index key as is found in
** sqlite_stat4.sample.  The nEq, nLt, and nDLt entries of sqlite_stat3
** all contain just a single integer which is the same as the first
** integer in the equivalent columns in sqlite_stat4.
*/
#ifndef SQLITE_OMIT_ANALYZE

#if defined(SQLITE_ENABLE_STAT4)
# define IsStat4     1
# define IsStat3     0
#elif defined(SQLITE_ENABLE_STAT3)
# define IsStat4     0
# define IsStat3     1
#else
# define IsStat4     0
# define IsStat3     0
# undef SQLITE_STAT4_SAMPLES
# define SQLITE_STAT4_SAMPLES 1
#endif
#define IsStat34    (IsStat3+IsStat4)  /* 1 for STAT3 or STAT4. 0 otherwise */

/*
** This routine generates code that opens the sqlite_stat1 table for
** This routine generates code that opens the sqlite_statN tables.
** writing with cursor iStatCur. If the library was built with the
** SQLITE_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is
** opened for writing using cursor (iStatCur+1)
** The sqlite_stat1 table is always relevant.  sqlite_stat2 is now
** obsolete.  sqlite_stat3 and sqlite_stat4 are only opened when
** appropriate compile-time options are provided.
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** If the sqlite_statN tables do not previously exist, it is created.
** Similarly, if the sqlite_stat3 table does not exist and the library
** is compiled with SQLITE_ENABLE_STAT3 defined, it is created. 
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated
** with the named table are deleted. If zWhere==0, then code is generated
** to delete all stat table entries.
** the sqlite_statN tables associated with the named table are deleted.
** If zWhere==0, then code is generated to delete all stat table entries.
*/
static void openStatTable(
  Parse *pParse,          /* Parsing context */
  int iDb,                /* The database we are looking in */
  int iStatCur,           /* Open the sqlite_stat1 table on this cursor */
  const char *zWhere,     /* Delete entries for this table or index */
  const char *zWhereType  /* Either "tbl" or "idx" */
){
  static const struct {
    const char *zName;
    const char *zCols;
  } aTable[] = {
    { "sqlite_stat1", "tbl,idx,stat" },
#if defined(SQLITE_ENABLE_STAT4)
    { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
    { "sqlite_stat3", 0 },
#ifdef SQLITE_ENABLE_STAT3
#elif defined(SQLITE_ENABLE_STAT3)
    { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
    { "sqlite_stat4", 0 },
#else
    { "sqlite_stat3", 0 },
    { "sqlite_stat4", 0 },
#endif
  };

  int aRoot[] = {0, 0};
  u8 aCreateTbl[] = {0, 0};

  int i;
  sqlite3 *db = pParse->db;
  Db *pDb;
  Vdbe *v = sqlite3GetVdbe(pParse);
  int aRoot[ArraySize(aTable)];
  u8 aCreateTbl[ArraySize(aTable)];

  if( v==0 ) return;
  assert( sqlite3BtreeHoldsAllMutexes(db) );
  assert( sqlite3VdbeDb(v)==db );
  pDb = &db->aDb[iDb];

  /* Create new statistic tables if they do not exist, or clear them
  ** if they do already exist.
  */
  for(i=0; i<ArraySize(aTable); i++){
    const char *zTab = aTable[i].zName;
    Table *pStat;
    if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
      if( aTable[i].zCols ){
      /* The sqlite_stat[12] table does not exist. Create it. Note that a 
      ** side-effect of the CREATE TABLE statement is to leave the rootpage 
      ** of the new table in register pParse->regRoot. This is important 
      ** because the OpenWrite opcode below will be needing it. */
      sqlite3NestedParse(pParse,
          "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
      );
      aRoot[i] = pParse->regRoot;
      aCreateTbl[i] = OPFLAG_P2ISREG;
        /* The sqlite_statN table does not exist. Create it. Note that a 
        ** side-effect of the CREATE TABLE statement is to leave the rootpage 
        ** of the new table in register pParse->regRoot. This is important 
        ** because the OpenWrite opcode below will be needing it. */
        sqlite3NestedParse(pParse,
            "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
        );
        aRoot[i] = pParse->regRoot;
        aCreateTbl[i] = OPFLAG_P2ISREG;
      }
    }else{
      /* The table already exists. If zWhere is not NULL, delete all entries 
      ** associated with the table zWhere. If zWhere is NULL, delete the
      ** entire contents of the table. */
      aRoot[i] = pStat->tnum;
      aCreateTbl[i] = 0;
      sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
      if( zWhere ){
        sqlite3NestedParse(pParse,
           "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
           "DELETE FROM %Q.%s WHERE %s=%Q",
           pDb->zName, zTab, zWhereType, zWhere
        );
      }else{
        /* The sqlite_stat[12] table already exists.  Delete all rows. */
        /* The sqlite_stat[134] table already exists.  Delete all rows. */
        sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
      }
    }
  }

  /* Open the sqlite_stat[13] tables for writing. */
  for(i=0; i<ArraySize(aTable); i++){
  /* Open the sqlite_stat[134] tables for writing. */
  for(i=0; aTable[i].zCols; i++){
    assert( i<ArraySize(aTable) );
    sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
    sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
    sqlite3VdbeChangeP5(v, aCreateTbl[i]);
  }
}

/*
** Recommended number of samples for sqlite_stat3
** Recommended number of samples for sqlite_stat4
*/
#ifndef SQLITE_STAT3_SAMPLES
# define SQLITE_STAT3_SAMPLES 24
#ifndef SQLITE_STAT4_SAMPLES
# define SQLITE_STAT4_SAMPLES 24
#endif

/*
** Three SQL functions - stat3_init(), stat3_push(), and stat3_pop() -
** Three SQL functions - stat_init(), stat_push(), and stat_get() -
** share an instance of the following structure to hold their state
** information.
*/
typedef struct Stat3Accum Stat3Accum;
struct Stat3Accum {
typedef struct Stat4Accum Stat4Accum;
typedef struct Stat4Sample Stat4Sample;
struct Stat4Sample {
  tRowcnt *anEq;                  /* sqlite_stat4.nEq */
  tRowcnt *anDLt;                 /* sqlite_stat4.nDLt */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  tRowcnt *anLt;                  /* sqlite_stat4.nLt */
  i64 iRowid;                     /* Rowid in main table of the key */
  u8 isPSample;                   /* True if a periodic sample */
  int iCol;                       /* If !isPSample, the reason for inclusion */
  u32 iHash;                      /* Tiebreaker hash */
#endif
};                                                    
struct Stat4Accum {
  tRowcnt nRow;             /* Number of rows in the entire table */
  tRowcnt nPSample;         /* How often to do a periodic sample */
  int iMin;                 /* Index of entry with minimum nEq and hash */
  int nCol;                 /* Number of columns in index + rowid */
  int mxSample;             /* Maximum number of samples to accumulate */
  int nSample;              /* Current number of samples */
  Stat4Sample current;      /* Current row as a Stat4Sample */
  u32 iPrn;                 /* Pseudo-random number used for sampling */
  struct Stat3Sample {
    i64 iRowid;                /* Rowid in main table of the key */
    tRowcnt nEq;               /* sqlite_stat3.nEq */
    tRowcnt nLt;               /* sqlite_stat3.nLt */
  Stat4Sample *aBest;       /* Array of (nCol-1) best samples */
  int iMin;                 /* Index in a[] of entry with minimum score */
    tRowcnt nDLt;              /* sqlite_stat3.nDLt */
    u8 isPSample;              /* True if a periodic sample */
    u32 iHash;                 /* Tiebreaker hash */
  } *a;                     /* An array of samples */
  int nSample;              /* Current number of samples */
  int iGet;                 /* Index of current sample accessed by stat_get() */
  Stat4Sample *a;           /* Array of mxSample Stat4Sample objects */
};

#ifdef SQLITE_ENABLE_STAT3
/*
** Implementation of the stat3_init(C,S) SQL function.  The two parameters
** are the number of rows in the table or index (C) and the number of samples
** Implementation of the stat_init(N,C) SQL function. The two parameters
** are the number of rows in the table or index (C) and the number of columns
** to accumulate (S).
** in the index (N).  The second argument (C) is only used for STAT3 and STAT4.
**
** This routine allocates the Stat3Accum object.
** This routine allocates the Stat4Accum object in heap memory. The return 
**
** The return value is the Stat3Accum object (P).
** value is a pointer to the the Stat4Accum object encoded as a blob (i.e. 
** the size of the blob is sizeof(void*) bytes). 
*/
static void stat3Init(
static void statInit(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Stat3Accum *p;
  tRowcnt nRow;
  int mxSample;
  int n;
  Stat4Accum *p;
  int nCol;                       /* Number of columns in index being sampled */
  int nColUp;                     /* nCol rounded up for alignment */
  int n;                          /* Bytes of space to allocate */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int mxSample = SQLITE_STAT4_SAMPLES;
#endif

  /* Decode the three function arguments */
  UNUSED_PARAMETER(argc);
  nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
  mxSample = sqlite3_value_int(argv[1]);
  n = sizeof(*p) + sizeof(p->a[0])*mxSample;
  p = sqlite3MallocZero( n );
  nCol = sqlite3_value_int(argv[0]);
  assert( nCol>1 );               /* >1 because it includes the rowid column */
  nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;

  /* Allocate the space required for the Stat4Accum object */
  n = sizeof(*p) 
    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anEq */
    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anDLt */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anLt */
    + sizeof(Stat4Sample)*(nCol+mxSample)   /* Stat4Accum.aBest[], a[] */
    + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
#endif
  ;
  p = sqlite3MallocZero(n);
  if( p==0 ){
    sqlite3_result_error_nomem(context);
    return;
  }
  p->a = (struct Stat3Sample*)&p[1];
  p->nRow = nRow;
  p->mxSample = mxSample;
  p->nPSample = p->nRow/(mxSample/3+1) + 1;
  sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);

  p->nRow = 0;
  p->nCol = nCol;
  p->current.anDLt = (tRowcnt*)&p[1];
  p->current.anEq = &p->current.anDLt[nColUp];

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  {
    u8 *pSpace;                     /* Allocated space not yet assigned */
    int i;                          /* Used to iterate through p->aSample[] */

    p->iGet = -1;
    p->mxSample = mxSample;
    p->nPSample = sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1;
    p->current.anLt = &p->current.anEq[nColUp];
    sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
  
    /* Set up the Stat4Accum.a[] and aBest[] arrays */
    p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
    p->aBest = &p->a[mxSample];
    pSpace = (u8*)(&p->a[mxSample+nCol]);
    for(i=0; i<(mxSample+nCol); i++){
      p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
      p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
      p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
    }
    assert( (pSpace - (u8*)p)==n );
  
    for(i=0; i<nCol; i++){
      p->aBest[i].iCol = i;
    }
  }
#endif

  /* Return a pointer to the allocated object to the caller */
  sqlite3_result_blob(context, p, sizeof(p), sqlite3_free);
}
static const FuncDef stat3InitFuncdef = {
  2,                /* nArg */
  SQLITE_UTF8,      /* iPrefEnc */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
  stat3Init,        /* xFunc */
  0,                /* xStep */
  0,                /* xFinalize */
  "stat3_init",     /* zName */
  0,                /* pHash */
  0                 /* pDestructor */
static const FuncDef statInitFuncdef = {
  1+IsStat34,      /* nArg */
  SQLITE_UTF8,     /* iPrefEnc */
  0,               /* flags */
  0,               /* pUserData */
  0,               /* pNext */
  statInit,        /* xFunc */
  0,               /* xStep */
  0,               /* xFinalize */
  "stat_init",     /* zName */
  0,               /* pHash */
  0                /* pDestructor */
};

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Return true if pNew is to be preferred over pOld.
*/
static int sampleIsBetter(Stat4Sample *pNew, Stat4Sample *pOld){
  tRowcnt nEqNew = pNew->anEq[pNew->iCol];
  tRowcnt nEqOld = pOld->anEq[pOld->iCol];

  assert( pOld->isPSample==0 && pNew->isPSample==0 );
  assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) );

  if( (nEqNew>nEqOld)
   || (nEqNew==nEqOld && pNew->iCol<pOld->iCol)
   || (nEqNew==nEqOld && pNew->iCol==pOld->iCol && pNew->iHash>pOld->iHash)
  ){
    return 1;
  }
  return 0;
}

/*
** Implementation of the stat3_push(nEq,nLt,nDLt,rowid,P) SQL function.  The
** arguments describe a single key instance.  This routine makes the 
** decision about whether or not to retain this key for the sqlite_stat3
** table.
** Copy the contents of object (*pFrom) into (*pTo).
**
** The return value is NULL.
*/
static void stat3Push(
void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[4]);
  tRowcnt nEq = sqlite3_value_int64(argv[0]);
  tRowcnt nLt = sqlite3_value_int64(argv[1]);
  tRowcnt nDLt = sqlite3_value_int64(argv[2]);
  i64 rowid = sqlite3_value_int64(argv[3]);
  u8 isPSample = 0;
  u8 doInsert = 0;
  int iMin = p->iMin;
  pTo->iRowid = pFrom->iRowid;
  pTo->isPSample = pFrom->isPSample;
  pTo->iCol = pFrom->iCol;
  pTo->iHash = pFrom->iHash;
  struct Stat3Sample *pSample;
  int i;
  u32 h;
  memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
  memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol);
  memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol);
}

/*
** Copy the contents of sample *pNew into the p->a[] array. If necessary,
** remove the least desirable sample from p->a[] to make room.
*/
static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
  Stat4Sample *pSample;
  UNUSED_PARAMETER(context);
  UNUSED_PARAMETER(argc);
  if( nEq==0 ) return;
  h = p->iPrn = p->iPrn*1103515245 + 12345;
  int i;
  i64 iSeq;
  i64 iPos;

  assert( IsStat4 || nEqZero==0 );

  if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){
    doInsert = isPSample = 1;
  }else if( p->nSample<p->mxSample ){
    doInsert = 1;
  }else{
    if( nEq>p->a[iMin].nEq || (nEq==p->a[iMin].nEq && h>p->a[iMin].iHash) ){
      doInsert = 1;
    }
  }
  if( !doInsert ) return;
  if( p->nSample==p->mxSample ){
    assert( p->nSample - iMin - 1 >= 0 );
    memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1));
  if( pNew->isPSample==0 ){
    Stat4Sample *pUpgrade = 0;
    assert( pNew->anEq[pNew->iCol]>0 );

    /* This sample is being added because the prefix that ends in column 
    ** iCol occurs many times in the table. However, if we have already
    ** added a sample that shares this prefix, there is no need to add
    ** this one. Instead, upgrade the priority of the highest priority
    ** existing sample that shares this prefix.  */
    for(i=p->nSample-1; i>=0; i--){
      Stat4Sample *pOld = &p->a[i];
      if( pOld->anEq[pNew->iCol]==0 ){
        if( pOld->isPSample ) return;
        assert( sampleIsBetter(pNew, pOld) );
        if( pUpgrade==0 || sampleIsBetter(pOld, pUpgrade) ){
          pUpgrade = pOld;
        }
      }
    }
    if( pUpgrade ){
      pUpgrade->iCol = pNew->iCol;
      pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol];
      goto find_new_min;
    }
  }

  /* If necessary, remove sample iMin to make room for the new sample. */
  if( p->nSample>=p->mxSample ){
    Stat4Sample *pMin = &p->a[p->iMin];
    tRowcnt *anEq = pMin->anEq;
    tRowcnt *anLt = pMin->anLt;
    tRowcnt *anDLt = pMin->anDLt;
    memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1));
    pSample = &p->a[p->nSample-1];
  }else{
    pSample = &p->a[p->nSample++];
    pSample->anEq = anEq;
    pSample->anDLt = anDLt;
    pSample->anLt = anLt;
    p->nSample = p->mxSample-1;
  }
  pSample->iRowid = rowid;
  pSample->nEq = nEq;
  pSample->nLt = nLt;

  /* Figure out where in the a[] array the new sample should be inserted. */
  iSeq = pNew->anLt[p->nCol-1];
  pSample->nDLt = nDLt;
  pSample->iHash = h;
  for(iPos=p->nSample; iPos>0; iPos--){
  pSample->isPSample = isPSample;

  /* Find the new minimum */
  if( p->nSample==p->mxSample ){
    pSample = p->a;
    if( iSeq>p->a[iPos-1].anLt[p->nCol-1] ) break;
  }

  /* Insert the new sample */
  pSample = &p->a[iPos];
    i = 0;
    while( pSample->isPSample ){
  if( iPos!=p->nSample ){
      i++;
      pSample++;
      assert( i<p->nSample );
    }
    nEq = pSample->nEq;
    h = pSample->iHash;
    iMin = i;
    for(i++, pSample++; i<p->nSample; i++, pSample++){
      if( pSample->isPSample ) continue;
      if( pSample->nEq<nEq
    Stat4Sample *pEnd = &p->a[p->nSample];
    tRowcnt *anEq = pEnd->anEq;
    tRowcnt *anLt = pEnd->anLt;
    tRowcnt *anDLt = pEnd->anDLt;
    memmove(&p->a[iPos], &p->a[iPos+1], (p->nSample-iPos)*sizeof(p->a[0]));
    pSample->anEq = anEq;
    pSample->anDLt = anDLt;
    pSample->anLt = anLt;
  }
  p->nSample++;
  sampleCopy(p, pSample, pNew);

  /* Zero the first nEqZero entries in the anEq[] array. */
  memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero);

 find_new_min:
  if( p->nSample>=p->mxSample ){
    int iMin = -1;
    for(i=0; i<p->mxSample; i++){
      if( p->a[i].isPSample ) continue;
      if( iMin<0 || sampleIsBetter(&p->a[iMin], &p->a[i]) ){
       || (pSample->nEq==nEq && pSample->iHash<h)
      ){
        iMin = i;
        nEq = pSample->nEq;
        h = pSample->iHash;
      }
    }
    assert( iMin>=0 );
    p->iMin = iMin;
  }
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
static const FuncDef stat3PushFuncdef = {
  5,                /* nArg */
  SQLITE_UTF8,      /* iPrefEnc */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
  stat3Push,        /* xFunc */
  0,                /* xStep */
  0,                /* xFinalize */
  "stat3_push",     /* zName */
  0,                /* pHash */
  0                 /* pDestructor */
};

/*
** Field iChng of the index being scanned has changed. So at this point
** p->current contains a sample that reflects the previous row of the
** index. The value of anEq[iChng] and subsequent anEq[] elements are
** correct at this point.
*/
static void samplePushPrevious(Stat4Accum *p, int iChng){
#ifdef SQLITE_ENABLE_STAT4
  int i;

  /* Check if any samples from the aBest[] array should be pushed
  ** into IndexSample.a[] at this point.  */
  for(i=(p->nCol-2); i>=iChng; i--){
    Stat4Sample *pBest = &p->aBest[i];
    if( p->nSample<p->mxSample
     || sampleIsBetter(pBest, &p->a[p->iMin])
    ){
      sampleInsert(p, pBest, i);
    }
  }

  /* Update the anEq[] fields of any samples already collected. */
  for(i=p->nSample-1; i>=0; i--){
    int j;
    for(j=iChng; j<p->nCol; j++){
      if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
    }
  }
#endif

#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
  if( iChng==0 ){
    tRowcnt nLt = p->current.anLt[0];
    tRowcnt nEq = p->current.anEq[0];

    /* Check if this is to be a periodic sample. If so, add it. */
    if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){
      p->current.isPSample = 1;
      sampleInsert(p, &p->current, 0);
      p->current.isPSample = 0;
    }else 

    /* Or if it is a non-periodic sample. Add it in this case too. */
    if( p->nSample<p->mxSample || sampleIsBetter(&p->current, &p->a[p->iMin]) ){
      sampleInsert(p, &p->current, 0);
    }
  }
#endif
}

/*
** Implementation of the stat_push SQL function:  stat_push(P,R,C)
** Arguments:
**
**    P     Pointer to the Stat4Accum object created by stat_init()
**    C     Index of left-most column to differ from previous row
**    R     Rowid for the current row
**
** The SQL function always returns NULL.
**
** The R parameter is only used for STAT3 and STAT4.
*/
static void statPush(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int i;

  /* The three function arguments */
  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
  int iChng = sqlite3_value_int(argv[1]);

  assert( p->nCol>1 );        /* Includes rowid field */
  assert( iChng<p->nCol );

  if( p->nRow==0 ){
    /* anEq[0] is only zero for the very first call to this function.  Do
    ** appropriate initialization */
    for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
  }else{
    /* Second and subsequent calls get processed here */
    samplePushPrevious(p, iChng);

    /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
    ** to the current row of the index. */
    for(i=0; i<iChng; i++){
      p->current.anEq[i]++;
    }
    for(i=iChng; i<p->nCol; i++){
      p->current.anDLt[i]++;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
      p->current.anLt[i] += p->current.anEq[i];
#endif
      p->current.anEq[i] = 1;
    }
  }
  p->nRow++;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  p->current.iRowid = sqlite3_value_int64(argv[2]);
  p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
#endif

#ifdef SQLITE_ENABLE_STAT4
  {
    tRowcnt nLt = p->current.anLt[p->nCol-1];

    /* Check if this is to be a periodic sample. If so, add it. */
    if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
      p->current.isPSample = 1;
      p->current.iCol = 0;
      sampleInsert(p, &p->current, p->nCol-1);
      p->current.isPSample = 0;
    }

    /* Update the aBest[] array. */
    for(i=0; i<(p->nCol-1); i++){
      p->current.iCol = i;
      if( i>=iChng || sampleIsBetter(&p->current, &p->aBest[i]) ){
        sampleCopy(p, &p->aBest[i], &p->current);
      }
    }
  }
#endif
}
static const FuncDef statPushFuncdef = {
  2+IsStat34,      /* nArg */
  SQLITE_UTF8,     /* iPrefEnc */
  0,               /* flags */
  0,               /* pUserData */
  0,               /* pNext */
  statPush,        /* xFunc */
  0,               /* xStep */
  0,               /* xFinalize */
  "stat_push",     /* zName */
  0,               /* pHash */
  0                /* pDestructor */
};

#define STAT_GET_STAT1 0          /* "stat" column of stat1 table */
#define STAT_GET_ROWID 1          /* "rowid" column of stat[34] entry */
#define STAT_GET_NEQ   2          /* "neq" column of stat[34] entry */
#define STAT_GET_NLT   3          /* "nlt" column of stat[34] entry */
#define STAT_GET_NDLT  4          /* "ndlt" column of stat[34] entry */

/*
** Implementation of the stat3_get(P,N,...) SQL function.  This routine is
** used to query the results.  Content is returned for the Nth sqlite_stat3
** Implementation of the stat_get(P,J) SQL function.  This routine is
** used to query the results.  Content is returned for parameter J
** row where N is between 0 and S-1 and S is the number of samples.  The
** value returned depends on the number of arguments.
** which is one of the STAT_GET_xxxx values defined above.
**
** If neither STAT3 nor STAT4 are enabled, then J is always
** STAT_GET_STAT1 and is hence omitted and this routine becomes
** a one-parameter function, stat_get(P), that always returns the
**   argc==2    result:  rowid
** stat1 table entry information.
**   argc==3    result:  nEq
**   argc==4    result:  nLt
**   argc==5    result:  nDLt
*/
static void stat3Get(
static void statGet(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  /* STAT3 and STAT4 have a parameter on this routine. */
  int n = sqlite3_value_int(argv[1]);
  Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[0]);

  assert( p!=0 );
  if( p->nSample<=n ) return;
  int eCall = sqlite3_value_int(argv[1]);
  assert( argc==2 );
  assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ 
       || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
       || eCall==STAT_GET_NDLT 
  );
  if( eCall==STAT_GET_STAT1 )
#else
  assert( argc==1 );
#endif
  {
    /* Return the value to store in the "stat" column of the sqlite_stat1
    ** table for this index.
    **
    ** The value is a string composed of a list of integers describing 
    ** the index. The first integer in the list is the total number of 
    ** entries in the index. There is one additional integer in the list 
    ** for each indexed column. This additional integer is an estimate of
    ** the number of rows matched by a stabbing query on the index using
    ** a key with the corresponding number of fields. In other words,
    ** if the index is on columns (a,b) and the sqlite_stat1 value is 
    ** "100 10 2", then SQLite estimates that:
    **
    **   * the index contains 100 rows,
    **   * "WHERE a=?" matches 10 rows, and
    **   * "WHERE a=? AND b=?" matches 2 rows.
    **
    ** If D is the count of distinct values and K is the total number of 
    ** rows, then each estimate is computed as:
    **
    **        I = (K+D-1)/D
    */
    char *z;
    int i;

    char *zRet = sqlite3MallocZero(p->nCol * 25);
    if( zRet==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }

    sqlite3_snprintf(24, zRet, "%lld", p->nRow);
    z = zRet + sqlite3Strlen30(zRet);
    for(i=0; i<(p->nCol-1); i++){
      i64 nDistinct = p->current.anDLt[i] + 1;
      i64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
      sqlite3_snprintf(24, z, " %lld", iVal);
      z += sqlite3Strlen30(z);
      assert( p->current.anEq[i] );
    }
    assert( z[0]=='\0' && z>zRet );

    sqlite3_result_text(context, zRet, -1, sqlite3_free);
  }
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  else if( eCall==STAT_GET_ROWID ){
    if( p->iGet<0 ){
      samplePushPrevious(p, 0);
      p->iGet = 0;
    }
    if( p->iGet<p->nSample ){
  switch( argc ){
    case 2:  sqlite3_result_int64(context, p->a[n].iRowid); break;
    case 3:  sqlite3_result_int64(context, p->a[n].nEq);    break;
    case 4:  sqlite3_result_int64(context, p->a[n].nLt);    break;
    default: sqlite3_result_int64(context, p->a[n].nDLt);   break;
  }
}
static const FuncDef stat3GetFuncdef = {
      sqlite3_result_int64(context, p->a[p->iGet].iRowid);
    }
  }else{
    tRowcnt *aCnt = 0;

    assert( p->iGet<p->nSample );
    switch( eCall ){
      case STAT_GET_NEQ:  aCnt = p->a[p->iGet].anEq; break;
      case STAT_GET_NLT:  aCnt = p->a[p->iGet].anLt; break;
      default: {
        aCnt = p->a[p->iGet].anDLt; 
        p->iGet++;
        break;
      }
    }

  -1,               /* nArg */
  SQLITE_UTF8,      /* iPrefEnc */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
  stat3Get,         /* xFunc */
    if( IsStat3 ){
  0,                /* xStep */
  0,                /* xFinalize */
  "stat3_get",     /* zName */
  0,                /* pHash */
      sqlite3_result_int64(context, (i64)aCnt[0]);
  0                 /* pDestructor */
};
#endif /* SQLITE_ENABLE_STAT3 */



    }else{
      char *zRet = sqlite3MallocZero(p->nCol * 25);
      if( zRet==0 ){
        sqlite3_result_error_nomem(context);
      }else{
        int i;
        char *z = zRet;
        for(i=0; i<p->nCol; i++){
          sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
          z += sqlite3Strlen30(z);
        }
        assert( z[0]=='\0' && z>zRet );
        z[-1] = '\0';
        sqlite3_result_text(context, zRet, -1, sqlite3_free);
      }
    }
  }
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
}
static const FuncDef statGetFuncdef = {
  1+IsStat34,      /* nArg */
  SQLITE_UTF8,     /* iPrefEnc */
  0,               /* flags */
  0,               /* pUserData */
  0,               /* pNext */
  statGet,         /* xFunc */
  0,               /* xStep */
  0,               /* xFinalize */
  "stat_get",      /* zName */
  0,               /* pHash */
  0                /* pDestructor */
};

static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
  assert( regOut!=regStat4 && regOut!=regStat4+1 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
#else
  assert( iParam==STAT_GET_STAT1 );
#endif
  sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
  sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
  sqlite3VdbeChangeP5(v, 1 + IsStat34);
}

/*
** Generate code to do an analysis of all indices associated with
** a single table.
*/
static void analyzeOneTable(
  Parse *pParse,   /* Parser context */
  Table *pTab,     /* Table whose indices are to be analyzed */
  Index *pOnlyIdx, /* If not NULL, only analyze this one index */
  int iStatCur,    /* Index of VdbeCursor that writes the sqlite_stat1 table */
  int iMem         /* Available memory locations begin here */
  int iMem,        /* Available memory locations begin here */
  int iTab         /* Next available cursor */
){
  sqlite3 *db = pParse->db;    /* Database handle */
  Index *pIdx;                 /* An index to being analyzed */
  int iIdxCur;                 /* Cursor open on index being analyzed */
  int iTabCur;                 /* Table cursor */
  Vdbe *v;                     /* The virtual machine being built up */
  int i;                       /* Loop counter */
  int topOfLoop;               /* The top of the loop */
  int endOfLoop;               /* The end of the loop */
  int jZeroRows = -1;          /* Jump from here if number of rows is zero */
  int iDb;                     /* Index of database containing pTab */
  u8 needTableCnt = 1;         /* True to count the table */
  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* The stat column of sqlite_stat1 */
#ifdef SQLITE_ENABLE_STAT3
  int regNewRowid = iMem++;    /* Rowid for the inserted record */
  int regStat4 = iMem++;       /* Register to hold Stat4Accum object */
  int regChng = iMem++;        /* Index of changed index field */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  int regNumEq = regStat1;     /* Number of instances.  Same as regStat1 */
  int regNumLt = iMem++;       /* Number of keys less than regSample */
  int regNumDLt = iMem++;      /* Number of distinct keys less than regSample */
  int regSample = iMem++;      /* The next sample value */
  int regRowid = regSample;    /* Rowid of a sample */
  int regAccum = iMem++;       /* Register to hold Stat3Accum object */
  int regLoop = iMem++;        /* Loop counter */
  int regCount = iMem++;       /* Number of rows in the table or index */
  int regTemp1 = iMem++;       /* Intermediate register */
  int regRowid = iMem++;       /* Rowid argument passed to stat_push() */
  int regTemp2 = iMem++;       /* Intermediate register */
  int once = 1;                /* One-time initialization */
  int shortJump = 0;           /* Instruction address */
  int iTabCur = pParse->nTab++; /* Table cursor */
#endif
  int regCol = iMem++;         /* Content of a column in analyzed table */
  int regRec = iMem++;         /* Register holding completed record */
  int regTemp = iMem++;        /* Temporary use register */
  int regNewRowid = iMem++;    /* Rowid for the inserted record */

  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* Value for the stat column of sqlite_stat1 */
  int regPrev = iMem;          /* MUST BE LAST (see below) */

  pParse->nMem = MAX(pParse->nMem, iMem);
  v = sqlite3GetVdbe(pParse);
  if( v==0 || NEVER(pTab==0) ){
    return;
  }
  if( pTab->tnum==0 ){
    /* Do not gather statistics on views or virtual tables */
    return;
80963
80964
80965
80966
80967
80968
80969
80970




80971
80972
80973




80974

80975
80976
80977


80978
80979




80980
80981
80982
80983
80984
80985
80986


80987
80988
80989
80990
80991
80992
80993
80994
80995
80996
80997
80998
80999
81000
81001
81002
81003






81004
81005
81006
81007

81008
81009
81010
81011
81012
81013
81014
81015
81016









81017
81018
81019
81020





81021
81022
81023


81024
81025
81026
81027



81028
81029
81030
81031

81032
81033
81034
81035







81036
81037
81038




















81039
81040
81041
81042
81043
81044











81045
81046











81047
81048
81049



81050
81051
81052
81053
81054
81055

81056
81057

81058
81059
81060
81061
81062
81063
81064
81065

81066
81067
81068











81069
81070
81071
81072

81073
81074
81075
81076
81077
81078
81079
81080
81081
81082
81083
81084

81085
81086
81087

81088
81089
81090
81091
81092
81093
81094
81095
81096
81097
81098
81099
81100




















81101
81102
81103
81104


81105
81106
81107
81108
81109
81110
81111
81112
81113
81114







81115
81116
81117
81118
81119
81120
81121






81122
81123

81124
81125
81126
81127
81128
81129
81130
81131
81132
81133
81134

81135
81136
81137

81138
81139
81140
81141
81142
81143











81144
81145
81146
81147

81148
81149

81150
81151
81152
81153
81154
81155
81156
81157














81158

81159
81160
81161
81162
81163
81164
81165
81166

81167
81168
81169
81170

81171
81172

81173
81174
81175
81176
81177
81178
81179
81180
81181
81182
81183
81765
81766
81767
81768
81769
81770
81771

81772
81773
81774
81775
81776


81777
81778
81779
81780
81781
81782
81783


81784
81785


81786
81787
81788
81789
81790
81791
81792
81793
81794


81795
81796
81797









81798
81799
81800
81801



81802
81803
81804
81805
81806
81807




81808









81809
81810
81811
81812
81813
81814
81815
81816
81817

81818


81819
81820
81821
81822
81823
81824


81825
81826




81827
81828
81829

81830


81831
81832



81833
81834
81835
81836
81837
81838
81839



81840
81841
81842
81843
81844
81845
81846
81847
81848
81849
81850
81851
81852
81853
81854
81855
81856
81857
81858
81859
81860





81861
81862
81863
81864
81865
81866
81867
81868
81869
81870
81871

81872
81873
81874
81875
81876
81877
81878
81879
81880
81881
81882
81883
81884


81885
81886
81887






81888


81889

81890






81891



81892
81893
81894
81895
81896
81897
81898
81899
81900
81901
81902
81903



81904












81905
81906

81907
81908













81909
81910
81911
81912
81913
81914
81915
81916
81917
81918
81919
81920
81921
81922
81923
81924
81925
81926
81927
81928




81929
81930










81931
81932
81933
81934
81935
81936
81937







81938
81939
81940
81941
81942
81943
81944

81945











81946



81947






81948
81949
81950
81951
81952
81953
81954
81955
81956
81957
81958




81959


81960








81961
81962
81963
81964
81965
81966
81967
81968
81969
81970
81971
81972
81973
81974
81975
81976
81977
81978
81979
81980
81981

81982

81983

81984
81985

81986
81987

81988
81989
81990
81991

81992
81993
81994
81995
81996
81997
81998







-
+
+
+
+

-
-
+
+
+
+

+

-
-
+
+
-
-
+
+
+
+





-
-
+
+

-
-
-
-
-
-
-
-
-




-
-
-
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-

-
-
+
+
+
+
+

-
-
+
+
-
-
-
-
+
+
+
-

-
-
+

-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-

+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+
-
-
-
-
-
-
+
-
-
+
-

-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+

-

+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+





-

-
+
-


-
+

-
+



-







#ifndef SQLITE_OMIT_AUTHORIZATION
  if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
      db->aDb[iDb].zName ) ){
    return;
  }
#endif

  /* Establish a read-lock on the table at the shared-cache level. */
  /* Establish a read-lock on the table at the shared-cache level. 
  ** Open a read-only cursor on the table. Also allocate a cursor number
  ** to use for scanning indexes (iIdxCur). No index cursor is opened at
  ** this time though.  */
  sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);

  iIdxCur = pParse->nTab++;
  iTabCur = iTab++;
  iIdxCur = iTab++;
  pParse->nTab = MAX(pParse->nTab, iTab);
  sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
  sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);

  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int nCol;
    KeyInfo *pKey;
    int nCol;                     /* Number of columns indexed by pIdx */
    KeyInfo *pKey;                /* KeyInfo structure for pIdx */
    int addrIfNot = 0;           /* address of OP_IfNot */
    int *aChngAddr;              /* Array of jump instruction addresses */
    int *aGotoChng;               /* Array of jump instruction addresses */
    int addrRewind;               /* Address of "OP_Rewind iIdxCur" */
    int addrGotoChng0;            /* Address of "Goto addr_chng_0" */
    int addrNextRow;              /* Address of "next_row:" */

    if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
    if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
    VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
    nCol = pIdx->nColumn;
    aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*nCol);
    if( aChngAddr==0 ) continue;
    aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1));
    if( aGotoChng==0 ) continue;
    pKey = sqlite3IndexKeyinfo(pParse, pIdx);
    if( iMem+1+(nCol*2)>pParse->nMem ){
      pParse->nMem = iMem+1+(nCol*2);
    }

    /* Open a cursor to the index to be analyzed. */
    assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
    sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb,
        (char *)pKey, P4_KEYINFO_HANDOFF);
    VdbeComment((v, "%s", pIdx->zName));

    /* Populate the register containing the index name. */
    sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0);

#ifdef SQLITE_ENABLE_STAT3
    if( once ){
      once = 0;
    /*
    ** Pseudo-code for loop that calls stat_push():
    **
    **   Rewind csr
    **   if eof(csr) goto end_of_scan;
    **   regChng = 0
      sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
    }
    sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount);
    sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_STAT3_SAMPLES, regTemp1);
    **   goto chng_addr_0;
    sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumEq);
    sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumLt);
    sqlite3VdbeAddOp2(v, OP_Integer, -1, regNumDLt);
    sqlite3VdbeAddOp3(v, OP_Null, 0, regSample, regAccum);
    sqlite3VdbeAddOp4(v, OP_Function, 1, regCount, regAccum,
                      (char*)&stat3InitFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 2);
#endif /* SQLITE_ENABLE_STAT3 */

    **
    **  next_row:
    **   regChng = 0
    **   if( idx(0) != regPrev(0) ) goto chng_addr_0
    **   regChng = 1
    **   if( idx(1) != regPrev(1) ) goto chng_addr_1
    **   ...
    **   regChng = N
    **   goto chng_addr_N
    /* The block of memory cells initialized here is used as follows.
    **
    **    iMem:                
    **        The total number of rows in the table.
    **  chng_addr_0:
    **   regPrev(0) = idx(0)
    **  chng_addr_1:
    **   regPrev(1) = idx(1)
    **  ...
    **
    **    iMem+1 .. iMem+nCol: 
    **        Number of distinct entries in index considering the 
    **  chng_addr_N:
    **   regRowid = idx(rowid)
    **        left-most N columns only, where N is between 1 and nCol, 
    **        inclusive.
    **
    **    iMem+nCol+1 .. Mem+2*nCol:  
    **   stat_push(P, regChng, regRowid)
    **   Next csr
    **   if !eof(csr) goto next_row;
    **        Previous value of indexed columns, from left to right.
    **
    ** Cells iMem through iMem+nCol are initialized to 0. The others are 
    ** initialized to contain an SQL NULL.
    **  end_of_scan:
    */
    for(i=0; i<=nCol; i++){
      sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i);
    }

    /* Make sure there are enough memory cells allocated to accommodate 
    ** the regPrev array and a trailing rowid (the rowid slot is required
    ** when building a record to insert into the sample column of 
    ** the sqlite_stat4 table.  */
    pParse->nMem = MAX(pParse->nMem, regPrev+nCol);

    for(i=0; i<nCol; i++){
      sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1);
    }
    /* Open a read-only cursor on the index being analyzed. */
    assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
    sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
    sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); 
    VdbeComment((v, "%s", pIdx->zName));

    /* Invoke the stat_init() function. The arguments are:
    ** 
    **    (1) the number of columns in the index including the rowid,
    **    (2) the number of rows in the index,
    **
    ** The second argument is only used for STAT3 and STAT4
    */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+2);
#endif
    sqlite3VdbeAddOp2(v, OP_Integer, nCol+1, regStat4+1);
    sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4+1, regStat4);
    sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 1+IsStat34);

    /* Start the analysis loop. This loop runs through all the entries in
    ** the index b-tree.  */
    endOfLoop = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
    topOfLoop = sqlite3VdbeCurrentAddr(v);
    /* Implementation of the following:
    **
    **   Rewind csr
    **   if eof(csr) goto end_of_scan;
    **   regChng = 0
    **   goto next_push_0;
    **
    */
    addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
    sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
    addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto);
    sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1);  /* Increment row counter */

    /*
    **  next_row:
    **   regChng = 0
    **   if( idx(0) != regPrev(0) ) goto chng_addr_0
    **   regChng = 1
    **   if( idx(1) != regPrev(1) ) goto chng_addr_1
    **   ...
    **   regChng = N
    **   goto chng_addr_N
    */
    addrNextRow = sqlite3VdbeCurrentAddr(v);
    for(i=0; i<nCol; i++){
      CollSeq *pColl;
      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
      char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
      sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
      if( i==0 ){
        /* Always record the very first row */
        addrIfNot = sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
      }
      assert( pIdx->azColl!=0 );
      assert( pIdx->azColl[i]!=0 );
      aGotoChng[i] = 
      pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
      aChngAddr[i] = sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1,
      sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
                                      (char*)pColl, P4_COLLSEQ);
      sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
      VdbeComment((v, "jump if column %d changed", i));
#ifdef SQLITE_ENABLE_STAT3
      if( i==0 ){
        sqlite3VdbeAddOp2(v, OP_AddImm, regNumEq, 1);
        VdbeComment((v, "incr repeat count"));
      }
    }
#endif
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
    sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng);
    aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto);

    /*
    **  chng_addr_0:
    **   regPrev(0) = idx(0)
    **  chng_addr_1:
    **   regPrev(1) = idx(1)
    **  ...
    */
    sqlite3VdbeJumpHere(v, addrGotoChng0);
    for(i=0; i<nCol; i++){
      sqlite3VdbeJumpHere(v, aChngAddr[i]);  /* Set jump dest for the OP_Ne */
      if( i==0 ){
        sqlite3VdbeJumpHere(v, addrIfNot);   /* Jump dest for OP_IfNot */
      sqlite3VdbeJumpHere(v, aGotoChng[i]);
#ifdef SQLITE_ENABLE_STAT3
        sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
                          (char*)&stat3PushFuncdef, P4_FUNCDEF);
        sqlite3VdbeChangeP5(v, 5);
        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, pIdx->nColumn, regRowid);
        sqlite3VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt);
        sqlite3VdbeAddOp2(v, OP_AddImm, regNumDLt, 1);
        sqlite3VdbeAddOp2(v, OP_Integer, 1, regNumEq);
#endif        
      }
      sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
    }
    sqlite3DbFree(db, aChngAddr);

    /*
    /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
    sqlite3VdbeResolveLabel(v, endOfLoop);

    sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
    sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
#ifdef SQLITE_ENABLE_STAT3
    sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
                      (char*)&stat3PushFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 5);
    sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop);
    shortJump = 
    sqlite3VdbeAddOp2(v, OP_AddImm, regLoop, 1);
    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regTemp1,
    **  chng_addr_N:
    **   regRowid = idx(rowid)            // STAT34 only
    **   stat_push(P, regChng, regRowid)  // 3rd parameter STAT34 only
    **   Next csr
    **   if !eof(csr) goto next_row;
    */
    sqlite3VdbeJumpHere(v, aGotoChng[nCol]);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
    assert( regRowid==(regStat4+2) );
#endif
    assert( regChng==(regStat4+1) );
    sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp);
    sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 2+IsStat34);
    sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow);

    /* Add the entry to the stat1 table. */
    callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 2);
    sqlite3VdbeAddOp1(v, OP_IsNull, regTemp1);
    sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, shortJump, regTemp1);
    sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
    sqlite3VdbeAddOp3(v, OP_Column, iTabCur, pIdx->aiColumn[0], regSample);
    sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[0], regSample);
    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumEq,
                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 3);
    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumLt,
                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, 4);
    sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumDLt,
                      (char*)&stat3GetFuncdef, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);

    /* Add the entries to the stat3 or stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    {
      int regEq = regStat1;
      int regLt = regStat1+1;
    sqlite3VdbeChangeP5(v, 5);
    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0);
    sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, shortJump);
    sqlite3VdbeJumpHere(v, shortJump+2);
#endif        
      int regDLt = regStat1+2;
      int regSample = regStat1+3;
      int regCol = regStat1+4;
      int regSampleRowid = regCol + nCol;
      int addrNext;
      int addrIsNull;

    /* Store the results in sqlite_stat1.
      pParse->nMem = MAX(pParse->nMem, regCol+nCol+1);
    **
    ** The result is a single row of the sqlite_stat1 table.  The first
    ** two columns are the names of the table and index.  The third column
    ** is a string composed of a list of integer statistics about the
    ** index.  The first integer in the list is the total number of entries
    ** in the index.  There is one additional integer in the list for each
    ** column of the table.  This additional integer is a guess of how many
    ** rows of the table the index will select.  If D is the count of distinct
    ** values and K is the total number of rows, then the integer is computed
    ** as:
    **

    **        I = (K+D-1)/D
    **
    ** If K==0 then no entry is made into the sqlite_stat1 table.  
      addrNext = sqlite3VdbeCurrentAddr(v);
    ** If K>0 then it is always the case the D>0 so division by zero
    ** is never possible.
    */
    sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
    jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
    for(i=0; i<nCol; i++){
      callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
      addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
      callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
      callStatGet(v, regStat4, STAT_GET_NLT, regLt);
      callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
      sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, addrNext, regSampleRowid);
#ifdef SQLITE_ENABLE_STAT3
      sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, 
                                      pIdx->aiColumn[0], regSample);
#else
      for(i=0; i<nCol; i++){
      sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
      sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
      sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp);
      sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1);
        int iCol = pIdx->aiColumn[i];
      sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp);
      sqlite3VdbeAddOp1(v, OP_ToInt, regTemp);
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
      sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
    }
    if( pIdx->pPartIdxWhere!=0 ) sqlite3VdbeJumpHere(v, jZeroRows);
    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
    sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
    if( pIdx->pPartIdxWhere==0 ) sqlite3VdbeJumpHere(v, jZeroRows);
      }
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample);
#endif
      sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regTemp, "bbbbbb", 0);
      sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
      sqlite3VdbeJumpHere(v, addrIsNull);
    }
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */

    /* End of analysis */
    sqlite3VdbeJumpHere(v, addrRewind);
    sqlite3DbFree(db, aGotoChng);
  }


  /* Create a single sqlite_stat1 entry containing NULL as the index
  ** name and the row count as the content.
  */
  if( pOnlyIdx==0 && needTableCnt ){
    sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb);
    VdbeComment((v, "%s", pTab->zName));
    sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat1);
    sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1);
    sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
    jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
    sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
    sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
    sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
    sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite3VdbeJumpHere(v, jZeroRows);
  }
  if( pParse->nMem<regRec ) pParse->nMem = regRec;
}


/*
** Generate code that will cause the most recent index analysis to
** be loaded into internal hash tables where is can be used.
*/
81193
81194
81195
81196
81197
81198
81199

81200
81201
81202
81203
81204
81205

81206
81207
81208
81209

81210
81211
81212
81213
81214
81215
81216
82008
82009
82010
82011
82012
82013
82014
82015
82016
82017
82018
82019
82020
82021
82022
82023
82024
82025

82026
82027
82028
82029
82030
82031
82032
82033







+






+



-
+







*/
static void analyzeDatabase(Parse *pParse, int iDb){
  sqlite3 *db = pParse->db;
  Schema *pSchema = db->aDb[iDb].pSchema;    /* Schema of database iDb */
  HashElem *k;
  int iStatCur;
  int iMem;
  int iTab;

  sqlite3BeginWriteOperation(pParse, 0, iDb);
  iStatCur = pParse->nTab;
  pParse->nTab += 3;
  openStatTable(pParse, iDb, iStatCur, 0, 0);
  iMem = pParse->nMem+1;
  iTab = pParse->nTab;
  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
    Table *pTab = (Table*)sqliteHashData(k);
    analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
    analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab);
  }
  loadAnalysis(pParse, iDb);
}

/*
** Generate code that will do an analysis of a single table in
** a database.  If pOnlyIdx is not NULL then it is a single index
81227
81228
81229
81230
81231
81232
81233
81234

81235
81236
81237
81238
81239
81240
81241
82044
82045
82046
82047
82048
82049
82050

82051
82052
82053
82054
82055
82056
82057
82058







-
+







  iStatCur = pParse->nTab;
  pParse->nTab += 3;
  if( pOnlyIdx ){
    openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx");
  }else{
    openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
  }
  analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1);
  analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1,pParse->nTab);
  loadAnalysis(pParse, iDb);
}

/*
** Generate code for the ANALYZE command.  The parser calls this routine
** when it recognizes an ANALYZE command.
**
81309
81310
81311
81312
81313
81314
81315





































81316
81317
81318
81319
81320
81321
81322
81323
81324
81325
81326
81327
81328
81329
81330
81331
81332
81333
81334
81335
81336
81337
81338
81339
81340
81341
81342
81343
81344
81345
81346
81347
81348
81349
81350
81351
81352
81353
81354
81355
81356
81357
81358

81359
81360
81361

81362
81363


81364
81365
81366
81367
81368
81369






81370
81371
81372
81373
81374
81375
81376
81377
81378

81379
81380
81381
81382
81383
81384

81385
81386
81387
81388
81389
81390
81391
81392
81393
81394
81395
81396

81397
81398
81399

81400














81401
81402


































81403
81404







81405
81406
81407
81408
81409
81410
81411
81412
81413
81414
81415
81416
81417
81418

81419
81420
81421
81422
81423
81424
81425
81426
81427
81428



81429
81430
81431



81432
81433
81434
81435
81436



81437
81438
81439
81440











81441
81442
81443
81444
81445
81446








81447
81448
81449
81450
81451

81452
81453
81454
81455
81456
81457
81458
81459
81460
81461
81462
81463



81464
81465
81466
81467
81468
81469




81470
81471


81472
81473
81474
81475
81476
81477
81478
81479
81480
81481
81482














81483
81484
81485



81486
81487
81488
81489


81490
81491
81492
81493
81494

81495
81496
81497
81498




81499
81500
81501
81502
81503
81504
81505
81506
81507















81508
81509
81510
81511
81512
81513
81514
81515
81516
81517
81518

81519
81520
81521
81522









81523
81524

81525
81526

81527
81528
81529

81530
81531

81532
81533
81534
81535
81536


81537
81538
81539
81540


81541
81542
81543
81544
81545
81546
81547
82126
82127
82128
82129
82130
82131
82132
82133
82134
82135
82136
82137
82138
82139
82140
82141
82142
82143
82144
82145
82146
82147
82148
82149
82150
82151
82152
82153
82154
82155
82156
82157
82158
82159
82160
82161
82162
82163
82164
82165
82166
82167
82168
82169
82170
82171
82172
82173
82174
82175
82176
82177
82178
82179
82180
82181
82182
82183
82184
82185


82186
82187
82188
82189
82190
82191
82192
82193
82194
82195
82196
82197
82198
82199
82200
82201
82202

82203






82204



82205


82206
82207






82208
82209
82210
82211
82212
82213
82214
82215
82216
82217
82218
82219
82220
82221

82222
82223
82224
82225
82226


82227

82228
82229
82230
82231
82232
82233
82234
82235
82236
82237

82238
82239
82240

82241
82242
82243
82244
82245
82246
82247
82248
82249
82250
82251
82252
82253
82254
82255
82256


82257
82258
82259
82260
82261
82262
82263
82264
82265
82266
82267
82268
82269
82270
82271
82272
82273
82274
82275
82276
82277
82278
82279
82280
82281
82282
82283
82284
82285
82286
82287
82288
82289
82290
82291

82292
82293
82294
82295
82296
82297
82298
82299
82300
82301
82302


82303
82304
82305





82306


82307
82308
82309
82310
82311
82312
82313
82314
82315
82316
82317
82318
82319
82320
82321
82322
82323
82324
82325
82326
82327
82328
82329
82330
82331




82332
82333
82334
82335
82336
82337
82338
82339
82340
82341
82342

82343

82344
82345
82346
82347
82348
82349
82350
82351
82352
82353
82354
82355
82356
82357
82358

82359

82360
82361
82362
82363
82364
82365
82366
82367



82368
82369
82370

82371
82372
82373
82374
82375
82376
82377
82378
82379


82380
82381

82382

82383







82384
82385
82386
82387
82388
82389
82390
82391
82392
82393
82394
82395
82396
82397



82398
82399
82400




82401
82402





82403




82404
82405
82406
82407









82408
82409
82410
82411
82412
82413
82414
82415
82416
82417
82418
82419
82420
82421
82422











82423




82424
82425
82426
82427
82428
82429
82430
82431
82432


82433
82434

82435
82436
82437

82438
82439

82440
82441
82442
82443


82444
82445
82446
82447


82448
82449
82450
82451
82452
82453
82454
82455
82456







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
-

















-

-
-
-
-
-
-
+
-
-
-
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+








-
+




-
-
+
-










-
+


-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+
+
+
+




-
-



-
-
-
-
-
+
-
-








+
+
+



+
+
+





+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-

-



+
+
+
+
+
+
+
+




-
+
-








-
-
-
+
+
+
-





+
+
+
+
-
-
+
+
-

-

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
-
-
-
-
-
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+

-
+


-
+

-
+



-
-
+
+


-
-
+
+







** callback routine.
*/
typedef struct analysisInfo analysisInfo;
struct analysisInfo {
  sqlite3 *db;
  const char *zDatabase;
};

/*
** The first argument points to a nul-terminated string containing a
** list of space separated integers. Read the first nOut of these into
** the array aOut[].
*/
static void decodeIntArray(
  char *zIntArray, 
  int nOut, 
  tRowcnt *aOut, 
  int *pbUnordered
){
  char *z = zIntArray;
  int c;
  int i;
  tRowcnt v;

  assert( pbUnordered==0 || *pbUnordered==0 );

#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  if( z==0 ) z = "";
#else
  if( NEVER(z==0) ) z = "";
#endif
  for(i=0; *z && i<nOut; i++){
    v = 0;
    while( (c=z[0])>='0' && c<='9' ){
      v = v*10 + c - '0';
      z++;
    }
    aOut[i] = v;
    if( *z==' ' ) z++;
  }
  if( pbUnordered && strcmp(z, "unordered")==0 ){
    *pbUnordered = 1;
  }
}

/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.  
**
**     argv[0] = name of the table
**     argv[1] = name of the index (might be NULL)
**     argv[2] = results of analysis - on integer for each column
**
** Entries for which argv[1]==NULL simply record the number of rows in
** the table.
*/
static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
  analysisInfo *pInfo = (analysisInfo*)pData;
  Index *pIndex;
  Table *pTable;
  int i, c, n;
  tRowcnt v;
  const char *z;

  assert( argc==3 );
  UNUSED_PARAMETER2(NotUsed, argc);

  if( argv==0 || argv[0]==0 || argv[2]==0 ){
    return 0;
  }
  pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase);
  if( pTable==0 ){
    return 0;
  }
  if( argv[1] ){
    pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
  }else{
    pIndex = 0;
  }
  n = pIndex ? pIndex->nColumn : 0;
  z = argv[2];
  for(i=0; *z && i<=n; i++){
    v = 0;
    while( (c=z[0])>='0' && c<='9' ){
      v = v*10 + c - '0';
      z++;
    }

    if( i==0 && (pIndex==0 || pIndex->pPartIdxWhere==0) ){
      if( v>0 ) pTable->nRowEst = v;
      if( pIndex==0 ) break;
  if( pIndex ){
    }
    pIndex->aiRowEst[i] = v;
    int bUnordered = 0;
    decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst,&bUnordered);
    if( *z==' ' ) z++;
    if( strcmp(z, "unordered")==0 ){
      pIndex->bUnordered = 1;
      break;
    }
  }
    if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
    pIndex->bUnordered = bUnordered;
  }else{
    decodeIntArray((char*)z, 1, &pTable->nRowEst, 0);
  }

  return 0;
}

/*
** If the Index.aSample variable is not NULL, delete the aSample[] array
** and its contents.
*/
SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  if( pIdx->aSample ){
    int j;
    for(j=0; j<pIdx->nSample; j++){
      IndexSample *p = &pIdx->aSample[j];
      if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
        sqlite3DbFree(db, p->u.z);
      sqlite3DbFree(db, p->p);
      }
    }
    sqlite3DbFree(db, pIdx->aSample);
  }
  if( db && db->pnBytesFreed==0 ){
    pIdx->nSample = 0;
    pIdx->aSample = 0;
  }
#else
  UNUSED_PARAMETER(db);
  UNUSED_PARAMETER(pIdx);
#endif
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
}

#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Populate the pIdx->aAvgEq[] array based on the samples currently
** stored in pIdx->aSample[]. 
*/
static void initAvgEq(Index *pIdx){
  if( pIdx ){
    IndexSample *aSample = pIdx->aSample;
    IndexSample *pFinal = &aSample[pIdx->nSample-1];
    int iCol;
    for(iCol=0; iCol<pIdx->nColumn; iCol++){
      int i;                    /* Used to iterate through samples */
      tRowcnt sumEq = 0;        /* Sum of the nEq values */
      int nSum = 0;             /* Number of terms contributing to sumEq */
      tRowcnt avgEq = 0;
      tRowcnt nDLt = pFinal->anDLt[iCol];
** Load content from the sqlite_stat3 table into the Index.aSample[]
** arrays of all indices.

      /* Set nSum to the number of distinct (iCol+1) field prefixes that
      ** occur in the stat4 table for this index before pFinal. Set
      ** sumEq to the sum of the nEq values for column iCol for the same
      ** set (adding the value only once where there exist dupicate 
      ** prefixes).  */
      for(i=0; i<(pIdx->nSample-1); i++){
        if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
          sumEq += aSample[i].anEq[iCol];
          nSum++;
        }
      }
      if( nDLt>nSum ){
        avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum);
      }
      if( avgEq==0 ) avgEq = 1;
      pIdx->aAvgEq[iCol] = avgEq;
      if( pIdx->nSampleCol==1 ) break;
    }
  }
}

/*
** Load the content from either the sqlite_stat4 or sqlite_stat3 table 
** into the relevant Index.aSample[] arrays.
**
** Arguments zSql1 and zSql2 must point to SQL statements that return
** data equivalent to the following (statements are different for stat3,
** see the caller of this function for details):
**
**    zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx
**    zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4
**
** where %Q is replaced with the database name before the SQL is executed.
*/
static int loadStat3(sqlite3 *db, const char *zDb){
static int loadStatTbl(
  sqlite3 *db,                  /* Database handle */
  int bStat3,                   /* Assume single column records only */
  const char *zSql1,            /* SQL statement 1 (see above) */
  const char *zSql2,            /* SQL statement 2 (see above) */
  const char *zDb               /* Database name (e.g. "main") */
){
  int rc;                       /* Result codes from subroutines */
  sqlite3_stmt *pStmt = 0;      /* An SQL statement being run */
  char *zSql;                   /* Text of the SQL statement */
  Index *pPrevIdx = 0;          /* Previous index in the loop */
  int idx = 0;                  /* slot in pIdx->aSample[] for next sample */
  int eType;                    /* Datatype of a sample */
  IndexSample *pSample;         /* A slot in pIdx->aSample[] */

  assert( db->lookaside.bEnabled==0 );
  if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
    return SQLITE_OK;
  }

  zSql = sqlite3MPrintf(db, 
  zSql = sqlite3MPrintf(db, zSql1, zDb);
      "SELECT idx,count(*) FROM %Q.sqlite_stat3"
      " GROUP BY idx", zDb);
  if( !zSql ){
    return SQLITE_NOMEM;
  }
  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
  sqlite3DbFree(db, zSql);
  if( rc ) return rc;

  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    int nIdxCol = 1;              /* Number of columns in stat4 records */
    int nAvgCol = 1;              /* Number of entries in Index.aAvgEq */

    char *zIndex;   /* Index name */
    Index *pIdx;    /* Pointer to the index object */
    int nSample;    /* Number of samples */
    int nByte;      /* Bytes of space required */
    int i;          /* Bytes of space required */
    tRowcnt *pSpace;

    zIndex = (char *)sqlite3_column_text(pStmt, 0);
    if( zIndex==0 ) continue;
    nSample = sqlite3_column_int(pStmt, 1);
    pIdx = sqlite3FindIndex(db, zIndex, zDb);
    assert( pIdx==0 || bStat3 || pIdx->nSample==0 );
    /* Index.nSample is non-zero at this point if data has already been
    ** loaded from the stat4 table. In this case ignore stat3 data.  */
    if( pIdx==0 ) continue;
    assert( pIdx->nSample==0 );
    pIdx->nSample = nSample;
    pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample));
    if( pIdx==0 || pIdx->nSample ) continue;
    if( bStat3==0 ){
      nIdxCol = pIdx->nColumn+1;
      nAvgCol = pIdx->nColumn;
    }
    pIdx->nSampleCol = nIdxCol;
    nByte = sizeof(IndexSample) * nSample;
    nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
    nByte += nAvgCol * sizeof(tRowcnt);     /* Space for Index.aAvgEq[] */

    pIdx->aSample = sqlite3DbMallocZero(db, nByte);
    pIdx->avgEq = pIdx->aiRowEst[1];
    if( pIdx->aSample==0 ){
      db->mallocFailed = 1;
      sqlite3_finalize(pStmt);
      return SQLITE_NOMEM;
    }
    pSpace = (tRowcnt*)&pIdx->aSample[nSample];
    pIdx->aAvgEq = pSpace; pSpace += nAvgCol;
    for(i=0; i<nSample; i++){
      pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
      pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
      pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol;
    }
    assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) );
  }
  rc = sqlite3_finalize(pStmt);
  if( rc ) return rc;

  zSql = sqlite3MPrintf(db, 
  zSql = sqlite3MPrintf(db, zSql2, zDb);
      "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
  if( !zSql ){
    return SQLITE_NOMEM;
  }
  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
  sqlite3DbFree(db, zSql);
  if( rc ) return rc;

  while( sqlite3_step(pStmt)==SQLITE_ROW ){
    char *zIndex;   /* Index name */
    Index *pIdx;    /* Pointer to the index object */
    int i;          /* Loop counter */
    char *zIndex;                 /* Index name */
    Index *pIdx;                  /* Pointer to the index object */
    int nCol = 1;                 /* Number of columns in index */
    tRowcnt sumEq;  /* Sum of the nEq values */

    zIndex = (char *)sqlite3_column_text(pStmt, 0);
    if( zIndex==0 ) continue;
    pIdx = sqlite3FindIndex(db, zIndex, zDb);
    if( pIdx==0 ) continue;
    /* This next condition is true if data has already been loaded from 
    ** the sqlite_stat4 table. In this case ignore stat3 data.  */
    nCol = pIdx->nSampleCol;
    if( bStat3 && nCol>1 ) continue;
    if( pIdx==pPrevIdx ){
      idx++;
    if( pIdx!=pPrevIdx ){
      initAvgEq(pPrevIdx);
    }else{
      pPrevIdx = pIdx;
      idx = 0;
    }
    assert( idx<pIdx->nSample );
    pSample = &pIdx->aSample[idx];
    pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1);
    pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2);
    pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3);
    if( idx==pIdx->nSample-1 ){
      if( pSample->nDLt>0 ){
    pSample = &pIdx->aSample[pIdx->nSample];
    decodeIntArray((char*)sqlite3_column_text(pStmt,1), nCol, pSample->anEq, 0);
    decodeIntArray((char*)sqlite3_column_text(pStmt,2), nCol, pSample->anLt, 0);
    decodeIntArray((char*)sqlite3_column_text(pStmt,3), nCol, pSample->anDLt,0);

    /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer.
    ** This is in case the sample record is corrupted. In that case, the
    ** sqlite3VdbeRecordCompare() may read up to two varints past the
    ** end of the allocated buffer before it realizes it is dealing with
    ** a corrupt record. Adding the two 0x00 bytes prevents this from causing
    ** a buffer overread.  */
    pSample->n = sqlite3_column_bytes(pStmt, 4);
    pSample->p = sqlite3DbMallocZero(db, pSample->n + 2);
    if( pSample->p==0 ){
        for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
        pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
      }
      sqlite3_finalize(pStmt);
      return SQLITE_NOMEM;
    }
      if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
    }
    eType = sqlite3_column_type(pStmt, 4);
    pSample->eType = (u8)eType;
    memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
    pIdx->nSample++;
    switch( eType ){
      case SQLITE_INTEGER: {
        pSample->u.i = sqlite3_column_int64(pStmt, 4);
        break;
      }
  }
      case SQLITE_FLOAT: {
        pSample->u.r = sqlite3_column_double(pStmt, 4);
        break;
      }
  rc = sqlite3_finalize(pStmt);
  if( rc==SQLITE_OK ) initAvgEq(pPrevIdx);
  return rc;
}
      case SQLITE_NULL: {
        break;
      }
      default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); {
        const char *z = (const char *)(
              (eType==SQLITE_BLOB) ?
              sqlite3_column_blob(pStmt, 4):
              sqlite3_column_text(pStmt, 4)
           );

/*
** Load content from the sqlite_stat4 and sqlite_stat3 tables into 
** the Index.aSample[] arrays of all indices.
*/
static int loadStat4(sqlite3 *db, const char *zDb){
  int rc = SQLITE_OK;             /* Result codes from subroutines */

  assert( db->lookaside.bEnabled==0 );
  if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
    rc = loadStatTbl(db, 0,
      "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", 
      "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
      zDb
    );
        int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
        pSample->nByte = n;
        if( n < 1){
          pSample->u.z = 0;
        }else{
          pSample->u.z = sqlite3DbMallocRaw(db, n);
          if( pSample->u.z==0 ){
            db->mallocFailed = 1;
            sqlite3_finalize(pStmt);
            return SQLITE_NOMEM;
          }
  }
          memcpy(pSample->u.z, z, n);
        }
      }
    }

  if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){
    rc = loadStatTbl(db, 1,
      "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx", 
      "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3",
      zDb
    );
  }

  }
  return sqlite3_finalize(pStmt);
  return rc;
}
#endif /* SQLITE_ENABLE_STAT3 */
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */

/*
** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The
** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The
** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
** arrays. The contents of sqlite_stat3 are used to populate the
** arrays. The contents of sqlite_stat3/4 are used to populate the
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined 
** during compilation and the sqlite_stat3 table is present, no data is 
** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined 
** during compilation and the sqlite_stat3/4 table is present, no data is 
** read from it.
**
** If SQLITE_ENABLE_STAT3 was defined during compilation and the 
** sqlite_stat3 table is not present in the database, SQLITE_ERROR is
** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the 
** sqlite_stat4 table is not present in the database, SQLITE_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
**
** If an OOM error occurs, this function always sets db->mallocFailed.
** This means if the caller does not care about other errors, the return
** code may be ignored.
*/
81555
81556
81557
81558
81559
81560
81561
81562

81563
81564
81565
81566
81567
81568
81569
82464
82465
82466
82467
82468
82469
82470

82471
82472
82473
82474
82475
82476
82477
82478







-
+







  assert( db->aDb[iDb].pBt!=0 );

  /* Clear any prior statistics */
  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
    Index *pIdx = sqliteHashData(i);
    sqlite3DefaultRowEst(pIdx);
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    sqlite3DeleteIndexSamples(db, pIdx);
    pIdx->aSample = 0;
#endif
  }

  /* Check to make sure the sqlite_stat1 table exists */
  sInfo.db = db;
81579
81580
81581
81582
81583
81584
81585
81586
81587


81588
81589
81590
81591

81592
81593
81594
81595
81596
81597
81598
82488
82489
82490
82491
82492
82493
82494


82495
82496
82497
82498
82499

82500
82501
82502
82503
82504
82505
82506
82507







-
-
+
+



-
+







    rc = SQLITE_NOMEM;
  }else{
    rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
    sqlite3DbFree(db, zSql);
  }


  /* Load the statistics from the sqlite_stat3 table. */
#ifdef SQLITE_ENABLE_STAT3
  /* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  if( rc==SQLITE_OK ){
    int lookasideEnabled = db->lookaside.bEnabled;
    db->lookaside.bEnabled = 0;
    rc = loadStat3(db, sInfo.zDatabase);
    rc = loadStat4(db, sInfo.zDatabase);
    db->lookaside.bEnabled = lookasideEnabled;
  }
#endif

  if( rc==SQLITE_NOMEM ){
    db->mallocFailed = 1;
  }
81759
81760
81761
81762
81763
81764
81765



81766
81767
81768
81769
81770
81771
81772
82668
82669
82670
82671
82672
82673
82674
82675
82676
82677
82678
82679
82680
82681
82682
82683
82684







+
+
+







        "attached databases must use the same text encoding as main database");
      rc = SQLITE_ERROR;
    }
    pPager = sqlite3BtreePager(aNew->pBt);
    sqlite3PagerLockingMode(pPager, db->dfltLockMode);
    sqlite3BtreeSecureDelete(aNew->pBt,
                             sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
    sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
#endif
  }
  aNew->safety_level = 3;
  aNew->zName = sqlite3DbStrDup(db, zName);
  if( rc==SQLITE_OK && aNew->zName==0 ){
    rc = SQLITE_NOMEM;
  }

84437
84438
84439
84440
84441
84442
84443
84444

84445
84446
84447
84448
84449
84450
84451
85349
85350
85351
85352
85353
85354
85355

85356
85357
85358
85359
85360
85361
85362
85363







-
+







  Parse *pParse,         /* The parsing context */
  int iDb,               /* The database number */
  const char *zType,     /* "idx" or "tbl" */
  const char *zName      /* Name of index or table */
){
  int i;
  const char *zDbName = pParse->db->aDb[iDb].zName;
  for(i=1; i<=3; i++){
  for(i=1; i<=4; i++){
    char zTab[24];
    sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
    if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
      sqlite3NestedParse(pParse,
        "DELETE FROM %Q.%s WHERE %s=%Q",
        zDbName, zTab, zType, zName
      );
85279
85280
85281
85282
85283
85284
85285
85286

85287
85288
85289
85290
85291
85292
85293
86191
86192
86193
86194
86195
86196
86197

86198
86199
86200
86201
86202
86203
86204
86205







-
+







    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);

    /* Gather the complete text of the CREATE INDEX statement into
    ** the zStmt variable
    */
    if( pStart ){
      int n = (pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
      int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
      if( pName->z[n-1]==';' ) n--;
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
        onError==OE_None ? "" : " UNIQUE", n, pName->z);
    }else{
      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
      /* zStmt = sqlite3MPrintf(""); */
88916
88917
88918
88919
88920
88921
88922
88923

88924
88925

88926
88927
88928
88929
88930
88931
88932
89828
89829
89830
89831
89832
89833
89834

89835
89836

89837
89838
89839
89840
89841
89842
89843
89844







-
+

-
+







    sqlite3StrAccumAppend(pAccum, zVal, nVal);
  }
}
static void groupConcatFinalize(sqlite3_context *context){
  StrAccum *pAccum;
  pAccum = sqlite3_aggregate_context(context, 0);
  if( pAccum ){
    if( pAccum->tooBig ){
    if( pAccum->accError==STRACCUM_TOOBIG ){
      sqlite3_result_error_toobig(context);
    }else if( pAccum->mallocFailed ){
    }else if( pAccum->accError==STRACCUM_NOMEM ){
      sqlite3_result_error_nomem(context);
    }else{    
      sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, 
                          sqlite3_free);
    }
  }
}
89108
89109
89110
89111
89112
89113
89114



89115
89116
89117
89118
89119
89120
89121
90020
90021
90022
90023
90024
90025
90026
90027
90028
90029
90030
90031
90032
90033
90034
90035
90036







+
+
+








  for(i=0; i<ArraySize(aBuiltinFunc); i++){
    sqlite3FuncDefInsert(pHash, &aFunc[i]);
  }
  sqlite3RegisterDateTimeFunctions();
#ifndef SQLITE_OMIT_ALTERTABLE
  sqlite3AlterFunctions();
#endif
#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
  sqlite3AnalyzeFunctions();
#endif
}

/************** End of func.c ************************************************/
/************** Begin file fkey.c ********************************************/
/*
**
93824
93825
93826
93827
93828
93829
93830






























93831
93832
93833
93834
93835
93836
93837
93838
93839
93840
93841
93842
93843
93844
93845
93846
93847
93848
93849

93850
93851
93852
93853
93854
93855
93856
94739
94740
94741
94742
94743
94744
94745
94746
94747
94748
94749
94750
94751
94752
94753
94754
94755
94756
94757
94758
94759
94760
94761
94762
94763
94764
94765
94766
94767
94768
94769
94770
94771
94772
94773
94774
94775
94776
94777
94778
94779
94780
94781
94782
94783
94784
94785
94786
94787
94788
94789
94790
94791
94792
94793
94794
94795
94796
94797
94798
94799
94800
94801
94802







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



















+







    memcpy(pI64, &value, sizeof(value));
  }
  sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
  sqlite3VdbeSetNumCols(v, 1);
  sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
  sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
}


/*
** Set the safety_level and pager flags for pager iDb.  Or if iDb<0
** set these values for all pagers.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
static void setAllPagerFlags(sqlite3 *db){
  if( db->autoCommit ){
    Db *pDb = db->aDb;
    int n = db->nDb;
    assert( SQLITE_FullFSync==PAGER_FULLFSYNC );
    assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC );
    assert( SQLITE_CacheSpill==PAGER_CACHESPILL );
    assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL)
             ==  PAGER_FLAGS_MASK );
    assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level );
    while( (n--) > 0 ){
      if( pDb->pBt ){
        sqlite3BtreeSetPagerFlags(pDb->pBt,
                 pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) );
      }
      pDb++;
    }
  }
}
#else
# define setAllPagerFlags(X)  /* no-op */
#endif


#ifndef SQLITE_OMIT_FLAG_PRAGMAS
/*
** Check to see if zRight and zLeft refer to a pragma that queries
** or changes one of the flags in db->flags.  Return 1 if so and 0 if not.
** Also, implement the pragma.
*/
static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
  static const struct sPragmaType {
    const char *zName;  /* Name of the pragma */
    int mask;           /* Mask for the db->flags value */
  } aPragma[] = {
    { "full_column_names",        SQLITE_FullColNames  },
    { "short_column_names",       SQLITE_ShortColNames },
    { "count_changes",            SQLITE_CountRows     },
    { "empty_result_callbacks",   SQLITE_NullCallback  },
    { "legacy_file_format",       SQLITE_LegacyFileFmt },
    { "fullfsync",                SQLITE_FullFSync     },
    { "checkpoint_fullfsync",     SQLITE_CkptFullFSync },
    { "cache_spill",              SQLITE_CacheSpill    },
    { "reverse_unordered_selects", SQLITE_ReverseOrder  },
    { "query_only",               SQLITE_QueryOnly     },
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    { "automatic_index",          SQLITE_AutoIndex     },
#endif
#ifdef SQLITE_DEBUG
    { "sql_trace",                SQLITE_SqlTrace      },
94297
94298
94299
94300
94301
94302
94303
94304

94305
94306
94307
94308
94309
94310
94311
95243
95244
95245
95246
95247
95248
95249

95250
95251
95252
95253
95254
95255
95256
95257







-
+







  **
  ** Get or set the size limit on rollback journal files.
  */
  if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){
    Pager *pPager = sqlite3BtreePager(pDb->pBt);
    i64 iLimit = -2;
    if( zRight ){
      sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8);
      sqlite3Atoi64(zRight, &iLimit, sqlite3Strlen30(zRight), SQLITE_UTF8);
      if( iLimit<-1 ) iLimit = -1;
    }
    iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
    returnSingleInt(pParse, "journal_size_limit", iLimit);
  }else

#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
94431
94432
94433
94434
94435
94436
94437

94438
94439
94440
94441

94442
94443
94444
94445
94446
94447
94448
94449
94450
94451
94452

94453

94454
94455
94456
94457
94458
94459
94460
95377
95378
95379
95380
95381
95382
95383
95384
95385
95386
95387

95388
95389
95390
95391
95392
95393
95394
95395
95396
95397
95398

95399
95400
95401
95402
95403
95404
95405
95406
95407
95408







+



-
+










-
+

+







  **
  ** This value is advisory.  The underlying VFS is free to memory map
  ** as little or as much as it wants.  Except, if N is set to 0 then the
  ** upper layers will never invoke the xFetch interfaces to the VFS.
  */
  if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){
    sqlite3_int64 sz;
#if SQLITE_MAX_MMAP_SIZE>0
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    if( zRight ){
      int ii;
      sqlite3Atoi64(zRight, &sz, 1000, SQLITE_UTF8);
      sqlite3Atoi64(zRight, &sz, sqlite3Strlen30(zRight), SQLITE_UTF8);
      if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
      if( pId2->n==0 ) db->szMmap = sz;
      for(ii=db->nDb-1; ii>=0; ii--){
        if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){
          sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz);
        }
      }
    }
    sz = -1;
    rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz);
#if SQLITE_MAX_MMAP_SIZE==0
#else
    sz = 0;
    rc = SQLITE_OK;
#endif
    if( rc==SQLITE_OK ){
      returnSingleInt(pParse, "mmap_size", sz);
    }else if( rc!=SQLITE_NOTFOUND ){
      pParse->nErr++;
      pParse->rc = rc;
    }
94633
94634
94635
94636
94637
94638
94639

94640
94641
94642
94643
94644
94645
94646
94647

94648
94649
94650
94651
94652
94653
94654
94655
95581
95582
95583
95584
95585
95586
95587
95588
95589
95590
95591
95592
95593
95594
95595

95596

95597
95598
95599
95600
95601
95602
95603







+







-
+
-







      returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
    }else{
      if( !db->autoCommit ){
        sqlite3ErrorMsg(pParse, 
            "Safety level may not be changed inside a transaction");
      }else{
        pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
        setAllPagerFlags(db);
      }
    }
  }else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */

#ifndef SQLITE_OMIT_FLAG_PRAGMAS
  if( flagPragma(pParse, zLeft, zRight) ){
    /* The flagPragma() subroutine also generates any necessary code
    setAllPagerFlags(db);
    ** there is nothing more to do here */
  }else
#endif /* SQLITE_OMIT_FLAG_PRAGMAS */

#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
  /*
  **   PRAGMA table_info(<table>)
  **
95472
95473
95474
95475
95476
95477
95478
95479
95480
95481
95482
95483
95484
95485
95486
95487
95488
95489
95490
95491
95492
95493
95494
95495
95496
96420
96421
96422
96423
96424
96425
96426











96427
96428
96429
96430
96431
96432
96433







-
-
-
-
-
-
-
-
-
-
-







#endif
  }else
#endif

 
  {/* Empty ELSE clause */}

  /*
  ** Reset the safety level, in case the fullfsync flag or synchronous
  ** setting changed.
  */
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
  if( db->autoCommit ){
    sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
               (db->flags&SQLITE_FullFSync)!=0,
               (db->flags&SQLITE_CkptFullFSync)!=0);
  }
#endif
pragma_out:
  sqlite3DbFree(db, zLeft);
  sqlite3DbFree(db, zRight);
}

#endif /* SQLITE_OMIT_PRAGMA */

102609
102610
102611
102612
102613
102614
102615
102616

102617
102618
102619
102620
102621
102622
102623
103546
103547
103548
103549
103550
103551
103552

103553
103554
103555
103556
103557
103558
103559
103560







-
+







** on register iReg. This is used when an equivalent integer value is 
** stored in place of an 8-byte floating point value in order to save 
** space.
*/
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
  assert( pTab!=0 );
  if( !pTab->pSelect ){
    sqlite3_value *pValue;
    sqlite3_value *pValue = 0;
    u8 enc = ENC(sqlite3VdbeDb(v));
    Column *pCol = &pTab->aCol[i];
    VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
    assert( i<pTab->nCol );
    sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, 
                         pCol->affinity, &pValue);
    if( pValue ){
104385
104386
104387
104388
104389
104390
104391
104392
104393

104394
104395

104396
104397
104398
104399
104400
104401
104402
104403
104404
104405
104406

104407
104408
104409
104410
104411
104412
104413
104414
104415
105322
105323
105324
105325
105326
105327
105328


105329
105330

105331
105332
105333
105334
105335
105336
105337
105338
105339
105340
105341

105342


105343
105344
105345
105346
105347
105348
105349







-
-
+

-
+










-
+
-
-







}

/*
** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
** array. Return the error code for the first error that occurs, or
** SQLITE_OK if all xSync operations are successful.
**
** Set *pzErrmsg to point to a buffer that should be released using 
** sqlite3DbFree() containing an error message, if one is available.
** If an error message is available, leave it in p->zErrMsg.
*/
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe *p){
  int i;
  int rc = SQLITE_OK;
  VTable **aVTrans = db->aVTrans;

  db->aVTrans = 0;
  for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
    int (*x)(sqlite3_vtab *);
    sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
    if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
      rc = x(pVtab);
      sqlite3DbFree(db, *pzErrmsg);
      sqlite3VtabImportErrmsg(p, pVtab);
      *pzErrmsg = pVtab->zErrMsg;
      pVtab->zErrMsg = 0;
    }
  }
  db->aVTrans = aVTrans;
  return rc;
}

/*
104709
104710
104711
104712
104713
104714
104715
104716

104717
104718
104719
104720
104721
104722
104723
105643
105644
105645
105646
105647
105648
105649

105650
105651
105652
105653
105654
105655
105656
105657







-
+







    && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
# define WHERETRACE(K,X)  if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
# define WHERETRACE_ENABLED 1
#else
# define WHERETRACE(K,X)
#endif

/* Forward reference
/* Forward references
*/
typedef struct WhereClause WhereClause;
typedef struct WhereMaskSet WhereMaskSet;
typedef struct WhereOrInfo WhereOrInfo;
typedef struct WhereAndInfo WhereAndInfo;
typedef struct WhereLevel WhereLevel;
typedef struct WhereLoop WhereLoop;
104731
104732
104733
104734
104735
104736
104737
104738
104739
104740



104741
104742
104743
104744
104745




104746
104747
104748
104749
104750
104751
104752
105665
105666
105667
105668
105669
105670
105671



105672
105673
105674
105675
105676



105677
105678
105679
105680
105681
105682
105683
105684
105685
105686
105687







-
-
-
+
+
+


-
-
-
+
+
+
+







/*
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer.  The
** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
** (Virtual tables can return a larger cost, but let's assume they do not.)
** So all costs can be stored in a 16-bit unsigned integer without risk
** of overflow.
**
** Costs are estimates, so don't go to the computational trouble to compute
** 10*log2(X) exactly.  Instead, a close estimate is used.  Any value of
** X<=1 is stored as 0.  X=2 is 10.  X=3 is 16.  X=1000 is 99. etc.
** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
** Instead, a close estimate is used.  Any value of X<=1 is stored as 0.
** X=2 is 10.  X=3 is 16.  X=1000 is 99. etc.
**
** The tool/wherecosttest.c source file implements a command-line program
** that will convert between WhereCost to integers and do addition and
** multiplication on WhereCost values.  That command-line program is a
** useful utility to have around when working with this module.
** that will convert WhereCosts to integers, convert integers to WhereCosts
** and do addition and multiplication on WhereCost values.  The wherecosttest
** command-line program is a useful utility to have around when working with
** this module.
*/
typedef unsigned short int WhereCost;

/*
** This object contains information needed to implement a single nested
** loop in WHERE clause.
**
104765
104766
104767
104768
104769
104770
104771

104772
104773
104774
104775
104776
104777
104778
105700
105701
105702
105703
105704
105705
105706
105707
105708
105709
105710
105711
105712
105713
105714







+







  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
  int iTabCur;          /* The VDBE cursor used to access the table */
  int iIdxCur;          /* The VDBE cursor used to access pIdx */
  int addrBrk;          /* Jump here to break out of the loop */
  int addrNxt;          /* Jump here to start the next IN combination */
  int addrCont;         /* Jump here to continue with the next loop cycle */
  int addrFirst;        /* First instruction of interior of the loop */
  int addrBody;         /* Beginning of the body of this loop */
  u8 iFrom;             /* Which entry in the FROM clause */
  u8 op, p5;            /* Opcode and P5 of the opcode that ends the loop */
  int p1, p2;           /* Operands of the opcode used to ends the loop */
  union {               /* Information that depends on pWLoop->wsFlags */
    struct {
      int nIn;              /* Number of entries in aInLoop[] */
      struct InLoop {
104841
104842
104843
104844
104845
104846
104847
104848
104849


104850
104851
104852
104853
104854
104855
104856
105777
105778
105779
105780
105781
105782
105783


105784
105785
105786
105787
105788
105789
105790
105791
105792







-
-
+
+







struct WhereOrCost {
  Bitmask prereq;     /* Prerequisites */
  WhereCost rRun;     /* Cost of running this subquery */
  WhereCost nOut;     /* Number of outputs for this subquery */
};

/* The WhereOrSet object holds a set of possible WhereOrCosts that
** correspond to the subquery(s) of OR-clause processing.  At most
** favorable N_OR_COST elements are retained.
** correspond to the subquery(s) of OR-clause processing.  Only the
** best N_OR_COST elements are retained.
*/
#define N_OR_COST 3
struct WhereOrSet {
  u16 n;                      /* Number of valid a[] entries */
  WhereOrCost a[N_OR_COST];   /* Set of best costs */
};

104908
104909
104910
104911
104912
104913
104914
104915

104916
104917

104918
104919
104920
104921
104922
104923
104924
105844
105845
105846
105847
105848
105849
105850

105851
105852

105853
105854
105855
105856
105857
105858
105859
105860







-
+

-
+







** use of a bitmask encoding for the operator allows us to search
** quickly for terms that match any of several different operators.
**
** A WhereTerm might also be two or more subterms connected by OR:
**
**         (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
**
** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR
** and the WhereTerm.u.pOrInfo field points to auxiliary information that
** is collected about the
** is collected about the OR clause.
**
** If a term in the WHERE clause does not match either of the two previous
** categories, then eOperator==0.  The WhereTerm.pExpr field is still set
** to the original subexpression content and wtFlags is set up appropriately
** but no other fields in the WhereTerm object are meaningful.
**
** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers,
104960
104961
104962
104963
104964
104965
104966
104967

104968
104969
104970
104971
104972
104973
104974
105896
105897
105898
105899
105900
105901
105902

105903
105904
105905
105906
105907
105908
105909
105910







-
+







#define TERM_DYNAMIC    0x01   /* Need to call sqlite3ExprDelete(db, pExpr) */
#define TERM_VIRTUAL    0x02   /* Added by the optimizer.  Do not code */
#define TERM_CODED      0x04   /* This term is already coded */
#define TERM_COPIED     0x08   /* Has a child */
#define TERM_ORINFO     0x10   /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO    0x20   /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK      0x40   /* Used during OR-clause processing */
#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#  define TERM_VNULL    0x80   /* Manufactured x>NULL or x<=NULL term */
#else
#  define TERM_VNULL    0x00   /* Disabled if not using stat3 */
#endif

/*
** An instance of the WhereScan object is used as an iterator for locating
105066
105067
105068
105069
105070
105071
105072




105073
105074
105075
105076
105077
105078
105079
106002
106003
106004
106005
106006
106007
106008
106009
106010
106011
106012
106013
106014
106015
106016
106017
106018
106019







+
+
+
+







*/
struct WhereLoopBuilder {
  WhereInfo *pWInfo;        /* Information about this WHERE */
  WhereClause *pWC;         /* WHERE clause terms */
  ExprList *pOrderBy;       /* ORDER BY clause */
  WhereLoop *pNew;          /* Template WhereLoop */
  WhereOrSet *pOrSet;       /* Record best loops here, if not NULL */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  UnpackedRecord *pRec;     /* Probe for stat4 (if required) */
  int nRecValid;            /* Number of valid fields currently in pRec */
#endif
};

/*
** The WHERE clause processing routine has two halves.  The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop.  An instance of
** this structure is returned by the first half and passed
105422
105423
105424
105425
105426
105427
105428
105429

105430
105431
105432
105433
105434
105435
105436
106362
106363
106364
106365
106366
106367
106368

106369
106370
106371
106372
106373
106374
106375
106376







-
+







*/
static void createMask(WhereMaskSet *pMaskSet, int iCursor){
  assert( pMaskSet->n < ArraySize(pMaskSet->ix) );
  pMaskSet->ix[pMaskSet->n++] = iCursor;
}

/*
** These routine walk (recursively) an expression tree and generates
** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
*/
static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*);
static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*);
static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){
  Bitmask mask = 0;
105879
105880
105881
105882
105883
105884
105885

105886
105887



105888
105889
105890
105891
105892
105893
105894
106819
106820
106821
106822
106823
106824
106825
106826


106827
106828
106829
106830
106831
106832
106833
106834
106835
106836







+
-
-
+
+
+







#endif /* SQLITE_OMIT_VIRTUALTABLE */

/*
** If the pBase expression originated in the ON or USING clause of
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
  if( pDerived ){
  pDerived->flags |= pBase->flags & EP_FromJoin;
  pDerived->iRightJoinTable = pBase->iRightJoinTable;
    pDerived->flags |= pBase->flags & EP_FromJoin;
    pDerived->iRightJoinTable = pBase->iRightJoinTable;
  }
}

#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
/*
** Analyze a term that consists of two or more OR-connected
** subterms.  So in:
**
105939
105940
105941
105942
105943
105944
105945
105946
105947


105948
105949

105950
105951
105952
105953
105954
105955
105956
106881
106882
106883
106884
106885
106886
106887


106888
106889
106890

106891
106892
106893
106894
106895
106896
106897
106898







-
-
+
+

-
+







** subsubterms at least one of which is indexable.  Indexable AND 
** subterms have their eOperator set to WO_AND and they have
** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
**
** From another point of view, "indexable" means that the subterm could
** potentially be used with an index if an appropriate index exists.
** This analysis does not consider whether or not the index exists; that
** is something the bestIndex() routine will determine.  This analysis
** only looks at whether subterms appropriate for indexing exist.
** is decided elsewhere.  This analysis only looks at whether subterms
** appropriate for indexing exist.
**
** All examples A through E above all satisfy case 2.  But if a term
** All examples A through E above satisfy case 2.  But if a term
** also statisfies case 1 (such as B) we know that the optimizer will
** always prefer case 1, so in that case we pretend that case 2 is not
** satisfied.
**
** It might be the case that multiple tables are indexable.  For example,
** (E) above is indexable on tables P, Q, and R.
**
106337
106338
106339
106340
106341
106342
106343

106344
106345
106346
106347
106348
106349
106350
107279
107280
107281
107282
107283
107284
107285
107286
107287
107288
107289
107290
107291
107292
107293







+







    assert( pList->nExpr==2 );
    for(i=0; i<2; i++){
      Expr *pNewExpr;
      int idxNew;
      pNewExpr = sqlite3PExpr(pParse, ops[i], 
                             sqlite3ExprDup(db, pExpr->pLeft, 0),
                             sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
      transferJoinMarkings(pNewExpr, pExpr);
      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
      testcase( idxNew==0 );
      exprAnalyze(pSrc, pWC, idxNew);
      pTerm = &pWC->a[idxTerm];
      pWC->a[idxNew].iParent = idxTerm;
    }
    pTerm->nChild = 2;
106404
106405
106406
106407
106408
106409
106410

106411
106412
106413
106414
106415
106416
106417

106418
106419
106420
106421
106422
106423
106424
107347
107348
107349
107350
107351
107352
107353
107354
107355
107356
107357
107358
107359
107360
107361
107362
107363
107364
107365
107366
107367
107368
107369







+







+







    }
    sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
    sCollSeqName.n = 6;
    pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
    pNewExpr1 = sqlite3PExpr(pParse, TK_GE, 
           sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
           pStr1, 0);
    transferJoinMarkings(pNewExpr1, pExpr);
    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
    testcase( idxNew1==0 );
    exprAnalyze(pSrc, pWC, idxNew1);
    pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
    pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
           sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
           pStr2, 0);
    transferJoinMarkings(pNewExpr2, pExpr);
    idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
    testcase( idxNew2==0 );
    exprAnalyze(pSrc, pWC, idxNew2);
    pTerm = &pWC->a[idxTerm];
    if( isComplete ){
      pWC->a[idxNew1].iParent = idxTerm;
      pWC->a[idxNew2].iParent = idxTerm;
106460
106461
106462
106463
106464
106465
106466
106467

106468
106469
106470
106471
106472
106473
106474
107405
107406
107407
107408
107409
107410
107411

107412
107413
107414
107415
107416
107417
107418
107419







-
+







      pTerm->nChild = 1;
      pTerm->wtFlags |= TERM_COPIED;
      pNewTerm->prereqAll = pTerm->prereqAll;
    }
  }
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  /* When sqlite_stat3 histogram data is available an operator of the
  ** form "x IS NOT NULL" can sometimes be evaluated more efficiently
  ** as "x>NULL" if x is not an INTEGER PRIMARY KEY.  So construct a
  ** virtual term of that form.
  **
  ** Note that the virtual term must be tagged with TERM_VNULL.  This
  ** TERM_VNULL tag will suppress the not-null check at the beginning
106500
106501
106502
106503
106504
106505
106506
106507

106508
106509
106510
106511
106512
106513
106514
107445
107446
107447
107448
107449
107450
107451

107452
107453
107454
107455
107456
107457
107458
107459







-
+







      pNewTerm->iParent = idxTerm;
      pTerm = &pWC->a[idxTerm];
      pTerm->nChild = 1;
      pTerm->wtFlags |= TERM_COPIED;
      pNewTerm->prereqAll = pTerm->prereqAll;
    }
  }
#endif /* SQLITE_ENABLE_STAT */
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */

  /* 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;
}

106609
106610
106611
106612
106613
106614
106615
106616

106617
106618
106619
106620
106621
106622
106623
107554
107555
107556
107557
107558
107559
107560

107561
107562
107563
107564
107565
107566
107567
107568







-
+







    }
  }

  return 0;
}

/* 
** The (an approximate) sum of two WhereCosts.  This computation is
** Find (an approximate) sum of two WhereCosts.  This computation is
** not a simple "+" operator because WhereCost is stored as a logarithmic
** value.
** 
*/
static WhereCost whereCostAdd(WhereCost a, WhereCost b){
  static const unsigned char x[] = {
     10, 10,                         /* 0,1 */
107068
107069
107070
107071
107072
107073
107074
107075

107076
107077
107078
107079
107080
107081
107082
107083
107084
107085

107086
107087
107088

107089
107090
107091
107092
107093
107094
107095
107096
107097






107098
107099
107100
107101
107102
107103

107104
107105

107106
107107
107108

107109
107110

107111
107112
107113
107114


107115
107116
107117

107118
107119
107120

107121
107122
107123



107124
107125

107126
107127
107128
107129
107130
107131
107132



107133
107134
107135

107136
107137
107138
107139
107140
107141
107142
107143
107144
107145

107146
107147
107148
107149
107150
107151



107152
107153
107154
107155
107156
107157
107158

107159
107160
107161
107162
107163
107164
107165
107166
107167
107168
107169
107170
107171
107172


107173
107174
107175
107176
107177
107178
107179

107180
107181
107182
107183
107184





107185
107186

107187
107188
107189
107190

107191
107192
107193
107194
107195
107196
107197
107198
107199
107200
107201
107202
107203
107204

107205
107206

107207
107208
107209


107210
107211
107212
107213
107214

107215
107216
107217


107218
107219

107220
107221
107222
107223
107224
107225
107226
107227
107228
107229
107230
107231
107232
107233
107234

107235
107236
107237
107238
107239
107240
107241
107242
107243
107244
107245
107246
107247
107248
107249
107250
107251
107252
107253
107254
107255
107256
107257
107258
107259
107260
107261
107262
107263
107264
107265
107266
107267
107268
107269
107270
107271
107272
107273
107274
107275
107276
107277
107278
107279
107280
107281
107282
107283
107284
107285
107286
107287
107288
107289




107290
107291
107292
107293
107294


107295
107296
107297
107298

107299
107300
107301
107302
107303
107304
107305
107306
107307
107308










107309
107310
107311
107312
107313

107314
107315
107316

107317
107318

107319
107320



107321



107322
107323
107324
107325
107326
107327
107328







































107329

107330
107331
107332

107333
107334



107335
107336
107337


107338
107339
107340


107341


107342
107343
107344

107345
107346



107347
107348
107349


107350
107351
107352


107353
107354

107355
107356



107357

107358
107359
107360





107361
107362
107363
107364
107365
107366
107367

107368
107369
107370
107371
107372
107373
107374

107375
107376
107377

107378


107379
107380
107381
107382

107383
107384
107385
107386
107387
107388
107389
107390
107391
107392
107393
107394
107395
107396
107397
107398
107399
107400
107401
107402

107403
107404
107405
107406



107407
107408
107409

107410


107411
107412

107413
107414
107415
107416










107417
107418


107419





107420
107421




107422
107423
107424
107425



107426
107427
107428
107429
107430

107431
107432

107433
107434
107435
107436
107437
107438
107439
107440
107441
107442
107443
107444
107445
107446
107447
107448
107449
107450
107451

107452
107453
107454


107455
107456
107457
107458
107459
107460
107461
107462
107463

107464

107465

107466
107467
107468
107469
107470

107471
107472
107473

107474
107475
107476
107477
107478
107479
107480
108013
108014
108015
108016
108017
108018
108019

108020
108021
108022
108023
108024
108025
108026
108027
108028
108029

108030
108031
108032

108033
108034
108035
108036






108037
108038
108039
108040
108041
108042
108043

108044



108045


108046



108047


108048




108049
108050



108051



108052



108053
108054
108055


108056







108057
108058
108059



108060










108061






108062
108063
108064







108065














108066
108067







108068





108069
108070
108071
108072
108073


108074




108075










108076
108077
108078

108079
108080

108081



108082
108083
108084
108085
108086
108087

108088
108089


108090
108091
108092

108093
108094
108095
108096
108097
108098
108099
108100
108101
108102
108103
108104
108105

108106

108107



































108108
108109
108110
108111
108112
108113
108114
108115
108116
108117
108118
108119
108120
108121
108122
108123




108124
108125
108126
108127
108128
108129
108130


108131
108132
108133
108134
108135

108136
108137









108138
108139
108140
108141
108142
108143
108144
108145
108146
108147
108148
108149
108150


108151
108152
108153

108154
108155
108156
108157
108158

108159
108160
108161
108162
108163
108164
108165







108166
108167
108168
108169
108170
108171
108172
108173
108174
108175
108176
108177
108178
108179
108180
108181
108182
108183
108184
108185
108186
108187
108188
108189
108190
108191
108192
108193
108194
108195
108196
108197
108198
108199
108200
108201
108202
108203
108204
108205
108206
108207

108208
108209


108210
108211
108212



108213
108214
108215

108216
108217
108218

108219
108220
108221

108222
108223


108224
108225
108226



108227
108228
108229

108230
108231
108232
108233

108234
108235

108236
108237
108238
108239
108240



108241
108242
108243
108244
108245
108246
108247
108248
108249
108250


108251
108252
108253

108254
108255
108256

108257
108258
108259

108260
108261
108262
108263
108264
108265
108266

108267
108268
108269
108270
108271
108272
108273
108274
108275
108276
108277
108278
108279
108280
108281
108282
108283
108284
108285
108286

108287
108288
108289
108290

108291
108292
108293
108294
108295
108296
108297
108298
108299
108300
108301
108302
108303




108304
108305
108306
108307
108308
108309
108310
108311
108312
108313


108314
108315
108316
108317
108318
108319
108320
108321


108322
108323
108324
108325




108326
108327
108328


108329
108330

108331
108332

108333
108334
108335
108336
108337
108338
108339
108340
108341
108342
108343
108344
108345
108346
108347
108348
108349
108350
108351

108352
108353
108354
108355
108356
108357
108358
108359
108360
108361
108362
108363
108364
108365

108366
108367
108368
108369
108370
108371
108372
108373
108374
108375
108376
108377
108378

108379
108380
108381
108382
108383
108384
108385
108386







-
+









-
+


-
+



-
-
-
-
-
-
+
+
+
+
+
+

-

-
-
-
+
-
-
+
-
-
-
+
-
-
+
-
-
-
-
+
+
-
-
-
+
-
-
-
+
-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-



-
+

-
+
-
-
-
+
+




-
+

-
-
+
+

-
+












-

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
-
-
-
+
+
+
+



-
-
+
+



-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+



-
-
+


-
+


+

-
+
+
+

+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

-

+
-
-
+
+
+
-
-
-
+
+

-

+
+
-
+
+

-

+
-
-
+
+
+
-
-
-
+
+

-

+
+

-
+

-
+
+
+

+
-
-
-
+
+
+
+
+





-
-
+


-



-
+


-
+

+
+



-
+



















-
+



-
+
+
+



+

+
+


+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+

+
+
+
+
+
-
-
+
+
+
+
-
-
-
-
+
+
+
-
-


-
+

-
+


















-
+



+
+








-
+

+

+





+


-
+







  }

  return pParse->nErr;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */


#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Estimate the location of a particular key among all keys in an
** index.  Store the results in aStat as follows:
**
**    aStat[0]      Est. number of rows less than pVal
**    aStat[1]      Est. number of rows equal to pVal
**
** Return SQLITE_OK on success.
*/
static int whereKeyStats(
static void whereKeyStats(
  Parse *pParse,              /* Database connection */
  Index *pIdx,                /* Index to consider domain of */
  sqlite3_value *pVal,        /* Value to consider */
  UnpackedRecord *pRec,       /* Vector of values to consider */
  int roundUp,                /* Round up if true.  Round down if false */
  tRowcnt *aStat              /* OUT: stats written here */
){
  tRowcnt n;
  IndexSample *aSample;
  int i, eType;
  int isEq = 0;
  i64 v;
  double r, rS;
  IndexSample *aSample = pIdx->aSample;
  int iCol = pRec->nField-1;  /* Index of required stats in anEq[] etc. */
  int iMin = 0;               /* Smallest sample not yet tested */
  int i = pIdx->nSample;      /* Smallest sample larger than or equal to pRec */
  int iTest;                  /* Next sample to test */
  int res;                    /* Result of comparison operation */

  assert( roundUp==0 || roundUp==1 );
  assert( pIdx->nSample>0 );
  if( pVal==0 ) return SQLITE_ERROR;
  n = pIdx->aiRowEst[0];
  aSample = pIdx->aSample;
  assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
  eType = sqlite3_value_type(pVal);

  do{
  if( eType==SQLITE_INTEGER ){
    v = sqlite3_value_int64(pVal);
    r = (i64)v;
    iTest = (iMin+i)/2;
    for(i=0; i<pIdx->nSample; i++){
      if( aSample[i].eType==SQLITE_NULL ) continue;
    res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
      if( aSample[i].eType>=SQLITE_TEXT ) break;
      if( aSample[i].eType==SQLITE_INTEGER ){
        if( aSample[i].u.i>=v ){
          isEq = aSample[i].u.i==v;
    if( res<0 ){
      iMin = iTest+1;
          break;
        }
      }else{
    }else{
        assert( aSample[i].eType==SQLITE_FLOAT );
        if( aSample[i].u.r>=r ){
          isEq = aSample[i].u.r==r;
      i = iTest;
          break;
        }
      }
    }
  }while( res && iMin<i );

    }
  }else if( eType==SQLITE_FLOAT ){
#ifdef SQLITE_DEBUG
    r = sqlite3_value_double(pVal);
    for(i=0; i<pIdx->nSample; i++){
      if( aSample[i].eType==SQLITE_NULL ) continue;
      if( aSample[i].eType>=SQLITE_TEXT ) break;
      if( aSample[i].eType==SQLITE_FLOAT ){
        rS = aSample[i].u.r;
      }else{
  /* The following assert statements check that the binary search code
  ** above found the right answer. This block serves no purpose other
  ** than to invoke the asserts.  */
        rS = aSample[i].u.i;
      }
      if( rS>=r ){
  if( res==0 ){
        isEq = rS==r;
        break;
      }
    }
  }else if( eType==SQLITE_NULL ){
    i = 0;
    if( aSample[0].eType==SQLITE_NULL ) isEq = 1;
  }else{
    assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
    for(i=0; i<pIdx->nSample; i++){
    /* If (res==0) is true, then sample $i must be equal to pRec */
      if( aSample[i].eType==SQLITE_TEXT || aSample[i].eType==SQLITE_BLOB ){
        break;
      }
    }
    if( i<pIdx->nSample ){      
      sqlite3 *db = pParse->db;
    assert( i<pIdx->nSample );
    assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
         || pParse->db->mallocFailed );
      CollSeq *pColl;
      const u8 *z;
      if( eType==SQLITE_BLOB ){
        z = (const u8 *)sqlite3_value_blob(pVal);
        pColl = db->pDfltColl;
        assert( pColl->enc==SQLITE_UTF8 );
      }else{
  }else{
        pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
        /* If the collating sequence was unavailable, we should have failed
        ** long ago and never reached this point.  But we'll check just to
        ** be doubly sure. */
        if( NEVER(pColl==0) ) return SQLITE_ERROR;
        z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
        if( !z ){
          return SQLITE_NOMEM;
        }
        assert( z && pColl && pColl->xCmp );
      }
      n = sqlite3ValueBytes(pVal, pColl->enc);
  
      for(; i<pIdx->nSample; i++){
    /* Otherwise, pRec must be smaller than sample $i and larger than
    ** sample ($i-1).  */
        int c;
        int eSampletype = aSample[i].eType;
        if( eSampletype<eType ) continue;
        if( eSampletype!=eType ) break;
#ifndef SQLITE_OMIT_UTF16
        if( pColl->enc!=SQLITE_UTF8 ){
          int nSample;
    assert( i==pIdx->nSample 
          char *zSample = sqlite3Utf8to16(
              db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample
          );
          if( !zSample ){
            assert( db->mallocFailed );
         || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
         || pParse->db->mallocFailed );
    assert( i==0
         || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
         || pParse->db->mallocFailed );
            return SQLITE_NOMEM;
          }
  }
          c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z);
          sqlite3DbFree(db, zSample);
        }else
#endif
#endif /* ifdef SQLITE_DEBUG */
        {
          c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
        }
        if( c>=0 ){
          if( c==0 ) isEq = 1;
          break;
        }
      }
    }
  }

  /* At this point, aSample[i] is the first sample that is greater than
  ** or equal to pVal.  Or if i==pIdx->nSample, then all samples are less
  ** than pVal.  If aSample[i]==pVal, then isEq==1.
  ** than pVal.  If aSample[i]==pVal, then res==0.
  */
  if( isEq ){
  if( res==0 ){
    assert( i<pIdx->nSample );
    aStat[0] = aSample[i].nLt;
    aStat[1] = aSample[i].nEq;
    aStat[0] = aSample[i].anLt[iCol];
    aStat[1] = aSample[i].anEq[iCol];
  }else{
    tRowcnt iLower, iUpper, iGap;
    if( i==0 ){
      iLower = 0;
      iUpper = aSample[0].nLt;
      iUpper = aSample[0].anLt[iCol];
    }else{
      iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
      iLower = aSample[i-1].nEq + aSample[i-1].nLt;
      iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[iCol];
      iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
    }
    aStat[1] = pIdx->avgEq;
    aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 1);
    if( iLower>=iUpper ){
      iGap = 0;
    }else{
      iGap = iUpper - iLower;
    }
    if( roundUp ){
      iGap = (iGap*2)/3;
    }else{
      iGap = iGap/3;
    }
    aStat[0] = iLower + iGap;
  }
  return SQLITE_OK;
}
#endif /* SQLITE_ENABLE_STAT3 */
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */

/*
** If expression pExpr represents a literal value, set *pp to point to
** an sqlite3_value structure containing the same value, with affinity
** aff applied to it, before returning. It is the responsibility of the 
** caller to eventually release this structure by passing it to 
** sqlite3ValueFree().
**
** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
** is an SQL variable that currently has a non-NULL value bound to it,
** create an sqlite3_value structure containing this value, again with
** affinity aff applied to it, instead.
**
** If neither of the above apply, set *pp to NULL.
**
** If an error occurs, return an error code. Otherwise, SQLITE_OK.
*/
#ifdef SQLITE_ENABLE_STAT3
static int valueFromExpr(
  Parse *pParse, 
  Expr *pExpr, 
  u8 aff, 
  sqlite3_value **pp
){
  if( pExpr->op==TK_VARIABLE
   || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
  ){
    int iVar = pExpr->iColumn;
    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
    *pp = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, aff);
    return SQLITE_OK;
  }
  return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
}
#endif

/*
** This function is used to estimate the number of rows that will be visited
** by scanning an index for a range of values. The range may have an upper
** bound, a lower bound, or both. The WHERE clause terms that set the upper
** and lower bounds are represented by pLower and pUpper respectively. For
** example, assuming that index p is on t1(a):
**
**   ... FROM t1 WHERE a > ? AND a < ? ...
**                    |_____|   |_____|
**                       |         |
**                     pLower    pUpper
**
** If either of the upper or lower bound is not present, then NULL is passed in
** place of the corresponding WhereTerm.
**
** The nEq parameter is passed the index of the index column subject to the
** range constraint. Or, equivalently, the number of equality constraints
** optimized by the proposed index scan. For example, assuming index p is
** on t1(a, b), and the SQL query is:
** The value in (pBuilder->pNew->u.btree.nEq) is the index of the index
** column subject to the range constraint. Or, equivalently, the number of
** equality constraints optimized by the proposed index scan. For example,
** assuming index p is on t1(a, b), and the SQL query is:
**
**   ... FROM t1 WHERE a = ? AND b > ? AND b < ? ...
**
** then nEq should be passed the value 1 (as the range restricted column,
** b, is the second left-most column of the index). Or, if the query is:
** then nEq is set to 1 (as the range restricted column, b, is the second 
** left-most column of the index). Or, if the query is:
**
**   ... FROM t1 WHERE a > ? AND a < ? ...
**
** then nEq should be passed 0.
** then nEq is set to 0.
**
** The returned value is an integer divisor to reduce the estimated
** search space.  A return value of 1 means that range constraints are
** no help at all.  A return value of 2 means range constraints are
** expected to reduce the search space by half.  And so forth...
**
** In the absence of sqlite_stat3 ANALYZE data, each range inequality
** reduces the search space by a factor of 4.  Hence a single constraint (x>?)
** results in a return of 4 and a range constraint (x>? AND x<?) results
** in a return of 16.
** When this function is called, *pnOut is set to the whereCost() of the
** number of rows that the index scan is expected to visit without 
** considering the range constraints. If nEq is 0, this is the number of 
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
** to account for the range contraints pLower and pUpper.
** 
** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be
** used, each range inequality reduces the search space by a factor of 4. 
** Hence a pair of constraints (x>? AND x<?) reduces the expected number of
** rows visited by a factor of 16.
*/
static int whereRangeScanEst(
  Parse *pParse,       /* Parsing & code generating context */
  Index *p,            /* The index containing the range-compared column; "x" */
  int nEq,             /* index into p->aCol[] of the range-compared column */
  WhereLoopBuilder *pBuilder,
  WhereTerm *pLower,   /* Lower bound on the range. ex: "x>123" Might be NULL */
  WhereTerm *pUpper,   /* Upper bound on the range. ex: "x<455" Might be NULL */
  WhereCost *pRangeDiv /* OUT: Reduce search space by this divisor */
  WhereCost *pnOut     /* IN/OUT: Number of rows visited */
){
  int rc = SQLITE_OK;
  int nOut = (int)*pnOut;

#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  Index *p = pBuilder->pNew->u.btree.pIndex;
  int nEq = pBuilder->pNew->u.btree.nEq;

  if( nEq==pBuilder->nRecValid
   && nEq<p->nSampleCol
   && p->nSample 
  if( nEq==0 && p->nSample && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){
    sqlite3_value *pRangeVal;
    tRowcnt iLower = 0;
    tRowcnt iUpper = p->aiRowEst[0];
    tRowcnt a[2];
    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;

   && OptimizationEnabled(pParse->db, SQLITE_Stat3) 
  ){
    UnpackedRecord *pRec = pBuilder->pRec;
    tRowcnt a[2];
    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;

    /* Variable iLower will be set to the estimate of the number of rows in 
    ** the index that are less than the lower bound of the range query. The
    ** lower bound being the concatenation of $P and $L, where $P is the
    ** key-prefix formed by the nEq values matched against the nEq left-most
    ** columns of the index, and $L is the value in pLower.
    **
    ** Or, if pLower is NULL or $L cannot be extracted from it (because it
    ** is not a simple variable or literal value), the lower bound of the
    ** range is $P. Due to a quirk in the way whereKeyStats() works, even
    ** if $L is available, whereKeyStats() is called for both ($P) and 
    ** ($P:$L) and the larger of the two returned values used.
    **
    ** Similarly, iUpper is to be set to the estimate of the number of rows
    ** less than the upper bound of the range query. Where the upper bound
    ** is either ($P) or ($P:$U). Again, even if $U is available, both values
    ** of iUpper are requested of whereKeyStats() and the smaller used.
    */
    tRowcnt iLower;
    tRowcnt iUpper;

    /* Determine iLower and iUpper using ($P) only. */
    if( nEq==0 ){
      iLower = 0;
      iUpper = p->aiRowEst[0];
    }else{
      /* Note: this call could be optimized away - since the same values must 
      ** have been requested when testing key $P in whereEqualScanEst().  */
      whereKeyStats(pParse, p, pRec, 0, a);
      iLower = a[0];
      iUpper = a[0] + a[1];
    }

    /* If possible, improve on the iLower estimate using ($P:$L). */
    if( pLower ){
      int bOk;                    /* True if value is extracted from pExpr */
      Expr *pExpr = pLower->pExpr->pRight;
      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
      rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
      if( rc==SQLITE_OK
       && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
      if( rc==SQLITE_OK && bOk ){
        tRowcnt iNew;
        whereKeyStats(pParse, p, pRec, 0, a);
      ){
        iLower = a[0];
        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
        iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0);
        if( iNew>iLower ) iLower = iNew;
      }
      sqlite3ValueFree(pRangeVal);
    }

    /* If possible, improve on the iUpper estimate using ($P:$U). */
    if( rc==SQLITE_OK && pUpper ){
    if( pUpper ){
      int bOk;                    /* True if value is extracted from pExpr */
      Expr *pExpr = pUpper->pExpr->pRight;
      rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
      rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
      if( rc==SQLITE_OK
       && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
      if( rc==SQLITE_OK && bOk ){
        tRowcnt iNew;
        whereKeyStats(pParse, p, pRec, 1, a);
      ){
        iUpper = a[0];
        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
        iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
        if( iNew<iUpper ) iUpper = iNew;
      }
      sqlite3ValueFree(pRangeVal);
    }

    pBuilder->pRec = pRec;
    if( rc==SQLITE_OK ){
      WhereCost iBase = whereCost(p->aiRowEst[0]);
      WhereCost nNew;
      if( iUpper>iLower ){
        iBase -= whereCost(iUpper - iLower);
        nNew = whereCost(iUpper - iLower);
      }else{
        nNew = 10;        assert( 10==whereCost(2) );
      }
      if( nNew<nOut ){
      *pRangeDiv = iBase;
      WHERETRACE(0x100, ("range scan regions: %u..%u  div=%d\n",
                         (u32)iLower, (u32)iUpper, *pRangeDiv));
        nOut = nNew;
      }
      *pnOut = (WhereCost)nOut;
      WHERETRACE(0x100, ("range scan regions: %u..%u  est=%d\n",
                         (u32)iLower, (u32)iUpper, nOut));
      return SQLITE_OK;
    }
  }
#else
  UNUSED_PARAMETER(pParse);
  UNUSED_PARAMETER(p);
  UNUSED_PARAMETER(nEq);
  UNUSED_PARAMETER(pBuilder);
#endif
  assert( pLower || pUpper );
  *pRangeDiv = 0;
  /* TUNING:  Each inequality constraint reduces the search space 4-fold.
  ** A BETWEEN operator, therefore, reduces the search space 16-fold */
  if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
    *pRangeDiv += 20;  assert( 20==whereCost(4) );
    nOut -= 20;        assert( 20==whereCost(4) );
  }
  if( pUpper ){
    *pRangeDiv += 20;  assert( 20==whereCost(4) );
    nOut -= 20;        assert( 20==whereCost(4) );
  }
  if( nOut<10 ) nOut = 10;
  *pnOut = (WhereCost)nOut;
  return rc;
}

#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Estimate the number of rows that will be returned based on
** an equality constraint x=VALUE and where that VALUE occurs in
** the histogram data.  This only works when x is the left-most
** column of an index and sqlite_stat3 histogram data is available
** for that index.  When pExpr==NULL that means the constraint is
** "x IS NULL" instead of "x=VALUE".
**
** Write the estimated row count into *pnRow and return SQLITE_OK. 
** If unable to make an estimate, leave *pnRow unchanged and return
** non-zero.
**
** This routine can fail if it is unable to load a collating sequence
** required for string comparison, or if unable to allocate memory
** for a UTF conversion required for comparison.  The error is stored
** in the pParse structure.
*/
static int whereEqualScanEst(
  Parse *pParse,       /* Parsing & code generating context */
  Index *p,            /* The index whose left-most column is pTerm */
  WhereLoopBuilder *pBuilder,
  Expr *pExpr,         /* Expression for VALUE in the x=VALUE constraint */
  tRowcnt *pnRow       /* Write the revised row estimate here */
){
  sqlite3_value *pRhs = 0;  /* VALUE on right-hand side of pTerm */
  Index *p = pBuilder->pNew->u.btree.pIndex;
  int nEq = pBuilder->pNew->u.btree.nEq;
  UnpackedRecord *pRec = pBuilder->pRec;
  u8 aff;                   /* Column affinity */
  int rc;                   /* Subfunction return code */
  tRowcnt a[2];             /* Statistics */
  int bOk;

  assert( nEq>=1 );
  assert( nEq<=(p->nColumn+1) );
  assert( p->aSample!=0 );
  assert( p->nSample>0 );
  assert( pBuilder->nRecValid<nEq );
  aff = p->pTable->aCol[p->aiColumn[0]].affinity;
  if( pExpr ){
    rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
    if( rc ) goto whereEqualScanEst_cancel;

  /* If values are not available for all fields of the index to the left
  ** of this one, no estimate can be made. Return SQLITE_NOTFOUND. */
  if( pBuilder->nRecValid<(nEq-1) ){
    return SQLITE_NOTFOUND;
  }

  /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue()
  ** below would return the same value.  */
  if( nEq>p->nColumn ){
  }else{
    pRhs = sqlite3ValueNew(pParse->db);
    *pnRow = 1;
    return SQLITE_OK;
  }

  aff = p->pTable->aCol[p->aiColumn[nEq-1]].affinity;
  rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk);
  pBuilder->pRec = pRec;
  if( rc!=SQLITE_OK ) return rc;
  if( pRhs==0 ) return SQLITE_NOTFOUND;
  rc = whereKeyStats(pParse, p, pRhs, 0, a);
  if( bOk==0 ) return SQLITE_NOTFOUND;
  pBuilder->nRecValid = nEq;

  whereKeyStats(pParse, p, pRec, 0, a);
  if( rc==SQLITE_OK ){
    WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
    *pnRow = a[1];
  }
  WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
  *pnRow = a[1];
  
whereEqualScanEst_cancel:
  sqlite3ValueFree(pRhs);
  return rc;
}
#endif /* defined(SQLITE_ENABLE_STAT3) */
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */

#ifdef SQLITE_ENABLE_STAT3
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Estimate the number of rows that will be returned based on
** an IN constraint where the right-hand side of the IN operator
** is a list of values.  Example:
**
**        WHERE x IN (1,2,3,4)
**
** Write the estimated row count into *pnRow and return SQLITE_OK. 
** If unable to make an estimate, leave *pnRow unchanged and return
** non-zero.
**
** This routine can fail if it is unable to load a collating sequence
** required for string comparison, or if unable to allocate memory
** for a UTF conversion required for comparison.  The error is stored
** in the pParse structure.
*/
static int whereInScanEst(
  Parse *pParse,       /* Parsing & code generating context */
  Index *p,            /* The index whose left-most column is pTerm */
  WhereLoopBuilder *pBuilder,
  ExprList *pList,     /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
  tRowcnt *pnRow       /* Write the revised row estimate here */
){
  Index *p = pBuilder->pNew->u.btree.pIndex;
  int nRecValid = pBuilder->nRecValid;
  int rc = SQLITE_OK;     /* Subfunction return code */
  tRowcnt nEst;           /* Number of rows for a single term */
  tRowcnt nRowEst = 0;    /* New estimate of the number of rows */
  int i;                  /* Loop counter */

  assert( p->aSample!=0 );
  for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
    nEst = p->aiRowEst[0];
    rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst);
    rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst);
    nRowEst += nEst;
    pBuilder->nRecValid = nRecValid;
  }

  if( rc==SQLITE_OK ){
    if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
    *pnRow = nRowEst;
    WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst));
  }
  assert( pBuilder->nRecValid==nRecValid );
  return rc;
}
#endif /* defined(SQLITE_ENABLE_STAT3) */
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */

/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.
**
** Consider the term t2.z='ok' in the following queries:
107704
107705
107706
107707
107708
107709
107710
107711

107712
107713
107714
107715
107716
107717
107718
108610
108611
108612
108613
108614
108615
108616

108617
108618
108619
108620
108621
108622
108623
108624







-
+







  zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx));
  if( !zAff ){
    pParse->db->mallocFailed = 1;
  }

  /* Evaluate the equality constraints
  */
  assert( pIdx->nColumn>=nEq );
  assert( zAff==0 || (int)strlen(zAff)>=nEq );
  for(j=0; j<nEq; j++){
    int r1;
    pTerm = pLoop->aLTerm[j];
    assert( pTerm!=0 );
    /* The following true for indices with redundant columns. 
    ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
    testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
107796
107797
107798
107799
107800
107801
107802

107803

107804
107805
107806
107807
107808
107809
107810
108702
108703
108704
108705
108706
108707
108708
108709

108710
108711
108712
108713
108714
108715
108716
108717







+
-
+







  if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
    return 0;
  }
  sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
  txt.db = db;
  sqlite3StrAccumAppend(&txt, " (", 2);
  for(i=0; i<nEq; i++){
    char *z = (i==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[i]].zName;
    explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "=");
    explainAppendTerm(&txt, i, z, "=");
  }

  j = i;
  if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
    char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
    explainAppendTerm(&txt, i++, z, ">");
  }
109010
109011
109012
109013
109014
109015
109016
109017
109018
109019
109020







109021

109022



109023
109024
109025
109026
109027
109028
109029
109917
109918
109919
109920
109921
109922
109923




109924
109925
109926
109927
109928
109929
109930
109931
109932

109933
109934
109935
109936
109937
109938
109939
109940
109941
109942







-
-
-
-
+
+
+
+
+
+
+

+
-
+
+
+







  saved_wsFlags = pNew->wsFlags;
  saved_prereq = pNew->prereq;
  saved_nOut = pNew->nOut;
  pNew->rSetup = 0;
  rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
  for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
    int nIn = 0;
    if( pTerm->prereqRight & pNew->maskSelf ) continue;
#ifdef SQLITE_ENABLE_STAT3
    if( (pTerm->wtFlags & TERM_VNULL)!=0 && pSrc->pTab->aCol[iCol].notNull ){
      continue; /* skip IS NOT NULL constraints on a NOT NULL column */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    int nRecValid = pBuilder->nRecValid;
#endif
    if( (pTerm->eOperator==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
     && (iCol<0 || pSrc->pTab->aCol[iCol].notNull)
    ){
      continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */
    }
    if( pTerm->prereqRight & pNew->maskSelf ) continue;
#endif

    assert( pNew->nOut==saved_nOut );

    pNew->wsFlags = saved_wsFlags;
    pNew->u.btree.nEq = saved_nEq;
    pNew->nLTerm = saved_nLTerm;
    if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
    pNew->aLTerm[pNew->nLTerm++] = pTerm;
    pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;
    pNew->rRun = rLogSize; /* Baseline cost is log2(N).  Adjustments below */
109072
109073
109074
109075
109076
109077
109078
109079
109080


109081
109082
109083
109084
109085
109086







109087
109088
109089
109090
109091

109092
109093
109094


109095
109096

109097



109098
109099
109100
109101
109102
109103
109104
109105
109106
109107
109108
109109
109110
109111
109112
109113




109114
109115
109116
109117
109118
109119
109120
109985
109986
109987
109988
109989
109990
109991


109992
109993


109994



109995
109996
109997
109998
109999
110000
110001
110002
110003
110004
110005

110006
110007


110008
110009
110010
110011
110012

110013
110014
110015
110016
110017
110018
110019
110020
110021
110022
110023
110024
110025
110026
110027
110028
110029
110030
110031
110032
110033
110034
110035
110036
110037
110038
110039
110040
110041
110042







-
-
+
+
-
-

-
-
-
+
+
+
+
+
+
+




-
+

-
-
+
+


+
-
+
+
+
















+
+
+
+







      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
      pTop = pTerm;
      pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
                     pNew->aLTerm[pNew->nLTerm-2] : 0;
    }
    if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
      /* Adjust nOut and rRun for STAT3 range values */
      WhereCost rDiv;
      whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq,
      assert( pNew->nOut==saved_nOut );
      whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
                        pBtm, pTop, &rDiv);
      pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10;
    }
#ifdef SQLITE_ENABLE_STAT3
    if( pNew->u.btree.nEq==1 && pProbe->nSample
     &&  OptimizationEnabled(db, SQLITE_Stat3) ){
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    if( nInMul==0 
     && pProbe->nSample 
     && pNew->u.btree.nEq<=pProbe->nSampleCol
     && OptimizationEnabled(db, SQLITE_Stat3) 
    ){
      Expr *pExpr = pTerm->pExpr;
      tRowcnt nOut = 0;
      if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
        testcase( pTerm->eOperator & WO_EQ );
        testcase( pTerm->eOperator & WO_ISNULL );
        rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight, &nOut);
        rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
      }else if( (pTerm->eOperator & WO_IN)
             &&  !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)  ){
        rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList, &nOut);
             &&  !ExprHasProperty(pExpr, EP_xIsSelect)  ){
        rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
      }
      assert( nOut==0 || rc==SQLITE_OK );
      if( nOut ){
      if( nOut ) pNew->nOut = whereCost(nOut);
        nOut = whereCost(nOut);
        pNew->nOut = MIN(nOut, saved_nOut);
      }
    }
#endif
    if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
      /* Each row involves a step of the index, then a binary search of
      ** the main table */
      pNew->rRun =  whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
    }
    /* Step cost for each output row */
    pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
    /* TBD: Adjust nOut for additional constraints */
    rc = whereLoopInsert(pBuilder, pNew);
    if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
     && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
    ){
      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
    }
    pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    pBuilder->nRecValid = nRecValid;
#endif
  }
  pNew->prereq = saved_prereq;
  pNew->u.btree.nEq = saved_nEq;
  pNew->wsFlags = saved_wsFlags;
  pNew->nOut = saved_nOut;
  pNew->nLTerm = saved_nLTerm;
  return rc;
109155
109156
109157
109158
109159
109160
109161

109162
109163
109164
109165
109166
109167
109168
110077
110078
110079
110080
110081
110082
110083
110084
110085
110086
110087
110088
110089
110090
110091







+







** the table is used by an index.  Only the first 63 columns are considered.
*/
static Bitmask columnsInIndex(Index *pIdx){
  Bitmask m = 0;
  int j;
  for(j=pIdx->nColumn-1; j>=0; j--){
    int x = pIdx->aiColumn[j];
    assert( x>=0 );
    testcase( x==BMS-1 );
    testcase( x==BMS-2 );
    if( x<BMS-1 ) m |= MASKBIT(x);
  }
  return m;
}

109233
109234
109235
109236
109237
109238
109239

109240
109241
109242
109243
109244
109245
109246
110156
110157
110158
110159
110160
110161
110162
110163
110164
110165
110166
110167
110168
110169
110170







+







      sPk.pNext = pFirst;
    }
    pProbe = &sPk;
  }
  rSize = whereCost(pSrc->pTab->nRowEst);
  rLogSize = estLog(rSize);

#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
  /* Automatic indexes */
  if( !pBuilder->pOrSet
   && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
   && pSrc->pIndex==0
   && !pSrc->viaCoroutine
   && !pSrc->notIndexed
   && !pSrc->isCorrelated
109267
109268
109269
109270
109271
109272
109273

109274
109275
109276
109277
109278
109279
109280
110191
110192
110193
110194
110195
110196
110197
110198
110199
110200
110201
110202
110203
110204
110205







+







        pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
        pNew->wsFlags = WHERE_AUTO_INDEX;
        pNew->prereq = mExtra | pTerm->prereqRight;
        rc = whereLoopInsert(pBuilder, pNew);
      }
    }
  }
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */

  /* Loop over all indices
  */
  for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
    if( pProbe->pPartIdxWhere!=0
     && !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){
      continue;  /* Partial index inappropriate for this query */
109333
109334
109335
109336
109337
109338
109339

109340





109341
109342
109343
109344
109345
109346
109347
110258
110259
110260
110261
110262
110263
110264
110265
110266
110267
110268
110269
110270
110271
110272
110273
110274
110275
110276
110277
110278







+

+
+
+
+
+







          ** which we will simplify to just N*log2(N) */
          pNew->rRun = rSize + rLogSize;
        }
        rc = whereLoopInsert(pBuilder, pNew);
        if( rc ) break;
      }
    }

    rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
    sqlite3Stat4ProbeFree(pBuilder->pRec);
    pBuilder->nRecValid = 0;
    pBuilder->pRec = 0;
#endif

    /* If there was an INDEXED BY clause, then only that one index is
    ** considered. */
    if( pSrc->pIndex ) break;
  }
  return rc;
}
109530
109531
109532
109533
109534
109535
109536

109537
109538
109539
109540
109541
109542
109543
110461
110462
110463
110464
110465
110466
110467
110468
110469
110470
110471
110472
110473
110474
110475







+







  WhereOrSet sSum, sCur, sPrev;
  struct SrcList_item *pItem;
  
  pWC = pBuilder->pWC;
  if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
  pWCEnd = pWC->a + pWC->nTerm;
  pNew = pBuilder->pNew;
  memset(&sSum, 0, sizeof(sSum));

  for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
    if( (pTerm->eOperator & WO_OR)!=0
     && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 
    ){
      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
110215
110216
110217
110218
110219
110220
110221


110222




110223
110224
110225
110226
110227
110228
110229
110230
110231
110232
110233
111147
111148
111149
111150
111151
111152
111153
111154
111155

111156
111157
111158
111159
111160
111161
111162

111163
111164
111165
111166
111167
111168
111169







+
+
-
+
+
+
+



-







    pLoop->aLTerm[0] = pTerm;
    pLoop->nLTerm = 1;
    pLoop->u.btree.nEq = 1;
    /* TUNING: Cost of a rowid lookup is 10 */
    pLoop->rRun = 33;  /* 33==whereCost(10) */
  }else{
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pLoop->aLTermSpace==pLoop->aLTerm );
      assert( ArraySize(pLoop->aLTermSpace)==4 );
      if( pIdx->onError==OE_None || pIdx->pPartIdxWhere!=0 ) continue;
      if( pIdx->onError==OE_None 
       || pIdx->pPartIdxWhere!=0 
       || pIdx->nColumn>ArraySize(pLoop->aLTermSpace) 
      ) continue;
      for(j=0; j<pIdx->nColumn; j++){
        pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
        if( pTerm==0 ) break;
        whereLoopResize(pWInfo->pParse->db, pLoop, j);
        pLoop->aLTerm[j] = pTerm;
      }
      if( j!=pIdx->nColumn ) continue;
      pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
      if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
        pLoop->wsFlags |= WHERE_IDX_ONLY;
      }
110656
110657
110658
110659
110660
110661
110662
110663
110664
110665
110666
110667
110668
110669
110670
110671
110672
110673
110674
111592
111593
111594
111595
111596
111597
111598





111599
111600
111601
111602
111603
111604
111605







-
-
-
-
-







        sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1, 
                            SQLITE_INT_TO_PTR(n), P4_INT32);
        assert( n<=pTab->nCol );
      }
    }else{
      sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
    }
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    if( (pLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
      constructAutomaticIndex(pParse, &pWInfo->sWC, pTabItem, notReady, pLevel);
    }else
#endif
    if( pLoop->wsFlags & WHERE_INDEXED ){
      Index *pIx = pLoop->u.btree.pIndex;
      KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
      /* FIXME:  As an optimization use pTabItem->iCursor if WHERE_IDX_ONLY */
      int iIndexCur = pLevel->iIdxCur = iIdxCur ? iIdxCur : pParse->nTab++;
      assert( pIx->pSchema==pTab->pSchema );
      assert( iIndexCur>=0 );
110685
110686
110687
110688
110689
110690
110691







110692

110693
110694
110695
110696
110697
110698
110699
111616
111617
111618
111619
111620
111621
111622
111623
111624
111625
111626
111627
111628
111629
111630
111631
111632
111633
111634
111635
111636
111637
111638







+
+
+
+
+
+
+

+







  /* Generate the code to do the search.  Each iteration of the for
  ** loop below generates code for a single nested loop of the VM
  ** program.
  */
  notReady = ~(Bitmask)0;
  for(ii=0; ii<nTabList; ii++){
    pLevel = &pWInfo->a[ii];
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
      constructAutomaticIndex(pParse, &pWInfo->sWC,
                &pTabList->a[pLevel->iFrom], notReady, pLevel);
      if( db->mallocFailed ) goto whereBeginError;
    }
#endif
    explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
    pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
    notReady = codeOneLoopStart(pWInfo, ii, notReady);
    pWInfo->iContinue = pLevel->addrCont;
  }

  /* Done. */
  return pWInfo;

110805
110806
110807
110808
110809
110810
110811
110812
110813


110814

110815
110816
110817
110818
110819
110820
110821
111744
111745
111746
111747
111748
111749
111750

111751
111752
111753

111754
111755
111756
111757
111758
111759
111760
111761







-

+
+
-
+







    }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
      pIdx = pLevel->u.pCovidx;
    }
    if( pIdx && !db->mallocFailed ){
      int k, j, last;
      VdbeOp *pOp;

      pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
      last = sqlite3VdbeCurrentAddr(v);
      k = pLevel->addrBody;
      pOp = sqlite3VdbeGetOp(v, k);
      for(k=pWInfo->iTop; k<last; k++, pOp++){
      for(; k<last; k++, pOp++){
        if( pOp->p1!=pLevel->iTabCur ) continue;
        if( pOp->opcode==OP_Column ){
          for(j=0; j<pIdx->nColumn; j++){
            if( pOp->p2==pIdx->aiColumn[j] ){
              pOp->p2 = j;
              pOp->p1 = pLevel->iIdxCur;
              break;
115612
115613
115614
115615
115616
115617
115618



115619
115620
115621
115622
115623
115624
115625
116552
116553
116554
116555
116556
116557
116558
116559
116560
116561
116562
116563
116564
116565
116566
116567
116568







+
+
+







**
**    *  Recursive calls to this routine from thread X return immediately
**       without blocking.
*/
SQLITE_API int sqlite3_initialize(void){
  MUTEX_LOGIC( sqlite3_mutex *pMaster; )       /* The main static mutex */
  int rc;                                      /* Result code */
#ifdef SQLITE_EXTRA_INIT
  int bRunExtraInit = 0;                       /* Extra initialization needed */
#endif

#ifdef SQLITE_OMIT_WSD
  rc = sqlite3_wsd_init(4096, 24);
  if( rc!=SQLITE_OK ){
    return rc;
  }
#endif
115709
115710
115711
115712
115713
115714
115715



115716
115717
115718
115719
115720
115721
115722
116652
116653
116654
116655
116656
116657
116658
116659
116660
116661
116662
116663
116664
116665
116666
116667
116668







+
+
+







      sqlite3GlobalConfig.isPCacheInit = 1;
      rc = sqlite3OsInit();
    }
    if( rc==SQLITE_OK ){
      sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, 
          sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
      sqlite3GlobalConfig.isInit = 1;
#ifdef SQLITE_EXTRA_INIT
      bRunExtraInit = 1;
#endif
    }
    sqlite3GlobalConfig.inProgress = 0;
  }
  sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);

  /* Go back under the static mutex and clean up the recursive
  ** mutex to prevent a resource leak.
115749
115750
115751
115752
115753
115754
115755
115756

115757
115758
115759
115760
115761
115762
115763
116695
116696
116697
116698
116699
116700
116701

116702
116703
116704
116705
116706
116707
116708
116709







-
+







#endif
#endif

  /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
  ** compile-time option.
  */
#ifdef SQLITE_EXTRA_INIT
  if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
  if( bRunExtraInit ){
    int SQLITE_EXTRA_INIT(const char*);
    rc = SQLITE_EXTRA_INIT(0);
  }
#endif

  return rc;
}
115937
115938
115939
115940
115941
115942
115943
115944
115945


115946
115947
115948
115949
115950
115951
115952
115953
115954
115955
115956
115957
115958
115959
115960
115961
115962
115963
115964

115965
115966
115967
115968
115969
115970
115971
116883
116884
116885
116886
116887
116888
116889


116890
116891
116892
116893
116894
116895
116896
116897
116898
116899
116900
116901
116902
116903
116904
116905
116906
116907
116908
116909

116910
116911
116912
116913
116914
116915
116916
116917







-
-
+
+


















-
+







        ** back to NULL pointers too.  This will cause the malloc to go
        ** back to its default implementation when sqlite3_initialize() is
        ** run.
        */
        memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
      }else{
        /* The heap pointer is not NULL, then install one of the
        ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
        ** ENABLE_MEMSYS5 is defined, return an error.
        ** mem5.c/mem3.c methods.  The enclosing #if guarantees at
        ** least one of these methods is currently enabled.
        */
#ifdef SQLITE_ENABLE_MEMSYS3
        sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
        sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();
#endif
      }
      break;
    }
#endif

    case SQLITE_CONFIG_LOOKASIDE: {
      sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
      sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
      break;
    }
    
    /* Record a pointer to the logger funcction and its first argument.
    /* Record a pointer to the logger function and its first argument.
    ** The default is NULL.  Logging is disabled if the function pointer is
    ** NULL.
    */
    case SQLITE_CONFIG_LOG: {
      /* MSVC is picky about pulling func ptrs from va lists.
      ** http://support.microsoft.com/kb/47961
      ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
117673
117674
117675
117676
117677
117678
117679


117680
117681
117682
117683
117684
117685
117686
117687
117688
117689
117690
117691
117692
117693

117694
117695
117696
117697
117698
117699
117700
118619
118620
118621
118622
118623
118624
118625
118626
118627
118628
118629
118630
118631

118632
118633
118634
118635
118636
118637


118638
118639
118640
118641
118642
118643
118644
118645
118646







+
+




-






-
-

+







    ** method that there may be extra parameters following the file-name.  */
    flags |= SQLITE_OPEN_URI;

    for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
    zFile = sqlite3_malloc(nByte);
    if( !zFile ) return SQLITE_NOMEM;

    iIn = 5;
#ifndef SQLITE_ALLOW_URI_AUTHORITY
    /* Discard the scheme and authority segments of the URI. */
    if( zUri[5]=='/' && zUri[6]=='/' ){
      iIn = 7;
      while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;

      if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
        *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s", 
            iIn-7, &zUri[7]);
        rc = SQLITE_ERROR;
        goto parse_uri_out;
      }
    }else{
      iIn = 5;
    }
#endif

    /* Copy the filename and any query parameters into the zFile buffer. 
    ** Decode %HH escape codes along the way. 
    **
    ** Within this loop, variable eState may be set to 0, 1 or 2, depending
    ** on the parsing context. As follows:
    **
117950
117951
117952
117953
117954
117955
117956
117957

117958
117959
117960
117961
117962
117963
117964
118896
118897
118898
118899
118900
118901
118902

118903
118904
118905
118906
118907
118908
118909
118910







-
+








  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  db->autoCommit = 1;
  db->nextAutovac = -1;
  db->szMmap = sqlite3GlobalConfig.szMmap;
  db->nextPagesize = 0;
  db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger
  db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
                 | SQLITE_AutoIndex
#endif
#if SQLITE_DEFAULT_FILE_FORMAT<4
                 | SQLITE_LegacyFileFmt
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
130863
130864
130865
130866
130867
130868
130869
130870

130871
130872
130873
130874
130875
130876
130877
131809
131810
131811
131812
131813
131814
131815

131816
131817
131818
131819
131820
131821
131822
131823







-
+







    ** following block advances it to point one byte past the end of
    ** the same offset list. */
    while( 1 ){
  
      /* The following line of code (and the "p++" below the while() loop) is
      ** normally all that is required to move pointer p to the desired 
      ** position. The exception is if this node is being loaded from disk
      ** incrementally and pointer "p" now points to the first byte passed
      ** incrementally and pointer "p" now points to the first byte past
      ** the populated part of pReader->aNode[].
      */
      while( *p | c ) c = *p++ & 0x80;
      assert( *p==0 );
  
      if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
      rc = fts3SegReaderIncrRead(pReader);
132250
132251
132252
132253
132254
132255
132256
132257
132258


132259
132260
132261
132262
132263
132264
132265
133196
133197
133198
133199
133200
133201
133202


133203
133204
133205
133206
133207
133208
133209
133210
133211







-
-
+
+







      */
      for(i=0; i<nMerge; i++){
        fts3SegReaderFirstDocid(p, apSegment[i]);
      }
      fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
      while( apSegment[0]->pOffsetList ){
        int j;                    /* Number of segments that share a docid */
        char *pList;
        int nList;
        char *pList = 0;
        int nList = 0;
        int nByte;
        sqlite3_int64 iDocid = apSegment[0]->iDocid;
        fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
        j = 1;
        while( j<nMerge
            && apSegment[j]->pOffsetList
            && apSegment[j]->iDocid==iDocid
134537
134538
134539
134540
134541
134542
134543
134544
134545
134546
134547





134548
134549
134550
134551
134552
134553
134554
134555
135483
135484
135485
135486
135487
135488
135489




135490
135491
135492
135493
135494

135495
135496
135497
135498
135499
135500
135501







-
-
-
-
+
+
+
+
+
-







              fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
            }
          }
        }
        if( pTC ) pModule->xClose(pTC);
        if( rc==SQLITE_DONE ) rc = SQLITE_OK;
      }

      for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
        if( pDef->pList ){
          rc = fts3PendingListAppendVarint(&pDef->pList, 0);
    }

    for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
      if( pDef->pList ){
        rc = fts3PendingListAppendVarint(&pDef->pList, 0);
        }
      }
    }
  }

  return rc;
}

135324
135325
135326
135327
135328
135329
135330

135331
135332
135333
135334
135335
135336
135337
136270
136271
136272
136273
136274
136275
136276
136277
136278
136279
136280
136281
136282
136283
136284







+







    char *zNew = sqlite3_realloc(pStr->z, nAlloc);
    if( !zNew ){
      return SQLITE_NOMEM;
    }
    pStr->z = zNew;
    pStr->nAlloc = nAlloc;
  }
  assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) );

  /* Append the data to the string buffer. */
  memcpy(&pStr->z[pStr->n], zAppend, nAppend);
  pStr->n += nAppend;
  pStr->z[pStr->n] = '\0';

  return SQLITE_OK;
Changes to src/sqlite3.h.
103
104
105
106
107
108
109
110
111
112



113
114
115
116
117
118
119
103
104
105
106
107
108
109



110
111
112
113
114
115
116
117
118
119







-
-
-
+
+
+







** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.0"
#define SQLITE_VERSION_NUMBER 3008000
#define SQLITE_SOURCE_ID      "2013-08-06 07:45:08 924f7e4d7a8fa2fe9100836663f3733b6e1a9084"
#define SQLITE_VERSION        "3.8.1"
#define SQLITE_VERSION_NUMBER 3008001
#define SQLITE_SOURCE_ID      "2013-08-30 06:20:23 d9c018f8155ab48df8e0e02519bba50588fe49fc"

/*
** 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
7229
7230
7231
7232
7233
7234
7235
7236

7237
7238
7239
7240
7241
7242
7243
7229
7230
7231
7232
7233
7234
7235

7236
7237
7238
7239
7240
7241
7242
7243







-
+







#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif
#endif /* _SQLITE3_H_ */

/*
** 2010 August 30
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
Changes to src/style.c.
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81







-
+







** The form of the anchor tag is determined by the g.javascriptHyperlink
** variable.  The href="URL" form is used if g.javascriptHyperlink is false.
** If g.javascriptHyperlink is true then the
** id="ID" form is used and javascript is generated in the footer to cause
** href values to be inserted after the page has loaded.  If
** g.perm.History is false, then the <a id="ID"> form is still
** generated but the javascript is not generated so the links never
** activate. 
** activate.
**
** If the user lacks the Hyperlink (h) property and the "auto-hyperlink"
** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and
** g.javascriptHyperlink is set to 1.  The g.javascriptHyperlink defaults
** to 0 and only changes to one if the user lacks the Hyperlink (h) property
** and the "auto-hyperlink" setting is enabled.
**
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







-
+

















-
+







    return zHUrl;
  }
  if( nHref>=nHrefAlloc ){
    nHrefAlloc = nHrefAlloc*2 + 10;
    aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
  }
  aHref[nHref++] = zUrl;
  return mprintf("<a %s id='a%d'>", zExtra, nHref);
  return mprintf("<a %s id='a%d' href='%R/honeypot'>", zExtra, nHref);
}
char *href(const char *zFormat, ...){
  char *zUrl;
  va_list ap;
  va_start(ap, zFormat);
  zUrl = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.perm.Hyperlink && !g.javascriptHyperlink ){
    char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
    fossil_free(zUrl);
    return zHUrl;
  }
  if( nHref>=nHrefAlloc ){
    nHrefAlloc = nHrefAlloc*2 + 10;
    aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
  }
  aHref[nHref++] = zUrl;
  return mprintf("<a id='a%d'>", nHref);
  return mprintf("<a id='a%d' href='%R/honeypot'>", nHref);
}

/*
** Generate <form method="post" action=ARG>.  The ARG value is inserted
** by javascript.
*/
void form_begin(const char *zOtherArgs, const char *zAction, ...){
970
971
972
973
974
975
976

977
978
979
980
981
982
983
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984







+







  { "ul.filelist",
    "List of files in a timeline",
    @   margin-top: 3px;
    @   line-height: 100%;
  },
  { "table.sbsdiffcols",
    "side-by-side diff display (column-based)",
    @   width: 90%;
    @   border-spacing: 0;
    @   font-size: xx-small;
  },
  { "table.sbsdiffcols td",
    "sbs diff table cell",
    @   padding: 0;
    @   vertical-align: top;
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065







-
+







    @   text-align: right;
    @   padding: 0.2ex 2ex;
  },
  { ".statistics-report-graph-line",
    "for the /stats_report views",
    @   background-color: #446979;
  },
  { ".statistics-report-table-events th"
  { ".statistics-report-table-events th",
    "",
    @   padding: 0 1em 0 1em;
  },
  { ".statistics-report-table-events td",
    "",
    @   padding: 0.1em 1em 0.1em 1em;
  },
1082
1083
1084
1085
1086
1087
1088




1089
1090
1091
1092
1093
1094
1095
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100







+
+
+
+







  { "tr.row0",
    "even table row color",
    @ /* use default */
  },
  { "tr.row1",
    "odd table row color",
    @ /* Use default */
  },
  { "#canvas", "timeline graph node colors",
    @ color: black;
    @ background-color: white;
  },
  { 0,
    0,
    0
  }
};

1149
1150
1151
1152
1153
1154
1155









1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195

1196










1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223







+
+
+
+
+
+
+
+
+





+




















+















+

+
+
+
+
+
+
+
+
+
+
** WEBPAGE: test_env
*/
void page_test_env(void){
  char c;
  int i;
  int showAll;
  char zCap[30];
  static const char *azCgiVars[] = {
    "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
    "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
    "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION", "HTTP_HOST",
    "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
    "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", "REQUEST_METHOD",
    "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL",
  };

  login_check_credentials();
  if( !g.perm.Admin && !g.perm.Setup && !db_get_boolean("test_env_enable",0) ){
    login_needed();
    return;
  }
  for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
  style_header("Environment Test");
  showAll = atoi(PD("showall","0"));
  if( !showAll ){
    style_submenu_element("Show Cookies", "Show Cookies",
                          "%s/test_env?showall=1", g.zTop);
  }else{
    style_submenu_element("Hide Cookies", "Hide Cookies",
                          "%s/test_env", g.zTop);
  }
#if !defined(_WIN32)
  @ uid=%d(getuid()), gid=%d(getgid())<br />
#endif
  @ g.zBaseURL = %h(g.zBaseURL)<br />
  @ g.zTop = %h(g.zTop)<br />
  for(i=0, c='a'; c<='z'; c++){
    if( login_has_capability(&c, 1) ) zCap[i++] = c;
  }
  zCap[i] = 0;
  @ g.userUid = %d(g.userUid)<br />
  @ g.zLogin = %h(g.zLogin)<br />
  @ g.isHuman = %d(g.isHuman)<br />
  @ capabilities = %s(zCap)<br />
  @ <hr>
  P("HTTP_USER_AGENT");
  cgi_print_all(showAll);
  if( showAll && blob_size(&g.httpHeader)>0 ){
    @ <hr>
    @ <pre>
    @ %h(blob_str(&g.httpHeader))
    @ </pre>
  }
  if( g.perm.Setup ){
    const char *zRedir = P("redirect");
    if( zRedir ) cgi_redirect(zRedir);
  }
  style_footer();
  if( g.perm.Admin && P("err") ) fossil_fatal("%s", P("err"));
}

/*
** This page is a honeypot for spiders and bots.
**
** WEBPAGE: honeypot
*/
void honeypot_page(void){
  cgi_set_status(403, "Forbidden");
  @ <p>Access by spiders and robots is forbidden</p>
}
Changes to src/sync.c.
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82







-
+







    ** autosync, or something?
    */
    configSync = CONFIGSET_SHUN;
  }
#endif
  if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
  is_fossil_user() ?
    fossil_print("Autosync: (%s) %s\n", g.zFossilUser, g.urlCanonical) :
    fossil_print("Autosync: (%s) %s\n", get_fossil_user(), g.urlCanonical) :
    fossil_print("Autosync:  %s\n", g.urlCanonical);
  url_enable_proxy("via proxy: ");
  rc = client_sync(flags, configSync, 0);
  if( rc ) fossil_warning("Autosync failed");
  return rc;
}

112
113
114
115
116
117
118



119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136

137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155


156
157
158
159
160
161
162
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138

139
140
141
142

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167







+
+
+













-
+



-
+



-
+















+
+







  clone_ssh_find_options();
  db_find_and_open_repository(0, 0);
  db_open_config(0);
  if( g.argc==2 ){
    if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
    if( urlFlags & URL_REMEMBER ){
      db_unset("ssh-fossil-user", 0);
    }
  }
  if( urlFlags & URL_REMEMBER ){
    clone_ssh_db_set_options();
  }
  url_parse(zUrl, urlFlags);
  if( g.urlProtocol==0 ){
    if( urlOptional ) fossil_exit(0);
    usage("URL");
  }
  user_select();
  if( g.argc==2 ){
    if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
      is_fossil_user() ? 
        fossil_print("Sync with (%s) %s\n", g.zFossilUser, g.urlCanonical) :
        fossil_print("Sync with (%s) %s\n",get_fossil_user(),g.urlCanonical):
        fossil_print("Sync with %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PUSH ){
      is_fossil_user() ? 
        fossil_print("Push to (%s) %s\n", g.zFossilUser, g.urlCanonical) :
        fossil_print("Push to (%s) %s\n", get_fossil_user(), g.urlCanonical):
        fossil_print("Push to %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PULL ){
      is_fossil_user() ? 
        fossil_print("Pull from (%s) %s\n", g.zFossilUser, g.urlCanonical) :
        fossil_print("Pull from (%s) %s\n",get_fossil_user(),g.urlCanonical):
        fossil_print("Pull from %s\n", g.urlCanonical);
    }
  }
  url_enable_proxy("via proxy: ");
  *pConfigFlags |= configSync;
}

/*
** COMMAND: pull
**
** Usage: %fossil pull ?URL? ?options?
**
** Pull changes from a remote repository into the local repository.
** Use the "-R REPO" or "--repository REPO" command-line options
** to specify an alternative repository file.
**
** See clone usage for possible URL formats.
**
** If the URL is not specified, then the URL from the most recent
** clone, push, pull, remote-url, or sync command is used.
**
** The URL specified normally becomes the new "remote-url" used for
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
178
179
180
181
182
183
184


185
186
187
188
189
190
191
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198







+
+







** COMMAND: push
**
** Usage: %fossil push ?URL? ?options?
**
** Push changes in the local repository over into a remote repository.
** Use the "-R REPO" or "--repository REPO" command-line options
** to specify an alternative repository file.
**
** See clone usage for possible URL formats.
**
** If the URL is not specified, then the URL from the most recent
** clone, push, pull, remote-url, or sync command is used.
**
** The URL specified normally becomes the new "remote-url" used for
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
213
214
215
216
217
218
219
220

221
222
223
224
225


226
227
228
229
230
231
232
220
221
222
223
224
225
226

227
228




229
230
231
232
233
234
235
236
237







-
+

-
-
-
-
+
+







** Usage: %fossil sync ?URL? ?options?
**
** Synchronize the local repository with a remote repository.  This is
** the equivalent of running both "push" and "pull" at the same time.
** Use the "-R REPO" or "--repository REPO" command-line options
** to specify an alternative repository file.
**
** If a user-id and password are required, specify them as follows:
** See clone usage for possible URL formats.
**
**     http://userid:password@www.domain.com:1234/path
**
** If the URL is not specified, then the URL from the most recent successful
** clone, push, pull, remote-url, or sync command is used.
** If the URL is not specified, then the URL from the most recent
** successful clone, push, pull, remote-url, or sync command is used.
**
** The URL specified normally becomes the new "remote-url" used for
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
** saved.
**
** Use the --private option to sync private branches with the
254
255
256
257
258
259
260


261
262
263
264
265
266
267
268
269
270
271

272
273
274
275
276
277
278
279
280


281

282
283
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
293







+
+











+









+
+
-
+


** and "sync" commands.
**
** The remote-url is set automatically by a "clone" command or by any
** "sync", "push", or "pull" command that specifies an explicit URL.
** The default remote-url is used by auto-syncing and by "sync", "push",
** "pull" that omit the server URL.
**
** See clone usage for possible URL formats.
**
** See also: clone, push, pull, sync
*/
void remote_url_cmd(void){
  char *zUrl;
  db_find_and_open_repository(0, 0);
  if( g.argc!=2 && g.argc!=3 ){
    usage("remote-url ?URL|off?");
  }
  if( g.argc==3 ){
    db_unset("last-sync-url", 0);
    db_unset("last-sync-pw", 0);
    db_unset("ssh-fossil-user", 0);
    if( is_false(g.argv[2]) ) return;
    url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW);
  }
  zUrl = db_get("last-sync-url", 0);
  if( zUrl==0 ){
    fossil_print("off\n");
    return;
  }else{
    url_parse(zUrl, 0);
    is_fossil_user() ?
      fossil_print("(%s) %s\n", get_fossil_user(), g.urlCanonical) :
    fossil_print("%s\n", g.urlCanonical);
      fossil_print("%s\n", g.urlCanonical);
  }
}
Changes to src/th.c.
1773
1774
1775
1776
1777
1778
1779
1780

1781
1782
1783
1784
1785
1786
1787
1773
1774
1775
1776
1777
1778
1779

1780
1781
1782
1783
1784
1785
1786
1787







-
+







  {"-",  OP_SUBTRACT,       3, ARG_NUMBER},
  {"<",  OP_LT,             5, ARG_NUMBER},
  {">",  OP_GT,             5, ARG_NUMBER},
  {"&",  OP_BITWISE_AND,    8, ARG_INTEGER},
  {"^",  OP_BITWISE_XOR,    9, ARG_INTEGER},
  {"|",  OP_BITWISE_OR,    10, ARG_INTEGER},

  {0,0,0}
  {0,0,0,0}
};

/*
** The first part of the string (zInput,nInput) contains a number.
** Set *pnVarname to the number of bytes in the numeric string. 
*/
static int thNextNumber(
Changes to src/th_main.c.
428
429
430
431
432
433
434
435
436



437
438
439
440
441
442
443
428
429
430
431
432
433
434


435
436
437
438
439
440
441
442
443
444







-
-
+
+
+







    char **azElem;
    int i;

    if( Th_ToInt(interp, argv[3], argl[3], &height) ) return TH_ERROR;
    Th_SplitList(interp, argv[2], argl[2], &azElem, &aszElem, &nElem);
    blob_init(&name, (char*)argv[1], argl[1]);
    zValue = Th_Fetch(blob_str(&name), &nValue);
    z = mprintf("<select name=\"%z\" size=\"%d\">", 
                 htmlize(blob_buffer(&name), blob_size(&name)), height);
    zH = htmlize(blob_buffer(&name), blob_size(&name));
    z = mprintf("<select id=\"%s\" name=\"%s\" size=\"%d\">", zH, zH, height);
    free(zH);
    sendText(z, -1, 0);
    free(z);
    blob_reset(&name);
    for(i=0; i<nElem; i++){
      zH = htmlize((char*)azElem[i], aszElem[i]);
      if( zValue && aszElem[i]==nValue 
             && memcmp(zValue, azElem[i], nValue)==0 ){
Changes to src/timeline.c.
647
648
649
650
651
652
653





654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678







+
+
+
+
+













-







      }
      if( cSep=='[' ) cgi_printf("[");
      cgi_printf("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n");
    }
    cgi_printf("var nrail = %d\n", pGraph->mxRail+1);
    graph_free(pGraph);
    @ var canvasDiv = gebi("canvas");
    @ var canvasStyle = window.getComputedStyle && window.getComputedStyle(canvasDiv,null);
    @ var lineColor = (canvasStyle && canvasStyle.getPropertyValue('color')) || 'black';
    @ var bgColor = (canvasStyle && canvasStyle.getPropertyValue('background-color')) || 'white';
    @ if( bgColor=='transparent' ) bgColor = 'white';
    @ var boxColor = lineColor;
    @ function drawBox(color,x0,y0,x1,y1){
    @   var n = document.createElement("div");
    @   if( x0>x1 ){ var t=x0; x0=x1; x1=t; }
    @   if( y0>y1 ){ var t=y0; y0=y1; y1=t; }
    @   var w = x1-x0+1;
    @   var h = y1-y0+1;
    @   n.style.position = "absolute";
    @   n.style.overflow = "hidden";
    @   n.style.left = x0+"px";
    @   n.style.top = y0+"px";
    @   n.style.width = w+"px";
    @   n.style.height = h+"px";
    @   n.style.backgroundColor = color;
    @   n.style.cursor = "pointer";
    @   canvasDiv.appendChild(n);
    @   return n;
    @ }
    @ function absoluteY(id){
    @   var obj = gebi(id);
    @   if( !obj ) return;
    @   var top = 0;
687
688
689
690
691
692
693
694

695
696
697


698
699
700


701
702
703
704
705
706
707



708
709
710
711



712
713
714
715

716



717
718
719


720
721

722
723
724
725
726
727
728
691
692
693
694
695
696
697

698
699


700
701
702


703
704
705
706
707
708



709
710
711
712



713
714
715
716
717
718

719
720
721
722
723
724


725
726
727

728
729
730
731
732
733
734
735







-
+

-
-
+
+

-
-
+
+




-
-
-
+
+
+

-
-
-
+
+
+



-
+

+
+
+

-
-
+
+

-
+







    @     do{
    @       left += obj.offsetLeft;
    @     }while( obj = obj.offsetParent );
    @   }
    @   return left;
    @ }
    @ function drawUpArrow(x,y0,y1){
    @   drawBox("black",x,y0,x+1,y1);
    @   drawBox(lineColor,x,y0,x+1,y1);
    @   if( y0+10>=y1 ){
    @     drawBox("black",x-1,y0+1,x+2,y0+2);
    @     drawBox("black",x-2,y0+3,x+3,y0+4);
    @     drawBox(lineColor,x-1,y0+1,x+2,y0+2);
    @     drawBox(lineColor,x-2,y0+3,x+3,y0+4);
    @   }else{
    @     drawBox("black",x-1,y0+2,x+2,y0+4);
    @     drawBox("black",x-2,y0+5,x+3,y0+7);
    @     drawBox(lineColor,x-1,y0+2,x+2,y0+4);
    @     drawBox(lineColor,x-2,y0+5,x+3,y0+7);
    @   }
    @ }
    @ function drawThinArrow(y,xFrom,xTo){
    @   if( xFrom<xTo ){
    @     drawBox("black",xFrom,y,xTo,y);
    @     drawBox("black",xTo-3,y-1,xTo-2,y+1);
    @     drawBox("black",xTo-4,y-2,xTo-4,y+2);
    @     drawBox(lineColor,xFrom,y,xTo,y);
    @     drawBox(lineColor,xTo-3,y-1,xTo-2,y+1);
    @     drawBox(lineColor,xTo-4,y-2,xTo-4,y+2);
    @   }else{
    @     drawBox("black",xTo,y,xFrom,y);
    @     drawBox("black",xTo+2,y-1,xTo+3,y+1);
    @     drawBox("black",xTo+4,y-2,xTo+4,y+2);
    @     drawBox(lineColor,xTo,y,xFrom,y);
    @     drawBox(lineColor,xTo+2,y-1,xTo+3,y+1);
    @     drawBox(lineColor,xTo+4,y-2,xTo+4,y+2);
    @   }
    @ }
    @ function drawThinLine(x0,y0,x1,y1){
    @   drawBox("black",x0,y0,x1,y1);
    @   drawBox(lineColor,x0,y0,x1,y1);
    @ }
    @ function drawNodeBox(color,x0,y0,x1,y1){
    @   drawBox(color,x0,y0,x1,y1).style.cursor = "pointer";
    @ }
    @ function drawNode(p, left, btm){
    @   drawBox("black",p.x-5,p.y-5,p.x+6,p.y+6);
    @   drawBox(p.bg,p.x-4,p.y-4,p.x+5,p.y+5);
    @   drawNodeBox(boxColor,p.x-5,p.y-5,p.x+6,p.y+6);
    @   drawNodeBox(p.bg||bgColor,p.x-4,p.y-4,p.x+5,p.y+5);
    @   if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5);
    @   if( p.f&1 ) drawBox("black",p.x-1,p.y-1,p.x+2,p.y+2);
    @   if( p.f&1 ) drawNodeBox(boxColor,p.x-1,p.y-1,p.x+2,p.y+2);
    if( !omitDescenders ){
      @   if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5);
      @   if( p.d ) drawUpArrow(p.x, p.y+6, btm);
    }
    @   if( p.mo>0 ){
    @     var x1 = p.mo + left - 1;
    @     var y1 = p.y-3;
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
745
746
747
748
749
750
751

752
753
754
755
756
757
758
759







-
+







    @   }
    @   var n = p.au.length;
    @   for(var i=0; i<n; i+=2){
    @     var x1 = p.au[i]*railPitch + left;
    @     var x0 = x1>p.x ? p.x+7 : p.x-6;
    @     var u = rowinfo[p.au[i+1]-1];
    @     if(u.id<p.id){
    @       drawBox("black",x0,p.y,x1,p.y+1);
    @       drawBox(lineColor,x0,p.y,x1,p.y+1);
    @       drawUpArrow(x1, u.y+6, p.y);
    @     }else{
    @       drawBox("#600000",x0,p.y,x1,p.y+1);
    @       drawBox("#600000",x1-1,p.y,x1,u.y+1);
    @       drawBox("#600000",x1,u.y,u.x-6,u.y+1);
    @       drawBox("#600000",u.x-9,u.y-1,u.x-8,u.y+2);
    @       drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3);
1895
1896
1897
1898
1899
1900
1901
1902
1903




1904
1905
1906
1907
1908
1909
1910
1902
1903
1904
1905
1906
1907
1908


1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919







-
-
+
+
+
+







  char zPrevYear[5] = {0};           /* For keeping track of when
                                        we change years while looping */
  int nEventsPerYear = 0;            /* Total event count for the
                                        current year */
  char showYearTotal = 0;            /* Flag telling us when to show
                                        the per-year event totals */
  Blob header = empty_blob;          /* Page header text */
  int nMaxEvents  = 1;            /* for calculating length of graph bars. */

  int nMaxEvents  = 1;               /* for calculating length of graph
                                        bars. */
  int iterations = 0;                /* number of weeks/months we iterate
                                        over */
  blob_appendf(&header, "Timeline Events by year%s",
               (includeMonth ? "/month" : ""));
  blob_appendf(&sql,
               "SELECT substr(date(mtime),1,%d) AS timeframe, "
               "count(*) AS eventCount "
               "FROM event ",
               includeMonth ? 7 : 4);
1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956







+







     Fu can re-implement this with a single query.
  */
  while( SQLITE_ROW == db_step(&query) ){
    const int nCount = db_column_int(&query, 1);
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
    ++iterations;
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    const char * zTimeframe = db_column_text(&query, 0);
    const int nCount = db_column_int(&query, 1);
    const int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
2018
2019
2020
2021
2022
2023
2024


2025



2026
2027
2028
2029
2030
2031
2032
2028
2029
2030
2031
2032
2033
2034
2035
2036

2037
2038
2039
2040
2041
2042
2043
2044
2045
2046







+
+
-
+
+
+







    @ <tr class='row%d(rowClass)'>
    @ <td></td>
    @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
    @</tr>    
  }
  @ </tbody></table>
  if(nEventTotal){
    char const * zAvgLabel = includeMonth ? "month" : "year";
    int nAvg = iterations ? (nEventTotal/iterations) : 0;
    @ <br><div>Total events: %d(nEventTotal)</div>
    @ <br><div>Total events: %d(nEventTotal)
    @ <br>Average per active %s(zAvgLabel): %d(nAvg)
    @ </div>
  }
  if( !includeMonth ){
    output_table_sorting_javascript("statsTable","tnx");
  }
}

/*
2103
2104
2105
2106
2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131







+







  int nYear = zYear ? strlen(zYear) : 0;
  int i = 0;
  Stmt qYears = empty_Stmt;
  char * zDefaultYear = NULL;
  Blob sql = empty_blob;
  int nMaxEvents = 1;                /* max number of events for
                                        all rows. */
  int iterations = 0;                /* # of active time periods. */

  cgi_printf("Select year: ");
  blob_append(&sql,
              "SELECT DISTINCT substr(date(mtime),1,4) AS y "
              "FROM event WHERE 1 ", -1);
  if(zUserName&&*zUserName){
    blob_appendf(&sql,"AND user=%Q ", zUserName);
2169
2170
2171
2172
2173
2174
2175

2176
2177
2178
2179
2180
2181
2182
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198







+







    db_prepare(&stWeek, blob_str(&sql));
    blob_reset(&sql);
    while( SQLITE_ROW == db_step(&stWeek) ){
      const int nCount = db_column_int(&stWeek, 1);
      if(nCount>nMaxEvents){
        nMaxEvents = nCount;
      }
      ++iterations;
    }
    db_reset(&stWeek);
    while( SQLITE_ROW == db_step(&stWeek) ){
      const char * zWeek = db_column_text(&stWeek,0);
      const int nCount = db_column_int(&stWeek,1);
      const int nSize = nCount
        ? (int)(100 * nCount / nMaxEvents)
2199
2200
2201
2202
2203
2204
2205

2206
2207



2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222


2223
2224
2225
2226
2227
2228
2229
2230
2231
2232







+
-
-
+
+
+







      }
      cgi_printf("</td></tr>");
    }
    db_finalize(&stWeek);
    free(zDefaultYear);
    cgi_printf("</tbody></table>");
    if(total){
      int nAvg = iterations ? (total/iterations) : 0;
      cgi_printf("<br><div>Total events: %d</div>",
                 total);
      cgi_printf("<br><div>Total events: %d<br>"
                 "Average per active week: %d</div>",
                 total, nAvg);
    }
    output_table_sorting_javascript("statsTable","tnx");
  }
}

/*
** WEBPAGE: reports
Changes to src/tkt.c.
518
519
520
521
522
523
524
525

526
527
528
529
530
531
532
518
519
520
521
522
523
524

525
526
527
528
529
530
531
532







-
+







static void ticket_put(
  Blob *pTicket,           /* The text of the ticket change record */
  const char *zTktId,      /* The ticket to which this change is applied */
  int needMod              /* True if moderation is needed */
){
  int rid = content_put_ex(pTicket, 0, 0, 0, needMod);
  if( rid==0 ){
    fossil_panic("trouble committing ticket: %s", g.zErrMsg);
    fossil_fatal("trouble committing ticket: %s", g.zErrMsg);
  }
  if( needMod ){
    moderation_table_create();
    db_multi_exec(
      "INSERT INTO modreq(objid, tktid) VALUES(%d,'%s')",
      rid, zTktId
    );
674
675
676
677
678
679
680
681

682
683
684
685
686
687
688
674
675
676
677
678
679
680

681
682
683
684
685
686
687
688







-
+







  Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd,
                   (void*)&zNewUuid, 0);
  if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1);
  if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){
    cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid));
    return;
  }
  captcha_generate();
  captcha_generate(0);
  @ </form>
  if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
  style_footer();
}

/*
** WEBPAGE: tktedit
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756







-
+







  Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0);
  Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0);
  if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1);
  if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){
    cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName));
    return;
  }
  captcha_generate();
  captcha_generate(0);
  @ </form>
  if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
  style_footer();
}

/*
** Check the ticket table schema in zSchema to see if it appears to
Changes to src/unicode.c.
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50







-
+







  ** The most significant 22 bits in each 32-bit value contain the first 
  ** codepoint in the range. The least significant 10 bits are used to store
  ** the size of the range (always at least 1). In other words, the value 
  ** ((C<<22) + N) represents a range of N codepoints starting with codepoint 
  ** C. It is not possible to represent a range larger than 1023 codepoints 
  ** using this format.
  */
  const static unsigned int aEntry[] = {
  static const unsigned int aEntry[] = {
    0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
    0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
    0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
    0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
    0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
    0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
    0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
Changes to src/update.c.
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211







-
+







    tid = db_int(0, "SELECT rid FROM leaves, event"
                    " WHERE event.objid=leaves.rid"
                    " ORDER BY event.mtime DESC"); 
    if( tid==0 ) tid = vid;
  }

  if( tid==0 ){
    fossil_panic("Internal Error: unable to find a version to update to.");
    fossil_panic("unable to find a version to update to.");
  }

  db_begin_transaction();
  vfile_check_signature(vid, CKSIG_ENOTFILE);
  if( !dryRunFlag && !internalUpdate ) undo_begin();
  load_vfile_from_rid(tid);

222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236







-
+







    "  idt INTEGER,"              /* VFILE entry for target version */
    "  chnged BOOLEAN,"           /* True if current version has been edited */
    "  islinkv BOOLEAN,"          /* True if current file is a link */
    "  islinkt BOOLEAN,"          /* True if target file is a link */
    "  ridv INTEGER,"             /* Record ID for current version */
    "  ridt INTEGER,"             /* Record ID for target */
    "  isexe BOOLEAN,"            /* Does target have execute permission? */
    "  deleted BOOLEAN DEFAULT 0,"/* File marke by "rm" to become unmanaged */
    "  deleted BOOLEAN DEFAULT 0,"/* File marked by "rm" to become unmanaged */
    "  fnt TEXT %s"               /* Filename of same file on target version */
    ");",
    filename_collation(), filename_collation()
  );

  /* Add files found in the current version
  */
398
399
400
401
402
403
404
405

406
407
408
409
410

411
412
413

414
415
416
417
418
419
420
421
398
399
400
401
402
403
404

405
406
407
408
409

410
411
412

413

414
415
416
417
418
419
420







-
+




-
+


-
+
-







      }
      undo_save(zName);
      if( !dryRunFlag ) vfile_to_disk(0, idt, 0, 0);
    }else if( idt>0 && idv>0 && ridt!=ridv && (chnged==0 || deleted) ){
      /* The file is unedited.  Change it to the target version */
      undo_save(zName);
      if( deleted ){
        fossil_print("UPDATE %s - change to unmanged file\n", zName);
        fossil_print("UPDATE %s - change to unmanaged file\n", zName);
      }else{
        fossil_print("UPDATE %s\n", zName);
      }
      if( !dryRunFlag ) vfile_to_disk(0, idt, 0, 0);
    }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){
    }else if( idt>0 && idv>0 && !deleted && file_wd_size(zFullPath)<0 ){
      /* The file missing from the local check-out. Restore it to the
      ** version that appears in the target. */
      fossil_print("UPDATE %s%s\n", zName,
      fossil_print("UPDATE %s\n", zName);
                    deleted?" - change to unmanaged file":"");
      undo_save(zName);
      if( !dryRunFlag ) vfile_to_disk(0, idt, 0, 0);
    }else if( idt==0 && idv>0 ){
      if( ridv==0 ){
        /* Added in current checkout.  Continue to hold the file as
        ** as an addition */
        db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670







-
+







    if( errCode<=0 ){
      fossil_fatal("file %s does not exist in checkin: %s", file, revision);
    }
  }else if( errCode<=0 ){
    if( revision==0 ){
      revision = db_text("current", "SELECT uuid FROM blob WHERE rid=%d", rid);
    }
    fossil_panic("could not parse manifest for checkin: %s", revision);
    fossil_fatal("could not parse manifest for checkin: %s", revision);
  }
  return errCode;
}


/*
** COMMAND: revert
Changes to src/url.c.
75
76
77
78
79
80
81

82







83
84
85
86
87
88
89
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96







+
-
+
+
+
+
+
+
+







  int bPrompted = 0;
  int bSetUrl = 1;
 
  if( zUrl==0 ){
    zUrl = db_get("last-sync-url", 0);
    if( zUrl==0 ) return;
    g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
    if( g.zFossilUser==0 ){
    g.zFossilUser = db_get("ssh-fossil-user", 0);
      g.zFossilUser = db_get("ssh-fossil-user", 0);
    }else{
      if( g.urlPasswd ) {
        free(g.urlPasswd);
        g.urlPasswd = 0;
      }
    }
    bSetUrl = 0;
  }

  if( strncmp(zUrl, "http://", 7)==0
   || strncmp(zUrl, "https://", 8)==0
   || strncmp(zUrl, "ssh://", 6)==0
  ){
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
193
194
195
196
197
198
199



200
201
202
203
204
205
206







-
-
-







      free(zFile);
      fossil_fatal("unknown repository: %s", zUrl);
    }
  }else{
    fossil_fatal("unknown repository: %s", zUrl);
  }
  g.urlFlags = urlFlags;
  if( g.urlIsSsh && g.zFossilUser==0 ){
    g.zFossilUser = db_get("ssh-fossil-user", 0);
  }
  if( g.urlIsFile ){
    Blob cfile;
    dehttpize(zFile);  
    file_canonical_name(zFile, &cfile, 0);
    free(zFile);
    g.urlProtocol = "file";
    g.urlPath = "";
410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
414
415
416
417
418
419
420

421
422
423
424
425
426
427
428







-
+







}

/*
** Prompt the user for the password for g.urlUser.  Store the result
** in g.urlPasswd.
*/
void url_prompt_for_password(void){
  if( g.urlIsFile ) return;
  if( g.urlIsFile || ( g.urlIsSsh && ! url_ssh_use_http() ) ) return;
  if( isatty(fileno(stdin))
   && (g.urlFlags & URL_PROMPT_PW)!=0
   && (g.urlFlags & URL_PROMPTED)==0
  ){
    g.urlFlags |= URL_PROMPTED;
    g.urlPasswd = prompt_for_user_password(url_or_fossil_user());
    if( g.urlPasswd[0]
432
433
434
435
436
437
438







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

455

456
457
458
459
460
461
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466

467
468
469
470
471
472
473







+
+
+
+
+
+
+
















+
-
+






      }
    }
  }else{
    fossil_fatal("missing or incorrect password for user \"%s\"",
                 url_or_fossil_user() );
  }
}

/*
** Return true if http mode is in use for "ssh://" URL.
*/
int url_ssh_use_http(void){
  return get_fossil_user()!=0;
}

/*
** Remember the URL if requested.
*/
void url_remember(void){
  db_set("last-sync-url", g.urlCanonical, 0);
  if( g.urlFlags & URL_REMEMBER_PW ){
    db_set("last-sync-pw", obscure(g.urlPasswd), 0);
  }
  g.urlFlags |= URL_REMEMBER;
}

/* Preemptively prompt for a password if a username is given in the
** URL but no password.
*/
void url_get_password_if_needed(void){
  const char *zFossilUser = url_or_fossil_user();
  if( (g.urlUser && g.urlUser[0])
  if( ( zFossilUser && zFossilUser[0] )
   && (g.urlPasswd==0 || g.urlPasswd[0]==0)
   && isatty(fileno(stdin)) 
  ){
    url_prompt_for_password();
  }
}
Changes to src/user.c.
158
159
160
161
162
163
164
165










166
167
168
169
170
171
172


173
174
175
176
177
178
179
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189







-
+
+
+
+
+
+
+
+
+
+






-
+
+







  return zPw;
}

/*
** Return Fossil user if allocated and URL is SSH or URL user
*/
const char *url_or_fossil_user(void){
  return is_fossil_user() ? g.zFossilUser : g.urlUser;
  return is_fossil_user() ? get_fossil_user() : g.urlUser;
}

/*
** Return the Fossil user from global variable (set from command line)
** or ssh-fossil-user database setting.
*/
const char *get_fossil_user(void){
  return ( g.zFossilUser && g.zFossilUser[0] ) ? g.zFossilUser :
    db_get("ssh-fossil-user", 0);
}

/*
** Return true if URL is SSH and Fossil user is allocated
*/
int is_fossil_user(void) {
  return g.urlIsSsh && g.zFossilUser && g.zFossilUser[0];
  return g.urlIsSsh && ( g.zFossilUser && g.zFossilUser[0] ||
   db_get("ssh-fossil-user", 0)!=0 );
}

/*
** Prompt the user to enter a single line of text.
*/
void prompt_user(const char *zPrompt, Blob *pIn){
  char *z;
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340







-
+







      db_multi_exec(
        "UPDATE user SET cap=%Q, mtime=now() WHERE uid=%d",
        g.argv[4], uid
      );
    }
    fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
  }else{
    fossil_panic("user subcommand should be one of: "
    fossil_fatal("user subcommand should be one of: "
                 "capabilities default list new password");
  }
}

/*
** Attempt to set the user to zLogin
*/
Changes to src/util.c.
24
25
26
27
28
29
30



31
32
33
34
35
36
37
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40







+
+
+







** For the fossil_timer_xxx() family of functions...
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/time.h>
# include <sys/resource.h>
# include <unistd.h>
# include <fcntl.h>
# include <errno.h>
#endif


/*
** Exit.  Take care to close the database first.
*/
NORETURN void fossil_exit(int rc){
297
298
299
300
301
302
303












300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318







+
+
+
+
+
+
+
+
+
+
+
+
    return 0;
  }else{
    int const rc = fossilTimerList[timerId-1].id;
    assert(!rc || (rc == timerId));
    return fossilTimerList[timerId-1].id;
  }
}

/*
** Return TRUE if fd is a valid open file descriptor.  This only
** works on unix.  The function always returns true on Windows.
*/
int is_valid_fd(int fd){
#ifdef _WIN32
  return 1;
#else
  return fcntl(fd, F_GETFL)!=(-1) || errno!=EBADF;
#endif
}
Changes to src/verify.c.
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







  Blob uuid, hash, content;
  if( content_size(rid, 0)<0 ){
    return;  /* No way to verify phantoms */
  }
  blob_zero(&uuid);
  db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( blob_size(&uuid)!=UUID_SIZE ){
    fossil_panic("not a valid rid: %d", rid);
    fossil_fatal("not a valid rid: %d", rid);
  }
  if( content_get(rid, &content) ){
    sha1sum_blob(&content, &hash);
    blob_reset(&content);
    if( blob_compare(&uuid, &hash) ){
      fossil_fatal("hash of rid %d (%b) does not match its uuid (%b)",
                    rid, &hash, &uuid);
Changes to src/vfile.c.
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
742
743
744
745
746
747
748

749
750
751
752
753
754
755
756







-
+







  blob_zero(pOut);
  if( pManOut ){
    blob_zero(pManOut);
  }
  db_must_be_within_tree();
  pManifest = manifest_get(vid, CFTYPE_MANIFEST);
  if( pManifest==0 ){
    fossil_panic("manifest file (%d) is malformed", vid);
    fossil_fatal("manifest file (%d) is malformed", vid);
  }
  manifest_file_rewind(pManifest);
  while( (pFile = manifest_file_next(pManifest,0))!=0 ){
    if( pFile->zUuid==0 ) continue;
    fid = uuid_to_rid(pFile->zUuid, 0);
    md5sum_step_text(pFile->zName, -1);
    content_get(fid, &file);
Changes to src/wiki.c.
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108







-
+







  }
  if( !g.perm.RdWiki ){
    cgi_redirectf("%s/login?g=%s/home", g.zTop, g.zTop);
  }
  if( zPageName ){
    login_check_credentials();
    g.zExtra = zPageName;
    cgi_set_parameter_nocopy("name", g.zExtra);
    cgi_set_parameter_nocopy("name", g.zExtra, 1);
    g.isHome = 1;
    wiki_page();
    return;
  }
  style_header("Home");
  @ <p>This is a stub home-page for the project.
  @ To fill in this page, first go to
491
492
493
494
495
496
497
498

499
500
501
502
503
504
505
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505







-
+







  }
  login_insert_csrf_secret();
  @ <input type="submit" name="submit" value="Apply These Changes" />
  @ <input type="hidden" name="name" value="%h(zPageName)" />
  @ <input type="submit" name="cancel" value="Cancel"
  @  onclick='confirm("Abandon your changes?")' />
  @ </div>
  captcha_generate();
  captcha_generate(0);
  @ </form>
  manifest_destroy(pWiki);
  blob_reset(&wiki);
  style_footer();
}

/*
694
695
696
697
698
699
700
701

702
703
704
705
706
707
708
694
695
696
697
698
699
700

701
702
703
704
705
706
707
708







-
+







  @ Comment to append (formatted as %s(zFormat)):<br />
  @ <textarea name="r" class="wikiedit" cols="80" 
  @  rows="10" wrap="virtual">%h(PD("r",""))</textarea>
  @ <br />
  @ <input type="submit" name="preview" value="Preview Your Comment" />
  @ <input type="submit" name="submit" value="Append Your Changes" />
  @ <input type="submit" name="cancel" value="Cancel" />
  captcha_generate();
  captcha_generate(0);
  @ </form>
  style_footer();
}

/*
** Name of the wiki history page being generated
*/
Changes to src/winhttp.c.
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73







-
+







  }
  return 0;
}

/*
** Process a single incoming HTTP request.
*/
static void win32_process_one_http_request(void *pAppData){
static void win32_http_request(void *pAppData){
  HttpRequest *p = (HttpRequest*)pAppData;
  FILE *in = 0, *out = 0;
  int amt, got;
  int wanted = 0;
  char *z;
  char zRequestFName[MAX_PATH];
  char zReplyFName[MAX_PATH];
126
127
128
129
130
131
132






























































133
134
135
136
137
138
139
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  if( out ) fclose(out);
  if( in ) fclose(in);
  closesocket(p->s);
  file_delete(zRequestFName);
  file_delete(zReplyFName);
  free(p);
}

/*
** Process a single incoming SCGI request.
*/
static void win32_scgi_request(void *pAppData){
  HttpRequest *p = (HttpRequest*)pAppData;
  FILE *in = 0, *out = 0;
  int amt, got, nHdr, i;
  int wanted = 0;
  char zRequestFName[MAX_PATH];
  char zReplyFName[MAX_PATH];
  char zCmd[2000];          /* Command-line to process the request */
  char zHdr[2000];          /* The SCGI request header */

  sqlite3_snprintf(MAX_PATH, zRequestFName,
                   "%s_in%d.txt", zTempPrefix, p->id);
  sqlite3_snprintf(MAX_PATH, zReplyFName,
                   "%s_out%d.txt", zTempPrefix, p->id);
  out = fossil_fopen(zRequestFName, "wb");
  if( out==0 ) goto end_request;
  amt = 0;
  got = recv(p->s, zHdr, sizeof(zHdr), 0);
  if( got==SOCKET_ERROR ) goto end_request;
  amt = fwrite(zHdr, 1, got, out);
  nHdr = 0;
  for(i=0; zHdr[i]>='0' && zHdr[i]<='9'; i++){
    nHdr = 10*nHdr + zHdr[i] - '0';
  }
  wanted = nHdr + i + 1;
  if( strcmp(zHdr+i+1, "CONTENT_LENGTH")==0 ){
    wanted += atoi(zHdr+i+15);
  }
  while( wanted>amt ){
    got = recv(p->s, zHdr, wanted<sizeof(zHdr) ? wanted : sizeof(zHdr), 0);
    if( got<=0 ) break;
    fwrite(zHdr, 1, got, out);
    wanted += got;
  }
  fclose(out);
  out = 0;
  sqlite3_snprintf(sizeof(zCmd), zCmd,
    "\"%s\" http \"%s\" %s %s %s --scgi --nossl%s",
    g.nameOfExe, g.zRepositoryName, zRequestFName, zReplyFName,
    inet_ntoa(p->addr.sin_addr), p->zOptions
  );
  fossil_system(zCmd);
  in = fossil_fopen(zReplyFName, "rb");
  if( in ){
    while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
      send(p->s, zHdr, got, 0);
    }
  }

end_request:
  if( out ) fclose(out);
  if( in ) fclose(in);
  closesocket(p->s);
  file_delete(zRequestFName);
  file_delete(zReplyFName);
  free(p);
}


/*
** Start a listening socket and process incoming HTTP requests on
** that socket.
*/
void win32_http_server(
  int mnPort, int mxPort,   /* Range of allowed TCP port numbers */
204
205
206
207
208
209
210
211


212
213
214
215
216
217
218
266
267
268
269
270
271
272

273
274
275
276
277
278
279
280
281







-
+
+







    }
  }
  if( !GetTempPathW(MAX_PATH, zTmpPath) ){
    fossil_fatal("unable to get path to the temporary directory.");
  }
  zTempPrefix = mprintf("%sfossil_server_P%d_",
                        fossil_unicode_to_utf8(zTmpPath), iPort);
  fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
  fossil_print("Listening for %s requests on TCP port %d\n",
               (flags&HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
  if( zBrowser ){
    zBrowser = mprintf(zBrowser, iPort);
    fossil_print("Launch webbrowser: %s\n", zBrowser);
    fossil_system(zBrowser);
  }
  fossil_print("Type Ctrl-C to stop the HTTP server\n");
  /* Set the service status to running and pass the listener socket to the
242
243
244
245
246
247
248



249


250
251
252
253
254
255
256
305
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322
323







+
+
+
-
+
+







      break;
    }
    p = fossil_malloc( sizeof(*p) );
    p->id = ++idCnt;
    p->s = client;
    p->addr = client_addr;
    p->zOptions = blob_str(&options);
    if( flags & HTTP_SERVER_SCGI ){
      _beginthread(win32_scgi_request, 0, (void*)p);
    }else{
    _beginthread(win32_process_one_http_request, 0, (void*)p);
      _beginthread(win32_http_request, 0, (void*)p);
    }
  }
  closesocket(s);
  WSACleanup();
}

/*
** The HttpService structure is used to pass information to the service main
537
538
539
540
541
542
543




544
545
546
547
548
549
550
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621







+
+
+
+







**
**         --localauth
**
**              Enables automatic login if the --localauth option is present
**              and the "localauth" setting is off and the connection is from
**              localhost.
**
**         --scgi
**
**              Create an SCGI server instead of an HTTP server
**
**
**    fossil winsrv delete ?SERVICE-NAME?
**
**         Deletes a service. If the service is currently running, it will be
**         stopped first and then deleted.
**
**
590
591
592
593
594
595
596

597
598
599
600
601
602
603
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675







+







    const char *zUsername   = find_option("username", "U", 1);
    const char *zPassword   = find_option("password", "W", 1);
    const char *zPort       = find_option("port", "P", 1);
    const char *zNotFound   = find_option("notfound", 0, 1);
    const char *zFileGlob   = find_option("files", 0, 1);
    const char *zLocalAuth  = find_option("localauth", 0, 0);
    const char *zRepository = find_option("repository", "R", 1);
    int useSCGI             = find_option("scgi", 0, 0)!=0;
    Blob binPath;

    verify_all_options();
    if( g.argc==4 ){
      zSvcName = g.argv[3];
    }else if( g.argc>4 ){
      fossil_fatal("to much arguments for create method.");
630
631
632
633
634
635
636

637
638
639
640
641
642
643
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716







+







      db_open_repository(zRepository);
    }
    db_close(0);
    /* Build the fully-qualified path to the service binary file. */
    blob_zero(&binPath);
    blob_appendf(&binPath, "\"%s\" server", g.nameOfExe);
    if( zPort ) blob_appendf(&binPath, " --port %s", zPort);
    if( useSCGI ) blob_appendf(&binPath, " --scgi");
    if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound);
    if( zFileGlob ) blob_appendf(&binPath, " --files-urlenc %T", zFileGlob);
    if( zLocalAuth ) blob_append(&binPath, " --localauth", -1);
    blob_appendf(&binPath, " \"%s\"", g.zRepositoryName);
    /* Create the service. */
    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
Changes to src/xfer.c.
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240







+







    /* Unknown message
    */
    {
      cgi_reset_content();
      @ error bad\scommand:\s%F(blob_str(&xfer.line))
    }
    blobarray_reset(xfer.aToken, xfer.nToken);
    blob_reset(&xfer.line);
  }
  if( isPush ){
    if( run_push_script()==TH_ERROR ){
      cgi_reset_content();
      @ error push\sscript\sfailed:\s%F(Th_GetResult(g.interp, 0))
      nErr++;
    }
1253
1254
1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268







+







    create_cluster();
    send_unclustered(&xfer);
    if( xfer.syncPrivate ) send_private(&xfer);
  }
  if( recvConfig ){
    configure_finalize_receive();
  }
  db_multi_exec("DROP TABLE onremote");
  manifest_crosslink_end();

  /* Send the server timestamp last, in case prior processing happened
  ** to use up a significant fraction of our time window.
  */
  zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')");
  @ # timestamp %s(zNow)
Changes to www/adding_code.wiki.
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168







-
+







it has extra logic to insert \r characters at the right times on
windows systems.

Once you have the command running, you can then start adding code to
make it do useful things.  There are lots of utility functions in
Fossil for parsing command-line options and for
opening and accessing and manipulating the repository and
the working check-out.  Study at the implementations of existing commands
the working check-out.  Study implementations of existing commands
to get an idea of how things are done.  You can easily find the implementations
of existing commands by searching for "COMMAND: <i>name</i>" in the
files of the "src/" directory.

<h2>5.0 Creating A New Web Page</h2>

As with commands, new webpages can be added simply by inserting a function
Changes to www/embeddeddoc.wiki.
101
102
103
104
105
106
107
108
109


110
111
112
113
114
115
116
101
102
103
104
105
106
107


108
109
110
111
112
113
114
115
116







-
-
+
+







CGI mode.  The "index.html" CGI script looks like this:

<blockquote><pre>
#!/usr/bin/fossil
repository: /fossil/fossil.fossil
</pre></blockquote>

This is one of three ways to set up a 
<a href="quickstart.wiki#serversetup">fossil web server</a>.
This is one of four ways to set up a 
<a href="./server.wiki">fossil web server</a>.

The "<b>/trunk/</b>" part of the URL tells fossil to use
the documentation files from the most recent trunk check-in.
If you wanted to see an historical version of this document,
you could substitute the name of a check-in for "<b>/trunk/</b>".
For example, to see the version of this document associated with
check-in [9be1b00392], simply replace the "<b>/trunk/</b>" with
Changes to www/fileformat.wiki.
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







<li> [#ctrl | Control Artifacts] </li>
<li> [#wikichng | Wiki Pages] </li>
<li> [#tktchng | Ticket Changes] </li>
<li> [#attachment | Attachments] </li>
<li> [#event | Events] </li>
</ul>

These seven artifact types are described in the sequel.
These seven artifact types are described in the following sections.

In the current implementation (as of 2009-01-25) the artifacts that
make up a fossil repository are stored in in as delta- and zlib-compressed
blobs in an <a href="http://www.sqlite.org/">SQLite</a> database.  This
is an implementation detail and might change in a future release.  For
the purpose of this article "file format" means the format of the artifacts,
not how the artifacts are stored on disk.  It is the artifact format that
96
97
98
99
100
101
102
103

104
105
106

107
108

109
110
111
112
113
114
115
96
97
98
99
100
101
102

103
104
105

106
107

108
109
110
111
112
113
114
115







-
+


-
+

-
+








Allowed cards in the manifest are as follows:

<blockquote>
<b>B</b> <i>baseline-manifest</i><br>
<b>C</b> <i>checkin-comment</i><br>
<b>D</b> <i>time-and-date-stamp</i><br>
<b>F</b> <i>filename</i> <i>SHA1-hash</i> <i>permissions</i> <i>old-name</i><br>
<b>F</b> <i>filename</i> ?<i>SHA1-hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br>
<b>N</b> <i>mimetype</i><br>
<b>P</b> <i>SHA1-hash</i>+<br>
<b>Q</b> (<b>+</b>|<b>-</b>)<i>SHA1-hash ?SHA1-hash?</i><br>
<b>Q</b> (<b>+</b>|<b>-</b>)<i>SHA1-hash</i> ?<i>SHA1-hash</i>?<br>
<b>R</b> <i>repository-checksum</i><br>
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name  <b>*</b> ?value?</i><br>
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br>
<b>U</b> <i>user-login</i><br>
<b>Z</b> <i>manifest-checksum</i>
</blockquote>

A manifest may optionally have a single B-card.  The B-card specifies
another manifest that serves as the "baseline" for this manifest.  A
manifest that has a B-card is called a delta-manifest and a manifest
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223







-
+







character (ASCII 0x0A), and the complete text of the file.
Compute the MD5 checksum of the result.

A manifest might contain one or more T-cards used to set
[./branching.wiki#tags | tags or properties]
on the check-in.  The format of the T-card is the same as
described in <i>Control Artifacts</i> section below, except that the
second argument is the single characcter "<b>*</b>" instead of an
second argument is the single character "<b>*</b>" instead of an
artifact ID.  The <b>*</b> in place of the artifact ID indicates that
the tag or property applies to the current artifact.  It is not
possible to encode the current artifact ID as part of an artifact,
since the act of inserting the artifact ID would change the artifact ID,
hence a <b>*</b> is used to represent "self".  T-cards are typically
added to manifests in order to set the <b>branch</b> property and a
symbolic name when the check-in is intended to start a new branch.
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303







-
+







the card type and the arguments.  No surplus whitespace is allowed.
All cards must occur in strict lexicographical order.

Allowed cards in a control artifact are as follows:

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name  artifact-id  ?value?</i><br />
<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br />
<b>U</b> <i>user-name</i><br />
<b>Z</b> <i>checksum</i><br />
</blockquote>

A control artifact must have one D card, one U card, one Z card and
one or more T cards.  No other cards or other text is
allowed in a control artifact.  Control artifacts might be PGP
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487

488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
473
474
475
476
477
478
479

480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520







-
+






-
+
















-
+








-
+








<blockquote>
<b>C</b> <i>comment</i><br>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>E</b> <i>event-time</i> <i>event-id</i><br />
<b>N</b> <i>mimetype</i><br />
<b>P</b> <i>parent-artifact-id</i>+<br />
<b>T</b> <b>+</b><i>tag-name</i> <b>*</b> <i>value</i><br />
<b>T</b> <b>+</b><i>tag-name</i> <b>*</b> ?<i>value</i>?<br />
<b>U</b> <i>user-name</i><br />
<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
<b>Z</b> <i>checksum</i>
</blockquote>

The C card contains text that is displayed on the timeline for the
event.  Exactly one C card is required on an event artifact.
event.  The C card is optional, but there can only be one.

A single D card is required to give the date and time when the 
event artifact was created.  This is different from the time at which
the event occurs.

A single E card gives the time of the event (the point on the timeline
where the event is displayed) and a unique identifier for the event.
When there are multiple artifacts with the same event-id, the one with
the most recent D card is the only one used.  The event-id must be a
40-character lower-case hexadecimal string.

The optional N card specifies the mimetype of the text of the event
that is contained in the W card.  If the N card is omitted, then the
W card text mimetype is assumed to be text/x-fossil, which is the
Fossil wiki format.

The option P card specifies a prior event with the same event-id from
The optional P card specifies a prior event with the same event-id from
which the current event is an edit.  The P card is a hint to the system
that it might be space efficient to store one event as a delta of the
other.

An event might contain one or more T-cards used to set
[./branching.wiki#tags | tags or properties]
on the event.  The format of the T-card is the same as
described in [#ctrl | Control Artifacts] section above, except that the
second argument is the single characcter "<b>*</b>" instead of an
second argument is the single character "<b>*</b>" instead of an
artifact ID and the name is always prefaced by "<b>+</b>".
The <b>*</b> in place of the artifact ID indicates that
the tag or property applies to the current artifact.  It is not
possible to encode the current artifact ID as part of an artifact,
since the act of inserting the artifact ID would change the artifact ID,
hence a <b>*</b> is used to represent "self".  The "<b>+</b>" on the
name means that tags can only be add and they can only be non-propagating
529
530
531
532
533
534
535
536
537






538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

555
556
557
558
559
560

561
562
563
564
565

566
567
568
569
570


571

572
573
574
575

576
577
578
579
580
581


582
583
584
585

586
587
588
589
590
591





592
593
594
595
596
597
598
599
600
601

602
603
604
605


606
607
608
609
610
611
612
613
614

615
616
617
618
619

620
621
622
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654
655

656
657
658

659
660
661


662
663
664
665

666
667
668

669
670
671

672
673
674
675


676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
693
694


695
696

697
698
699
700

701
702
703
704

705
706
707
708
709
710





711
712
713
714
715
716
717

718
719
720

721
722
723
724
725
726
727
728
729
730







731
732














































529
530
531
532
533
534
535


536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563

564
565
566
567
568

569
570
571
572
573
574
575
576

577

578
579

580
581
582
583
584


585
586
587
588
589

590
591





592
593
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608


609
610
611
612
613
614
615
616
617
618

619
620
621
622
623

624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
658
659

660
661
662

663
664


665
666
667
668
669

670
671
672

673
674
675

676
677
678


679
680
681
682
683
684
685
686
687
688
689

690
691
692
693
694
695
696
697


698
699
700

701
702
703
704

705
706
707
708

709
710





711
712
713
714
715
716
717
718
719
720
721

722
723
724

725
726
727
728







729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783







-
-
+
+
+
+
+
+
















-
+





-
+




-
+





+
+
-
+
-


-
+




-
-
+
+



-
+

-
-
-
-
-
+
+
+
+
+









-
+


-
-
+
+








-
+




-
+









-
+








-
+







-
+








-
+


-
+

-
-
+
+



-
+


-
+


-
+


-
-
+
+









-
+







-
-
+
+

-
+



-
+



-
+

-
-
-
-
-
+
+
+
+
+






-
+


-
+



-
-
-
-
-
-
-
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

The Z card is the required checksum over the rest of the artifact.


<a name="summary"></a>
<h2>8.0 Card Summary</h2>

The following table summaries the various kinds of cards that
appear on Fossil artifacts:
The following table summarizes the various kinds of cards that appear
on Fossil artifacts. A blank entry means that combination of card and
artifact is not legal. A number or range of numbers indicates the number
of times a card may (or must) appear in the corresponding artifact type.
e.g. a value of 1 indicates a required unique card and 1+ indicates that one
or more such cards are required.

<table border=1 width="100%">
<tr>
<th rowspan=2 valign=bottom>Card Format</th>
<th colspan=7>Used By</th>
</tr>
<tr>
<th>Manifest</th>
<th>Cluster</th>
<th>Control</th>
<th>Wiki</th>
<th>Ticket</th>
<th>Attachment</th>
<th>Event</th>
</tr>
<tr>
<td><b>A</b> <i>filename target source</i></td>
<td><b>A</b> <i>filename</i> <i>target</i> ?<i>source</i>?</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td>&nbsp;</td>
</tr>
<tr>
<td><b>B</b> <i>baseline</i></td>
<td align=center><b>X</b></td>
<td align=center><b>0-1*</b></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<td>&nbsp;</td>
<tr><td>&nbsp;</td><td colspan='7'>* = Required for delta manifests</td></tr>
</tr>
<tr>
<td><b>C</b> <i>comment-text</i></td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>0-1</b></td>
<td align=center><b>0-1</b></td>
</tr>
<tr>
<td><b>D</b> <i>date-time-stamp</i></td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
</tr>
<tr>
<td><b>E</b> <i>event-time event-id</i></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
</tr>
<tr>
<td><b>F</b> <i>filename uuid permissions oldname</i></td>
<td align=center><b>X</b></td>
<td><b>F</b> <i>filename</i> ?<i>uuid</i>? ?<i>permissions</i>? ?<i>oldname</i>?</td>
<td align=center><b>0+</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
</tr>
<tr>
<td><b>J</b> <i>name value</i></td>
<td><b>J</b> <i>name</i> ?<i>value</i>?</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1+</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
</tr>
<tr>
<td><b>K</b> <i>ticket-uuid</i></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
</tr>
<tr>
<td><b>L</b> <i>wiki-title</i></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
</tr>
<tr>
<td><b>M</b> <i>uuid</i></td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1+</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
</tr>
<tr>
<td><b>N</b> <i>mimetype</i></td>
<td align=center><b>X</b></td>
<td align=center><b>0-1</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>0-1</b></td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>0-1</b></td>
<td align=center><b>0-1</b></td>
</tr>
<tr>
<td><b>P</b> <i>uuid ...</i></td>
<td align=center><b>X</b></td>
<td align=center><b>0-1</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>0-1</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>0-1</b></td>
</tr>
<tr>
<td><b>Q</b> (<b>+</b>|<b>-</b>)<i>uuid uuid</i></td>
<td align=center><b>X</b></td>
<td><b>Q</b> (<b>+</b>|<b>-</b>)<i>uuid</i> ?<i>uuid</i>?</td>
<td align=center><b>0+</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
</tr>
<tr>
<td><b>R</b> <i>md5sum</i></td>
<td align=center><b>X</b></td>
<td align=center><b>0-1</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<tr>
<td><b>T</b> (<b>+</b>|<b>*</b>|<b>-</b>)<i>tagname uuid value</i></td>
<td align=center><b>X</b></td>
<td><b>T</b> (<b>+</b>|<b>*</b>|<b>-</b>)<i>tagname</i> <i>uuid</i> ?<i>value</i>?</td>
<td align=center><b>0+</b></td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1+</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>0+</b></td>
</tr>
<tr>
<td><b>U</b> <i>username</i></td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>0-1</b></td>
<td align=center><b>0-1</b></td>
</tr>
<tr>
<td><b>W</b> <i>size</i></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center>&nbsp;</td>
<td align=center>&nbsp;</td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
</tr>
<tr>
<td><b>Z</b> <i>md5sum</i></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>X</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
<td align=center><b>1</b></td>
</tr>
</table>


<a name="addenda"></a>
<h2>9.0 Addenda</h2>

This section contains additional information which may be useful when
implementing algorithms described above.

<h3>R Card Hash Calculation</h3>

Given a manifest file named <tt>MF</tt>, the following Bash shell code
demonstrates how to compute the value of the R card in that manifest.
This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are
shell input and other lines are output. This demonstration assumes that the
file versions represented by the input manifest are checked out
under the current directory.

<nowiki><pre>
# head MF
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

C Make\sthe\s"clearsign"\sPGP\ssigning\sdefault\sto\soff.
D 2010-02-23T15:33:14
F BUILD.txt 4f7988767e4e48b29f7eddd0e2cdea4555b9161c
F COPYRIGHT-GPL2.txt 06877624ea5c77efe3b7e39b0f909eda6e25a4ec
...

# grep '^R ' MF
R c0788982781981c96a0d81465fec7192

# for i in $(awk '/^F /{print $2}' MF); do \
  echo $i $(stat -c '%s' $i); \
  cat $i; \
done | md5sum
c0788982781981c96a0d81465fec7192  -
</pre></nowiki>

Minor caveats: the above demonstration will work only when none of the
filenames in the manifest are "fossilized" (encoded) because they contain
spaces. In that case the shell-generated hash would differ because the
<tt>stat</tt> calls will fail to find such files (which are output in encoded
form here). That approach also won't work for delta manifests. Calculating
the R-card for delta manifests requires traversing both the delta and its baseline in
lexical order of the files, prefering the delta's copy if both contain
a given file.
Added www/hacker-howto.wiki.













1
2
3
4
5
6
7
8
9
10
11
12
13
+
+
+
+
+
+
+
+
+
+
+
+
+
<title>Fossil Hackers How-To</title>

The following links are of interest to programmers who want to modify
or enhance Fossil.  Ordinary users can safely ignore this information.

  *  [./build.wiki | How To Compile And Install Fossil]
  *  [./makefile.wiki | The Fossil Build Process]
  *  [./tech_overview.wiki | A Technical Overview of Fossil]
  *  [./adding_code.wiki | Adding Features To Fossil]
  *  [./contribute.wiki|Contributing Code Or Enhancements To The Fossil Project]
  *  [./style.wiki | Coding Style Guidelines]
  *  [./checkin.wiki | Pre-checkin Checklist]
  *  [../test/release-checklist.wiki | Release Checklist]
Changes to www/index.wiki.
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







-
+







<ul>
<li> [http://www.fossil-scm.org/download.html | Download]
<li> [./quickstart.wiki | Quick Start]
<li> [./build.wiki | Install]
<li> [../COPYRIGHT-BSD2.txt | License]
<li> [/timeline | Recent changes]
<li> [./faq.wiki | FAQ]
<li> [./contribute.wiki | Contributing]
<li> [./hacker-howto.wiki | Hacker How-To]
<li> [./changes.wiki | Change Log]
<li> [./hints.wiki | Tip &amp; Hints]
<li> [./permutedindex.wiki#pindex | Documentation Index]
<li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
<li> Mailing list
     <ul>
     <li> [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | sign-up]
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
96

97
98
99


100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95

96
97


98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115







-
+









-
+

-
-
+
+








-
+







      Fossil is a single stand-alone executable that contains everything
      needed to do configuration management.
      Installation is trivial: simply download a 
      <a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
      for Linux, Mac, or Windows and put it on your $PATH.
      [./build.wiki | Easy-to-compile source code] is available for
      users on other platforms.  Fossil sources are also mostly self-contained,
      requiring only the "zlib" library and the standard C library to build.
      requiring only the standard C library to build.

  5.  <b>Simple Networking</b> -
      Fossil uses plain old HTTP (with
      [./quickstart.wiki#proxy | proxy support])
      for all network communications, meaning that it works fine from behind
      restrictive firewalls.  The protocol is
      [./stats.wiki | bandwidth efficient] to the point that Fossil can be
      used comfortably over a dial-up internet connection.

  6.  <b>CGI Enabled</b> -
  6.  <b>CGI/SCGI Enabled</b> -
      No server is required to use fossil.  But a
      server does make collaboration easier.  Fossil supports three different
      yet simple [./quickstart.wiki#serversetup | server configurations].
      server does make collaboration easier.  Fossil supports four different
      yet simple [./server.wiki | server configurations].
      The most popular is a 2-line CGI script.  This is the approach
      used by the [./selfhost.wiki | self-hosting fossil repositories].

  7.  <b>Robust &amp; Reliable</b> -
      Fossil stores content using an [./fileformat.wiki | enduring file format]
      in an SQLite database so that transactions are
      atomic even if interrupted by a power loss or system crash.  Furthermore,
      automatic [./selfcheck.wiki | self-checks] verify that all aspects of
      the repository are consistent prior to each commit.  In over three years
      the repository are consistent prior to each commit.  In over six years
      of operation, no work has ever been lost after having been committed to
      a Fossil repository.

<hr>
<h3>Links For Fossil Users:</h3>

  *  [./reviews.wiki | Testimonials] from satisfied fossil users and
Changes to www/mkindex.tcl.
26
27
28
29
30
31
32

33
34
35
36
37
38
39
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40







+







  event.wiki {Events}
  faq.wiki {Frequently Asked Questions}
  fileformat.wiki {Fossil File Format}
  fiveminutes.wiki {Update and Running in 5 Minutes as a Single User}
  foss-cklist.wiki {Checklist For Successful Open-Source Projects}
  fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
  fossil-v-git.wiki {Fossil Versus Git}
  hacker-howto.wiki {Hacker How-To}
  hints.wiki {Fossil Tips And Usage Hints}
  index.wiki {Home Page}
  inout.wiki {Import And Export To And From Git}
  makefile.wiki {The Fossil Build Process}
  newrepo.wiki {How To Create A New Fossil Repository}
  password.wiki {Password Management And Authentication}
  pop.wiki {Principles Of Operations}
Changes to www/permutedindex.wiki.
86
87
88
89
90
91
92

93
94
95
96
97
98

99
100
101
102
103
104
105
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107







+






+







<li><a href="inout.wiki">From Git &mdash; Import And Export To And</a></li>
<li><a href="quotes.wiki">General &mdash; Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li>
<li><a href="fossil-v-git.wiki">Git &mdash; Fossil Versus</a></li>
<li><a href="inout.wiki">Git &mdash; Import And Export To And From</a></li>
<li><a href="quotes.wiki">Git, and DVCSes in General &mdash; Quotes: What People Are Saying About Fossil,</a></li>
<li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
<li><a href="style.wiki">Guidelines &mdash; Source Code Style</a></li>
<li><a href="hacker-howto.wiki">Hacker How-To</a></li>
<li><a href="adding_code.wiki">Hacking Fossil</a></li>
<li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
<li><a href="index.wiki">Home Page</a></li>
<li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
<li><a href="server.wiki">How To Configure A Fossil Server</a></li>
<li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li>
<li><a href="hacker-howto.wiki">How-To &mdash; Hacker</a></li>
<li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>
<li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; A Technical Overview Of The Design And</a></li>
<li><a href="inout.wiki">Import And Export To And From Git</a></li>
<li><a href="build.wiki">Installing Fossil &mdash; Compiling and</a></li>
<li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li>
<li><a href="selfcheck.wiki">Integrity Self Checks &mdash; Fossil Repository</a></li>
<li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
Changes to www/quickstart.wiki.
283
284
285
286
287
288
289
290
291
292

293

294
295
296


297
298
299
300
301
302
303



304
305
306
307
308
309
310

311
312
313
314
315
316
317
318

319
320
321
322

323
324
325
326
327

328
329
330
331
332
333


334
335
336

337
338
339
340

341
342

343
344
345
346
347
348
349
350
351
352
353
354
355
283
284
285
286
287
288
289

290
291
292

293
294
295

296
297
298
299





300
301
302
303
304
305
306
307
308

309



310




311




312





313






314
315



316
317



318


319






320
321
322
323
324
325
326







-


+
-
+


-
+
+


-
-
-
-
-
+
+
+






-
+
-
-
-

-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
+

-
-
-
+
-
-
+
-
-
-
-
-
-







    <p>This will back out the changes that the merge or update made to the
    working checkout.  There is also a [/help/redo|redo] command if you undo by
    mistake.  Undo and redo only work for changes that have
    not yet been checked in using commit and there is only a single
    level of undo/redo.</p>


<a name="serversetup"></a>
<h2>Setting Up A Server</h2>

    <p>Fossil can act as a stand-alone web server using one of these
    <p>The easiest way to set up a server is:</p>
    commands:</p>

    <blockquote>
    <b>[/help/server | fossil server]</b> <i>repository-filename</i>
    <b>[/help/server | fossil server]</b> <i>repository-filename</i><br>
    <b>[/help/ui | fossil ui]</b> <i>repository-filename</i>
    </blockquote>

    <p>Or</b>

    <blockquote>
    <b>[/help/ui | fossil ui]</b> <i>repository-filename</i>
    </blockquote>
    <p>The <i>repository-filename</i> can be omitted when these commands
    are run from within an open check-out, which a particularly useful
    shortcut for the <b>fossil ui</b> command.

    <p>The <b>ui</b> command is intended for accessing the web interface
    from a local desktop.  The <b>ui</b> command binds to the loopback IP
    address only (and thus makes the web interface visible only on the
    local machine) and it automatically start your web browser pointing at the
    server.  For cross-machine collaboration, use the <b>server</b> command,
    which binds on all IP addresses and does not try to start a web browser.
    which binds on all IP addresses and does not try to start a web browser.</p>
    You can omit the <i>repository-filename</i> if you are within
    a checked-out local tree.  The <b>server</b> uses port 8080 by default
    but you can specify a different port using the <b>-port</b> option.</p>

    <p>Command-line servers like this are useful when two people want
    to share a repository on temporary or ad-hoc basis.  For a more
    permanent installation, you should use either the CGI server or the
    inetd server.
    <p>Servers are also easily configured as:
    <a name="cgiserver"></a>
    To use the CGI server, create a CGI script that
    looks something like this:</p>

    <ul>
    <blockquote><b>
    #!/usr/local/bin/fossil<br>
    repository: /home/proj1/repos1.fossil
    </b></blockquote>

    <li>[./server.wiki#inetd|inetd/xinetd]
    <p>Adjust the paths in this CGI script to match your installation
    and make sure both repository file and the directory that contains it
    are readable and writable by the user that CGI scripts run as.
    Then point clients at the CGI script.  That's all there is to it!</p>

    <a name="inetdserver"></a>
    <li>[./server.wiki#cgi|CGI]
    <li>[./server.wiki#scgi|SCGI]
    <p>You can also run fossil from inetd or xinetd.  For an inetd
    installation, make an entry in /etc/inetd.conf that looks something
    like this:</p>
    </ul>

    <blockquote><b>
    80 stream tcp nowait.1000 root /usr/bin/fossil \<br>
        /usr/bin/fossil http /home/proj1/repos1.fossil
    <p>The the [./selfhost.wiki | self-hosting fossil repositories] use
    </b></blockquote>

    CGI.  
    <p>Adjust the paths to suit your installation, of course.  Notice that
    fossil runs as root.  This is not required - you can run it as an
    unprivileged user.  But it is more secure to run fossil as root.
    When you do run fossil as root, it automatically puts itself in a
    chroot jail in the same directory as the repository, then drops
    root privileges prior to reading any information from the socket.</p>

<a name="proxy"></a>
<h2>HTTP Proxies</h2>

    <p>If you are behind a restrictive firewall that requires you to use
    an HTTP proxy to reach the internet, then you can configure the proxy
    in three different ways.  You can tell fossil about your proxy using
Added www/scgi.wiki.


























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<title>Fossil SCGI</title>

To run Fossil using SCGI, start the [/help/server|fossil server] command
with the --scgi command-line option.  You will probably also want to
specific an alternative TCP/IP port using --port.  For example:

<blockquote><pre>
fossil server $REPOSITORY --port 9000 --scgi
</pre></blockquote>

Then configure your SCGI-aware web-server to send SCGI requests to port
9000 on the machine where Fossil is running.  A typical configuration for
this in Nginx is:

<blockquote><pre>
location ~ ^/demo_project/ {
    include scgi_params;
    scgi_pass localhost:9000;
    scgi_param SCRIPT_NAME "/demo_project";
}
</pre></blockquote>

Note that Nginx does not normally send either the PATH_INFO or SCRIPT_NAME
variables via SCGI, but Fossil needs one or the other.  So the configuration
above needs to add SCRIPT_NAME.  If you do not do this, Fossil return an
error.
Changes to www/selfhost.wiki.
19
20
21
22
23
24
25
26
27


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43

44
45
46
47
48
49
50
19
20
21
22
23
24
25


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51







-
-
+
+















+
-
+







on any of the three servers and those changes automatically propagate to the
other two servers.

Server (1) runs as a CGI script on a
<a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX
- on the same virtual machine that 
hosts <a href="http://www.sqlite.org/">SQLite</a> and over a
dozen other smaller projects.  This demonstrates that Fossil does not
require much server power.
dozen other smaller projects.  This demonstrates that Fossil can run on
a low-power host processor.
Multiple fossil-based projects can easily be hosted on the same machine,
even if that machine is itself one of several dozen virtual machines on
single physical box.  The CGI script that runs the canonical Fossil
self-hosting repository is as follows:

<blockquote><pre>
#!/usr/bin/fossil
repository: /fossil/fossil.fossil
</pre></blockquote>

Server (3) runs as a CGI script on a shared hosting account at
<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.  
This server demonstrates the ability of
Fossil to run on an economical shared-host web account with no
privileges beyond port 80 HTTP access and CGI.  It is not necessary
to have a dedicated computer with administrator to run Fossil.
to have a dedicated server to run Fossil.  As far as we are aware, 
As far as we are aware, 
Fossil is the only full-featured configuration management system 
that can run in
such a restricted environment.  The CGI script that runs on the
Hurricane Electric server is the same as the CGI script shown above,
except that the pathnames are modified to suit the environment:

<blockquote><pre>
Changes to www/server.wiki.
1
2
3
4




















5
6

7
8
9

10
11
12


13
14
15


16
17
18
19
20
21










22
23
24
25
26
27
28
29














30
31


32
33
34












35




36
37











38
39

40
41
42
43




44
45
46
47
48
49




50
51
52
53







54
55







56


57
58
59







60

61
62
63
64
65





66
67

68



69
70
71





72















73
74


75

76
77
78
79







80
81
82



83
84
85










86
87
88



89
90
91
92
93

94





95
96
97



98
99
100


101
102
103
104
105
106
107
108
109


110
111


112
113
114
115
116






117
118
119









120
121
122
123
124
1



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23



24
25


26
27
28

29
30
31






32
33
34
35
36
37
38
39
40
41
42
43
44





45
46
47
48
49
50
51
52
53
54
55
56
57
58


59
60



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77


78
79
80
81
82
83
84
85
86
87
88


89




90
91
92
93



94
95

96
97
98
99
100



101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117
118



119
120
121
122
123
124
125
126
127





128
129
130
131
132
133
134
135

136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167



168
169
170
171
172
173
174



175
176
177



178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205

206
207
208
209
210

211
212
213
214
215
216
217
218
219
220

221
222
223

224
225
226
227
228
229

230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249



-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
+

-
-
+
+

-

+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
+
+
-
-
-


-
+
+
+
+

-
-
-
+
+
+
+
+
+
+

-
+
+
+
+
+
+
+

+
+
-
-
-
+
+
+
+
+
+
+

+
-
-
-
-
-
+
+
+
+
+


+
-
+
+
+


-
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
-
+

-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+


-
+
+
+





+
-
+
+
+
+
+


-
+
+
+


-
+
+








-
+
+

-
+
+




-
+
+
+
+
+
+


-
+
+
+
+
+
+
+
+
+



-
-
<title>How To Configure A Fossil Server</title>
<nowiki>
<p>This guide is intended to help guide you in setting up a Fossil server.</p>

<h2>Introduction</h2><blockquote>
<p>A server is not necessary to use Fossil, but a server does help in collaborating with
peers.  A Fossil server also works well as a complete website for a project.
For example, the complete <b>http://www.fossil-scm.org/</b> website, including the
page you are now reading (but excepting the download page),
is just a Fossil server displaying the content of the 
self-hosting repository for Fossil.</p>
<p>This article is a guide for setting up your own Fossil server.</p></blockquote>
<h2>Overview</h2><blockquote>
There are basically four ways to set up a Fossil server:
<ol>
<li>A stand-alone server
<li>Using inetd or xinetd or stunnel
<li>CGI
<li>SCGI (a.k.a. SimpleCGI)
</ol>
Each of these can serve either a single repository, or a directory hierarchy 
containing many repositories with names ending in ".fossil".
</blockquote>
<a name="standalone"></a>
<h2>Standalone server</h2><blockquote>
The easiest way to set up a Fossil server is to use the <tt>server</tt> or
The easiest way to set up a Fossil server is to use either the
<tt>ui</tt> command.  Assuming the repository you are interested in serving is
in the file "<tt>repo.fossil</tt>", you can use either of these commands to
start Fossil as a server:
[/help/server|server] or the [/help/ui|ui] commands:
<ul>
<li><tt>fossil server repo.fossil</tt>
<li><tt>fossil ui repo.fossil</tt>
<li><b>fossil server</b> <i>REPOSITORY</i>
<li><b>fossil ui</b> <i>REPOSITORY</i>
</ul>

<p>
The <i>REPOSITORY</i> argument is either the name of the repository file, or
a directory containing many repositories.
Both of these commands start a Fossil server on port 8080 on the local machine,
which can be accessed with the URL: <tt>http://localhost:8080/</tt> using any
handy web browser.  The difference between the two commands is that "ui", in
addition to starting the Fossil server, also starts a web browser and points it
to the URL mentioned above.  On the other hand, the "ui" command binds to
the loopback IP address only (127.0.0.1) so that the "ui" command cannot be
Both of these commands start a Fossil server, usually on TCP port 8080, though
a higher numbered port might also be used if 8080 is already occupied.  You can
access these using URLs of the form <b>http://localhost:8080/</b>, or if 
<i>REPOSITORY</i> is a directory, URLs of the form
<b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
name of the repository file without the ".fossil" suffix.
The difference between "ui" and "server" is that "ui" will
also start a web browser and points it
to the URL mentioned above, and "ui" command binds to
the loopback IP address (127.0.0.1) only so that the "ui" command cannot be
used to serve content to a different machine.
</p>
<p>
NOTES:
<ol>
<li>The option "--port NNN" will start the server on port "NNN" instead of 8080.  
<li>If port 8080 is already being used (perhaps by another Fossil server), then
Fossil will use the next available port number.
If one of the commands above is run from within an option checkout,
then the <i>REPOSITORY</i> argument can be omitted and the checkout is used as
the repository.
</p>
<p>
Both commands have additional command-line options that can be used to refine
their behavior.  See the [/help/server|online documentation] for an overview.
</p>
</blockquote>
<a name="inetd"></a>
<h2>Fossil as an inetd/xinetd or stunnel service</h2><blockquote>
<p>
A Fossil server can be launched on-demand by inetd or xinetd using
the [/help/http|fossil http] command.  To launch Fossil from inetd, modify
<li>Starting either command from within an "open" Fossil checkout will start a
server using the repository corresponding to the checkout.
your inetd configuration file (typically "/etc/inetd.conf") to contain a
line something like this:
<li>This is an excellent option for quickly sharing with coworkers on a small network.
<li>A huge advantage to this deployment scenario is that no special "root" or "administrator" access is required in order to share the repository.
</ol>
<blockquote>
<pre>
12345 stream tcp nowait.1000 root /usr/bin/fossil /usr/bin/fossil http /home/fossil/repo.fossil
</pre>
</blockquote>
In this example, you are telling "inetd" that when an incoming connection
appears on port "12345", that it should launch the binary "/usr/bin/fossil"
program with the arguments shown.
Obviously you will
need to modify the pathnames parts as appropriate for your particular setup.
The final argument is either the name of the fossil repository to be served,
or a directory containing multiple repositories.
</p>
<p>
If you system is running xinetd, then the configuration is likely to be
in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
An xinetd configuration file will appear like this:</p>
</blockquote>

<blockquote>
<pre>
service http-alt
{
  port = 591
  socket_type = stream
  wait = no
  user = root
  server = /usr/bin/fossil
  server_args = http /home/fossil/repos/
}
<h2>Fossil as an ''inetd'' service</h2><blockquote>
<p>
</pre>
Modify your <tt>/etc/inetd.conf</tt> (on Linux, modify as appropriate for your platform) so it contains a line like this:
<blockquote>
<tt>
12345 stream tcp nowait.1000 root /path-to/fossil /path-to/fossil http /other-path-to/repository
</blockquote>
<p>
The xinetd example above has Fossil configured to serve multiple
repositories, contained under the "/home/fossil/repos/" directory.
</tt>
</blockquote>
In this example, you are telling "inetd" that when an incoming connection on port "12345" happens, it should launch the binary "/path-to/fossil".  Obviously you will need to modify the "path-to" parts as appropriate for your particular setup.
</p>
<p>
This is a more complex setup than the "standalone" server, but it has the advantage of only using system resources when an actual connection is attempted.  If no-one ever connects to that port, a Fossil server will not (automatically) run.  It has the disadvantage of requiring "root" access and therefore may not normally be available to lower-priced "shared" servers on the internet.
In both cases notice that Fossil was launched as root.  This is not required,
but if it is done, then Fossil will automatically put itself into a chroot
jail for the user who owns the fossil repository before reading any information
off of the wire.
</p>
</blockquote>

<h2>Fossil as a ''CGI script''</h2><blockquote>
<p>
[http://www.stunnel.org/ | Stunnel version 4] is an inetd-like process that
accepts and decodes SSL-encrypted connections.  Fossil can be run directly from
stunnel in a mannar similar to inetd and xinetd.  This can be used to provide
a secure link to a Fossil project.  The configuration needed to get stunnel4
to invoke Fossil is very similar to the inetd and xinetd examples shown above.
See the stunnel4 documentation for details.
<p>
This is the most flexible and most likely to be widely usable of these deployment scenarios.  In order for it to work, you must have the ability to install "CGI scripts" on the server you are interested in using. 
Using inetd or xinetd or stunnel is a more complex setup 
than the "standalone" server, but it has the
advantage of only using system resources when an actual connection is
attempted.  If no-one ever connects to that port, a Fossil server will
not (automatically) run. It has the disadvantage of requiring "root" access
and therefore may not normally be available to lower-priced "shared" servers
on the internet.
</p>
</blockquote>
<a name="cgi"></a>
</blockquote>

<h3>One script per repository</h3><blockquote>
<h2>Fossil as CGI</h2><blockquote>
<p>
A Fossil server can also be run from an ordinary web server as a CGI program.
This feature allows Fossil to be seamlessly integrated into a larger website.
CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are 
implemented.
</p>
<p>
To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
Create a script (let's call it 'repo') in your CGI directory which has content like this:
<blockquote><tt>
#!/path-to/fossil<br>
repository: /path-to-repo/repository
</tt></blockquote>
of your web server and having content like this:
<blockquote><pre>
#!/usr/bin/fossil
repository: /home/fossil/repo.fossil
</pre></blockquote>
</p>
<p>
As always, adjust your paths appropriately.
It may be necessary to set permissions properly, or to modify an ".htaccess" file or other server-specific things like that.  Consult with your server provider if you need that sort of assistance.
It may be necessary to set permissions properly, or to modify an ".htaccess"
file or other server-specific things like that.  Consult the documentation
for your particular server.
</p>
<p>
Once the script is set up correctly, and assuming your server is also set correctly, you should be able to access your repository with a URL like: <tt>http://mydomain.org/cgi-bin/repo</tt> (assuming the "repo" script is accessible under "cgi-bin", which would be a typical deployment on Apache for instance).
Once the script is set up correctly, and assuming your server is also set
correctly, you should be able to access your repository with a URL like:
<b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is
accessible under "cgi-bin", which would be a typical deployment on Apache
for instance).
</p>
<p>
To server multiple repositories from a directory using CGI, use the "directory:"
tag in the CGI script rather than "repository:".   You might also want to add
a "notfound:" tag to tell where to redirect if the particular repository requested
by the URL is not found:
<blockquote><pre>
#!/usr/bin/fossil
directory: /home/fossil/repos
notfound: http://url-to-go-to-if-repo-not-found/
</pre></blockquote>
</p>
<p>
Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
will serve up the repository "/home/fossil/repos/XYX.fossil" (if it exists).
</p>
</blockquote>

<a name="scgi"></a>
<h2>Fossil as SCGI</h2><blockquote>
<h3>Serving multiple repositories with one script</h3><blockquote>

<p>
This scenario is almost identical to the previous one.  However, here we will assume you have multiple repositories, in one directory.
(Call the directory 'fossils').  All repositories served, in this case, must
use the ".fossil" filename suffix.
The [/help/server|fossil server] command, described above as a way of 
starting a stand-alone web server, can also be used for SCGI.  Simply add
the --scgi command-line option and the stand-alone server will interpret
and respond to the SimpleCGI or SCGI protocol rather than raw HTTP.  This can
be used in combination with a webserver (such as [http://nginx.org|Nginx])
that does not support CGI.  A typical Nginx configuration to support SCGI
with Fossil would look something like this:
As before, create a script (again, 'repo'):
<blockquote><tt>
#!/path-to/fossil<br>
<blockquote><pre>
location ~ ^/demo_project/ {
    include scgi_params;
directory: /path-to-repo/fossils<br>
notfound: http://url-to-go-to-if-repo-not-found/
</tt></blockquote>
    scgi_pass localhost:9000;
    scgi_param SCRIPT_NAME "/demo_project";
}
</pre></blockquote>
<p>
Note that Fossil requires the SCRIPT_NAME variable
in order to function properly, but Nginx does not provide this
variable by default.
So it is necessary to provide the SCRIPT_NAME parameter in the configuration.
Failure to do this will cause Fossil to return an error.
</p>
<p>
Once deployed, a URL like: <tt>http://mydomain.org/cgi-bin/repo/XYZ</tt> will serve up the repository "fossils/XYX.fossil" (if it exists).  This makes serving multiple projects on one server pretty painless.
All of the features of the stand-alone server mode described above,
such as the ability to server a directory full of Fossil repositories
rather than just a single repository, work the same way in SCGI mode.
</p>
</blockquote>

<h2>Securing a repository with SSL</h2><blockquote>
<p>
Using either CGI or SCGI, it is trivial to use SSL to
Using either of the CGI script approaches, it is trivial to use SSL to secure the server.  Simply set up the Fossil CGI scripts etc. as above, but modify the Apache (or IIS, etc.) server to require SSL (that is, a URL with "https://") in order to access the CGI script directory.  This may also be accomplished (on Apache, at least) using appropriate ".htaccess" rules.
secure the server.  Simply set up the Fossil CGI scripts etc. as above,
but modify the Apache (or IIS, etc.) server to require SSL (that is, a
URL with "https://") in order to access the CGI script directory.  This
may also be accomplished (on Apache, at least) using appropriate
".htaccess" rules.
</p>
<p>
If you are using "inetd" to serve your repository, then you simply need to add "/usr/bin/stunnel" (perhaps on a different path, depending on your setup) before the command line to launch Fossil.
If you are using "inetd" to serve your repository, then you simply need
to add "/usr/bin/stunnel" (perhaps on a different path, depending on your
setup) before the command line to launch Fossil.
</p>
<p>
At this stage, the standalone server (e.g. "fossil server") does not support SSL.
At this stage, the standalone server (e.g. "fossil server") does not
support SSL.
</p>
<p>
For more information, see <a href="./ssl.wiki">Using SSL with Fossil</a>.
</p>
</blockquote>

<h2>Various security concerns with hosted repositories</h2><blockquote>
<p>
There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data):
There are two main concerns relating to usage of Fossil for sharing
sensitive information (source or any other data):
<ul>
<li>Interception of the Fossil synchronization stream, thereby capturing data, and
<li>Interception of the Fossil synchronization stream, thereby capturing
data, and 
<li>Direct access to the Fossil repository on the server
</ul>
</p>
<p>
Regarding the first, it is adequate to secure the server using SSL, and disallowing any non-SSL access.  The data stream will be encrypted by the HTTPS protocol, rendering the data reasonably secure.  The truly paranoid may wish to deploy <i>ssh</i> encrypted tunnels, but that is quite a bit more difficult and cumbersome to set up (particularly for a larger number of users).
Regarding the first, it is adequate to secure the server using SSL, and
disallowing any non-SSL access.  The data stream will be encrypted by
the HTTPS protocol, rendering the data reasonably secure.  The truly
paranoid may wish to deploy <i>ssh</i> encrypted tunnels, but that is
quite a bit more difficult and cumbersome to set up (particularly for
a larger number of users).
</p>
<p>
As far as direct access to the repository, the same steps must be taken as for any other internet-facing data-store.  Access passwords to any disk-accessing accounts should be strong (and preferably changed from time to time).  However, the data in the repository itself are <i>not</i> encrypted (unless you save encrypted data yourself), and so the system administrators of your server will be able to access your data (as with any hosting service setup).  The only workaround in this case is to host the server yourself, in which case you will need to allocate resources to deal with administration issues.
As far as direct access to the repository, the same steps must be taken
as for any other internet-facing data-store.  Access passwords to any
disk-accessing accounts should be strong (and preferably changed from
time to time).  However, the data in the repository itself are <i>not</i>
encrypted (unless you save encrypted data yourself), and so the system
administrators of your server will be able to access your data (as with
any hosting service setup).  The only workaround in this case is to
host the server yourself, in which case you will need to allocate
resources to deal with administration issues.
</p>

</blockquote>

</nowiki>
Changes to www/webui.wiki.
65
66
67
68
69
70
71
72


73
74
75
76
77
78
79
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80







-
+
+







Notice that Fossil automatically finds an unused TCP port to run the
server own and automatically points your web browser to the correct
URL.  So there is never any fumbling around trying to find an open
port or to type arcane strings into your browser URL entry box.
The interface just pops right up, ready to run.

The Fossil web interface is also very easy to setup and run on a
network server, as either a CGI program or from inetd.  Details on how
network server, as either a CGI program or from inetd, or as an
SCGI server.  Details on how
to do that are described further below.

<h2>Things To Do Using The Web Interface</h2>

You can view <b>timelines</b> of changes to the project.  The default
"Timeline" link on the menu bar takes you to a page that shows the 20
most recent check-ins, wiki page edits, ticket/bug-report changes,
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
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174







-
+
+















+
+
+
-
+
+












"Home" page to be a wiki page or an embedded document.

<h2>Installing On A Network Server</h2>

When you create a new Fossil project and after you have configured it
like you want it using the web interface, you can make the project
available to a distributed team by simply copying the single
repository file up to a web server that supports CGI.  Just put the
repository file up to a web server that supports CGI or SCGI.  To
run Fossil as CGI, just put the
<b>sample-project.fossil</b> file in a directory where CGI scripts
have both read and write permission on the file and the directory that
contains the file, then add a CGI script that looks something like this:

  <verbatim>
  #!/usr/local/bin/fossil
  repository: /home/www/sample-project.fossil
  </verbatim>

Adjust the script above so that the paths are correct for your system,
of course, and also make sure the Fossil binary is installed on the server.
But that is <u>all</u> you have to do.  You now have everything you need to host
a distributed software development project in less than five minutes using a 
two-line CGI script.

Instructions for setting up an SCGI server are
[./scgi.wiki | available separately].

You don't have a CGI-capable web server running on your server machine?
You don't have a CGI- or SCGI-capable web server running on your
server machine?
Not a problem.  The Fossil interface can also be launched via inetd or
xinetd.  An inetd configuration line sufficient to launch the Fossil
web interface looks like this:

  <verbatim>
  80 stream tcp nowait.1000 root /usr/local/bin/fossil \
  /usr/local/bin/fossil http /home/www/sample-project.fossil 
  </verbatim>

As always, you'll want to adjust the pathnames to whatever is appropriate
for your system.  The xinetd setup uses a different syntax but follows
the same idea.