Fossil

Check-in [9cea672b5d]
Login

Check-in [9cea672b5d]

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

Overview
Comment:Sync with trunk.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | timeline-keyboard-navigation
Files: files | file ages | folders
SHA3-256: 9cea672b5d4dd7c4314c237bc436c1f5ee11a2abe3ba59add5eb0b986e1b0628
User & Date: florian 2025-09-26 12:50:00.000
Context
2026-01-10
14:02
Sync with trunk. ... (check-in: c50c8ed9d7 user: florian tags: timeline-keyboard-navigation)
2025-09-26
12:50
Sync with trunk. ... (check-in: 9cea672b5d user: florian tags: timeline-keyboard-navigation)
12:48
Prevent the cell background colors from extending beyond the outer rounded borders of the diff table in WebKit-based browsers. ... (check-in: b666bbc54d user: florian tags: trunk)
2025-08-21
12:04
Sync with trunk. ... (check-in: bab295db10 user: florian tags: timeline-keyboard-navigation)
Changes
Unified Diff Ignore Whitespace Patch
Changes to extsrc/shell.c.
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665













666
667
668
669
670
671
672
  return strncmp(a,b,n);
}

/* Return the current wall-clock time in microseconds since the
** Unix epoch (1970-01-01T00:00:00Z)
*/
static sqlite3_int64 timeOfDay(void){
#if defined(_WIN32)
  sqlite3_uint64 t;
  FILETIME tm;
  GetSystemTimePreciseAsFileTime(&tm);
  t =  ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
  t += 116444736000000000LL;
  t /= 10;
  return t;













#else
  struct timeval sNow;
  (void)gettimeofday(&sNow,0);
  return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
#endif
}








|







>
>
>
>
>
>
>
>
>
>
>
>
>







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
  return strncmp(a,b,n);
}

/* Return the current wall-clock time in microseconds since the
** Unix epoch (1970-01-01T00:00:00Z)
*/
static sqlite3_int64 timeOfDay(void){
#if defined(_WIN64)
  sqlite3_uint64 t;
  FILETIME tm;
  GetSystemTimePreciseAsFileTime(&tm);
  t =  ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
  t += 116444736000000000LL;
  t /= 10;
  return t;
#elif defined(_WIN32)
  static sqlite3_vfs *clockVfs = 0;
  sqlite3_int64 t;
  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
  if( clockVfs==0 ) return 0;  /* Never actually happens */
  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
  }else{
    double r;
    clockVfs->xCurrentTime(clockVfs, &r);
    t = (sqlite3_int64)(r*86400000.0);
  }
  return t*1000;
#else
  struct timeval sNow;
  (void)gettimeofday(&sNow,0);
  return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
#endif
}

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
** Print the timing results.
*/
static void endTimer(FILE *out){
  if( enableTimer ){
    sqlite3_int64 iEnd = timeOfDay();
    struct rusage sEnd;
    getrusage(RUSAGE_SELF, &sEnd);
    sqlite3_fprintf(out, "Run Time: real %.6f user %f sys %f\n",
          (iEnd - iBegin)*0.000001,
          timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
          timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
  }
}

#define BEGIN_TIMER beginTimer()







|







721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
** Print the timing results.
*/
static void endTimer(FILE *out){
  if( enableTimer ){
    sqlite3_int64 iEnd = timeOfDay();
    struct rusage sEnd;
    getrusage(RUSAGE_SELF, &sEnd);
    sqlite3_fprintf(out, "Run Time: real %.6f user %.6f sys %.6f\n",
          (iEnd - iBegin)*0.000001,
          timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
          timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
  }
}

#define BEGIN_TIMER beginTimer()
787
788
789
790
791
792
793


794
795
796
797







798
799
800
801
802
803
804
** Print the timing results.
*/
static void endTimer(FILE *out){
  if( enableTimer && getProcessTimesAddr){
    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
    sqlite3_int64 ftWallEnd = timeOfDay();
    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);


    sqlite3_fprintf(out, "Run Time: real %.6f user %f sys %f\n",
          (ftWallEnd - ftWallBegin)*0.000001,
          timeDiff(&ftUserBegin, &ftUserEnd),
          timeDiff(&ftKernelBegin, &ftKernelEnd));







  }
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER(X) endTimer(X)
#define HAS_TIMER hasTimer()








>
>




>
>
>
>
>
>
>







800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
** Print the timing results.
*/
static void endTimer(FILE *out){
  if( enableTimer && getProcessTimesAddr){
    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
    sqlite3_int64 ftWallEnd = timeOfDay();
    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
#ifdef _WIN64
    /* microsecond precision on 64-bit windows */
    sqlite3_fprintf(out, "Run Time: real %.6f user %f sys %f\n",
          (ftWallEnd - ftWallBegin)*0.000001,
          timeDiff(&ftUserBegin, &ftUserEnd),
          timeDiff(&ftKernelBegin, &ftKernelEnd));
#else
    /* millisecond precisino on 32-bit windows */
    sqlite3_fprintf(out, "Run Time: real %.3f user %.3f sys %.3f\n",
          (ftWallEnd - ftWallBegin)*0.000001,
          timeDiff(&ftUserBegin, &ftUserEnd),
          timeDiff(&ftKernelBegin, &ftKernelEnd));
#endif
  }
}

#define BEGIN_TIMER beginTimer()
#define END_TIMER(X) endTimer(X)
#define HAS_TIMER hasTimer()

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
    *pU = ((z[0] & 0x0f)<<12) | ((z[1] & 0x3f)<<6) | (z[2] & 0x3f);
    return 3;
  }
  if( (z[0] & 0xf8)==0xf0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80
   && (z[3] & 0xc0)==0x80
  ){
    *pU = ((z[0] & 0x0f)<<18) | ((z[1] & 0x3f)<<12) | ((z[2] & 0x3f))<<6
                              | (z[4] & 0x3f);
    return 4;
  }
  *pU = 0;
  return 1;
}









|







1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
    *pU = ((z[0] & 0x0f)<<12) | ((z[1] & 0x3f)<<6) | (z[2] & 0x3f);
    return 3;
  }
  if( (z[0] & 0xf8)==0xf0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80
   && (z[3] & 0xc0)==0x80
  ){
    *pU = ((z[0] & 0x0f)<<18) | ((z[1] & 0x3f)<<12) | ((z[2] & 0x3f))<<6
                              | (z[3] & 0x3f);
    return 4;
  }
  *pU = 0;
  return 1;
}


1193
1194
1195
1196
1197
1198
1199



1200
1201
1202

1203
1204
1205
1206






1207
1208
1209
1210
1211
1212
1213
1214
** then right-justify the text.  W is the width in UTF-8 characters, not
** in bytes.  This is different from the %*.*s specification in printf
** since with %*.*s the width is measured in bytes, not characters.
**
** Take into account zero-width and double-width Unicode characters.
** In other words, a zero-width character does not count toward the
** the w limit.  A double-width character counts as two.



*/
static void utf8_width_print(FILE *out, int w, const char *zUtf){
  const unsigned char *a = (const unsigned char*)zUtf;

  unsigned char c;
  int i = 0;
  int n = 0;
  int k;






  int aw = w<0 ? -w : w;
  if( zUtf==0 ) zUtf = "";
  while( (c = a[i])!=0 ){
    if( (c&0xc0)==0xc0 ){
      int u;
      int len = decodeUtf8(a+i, &u);
      int x = cli_wcwidth(u);
      if( x+n>aw ){







>
>
>



>




>
>
>
>
>
>
|







1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
** then right-justify the text.  W is the width in UTF-8 characters, not
** in bytes.  This is different from the %*.*s specification in printf
** since with %*.*s the width is measured in bytes, not characters.
**
** Take into account zero-width and double-width Unicode characters.
** In other words, a zero-width character does not count toward the
** the w limit.  A double-width character counts as two.
**
** w should normally be a small number.  A couple hundred at most.  This
** routine caps w at 100 million to avoid integer overflow issues.
*/
static void utf8_width_print(FILE *out, int w, const char *zUtf){
  const unsigned char *a = (const unsigned char*)zUtf;
  static const int mxW = 10000000;
  unsigned char c;
  int i = 0;
  int n = 0;
  int k;
  int aw;
  if( w<-mxW ){
    w = -mxW;
  }else if( w>mxW ){
    w= mxW;
  }
  aw = w<0 ? -w : w;
  if( zUtf==0 ) zUtf = "";
  while( (c = a[i])!=0 ){
    if( (c&0xc0)==0xc0 ){
      int u;
      int len = decodeUtf8(a+i, &u);
      int x = cli_wcwidth(u);
      if( x+n>aw ){
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
#undef STAT_CHR_SRC
}

/*
** 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.
**
** 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 *zLine, FILE *in){
  int nLine = zLine==0 ? 0 : 100;
  int n = 0;

  while( 1 ){
    if( n+100>nLine ){




      nLine = nLine*2 + 100;
      zLine = realloc(zLine, nLine);
      shell_check_oom(zLine);
    }
    if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){
      if( n==0 ){
        free(zLine);







|










>
>
>
>







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
#undef STAT_CHR_SRC
}

/*
** 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, or if the length of the line is longer than about a gigabyte.
**
** 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 *zLine, FILE *in){
  int nLine = zLine==0 ? 0 : 100;
  int n = 0;

  while( 1 ){
    if( n+100>nLine ){
      if( nLine>=1073741773 ){
        free(zLine);
        return 0;
      }
      nLine = nLine*2 + 100;
      zLine = realloc(zLine, nLine);
      shell_check_oom(zLine);
    }
    if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){
      if( n==0 ){
        free(zLine);
1421
1422
1423
1424
1425
1426
1427




1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
  if( c>='a' && c<='f' ) return c - 'a' + 10;
  if( c>='A' && c<='F' ) return c - 'A' + 10;
  return -1;
}

/*
** Interpret zArg as an integer value, possibly with suffixes.




*/
static sqlite3_int64 integerValue(const char *zArg){
  sqlite3_int64 v = 0;
  static const struct { char *zSuffix; int iMult; } aMult[] = {
    { "KiB", 1024 },
    { "MiB", 1024*1024 },
    { "GiB", 1024*1024*1024 },
    { "KB",  1000 },
    { "MB",  1000000 },
    { "GB",  1000000000 },
    { "K",   1000 },







>
>
>
>


|
|







1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
  if( c>='a' && c<='f' ) return c - 'a' + 10;
  if( c>='A' && c<='F' ) return c - 'A' + 10;
  return -1;
}

/*
** Interpret zArg as an integer value, possibly with suffixes.
**
** If the value specified by zArg is outside the range of values that
** can be represented using a 64-bit twos-complement integer, then return
** the nearest representable value.
*/
static sqlite3_int64 integerValue(const char *zArg){
  sqlite3_uint64 v = 0;
  static const struct { char *zSuffix; unsigned int iMult; } aMult[] = {
    { "KiB", 1024 },
    { "MiB", 1024*1024 },
    { "GiB", 1024*1024*1024 },
    { "KB",  1000 },
    { "MB",  1000000 },
    { "GB",  1000000000 },
    { "K",   1000 },
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
  }else if( zArg[0]=='+' ){
    zArg++;
  }
  if( zArg[0]=='0' && zArg[1]=='x' ){
    int x;
    zArg += 2;
    while( (x = hexDigitValue(zArg[0]))>=0 ){

      v = (v<<4) + x;
      zArg++;
    }
  }else{
    while( IsDigit(zArg[0]) ){



      v = v*10 + zArg[0] - '0';
      zArg++;
    }
  }
  for(i=0; i<ArraySize(aMult); i++){
    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){

      v *= aMult[i].iMult;
      break;
    }
  }

  return isNeg? -v : v;


}

/*
** A variable length string to which one can append text.
*/
typedef struct ShellText ShellText;
struct ShellText {







>





>
>
>
|





>




>
|
>
>







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
  }else if( zArg[0]=='+' ){
    zArg++;
  }
  if( zArg[0]=='0' && zArg[1]=='x' ){
    int x;
    zArg += 2;
    while( (x = hexDigitValue(zArg[0]))>=0 ){
      if( v > 0x0fffffffffffffffULL ) goto integer_overflow;
      v = (v<<4) + x;
      zArg++;
    }
  }else{
    while( IsDigit(zArg[0]) ){
      if( v>=922337203685477580 ){
        if( v>922337203685477580 || zArg[0]>='8' ) goto integer_overflow;
      }
      v = v*10 + (zArg[0] - '0');
      zArg++;
    }
  }
  for(i=0; i<ArraySize(aMult); i++){
    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
      if( 0x7fffffffffffffffULL/aMult[i].iMult < v ) goto integer_overflow;
      v *= aMult[i].iMult;
      break;
    }
  }
  if( isNeg && v>0x7fffffffffffffffULL ) goto integer_overflow;
  return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v;
integer_overflow:
  return isNeg ? 0x8000000000000000LL : 0x7fffffffffffffffLL;
}

/*
** A variable length string to which one can append text.
*/
typedef struct ShellText ShellText;
struct ShellText {
3698
3699
3700
3701
3702
3703
3704




3705
3706
3707
3708
3709
3710
3711
      if( p->a==0 ) goto new_from_text_failed;
      memmove(p->a+iExp, p->a, p->nDigit);
      memset(p->a, 0, iExp);
      p->nDigit += iExp;
      p->nFrac += iExp;
    }
  }




  return p;

new_from_text_failed:
  if( p ){
    if( p->a ) sqlite3_free(p->a);
    sqlite3_free(p);
  }







>
>
>
>







3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
      if( p->a==0 ) goto new_from_text_failed;
      memmove(p->a+iExp, p->a, p->nDigit);
      memset(p->a, 0, iExp);
      p->nDigit += iExp;
      p->nFrac += iExp;
    }
  }
  if( p->sign ){
    for(i=0; i<p->nDigit && p->a[i]==0; i++){}
    if( i>=p->nDigit ) p->sign = 0;
  }
  return p;

new_from_text_failed:
  if( p ){
    if( p->a ) sqlite3_free(p->a);
    sqlite3_free(p);
  }
3900
3901
3902
3903
3904
3905
3906
3907
3908








3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
** Preconditions for this routine:
**
**    pA!=0
**    pA->isNull==0
**    pB!=0
**    pB->isNull==0
*/
static int decimal_cmp(const Decimal *pA, const Decimal *pB){
  int nASig, nBSig, rc, n;








  if( pA->sign!=pB->sign ){
    return pA->sign ? -1 : +1;
  }
  if( pA->sign ){
    const Decimal *pTemp = pA;
    pA = pB;
    pB = pTemp;
  }
  nASig = pA->nDigit - pA->nFrac;
  nBSig = pB->nDigit - pB->nFrac;
  if( nASig!=nBSig ){
    return nASig - nBSig;







|

>
>
>
>
>
>
>
>




|







3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
** Preconditions for this routine:
**
**    pA!=0
**    pA->isNull==0
**    pB!=0
**    pB->isNull==0
*/
static int decimal_cmp(Decimal *pA, Decimal *pB){
  int nASig, nBSig, rc, n;
  while( pA->nFrac>0 && pA->a[pA->nDigit-1]==0 ){
    pA->nDigit--;
    pA->nFrac--;
  }
  while( pB->nFrac>0 && pB->a[pB->nDigit-1]==0 ){
    pB->nDigit--;
    pB->nFrac--;
  }
  if( pA->sign!=pB->sign ){
    return pA->sign ? -1 : +1;
  }
  if( pA->sign ){
    Decimal *pTemp = pA;
    pA = pB;
    pB = pTemp;
  }
  nASig = pA->nDigit - pA->nFrac;
  nBSig = pB->nDigit - pB->nFrac;
  if( nASig!=nBSig ){
    return nASig - nBSig;
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
  if( r<0.0 ){
    isNeg = 1;
    r = -r;
  }else{
    isNeg = 0;
  }
  memcpy(&a,&r,sizeof(a));
  if( a==0 ){
    e = 0;
    m = 0;
  }else{
    e = a>>52;
    m = a & ((((sqlite3_int64)1)<<52)-1);
    if( e==0 ){
      m <<= 1;







|







4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
  if( r<0.0 ){
    isNeg = 1;
    r = -r;
  }else{
    isNeg = 0;
  }
  memcpy(&a,&r,sizeof(a));
  if( a==0 || a==(sqlite3_int64)0x8000000000000000LL){
    e = 0;
    m = 0;
  }else{
    e = a>>52;
    m = a & ((((sqlite3_int64)1)<<52)-1);
    if( e==0 ){
      m <<= 1;
5148
5149
5150
5151
5152
5153
5154
5155

5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
    pOut += nbo;
  }
  return pOut;
}

/* This function does the work for the SQLite base64(x) UDF. */
static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
  int nb, nc, nv = sqlite3_value_bytes(av[0]);

  int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
                            SQLITE_LIMIT_LENGTH, -1);
  char *cBuf;
  u8 *bBuf;
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_BLOB:
    nb = nv;
    nc = 4*(nv+2/3); /* quads needed */
    nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
    if( nvMax < nc ){
      sqlite3_result_error(context, "blob expanded to base64 too big", -1);
      return;
    }
    bBuf = (u8*)sqlite3_value_blob(av[0]);
    if( !bBuf ){







|
>








|







5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
    pOut += nbo;
  }
  return pOut;
}

/* This function does the work for the SQLite base64(x) UDF. */
static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
  int nb, nv = sqlite3_value_bytes(av[0]);
  sqlite3_int64 nc;
  int nvMax = sqlite3_limit(sqlite3_context_db_handle(context),
                            SQLITE_LIMIT_LENGTH, -1);
  char *cBuf;
  u8 *bBuf;
  assert(na==1);
  switch( sqlite3_value_type(av[0]) ){
  case SQLITE_BLOB:
    nb = nv;
    nc = 4*((nv+2)/3); /* quads needed */
    nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */
    if( nvMax < nc ){
      sqlite3_result_error(context, "blob expanded to base64 too big", -1);
      return;
    }
    bBuf = (u8*)sqlite3_value_blob(av[0]);
    if( !bBuf ){
5833
5834
5835
5836
5837
5838
5839



5840
5841
5842
5843
5844
5845
5846
    }else{
      isNeg = 0;
    }
    memcpy(&a,&r,sizeof(a));
    if( a==0 ){
      e = 0;
      m = 0;



    }else{
      e = a>>52;
      m = a & ((((sqlite3_int64)1)<<52)-1);
      if( e==0 ){
        m <<= 1;
      }else{
        m |= ((sqlite3_int64)1)<<52;







>
>
>







5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
    }else{
      isNeg = 0;
    }
    memcpy(&a,&r,sizeof(a));
    if( a==0 ){
      e = 0;
      m = 0;
    }else if( a==(sqlite3_int64)0x8000000000000000LL ){
      e = -1996;
      m = -1;
    }else{
      e = a>>52;
      m = a & ((((sqlite3_int64)1)<<52)-1);
      if( e==0 ){
        m <<= 1;
      }else{
        m |= ((sqlite3_int64)1)<<52;
6593
6594
6595
6596
6597
6598
6599




6600
6601
6602
6603
6604
6605
6606
  /* Apply LIMIT and OFFSET constraints, if any */
  if( idxNum & 0x20 ){
    if( iOffset>0 ){
      pCur->ss.iBase += pCur->ss.iStep*iOffset;
    }
    if( iLimit>=0 ){
      sqlite3_int64 iTerm;




      iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
      if( pCur->ss.iStep<0 ){
        if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
      }else{
        if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
      }
    }







>
>
>
>







6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
  /* Apply LIMIT and OFFSET constraints, if any */
  if( idxNum & 0x20 ){
    if( iOffset>0 ){
      pCur->ss.iBase += pCur->ss.iStep*iOffset;
    }
    if( iLimit>=0 ){
      sqlite3_int64 iTerm;
      sqlite3_int64 mxLimit;
      assert( pCur->ss.iStep>0 );
      mxLimit = (LARGEST_INT64 - pCur->ss.iBase)/pCur->ss.iStep;
      if( iLimit>mxLimit ) iLimit = mxLimit;
      iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
      if( pCur->ss.iStep<0 ){
        if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
      }else{
        if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
      }
    }
10221
10222
10223
10224
10225
10226
10227

10228
10229
10230
10231
10232
10233
10234
    "data,"              /* 5: Uncompressed data */
    "method,"            /* 6: Compression method (integer) */
    "z HIDDEN"           /* 7: Name of zip file */
  ") WITHOUT ROWID;";

#define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
#define ZIPFILE_BUFFER_SIZE (64*1024)



/*
** Magic numbers used to read and write zip files.
**
** ZIPFILE_NEWENTRY_MADEBY:
**   Use this value for the "version-made-by" field in new zip file







>







10289
10290
10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
    "data,"              /* 5: Uncompressed data */
    "method,"            /* 6: Compression method (integer) */
    "z HIDDEN"           /* 7: Name of zip file */
  ") WITHOUT ROWID;";

#define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
#define ZIPFILE_BUFFER_SIZE (64*1024)
#define ZIPFILE_MX_NAME (250)     /* Windows limitation on filename size */


/*
** Magic numbers used to read and write zip files.
**
** ZIPFILE_NEWENTRY_MADEBY:
**   Use this value for the "version-made-by" field in new zip file
10777
10778
10779
10780
10781
10782
10783

10784
10785
10786
10787
10788
10789
10790
    pLFH->mTime = zipfileRead16(aRead);
    pLFH->mDate = zipfileRead16(aRead);
    pLFH->crc32 = zipfileRead32(aRead);
    pLFH->szCompressed = zipfileRead32(aRead);
    pLFH->szUncompressed = zipfileRead32(aRead);
    pLFH->nFile = zipfileRead16(aRead);
    pLFH->nExtra = zipfileRead16(aRead);

  }
  return rc;
}


/*
** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.







>







10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
    pLFH->mTime = zipfileRead16(aRead);
    pLFH->mDate = zipfileRead16(aRead);
    pLFH->crc32 = zipfileRead32(aRead);
    pLFH->szCompressed = zipfileRead32(aRead);
    pLFH->szUncompressed = zipfileRead32(aRead);
    pLFH->nFile = zipfileRead16(aRead);
    pLFH->nExtra = zipfileRead16(aRead);
    if( pLFH->nFile>ZIPFILE_MX_NAME ) rc = SQLITE_ERROR;
  }
  return rc;
}


/*
** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
10990
10991
10992
10993
10994
10995
10996



10997
10998

10999
11000
11001
11002
11003
11004
11005
      }

      if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
      if( rc==SQLITE_OK ){
        pNew->iDataOff =  pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
        pNew->iDataOff += lfh.nFile + lfh.nExtra;
        if( aBlob && pNew->cds.szCompressed ){



          pNew->aData = &pNew->aExtra[nExtra];
          memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);

        }
      }else{
        *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", 
            (int)pNew->cds.iOffset
        );
      }
    }







>
>
>
|
|
>







11060
11061
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
      }

      if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
      if( rc==SQLITE_OK ){
        pNew->iDataOff =  pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
        pNew->iDataOff += lfh.nFile + lfh.nExtra;
        if( aBlob && pNew->cds.szCompressed ){
          if( pNew->iDataOff + pNew->cds.szCompressed > nBlob ){
            rc = SQLITE_CORRUPT;
          }else{
            pNew->aData = &pNew->aExtra[nExtra];
            memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
          }
        }
      }else{
        *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", 
            (int)pNew->cds.iOffset
        );
      }
    }
11778
11779
11780
11781
11782
11783
11784





11785
11786
11787
11788
11789
11790
11791
      rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
    }

    if( rc==SQLITE_OK ){
      zPath = (const char*)sqlite3_value_text(apVal[2]);
      if( zPath==0 ) zPath = "";
      nPath = (int)strlen(zPath);





      mTime = zipfileGetTime(apVal[4]);
    }

    if( rc==SQLITE_OK && bIsDir ){
      /* For a directory, check that the last character in the path is a
      ** '/'. This appears to be required for compatibility with info-zip
      ** (the unzip command on unix). It does not create directories







>
>
>
>
>







11852
11853
11854
11855
11856
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
      rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
    }

    if( rc==SQLITE_OK ){
      zPath = (const char*)sqlite3_value_text(apVal[2]);
      if( zPath==0 ) zPath = "";
      nPath = (int)strlen(zPath);
      if( nPath>ZIPFILE_MX_NAME ){
        zipfileTableErr(pTab, "filename too long; max: %d bytes",
                        ZIPFILE_MX_NAME);
        rc = SQLITE_CONSTRAINT;
      }
      mTime = zipfileGetTime(apVal[4]);
    }

    if( rc==SQLITE_OK && bIsDir ){
      /* For a directory, check that the last character in the path is a
      ** '/'. This appears to be required for compatibility with info-zip
      ** (the unzip command on unix). It does not create directories
12138
12139
12140
12141
12142
12143
12144







12145
12146
12147
12148
12149
12150
12151
  /* Check that the 'name' parameter looks ok. */
  zName = (char*)sqlite3_value_text(pName);
  nName = sqlite3_value_bytes(pName);
  if( zName==0 ){
    zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
    rc = SQLITE_ERROR;
    goto zipfile_step_out;







  }

  /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
  ** deflate compression) or NULL (choose automatically).  */
  if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
    iMethod = (int)sqlite3_value_int64(pMethod);
    if( iMethod!=0 && iMethod!=8 ){







>
>
>
>
>
>
>







12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
  /* Check that the 'name' parameter looks ok. */
  zName = (char*)sqlite3_value_text(pName);
  nName = sqlite3_value_bytes(pName);
  if( zName==0 ){
    zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
    rc = SQLITE_ERROR;
    goto zipfile_step_out;
  }
  if( nName>ZIPFILE_MX_NAME ){
    zErr = sqlite3_mprintf(
               "filename argument to zipfile() too big; max: %d bytes",
               ZIPFILE_MX_NAME);
    rc = SQLITE_ERROR;
    goto zipfile_step_out;
  }

  /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
  ** deflate compression) or NULL (choose automatically).  */
  if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
    iMethod = (int)sqlite3_value_int64(pMethod);
    if( iMethod!=0 && iMethod!=8 ){
22031
22032
22033
22034
22035
22036
22037
22038
22039
22040
22041
22042
22043
22044
22045
  sqlite3_free(zStr);
}

/*
** Output the given string as a quoted string using SQL quoting conventions:
**
**   (1)   Single quotes (') within the string are doubled
**   (2)   The whle string is enclosed in '...'
**   (3)   Control characters other than \n, \t, and \r\n are escaped
**         using \u00XX notation and if such substitutions occur,
**         the whole string is enclosed in unistr('...') instead of '...'.
**         
** Step (3) is omitted if the control-character escape mode is OFF.
**
** See also: output_quoted_escaped_string() which does the same except







|







22117
22118
22119
22120
22121
22122
22123
22124
22125
22126
22127
22128
22129
22130
22131
  sqlite3_free(zStr);
}

/*
** Output the given string as a quoted string using SQL quoting conventions:
**
**   (1)   Single quotes (') within the string are doubled
**   (2)   The while string is enclosed in '...'
**   (3)   Control characters other than \n, \t, and \r\n are escaped
**         using \u00XX notation and if such substitutions occur,
**         the whole string is enclosed in unistr('...') instead of '...'.
**         
** Step (3) is omitted if the control-character escape mode is OFF.
**
** See also: output_quoted_escaped_string() which does the same except
22277
22278
22279
22280
22281
22282
22283
22284
22285
22286
22287
22288
22289
22290
22291
** Escape the input string if it is needed and in accordance with
** eEscMode.
**
** Escaping is needed if the string contains any control characters
** other than \t, \n, and \r\n
**
** If no escaping is needed (the common case) then set *ppFree to NULL
** and return the original string.  If escapingn is needed, write the
** escaped string into memory obtained from sqlite3_malloc64() or the
** equivalent, and return the new string and set *ppFree to the new string
** as well.
**
** The caller is responsible for freeing *ppFree if it is non-NULL in order
** to reclaim memory.
*/







|







22363
22364
22365
22366
22367
22368
22369
22370
22371
22372
22373
22374
22375
22376
22377
** Escape the input string if it is needed and in accordance with
** eEscMode.
**
** Escaping is needed if the string contains any control characters
** other than \t, \n, and \r\n
**
** If no escaping is needed (the common case) then set *ppFree to NULL
** and return the original string.  If escaping is needed, write the
** escaped string into memory obtained from sqlite3_malloc64() or the
** equivalent, and return the new string and set *ppFree to the new string
** as well.
**
** The caller is responsible for freeing *ppFree if it is non-NULL in order
** to reclaim memory.
*/
23282
23283
23284
23285
23286
23287
23288
23289
23290
23291
23292
23293
23294
23295
23296
23297
23298
23299
23300
23301
23302
23303
23304
23305
23306
23307
23308
23309
23310
23311
23312
23313
23314
23315
23316
23317

/*
** Set the destination table field of the ShellState structure to
** the name of the table given.  Escape any quote characters in the
** table name.
*/
static void set_table_name(ShellState *p, const char *zName){
  int i, n;
  char cQuote;
  char *z;

  if( p->zDestTable ){
    free(p->zDestTable);
    p->zDestTable = 0;
  }
  if( zName==0 ) return;
  cQuote = quoteChar(zName);
  n = strlen30(zName);
  if( cQuote ) n += n+2;
  z = p->zDestTable = malloc( n+1 );
  shell_check_oom(z);
  n = 0;
  if( cQuote ) z[n++] = cQuote;
  for(i=0; zName[i]; i++){
    z[n++] = zName[i];
    if( zName[i]==cQuote ) z[n++] = cQuote;
  }
  if( cQuote ) z[n++] = cQuote;
  z[n] = 0;
}

/*
** Maybe construct two lines of text that point out the position of a
** syntax error.  Return a pointer to the text, in memory obtained from
** sqlite3_malloc().  Or, if the most recent error does not involve a
** specific token that we can point to, return an empty string.







<
<
<
<

|



<
<
<
|
<
<
<
<
<
<
<
<
<







23368
23369
23370
23371
23372
23373
23374




23375
23376
23377
23378
23379



23380









23381
23382
23383
23384
23385
23386
23387

/*
** Set the destination table field of the ShellState structure to
** the name of the table given.  Escape any quote characters in the
** table name.
*/
static void set_table_name(ShellState *p, const char *zName){




  if( p->zDestTable ){
    sqlite3_free(p->zDestTable);
    p->zDestTable = 0;
  }
  if( zName==0 ) return;



  p->zDestTable = sqlite3_mprintf("\"%w\"", zName);









}

/*
** Maybe construct two lines of text that point out the position of a
** syntax error.  Return a pointer to the text, in memory obtained from
** sqlite3_malloc().  Or, if the most recent error does not involve a
** specific token that we can point to, return an empty string.
26833
26834
26835
26836
26837
26838
26839
26840
26841
26842

26843


26844
26845
26846
26847
26848
26849
26850
}

#if SQLITE_SHELL_HAVE_RECOVER
/*
** Convert a 2-byte or 4-byte big-endian integer into a native integer
*/
static unsigned int get2byteInt(unsigned char *a){
  return (a[0]<<8) + a[1];
}
static unsigned int get4byteInt(unsigned char *a){

  return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];


}

/*
** Implementation of the ".dbinfo" command.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/







|


>
|
>
>







26903
26904
26905
26906
26907
26908
26909
26910
26911
26912
26913
26914
26915
26916
26917
26918
26919
26920
26921
26922
26923
}

#if SQLITE_SHELL_HAVE_RECOVER
/*
** Convert a 2-byte or 4-byte big-endian integer into a native integer
*/
static unsigned int get2byteInt(unsigned char *a){
  return ((unsigned int)a[0]<<8) + (unsigned int)a[1];
}
static unsigned int get4byteInt(unsigned char *a){
  return ((unsigned int)a[0]<<24)
       + ((unsigned int)a[1]<<16)
       + ((unsigned int)a[2]<<8)
       + (unsigned int)a[3];
}

/*
** Implementation of the ".dbinfo" command.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
26973
26974
26975
26976
26977
26978
26979
26980
26981
26982
26983
26984
26985
26986
26987
26988
26989
26990

26991
26992
26993
26994
26995
26996
26997
  if( rc ) goto dbtotxt_error;
  rc = 0;
  if( sqlite3_step(pStmt)!=SQLITE_ROW ) goto dbtotxt_error;
  nPage = sqlite3_column_int64(pStmt, 0);
  sqlite3_finalize(pStmt);
  pStmt = 0;
  if( nPage<1 ) goto dbtotxt_error;
  rc = sqlite3_prepare_v2(p->db, "PRAGMA databases", -1, &pStmt, 0);
  if( rc ) goto dbtotxt_error;
  if( sqlite3_step(pStmt)!=SQLITE_ROW ){
    zTail = "unk.db";
  }else{
    const char *zFilename = (const char*)sqlite3_column_text(pStmt, 2);
    if( zFilename==0 || zFilename[0]==0 ) zFilename = "unk.db";
    zTail = strrchr(zFilename, '/');
#if defined(_WIN32)
    if( zTail==0 ) zTail = strrchr(zFilename, '\\');
#endif

  }
  zName = strdup(zTail);
  shell_check_oom(zName);
  sqlite3_fprintf(p->out, "| size %lld pagesize %d filename %s\n",
                  nPage*pgSz, pgSz, zName);
  sqlite3_finalize(pStmt);
  pStmt = 0;







|










>







27046
27047
27048
27049
27050
27051
27052
27053
27054
27055
27056
27057
27058
27059
27060
27061
27062
27063
27064
27065
27066
27067
27068
27069
27070
27071
  if( rc ) goto dbtotxt_error;
  rc = 0;
  if( sqlite3_step(pStmt)!=SQLITE_ROW ) goto dbtotxt_error;
  nPage = sqlite3_column_int64(pStmt, 0);
  sqlite3_finalize(pStmt);
  pStmt = 0;
  if( nPage<1 ) goto dbtotxt_error;
  rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
  if( rc ) goto dbtotxt_error;
  if( sqlite3_step(pStmt)!=SQLITE_ROW ){
    zTail = "unk.db";
  }else{
    const char *zFilename = (const char*)sqlite3_column_text(pStmt, 2);
    if( zFilename==0 || zFilename[0]==0 ) zFilename = "unk.db";
    zTail = strrchr(zFilename, '/');
#if defined(_WIN32)
    if( zTail==0 ) zTail = strrchr(zFilename, '\\');
#endif
    if( zTail && zTail[1]!=0 ) zTail++;
  }
  zName = strdup(zTail);
  shell_check_oom(zName);
  sqlite3_fprintf(p->out, "| size %lld pagesize %d filename %s\n",
                  nPage*pgSz, pgSz, zName);
  sqlite3_finalize(pStmt);
  pStmt = 0;
29844
29845
29846
29847
29848
29849
29850
29851
29852
29853
29854
29855
29856
29857
29858
29859
29860
29861
29862
29863
    char *zSql;
    char *zCollist = 0;
    sqlite3_stmt *pStmt;
    int tnum = 0;
    int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
    int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
    int i;
    if( !ShellHasFlag(p,SHFLG_TestingMode) ){
      sqlite3_fprintf(stderr,".%s unavailable without --unsafe-testing\n",
            "imposter");
      rc = 1;
      goto meta_command_exit;
    }
    if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
      eputz("Usage: .imposter INDEX IMPOSTER\n"
            "       .imposter off\n");
      /* Also allowed, but not documented:
      **
      **    .imposter TABLE IMPOSTER
      **







<
<
<
<
<
<







29918
29919
29920
29921
29922
29923
29924






29925
29926
29927
29928
29929
29930
29931
    char *zSql;
    char *zCollist = 0;
    sqlite3_stmt *pStmt;
    int tnum = 0;
    int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
    int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
    int i;






    if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
      eputz("Usage: .imposter INDEX IMPOSTER\n"
            "       .imposter off\n");
      /* Also allowed, but not documented:
      **
      **    .imposter TABLE IMPOSTER
      **
29921
29922
29923
29924
29925
29926
29927
29928
29929
29930
29931
29932
29933
29934
29935
29936
29937
29938
29939
29940
29941
29942
29943
29944
29945
29946
      goto meta_command_exit;
    }
    if( lenPK==0 ) lenPK = 100000;
    zSql = sqlite3_mprintf(
          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
          azArg[2], zCollist, lenPK, zCollist);
    sqlite3_free(zCollist);
    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
      if( rc ){
        sqlite3_fprintf(stderr,
              "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
      }else{
        sqlite3_fprintf(stdout, "%s;\n", zSql);
        sqlite3_fprintf(stdout,
              "WARNING: writing to an imposter table will corrupt"
              " the \"%s\" %s!\n", azArg[1], isWO ? "table" : "index");
      }
    }else{
      sqlite3_fprintf(stderr,"SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
      rc = 1;
    }
    sqlite3_free(zSql);
  }else







|








<
<
<







29989
29990
29991
29992
29993
29994
29995
29996
29997
29998
29999
30000
30001
30002
30003
30004



30005
30006
30007
30008
30009
30010
30011
      goto meta_command_exit;
    }
    if( lenPK==0 ) lenPK = 100000;
    zSql = sqlite3_mprintf(
          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
          azArg[2], zCollist, lenPK, zCollist);
    sqlite3_free(zCollist);
    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 2, tnum);
    if( rc==SQLITE_OK ){
      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
      if( rc ){
        sqlite3_fprintf(stderr,
              "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
      }else{
        sqlite3_fprintf(stdout, "%s;\n", zSql);



      }
    }else{
      sqlite3_fprintf(stderr,"SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
      rc = 1;
    }
    sqlite3_free(zSql);
  }else
31822
31823
31824
31825
31826
31827
31828
31829
31830
31831
31832
31833
31834
31835
31836
            { 0x00000008, 1, "FactorOutConst" },
            { 0x00000010, 1, "DistinctOpt" },
            { 0x00000020, 1, "CoverIdxScan" },
            { 0x00000040, 1, "OrderByIdxJoin" },
            { 0x00000080, 1, "Transitive" },
            { 0x00000100, 1, "OmitNoopJoin" },
            { 0x00000200, 1, "CountOfView" },
            { 0x00000400, 1, "CurosrHints" },
            { 0x00000800, 1, "Stat4" },
            { 0x00001000, 1, "PushDown" },
            { 0x00002000, 1, "SimplifyJoin" },
            { 0x00004000, 1, "SkipScan" },
            { 0x00008000, 1, "PropagateConst" },
            { 0x00010000, 1, "MinMaxOpt" },
            { 0x00020000, 1, "SeekScan" },







|







31887
31888
31889
31890
31891
31892
31893
31894
31895
31896
31897
31898
31899
31900
31901
            { 0x00000008, 1, "FactorOutConst" },
            { 0x00000010, 1, "DistinctOpt" },
            { 0x00000020, 1, "CoverIdxScan" },
            { 0x00000040, 1, "OrderByIdxJoin" },
            { 0x00000080, 1, "Transitive" },
            { 0x00000100, 1, "OmitNoopJoin" },
            { 0x00000200, 1, "CountOfView" },
            { 0x00000400, 1, "CursorHints" },
            { 0x00000800, 1, "Stat4" },
            { 0x00001000, 1, "PushDown" },
            { 0x00002000, 1, "SimplifyJoin" },
            { 0x00004000, 1, "SkipScan" },
            { 0x00008000, 1, "PropagateConst" },
            { 0x00010000, 1, "MinMaxOpt" },
            { 0x00020000, 1, "SeekScan" },
33366
33367
33368
33369
33370
33371
33372
33373
33374
33375
33376
33377
33378








33379
33380
33381
33382
33383
33384
33385
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#else
      (void)cmdline_option_value(argc, argv, ++i);
#endif
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      sqlite3_int64 n, sz;
      sz = integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>70000 ) sz = 70000;
      if( sz<0 ) sz = 0;
      n = integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
        n = 0xffffffffffffLL/sz;
      }








      verify_uninitialized();
      sqlite3_config(SQLITE_CONFIG_PAGECACHE,
                    (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
      data.shellFlgs |= SHFLG_Pagecache;
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));







|





>
>
>
>
>
>
>
>







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
      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#else
      (void)cmdline_option_value(argc, argv, ++i);
#endif
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      sqlite3_int64 n, sz;
      sz = integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>65536 ) sz = 65536;
      if( sz<0 ) sz = 0;
      n = integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
        n = 0xffffffffffffLL/sz;
      }
      if( sz>0 && (sz & (sz-1))==0 ){
        /* If SIZE is a power of two, round it up by the PCACHE_HDRSZ */
        int szHdr = 0;
        sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &szHdr);
        sz += szHdr;
        sqlite3_fprintf(stdout, "Page cache size increased to %d to accommodate"
                        " the %d-byte headers\n", (int)sz, szHdr);
      }
      verify_uninitialized();
      sqlite3_config(SQLITE_CONFIG_PAGECACHE,
                    (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
      data.shellFlgs |= SHFLG_Pagecache;
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
Changes to extsrc/sqlite3.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** the text of this file.  Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
** cf7163f82ca380958a79350473b2c5a2cebd with changes in files:
**
**    
*/
#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** the text of this file.  Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
** 821cc0e421bc14a68ebaee507e38a900e0c8 with changes in files:
**
**    
*/
#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
166
167
168
169
170
171
172

173

174
175
176
177
178
179
180
#define SQLITE_OS_OTHER 0
#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
#define SQLITE_OMIT_LOAD_EXTENSION 1
#define SQLITE_ENABLE_LOCKING_STYLE 0
#define HAVE_UTIME 1
#else
/* This is not VxWorks. */

#define OS_VXWORKS 0

#define HAVE_FCHOWN 1
#define HAVE_READLINK 1
#define HAVE_LSTAT 1
#endif /* defined(_WRS_KERNEL) */

/************** End of vxworks.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/







>
|
>







166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#define SQLITE_OS_OTHER 0
#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
#define SQLITE_OMIT_LOAD_EXTENSION 1
#define SQLITE_ENABLE_LOCKING_STYLE 0
#define HAVE_UTIME 1
#else
/* This is not VxWorks. */
#ifndef OS_VXWORKS
#  define OS_VXWORKS 0
#endif
#define HAVE_FCHOWN 1
#define HAVE_READLINK 1
#define HAVE_LSTAT 1
#endif /* defined(_WRS_KERNEL) */

/************** End of vxworks.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
463
464
465
466
467
468
469
470



471
472
473
474
475
476
477
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.51.0"
#define SQLITE_VERSION_NUMBER 3051000
#define SQLITE_SOURCE_ID      "2025-07-30 16:17:14 cf7163f82ca380958a79350473b2c5a2cebda7496d6d575fa2835c362010fea1"




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







|
>
>
>







465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.51.0"
#define SQLITE_VERSION_NUMBER 3051000
#define SQLITE_SOURCE_ID      "2025-09-24 19:10:58 821cc0e421bc14a68ebaee507e38a900e0c84ff6ba7ee95bf796cad387755232"
#define SQLITE_SCM_BRANCH     "trunk"
#define SQLITE_SCM_TAGS       ""
#define SQLITE_SCM_DATETIME   "2025-09-24T19:10:58.215Z"

/*
** 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
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666

2667
2668

2669
2670

2671
2672

2673
2674
2675
2676
2677
2678
2679
** SQLite version 3.35.0, TEMP views are still allowed even if
** this option is off.  So, in other words, this option now only disables
** views in the main database schema or in the schemas of ATTACH-ed
** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There must be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or

** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.

** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled

** following this call.  The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd>

**
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].







|
|
|
|
|
>
|
<
>
|
|
>
|
|
>







2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673

2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
** SQLite version 3.35.0, TEMP views are still allowed even if
** this option is off.  So, in other words, this option now only disables
** views in the main database schema or in the schemas of ATTACH-ed
** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable using the
** [fts3_tokenizer()] function - part of the [FTS3] full-text search engine
** extension - without using bound parameters as the parameters. Doing so
** is disabled by default. There must be two additional arguments. The first
** argument is an integer. If it is passed 0, then using fts3_tokenizer()
** without bound parameters is disabled. If it is passed a positive value,
** then calling fts3_tokenizer without bound parameters is enabled. If it

** is passed a negative value, this setting is not modified - this can be
** used to query for the current setting. The second parameter is a pointer
** to an integer into which is written 0 or 1 to indicate the current value
** of this setting (after it is modified, if applicable).  The second
** parameter may be a NULL pointer, in which case the value of the setting
** is not reported back. Refer to [FTS3] documentation for further details.
** </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
4515
4516
4517
4518
4519
4520
4521




























4522
4523
4524
4525
4526
4527
4528
SQLITE_API int sqlite3_errcode(sqlite3 *db);
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *sqlite3_errstr(int);
SQLITE_API int sqlite3_error_offset(sqlite3 *db);





























/*
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement that
** has been compiled into binary form and is ready to be evaluated.
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
SQLITE_API int sqlite3_errcode(sqlite3 *db);
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *sqlite3_errstr(int);
SQLITE_API int sqlite3_error_offset(sqlite3 *db);

/*
** CAPI3REF: Set Error Codes And Message
** METHOD: sqlite3
**
** Set the error code of the database handle passed as the first argument
** to errcode, and the error message to a copy of nul-terminated string
** zErrMsg. If zErrMsg is passed NULL, then the error message is set to
** the default message associated with the supplied error code.  Subsequent
** calls to [sqlite3_errcode()] and [sqlite3_errmsg()] and similar will
** return the values set by this routine in place of what was previously
** set by SQLite itself.
**
** This function returns SQLITE_OK if the error code and error message are
** successfully set, SQLITE_NOMEM if an OOM occurs, and SQLITE_MISUSE if
** the database handle is NULL or invalid.
**
** The error code and message set by this routine remains in effect until
** they are changed, either by another call to this routine or until they are
** changed to by SQLite itself to reflect the result of some subsquent
** API call.
**
** This function is intended for use by SQLite extensions or wrappers.  The
** idea is that an extension or wrapper can use this routine to set error
** messages and error codes and thus behave more like a core SQLite
** feature from the point of view of an application.
*/
SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zErrMsg);

/*
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement that
** has been compiled into binary form and is ready to be evaluated.
**
6525
6526
6527
6528
6529
6530
6531

6532
6533
6534
6535
6536
6537
6538
** with a [database connection].
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
** to be attached to [database connection] D using name N.  Subsequent
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
** or a NULL pointer if there were no prior calls to
** sqlite3_set_clientdata() with the same values of D and N.
** Names are compared using strcmp() and are thus case sensitive.

**
** If P and X are both non-NULL, then the destructor X is invoked with
** argument P on the first of the following occurrences:
** <ul>
** <li> An out-of-memory error occurs during the call to
**      sqlite3_set_clientdata() which attempts to register pointer P.
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made







>







6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
** with a [database connection].
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
** to be attached to [database connection] D using name N.  Subsequent
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
** or a NULL pointer if there were no prior calls to
** sqlite3_set_clientdata() with the same values of D and N.
** Names are compared using strcmp() and are thus case sensitive.
** It returns 0 on success and SQLITE_NOMEM on allocation failure.
**
** If P and X are both non-NULL, then the destructor X is invoked with
** argument P on the first of the following occurrences:
** <ul>
** <li> An out-of-memory error occurs during the call to
**      sqlite3_set_clientdata() which attempts to register pointer P.
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108
10109
10110
10111
10112
10113



10114

10115
10116
10117









10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150

10151
10152
10153
10154
10155
10156
10157
10158
10159
** is a copy of the third parameter passed to sqlite3_wal_hook() when
** registering the callback. ^The second is a copy of the database handle.
** ^The third parameter is the name of the database that was written to -
** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
** is the number of pages currently in the write-ahead log file,
** including those that were just committed.
**
** The callback function should normally return [SQLITE_OK].  ^If an error
** code is returned, that error will propagate back up through the
** SQLite code base to cause the statement that provoked the callback
** to report an error, though the commit will have still occurred. If the
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
** that does not correspond to any valid SQLite error code, the results
** are undefined.
**
** A single database handle may have at most a single write-ahead log callback
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
** previously registered write-ahead log callback. ^The return value is



** a copy of the third parameter from the previous call, if any, or 0.

** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
** overwrite any prior [sqlite3_wal_hook()] settings.









*/
SQLITE_API void *sqlite3_wal_hook(
  sqlite3*,
  int(*)(void *,sqlite3*,const char*,int),
  void*
);

/*
** CAPI3REF: Configure an auto-checkpoint
** METHOD: sqlite3
**
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
** [sqlite3_wal_hook()] that causes any database on [database connection] D
** to automatically [checkpoint]
** after committing a transaction if there are N or
** more frames in the [write-ahead log] file.  ^Passing zero or
** a negative value as the nFrame parameter disables automatic
** checkpoints entirely.
**
** ^The callback registered by this function replaces any existing callback
** registered using [sqlite3_wal_hook()].  ^Likewise, registering a callback
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
** configured by this function.
**
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.
**
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages.  The use of this interface

** is only necessary if the default setting is found to be suboptimal
** for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);

/*
** CAPI3REF: Checkpoint a database
** METHOD: sqlite3
**







|







|
|
|
>
>
>
|
>
|
|
|
>
>
>
>
>
>
>
>
>
















|















|
>
|
|







10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
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
** is a copy of the third parameter passed to sqlite3_wal_hook() when
** registering the callback. ^The second is a copy of the database handle.
** ^The third parameter is the name of the database that was written to -
** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
** is the number of pages currently in the write-ahead log file,
** including those that were just committed.
**
** ^The callback function should normally return [SQLITE_OK].  ^If an error
** code is returned, that error will propagate back up through the
** SQLite code base to cause the statement that provoked the callback
** to report an error, though the commit will have still occurred. If the
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
** that does not correspond to any valid SQLite error code, the results
** are undefined.
**
** ^A single database handle may have at most a single write-ahead log
** callback registered at one time. ^Calling [sqlite3_wal_hook()]
** replaces the default behavior or previously registered write-ahead
** log callback.
**
** ^The return value is a copy of the third parameter from the
** previous call, if any, or 0.
**
** ^The [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and
** will overwrite any prior [sqlite3_wal_hook()] settings.
**
** ^If a write-ahead log callback is set using this function then
** [sqlite3_wal_checkpoint_v2()] or [PRAGMA wal_checkpoint]
** should be invoked periodically to keep the write-ahead log file
** from growing without bound.
**
** ^Passing a NULL pointer for the callback disables automatic
** checkpointing entirely. To re-enable the default behavior, call
** sqlite3_wal_autocheckpoint(db,1000) or use [PRAGMA wal_checkpoint].
*/
SQLITE_API void *sqlite3_wal_hook(
  sqlite3*,
  int(*)(void *,sqlite3*,const char*,int),
  void*
);

/*
** CAPI3REF: Configure an auto-checkpoint
** METHOD: sqlite3
**
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
** [sqlite3_wal_hook()] that causes any database on [database connection] D
** to automatically [checkpoint]
** after committing a transaction if there are N or
** more frames in the [write-ahead log] file.  ^Passing zero or
** a negative value as the N parameter disables automatic
** checkpoints entirely.
**
** ^The callback registered by this function replaces any existing callback
** registered using [sqlite3_wal_hook()].  ^Likewise, registering a callback
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
** configured by this function.
**
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.
**
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages.
**
** ^The use of this interface is only necessary if the default setting
** is found to be suboptimal for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);

/*
** CAPI3REF: Checkpoint a database
** METHOD: sqlite3
**
10210
10211
10212
10213
10214
10215
10216





10217
10218
10219
10220
10221
10222
10223
**   ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
**   database writer attempts while it is pending, but does not impede readers.
**
** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
**   ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
**   addition that it also truncates the log file to zero bytes just prior
**   to a successful return.





** </dl>
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
** the log file or to -1 if the checkpoint could not run because
** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
** log file (including any that were already checkpointed before the function







>
>
>
>
>







10261
10262
10263
10264
10265
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275
10276
10277
10278
10279
**   ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
**   database writer attempts while it is pending, but does not impede readers.
**
** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
**   ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
**   addition that it also truncates the log file to zero bytes just prior
**   to a successful return.
**
** <dt>SQLITE_CHECKPOINT_NOOP<dd>
**   ^This mode always checkpoints zero frames. The only reason to invoke
**   a NOOP checkpoint is to access the values returned by
**   sqlite3_wal_checkpoint_v2() via output parameters *pnLog and *pnCkpt.
** </dl>
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
** the log file or to -1 if the checkpoint could not run because
** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
** log file (including any that were already checkpointed before the function
10280
10281
10282
10283
10284
10285
10286

10287
10288
10289
10290
10291
10292
10293
** KEYWORDS: {checkpoint mode}
**
** These constants define all valid values for the "checkpoint mode" passed
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/

#define SQLITE_CHECKPOINT_PASSIVE  0  /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL     1  /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3  /* Like RESTART but also truncate WAL */

/*
** CAPI3REF: Virtual Table Interface Configuration







>







10336
10337
10338
10339
10340
10341
10342
10343
10344
10345
10346
10347
10348
10349
10350
** KEYWORDS: {checkpoint mode}
**
** These constants define all valid values for the "checkpoint mode" passed
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/
#define SQLITE_CHECKPOINT_NOOP    -1  /* Do no work at all */
#define SQLITE_CHECKPOINT_PASSIVE  0  /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL     1  /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3  /* Like RESTART but also truncate WAL */

/*
** CAPI3REF: Virtual Table Interface Configuration
11107
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
11120
11121
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
** to avoid a memory leak.
**
** The [sqlite3_snapshot_get()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot **ppSnapshot
);

/*
** CAPI3REF: Start a read transaction on an historical snapshot







|







11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
** to avoid a memory leak.
**
** The [sqlite3_snapshot_get()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API int sqlite3_snapshot_get(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot **ppSnapshot
);

/*
** CAPI3REF: Start a read transaction on an historical snapshot
11156
11157
11158
11159
11160
11161
11162
11163
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183
11184
11185
11186
11187
** after the most recent I/O on the database connection.)^
** (Hint: Run "[PRAGMA application_id]" against a newly opened
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot *pSnapshot
);

/*
** CAPI3REF: Destroy a snapshot
** DESTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
** The application must eventually free every [sqlite3_snapshot] object
** using this routine to avoid a memory leak.
**
** The [sqlite3_snapshot_free()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);

/*
** CAPI3REF: Compare the ages of two snapshot handles.
** METHOD: sqlite3_snapshot
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
** of two valid snapshot handles.







|
















|







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
11244
** after the most recent I/O on the database connection.)^
** (Hint: Run "[PRAGMA application_id]" against a newly opened
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API int sqlite3_snapshot_open(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot *pSnapshot
);

/*
** CAPI3REF: Destroy a snapshot
** DESTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
** The application must eventually free every [sqlite3_snapshot] object
** using this routine to avoid a memory leak.
**
** The [sqlite3_snapshot_free()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*);

/*
** CAPI3REF: Compare the ages of two snapshot handles.
** METHOD: sqlite3_snapshot
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
** of two valid snapshot handles.
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212
11213
11214
** Otherwise, this API returns a negative value if P1 refers to an older
** snapshot than P2, zero if the two handles refer to the same database
** snapshot, and a positive value if P1 is a newer snapshot than P2.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
  sqlite3_snapshot *p1,
  sqlite3_snapshot *p2
);

/*
** CAPI3REF: Recover snapshots from a wal file
** METHOD: sqlite3_snapshot







|







11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
** Otherwise, this API returns a negative value if P1 refers to an older
** snapshot than P2, zero if the two handles refer to the same database
** snapshot, and a positive value if P1 is a newer snapshot than P2.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API int sqlite3_snapshot_cmp(
  sqlite3_snapshot *p1,
  sqlite3_snapshot *p2
);

/*
** CAPI3REF: Recover snapshots from a wal file
** METHOD: sqlite3_snapshot
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);

/*
** CAPI3REF: Serialize a database
**
** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
** memory that is a serialization of the S database on
** [database connection] D.  If S is a NULL pointer, the main database is used.







|







11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);

/*
** CAPI3REF: Serialize a database
**
** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
** memory that is a serialization of the S database on
** [database connection] D.  If S is a NULL pointer, the main database is used.
11302
11303
11304
11305
11306
11307
11308
11309

11310
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
#define SQLITE_SERIALIZE_NOCOPY 0x001   /* Do no memory allocations */

/*
** CAPI3REF: Deserialize a database
**
** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
** [database connection] D to disconnect from database S and then
** reopen S as an in-memory database based on the serialization contained

** in P.  The serialized database P is N bytes in size.  M is the size of
** the buffer P, which might be larger than N.  If M is larger than N, and
** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
** permitted to add content to the in-memory database as long as the total
** size does not exceed M bytes.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
** connection closes.  If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
** SQLite will try to increase the buffer size using sqlite3_realloc64()
** if writes on the database cause it to grow larger than M bytes.
**







|
>
|
|
|
|
|







11359
11360
11361
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
#define SQLITE_SERIALIZE_NOCOPY 0x001   /* Do no memory allocations */

/*
** CAPI3REF: Deserialize a database
**
** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
** [database connection] D to disconnect from database S and then
** reopen S as an in-memory database based on the serialization
** contained in P.  If S is a NULL pointer, the main database is
** used. The serialized database P is N bytes in size.  M is the size
** of the buffer P, which might be larger than N.  If M is larger than
** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
** SQLite is permitted to add content to the in-memory database as
** long as the total size does not exceed M bytes.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
** connection closes.  If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
** SQLite will try to increase the buffer size using sqlite3_realloc64()
** if writes on the database cause it to grow larger than M bytes.
**
12632
12633
12634
12635
12636
12637
12638









12639
12640
12641
12642
12643
12644
12645

/*
** CAPI3REF: Apply A Changeset To A Database
**
** Apply a changeset or patchset to a database. These functions attempt to
** update the "main" database attached to handle db with the changes found in
** the changeset passed via the second and third arguments.









**
** The fourth argument (xFilter) passed to these functions is the "filter
** callback". This may be passed NULL, in which case all changes in the
** changeset are applied to the database. For sqlite3changeset_apply() and
** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once
** for each table affected by at least one change in the changeset. In this
** case the table name is passed as the second argument, and a copy of







>
>
>
>
>
>
>
>
>







12690
12691
12692
12693
12694
12695
12696
12697
12698
12699
12700
12701
12702
12703
12704
12705
12706
12707
12708
12709
12710
12711
12712

/*
** CAPI3REF: Apply A Changeset To A Database
**
** Apply a changeset or patchset to a database. These functions attempt to
** update the "main" database attached to handle db with the changes found in
** the changeset passed via the second and third arguments.
**
** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned. Additionally, starting with version 3.51.0,
** an error code and error message that may be accessed using the
** [sqlite3_errcode()] and [sqlite3_errmsg()] APIs are left in the database
** handle.
**
** The fourth argument (xFilter) passed to these functions is the "filter
** callback". This may be passed NULL, in which case all changes in the
** changeset are applied to the database. For sqlite3changeset_apply() and
** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once
** for each table affected by at least one change in the changeset. In this
** case the table name is passed as the second argument, and a copy of
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783
12784
12785
12786
12787
12788
12789
** </dl>
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
** This can be used to further customize the application's conflict
** resolution strategy.
**
** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
**
** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
** may set (*ppRebase) to point to a "rebase" that may be used with the
** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
** is set to the size of the buffer in bytes. It is the responsibility of the
** caller to eventually free any such buffer using sqlite3_free(). The buffer
** is only allocated and populated if one or more conflicts were encountered







<
<
<
<
<
<







12837
12838
12839
12840
12841
12842
12843






12844
12845
12846
12847
12848
12849
12850
** </dl>
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
** This can be used to further customize the application's conflict
** resolution strategy.
**






** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
** may set (*ppRebase) to point to a "rebase" that may be used with the
** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
** is set to the size of the buffer in bytes. It is the responsibility of the
** caller to eventually free any such buffer using sqlite3_free(). The buffer
** is only allocated and populated if one or more conflicts were encountered
14354
14355
14356
14357
14358
14359
14360
14361
14362
14363
14364
14365
14366
14367
14368
#endif


/*
** Maximum number of pages in one database file.
**
** This is really just the default value for the max_page_count pragma.
** This value can be lowered (or raised) at run-time using that the
** max_page_count macro.
*/
#ifndef SQLITE_MAX_PAGE_COUNT
# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */
#endif

/*







|







14415
14416
14417
14418
14419
14420
14421
14422
14423
14424
14425
14426
14427
14428
14429
#endif


/*
** Maximum number of pages in one database file.
**
** This is really just the default value for the max_page_count pragma.
** This value can be lowered (or raised) at run-time using the
** max_page_count macro.
*/
#ifndef SQLITE_MAX_PAGE_COUNT
# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */
#endif

/*
18125
18126
18127
18128
18129
18130
18131
18132
18133
18134
18135
18136
18137
18138
18139
  int aLimit[SQLITE_N_LIMIT];   /* Limits */
  int nMaxSorterMmap;           /* Maximum size of regions mapped by sorter */
  struct sqlite3InitInfo {      /* Information used during initialization */
    Pgno newTnum;               /* Rootpage of table being initialized */
    u8 iDb;                     /* Which db file is being initialized */
    u8 busy;                    /* TRUE if currently initializing */
    unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
    unsigned imposterTable : 1; /* Building an imposter table */
    unsigned reopenMemdb : 1;   /* ATTACH is really a reopen using MemDB */
    const char **azInit;        /* "type", "name", and "tbl_name" columns */
  } init;
  int nVdbeActive;              /* Number of VDBEs currently running */
  int nVdbeRead;                /* Number of active VDBEs that read or write */
  int nVdbeWrite;               /* Number of active VDBEs that read and write */
  int nVdbeExec;                /* Number of nested calls to VdbeExec() */







|







18186
18187
18188
18189
18190
18191
18192
18193
18194
18195
18196
18197
18198
18199
18200
  int aLimit[SQLITE_N_LIMIT];   /* Limits */
  int nMaxSorterMmap;           /* Maximum size of regions mapped by sorter */
  struct sqlite3InitInfo {      /* Information used during initialization */
    Pgno newTnum;               /* Rootpage of table being initialized */
    u8 iDb;                     /* Which db file is being initialized */
    u8 busy;                    /* TRUE if currently initializing */
    unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
    unsigned imposterTable : 2; /* Building an imposter table */
    unsigned reopenMemdb : 1;   /* ATTACH is really a reopen using MemDB */
    const char **azInit;        /* "type", "name", and "tbl_name" columns */
  } init;
  int nVdbeActive;              /* Number of VDBEs currently running */
  int nVdbeRead;                /* Number of active VDBEs that read or write */
  int nVdbeWrite;               /* Number of active VDBEs that read and write */
  int nVdbeExec;                /* Number of nested calls to VdbeExec() */
18918
18919
18920
18921
18922
18923
18924

18925
18926
18927
18928
18929
18930
18931
#define TF_OOOHidden      0x00000400 /* Out-of-Order hidden columns */
#define TF_HasNotNull     0x00000800 /* Contains NOT NULL constraints */
#define TF_Shadow         0x00001000 /* True for a shadow table */
#define TF_HasStat4       0x00002000 /* STAT4 info available for this table */
#define TF_Ephemeral      0x00004000 /* An ephemeral table */
#define TF_Eponymous      0x00008000 /* An eponymous virtual table */
#define TF_Strict         0x00010000 /* STRICT mode */


/*
** Allowed values for Table.eTabType
*/
#define TABTYP_NORM      0     /* Ordinary table */
#define TABTYP_VTAB      1     /* Virtual table */
#define TABTYP_VIEW      2     /* A view */







>







18979
18980
18981
18982
18983
18984
18985
18986
18987
18988
18989
18990
18991
18992
18993
#define TF_OOOHidden      0x00000400 /* Out-of-Order hidden columns */
#define TF_HasNotNull     0x00000800 /* Contains NOT NULL constraints */
#define TF_Shadow         0x00001000 /* True for a shadow table */
#define TF_HasStat4       0x00002000 /* STAT4 info available for this table */
#define TF_Ephemeral      0x00004000 /* An ephemeral table */
#define TF_Eponymous      0x00008000 /* An eponymous virtual table */
#define TF_Strict         0x00010000 /* STRICT mode */
#define TF_Imposter       0x00020000 /* An imposter table */

/*
** Allowed values for Table.eTabType
*/
#define TABTYP_NORM      0     /* Ordinary table */
#define TABTYP_VTAB      1     /* Virtual table */
#define TABTYP_VIEW      2     /* A view */
20084
20085
20086
20087
20088
20089
20090

20091
20092
20093
20094
20095
20096
20097
#define SF_UFSrcCheck    0x0800000 /* Check pSrc as required by UPDATE...FROM */
#define SF_PushDown      0x1000000 /* Modified by WHERE-clause push-down opt */
#define SF_MultiPart     0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte       0x4000000 /* SELECT statement is a copy of a CTE */
#define SF_OrderByReqd   0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom   0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated   0x20000000 /* True if references the outer context */


/* True if SrcItem X is a subquery that has SF_NestedFrom */
#define IsNestedFrom(X) \
   ((X)->fg.isSubquery && \
    ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)

/*







>







20146
20147
20148
20149
20150
20151
20152
20153
20154
20155
20156
20157
20158
20159
20160
#define SF_UFSrcCheck    0x0800000 /* Check pSrc as required by UPDATE...FROM */
#define SF_PushDown      0x1000000 /* Modified by WHERE-clause push-down opt */
#define SF_MultiPart     0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte       0x4000000 /* SELECT statement is a copy of a CTE */
#define SF_OrderByReqd   0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom   0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated   0x20000000 /* True if references the outer context */
#define SF_OnToWhere    0x40000000 /* One or more ON clauses moved to WHERE */

/* True if SrcItem X is a subquery that has SF_NestedFrom */
#define IsNestedFrom(X) \
   ((X)->fg.isSubquery && \
    ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)

/*
20837
20838
20839
20840
20841
20842
20843

20844
20845
20846
20847
20848
20849
20850
    struct WhereConst *pConst;                /* WHERE clause constants */
    struct RenameCtx *pRename;                /* RENAME COLUMN context */
    struct Table *pTab;                       /* Table of generated column */
    struct CoveringIndexCheck *pCovIdxCk;     /* Check for covering index */
    SrcItem *pSrcItem;                        /* A single FROM clause item */
    DbFixer *pFix;                            /* See sqlite3FixSelect() */
    Mem *aMem;                                /* See sqlite3BtreeCursorHint() */

  } u;
};

/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.







>







20900
20901
20902
20903
20904
20905
20906
20907
20908
20909
20910
20911
20912
20913
20914
    struct WhereConst *pConst;                /* WHERE clause constants */
    struct RenameCtx *pRename;                /* RENAME COLUMN context */
    struct Table *pTab;                       /* Table of generated column */
    struct CoveringIndexCheck *pCovIdxCk;     /* Check for covering index */
    SrcItem *pSrcItem;                        /* A single FROM clause item */
    DbFixer *pFix;                            /* See sqlite3FixSelect() */
    Mem *aMem;                                /* See sqlite3BtreeCursorHint() */
    struct CheckOnCtx *pCheckOnCtx;           /* See selectCheckOnClauses() */
  } u;
};

/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
24207
24208
24209
24210
24211
24212
24213


24214

24215
24216
24217
24218
24219
24220
24221
  i64 iKey1;                      /* First key value passed to hook */
  i64 iKey2;                      /* Second key value passed to hook */
  Mem oldipk;                     /* Memory cell holding "old" IPK value */
  Mem *aNew;                      /* Array of new.* values */
  Table *pTab;                    /* Schema object being updated */
  Index *pPk;                     /* PK index if pTab is WITHOUT ROWID */
  sqlite3_value **apDflt;         /* Array of default values, if required */


  u8 keyinfoSpace[SZ_KEYINFO_0];  /* Space to hold pKeyinfo[0] content */

};

/*
** An instance of this object is used to pass an vector of values into
** OP_VFilter, the xFilter method of a virtual table.  The vector is the
** set of values on the right-hand side of an IN constraint.
**







>
>
|
>







24271
24272
24273
24274
24275
24276
24277
24278
24279
24280
24281
24282
24283
24284
24285
24286
24287
24288
  i64 iKey1;                      /* First key value passed to hook */
  i64 iKey2;                      /* Second key value passed to hook */
  Mem oldipk;                     /* Memory cell holding "old" IPK value */
  Mem *aNew;                      /* Array of new.* values */
  Table *pTab;                    /* Schema object being updated */
  Index *pPk;                     /* PK index if pTab is WITHOUT ROWID */
  sqlite3_value **apDflt;         /* Array of default values, if required */
  union {
    KeyInfo sKey;
    u8 keyinfoSpace[SZ_KEYINFO_0];  /* Space to hold pKeyinfo[0] content */
  } uKey;
};

/*
** An instance of this object is used to pass an vector of values into
** OP_VFilter, the xFilter method of a virtual table.  The vector is the
** set of values on the right-hand side of an IN constraint.
**
24974
24975
24976
24977
24978
24979
24980




24981
24982
24983
24984
24985
24986
24987
  }
  zDate++;
  if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){
    return 1;
  }
  zDate += 5;
  p->tz = sgn*(nMn + nHr*60);




zulu_time:
  while( sqlite3Isspace(*zDate) ){ zDate++; }
  return *zDate!=0;
}

/*
** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.







>
>
>
>







25041
25042
25043
25044
25045
25046
25047
25048
25049
25050
25051
25052
25053
25054
25055
25056
25057
25058
  }
  zDate++;
  if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){
    return 1;
  }
  zDate += 5;
  p->tz = sgn*(nMn + nHr*60);
  if( p->tz==0 ){   /* Forum post 2025-09-17T10:12:14z */
    p->isLocal = 0;
    p->isUtc = 1;
  }
zulu_time:
  while( sqlite3Isspace(*zDate) ){ zDate++; }
  return *zDate!=0;
}

/*
** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
33484
33485
33486
33487
33488
33489
33490
33491
33492
33493




33494
33495
33496
33497
33498
33499
33500
    if( pItem->fg.isSubquery )     sqlite3_str_appendf(&x, " isSubquery");

    sqlite3StrAccumFinish(&x);
    sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
    n = 0;
    if( pItem->fg.isSubquery ) n++;
    if( pItem->fg.isTabFunc ) n++;
    if( pItem->fg.isUsing ) n++;
    if( pItem->fg.isUsing ){
      sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");




    }
    if( pItem->fg.isSubquery ){
      assert( n==1 );
      if( pItem->pSTab ){
        Table *pTab = pItem->pSTab;
        sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
      }







|


>
>
>
>







33555
33556
33557
33558
33559
33560
33561
33562
33563
33564
33565
33566
33567
33568
33569
33570
33571
33572
33573
33574
33575
    if( pItem->fg.isSubquery )     sqlite3_str_appendf(&x, " isSubquery");

    sqlite3StrAccumFinish(&x);
    sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
    n = 0;
    if( pItem->fg.isSubquery ) n++;
    if( pItem->fg.isTabFunc ) n++;
    if( pItem->fg.isUsing || pItem->u3.pOn!=0 ) n++;
    if( pItem->fg.isUsing ){
      sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
    }else if( pItem->u3.pOn!=0 ){
      sqlite3TreeViewItem(pView, "ON", (--n)>0);
      sqlite3TreeViewExpr(pView, pItem->u3.pOn, 0);
      sqlite3TreeViewPop(&pView);
    }
    if( pItem->fg.isSubquery ){
      assert( n==1 );
      if( pItem->pSTab ){
        Table *pTab = pItem->pSTab;
        sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
      }
38129
38130
38131
38132
38133
38134
38135
38136
38137
38138
38139
38140
38141
38142
38143
*/
static int kvstorageWrite(const char*, const char *zKey, const char *zData);
static int kvstorageDelete(const char*, const char *zKey);
static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
#define KVSTORAGE_KEY_SZ  32

/* Expand the key name with an appropriate prefix and put the result
** zKeyOut[].  The zKeyOut[] buffer is assumed to hold at least
** KVSTORAGE_KEY_SZ bytes.
*/
static void kvstorageMakeKey(
  const char *zClass,
  const char *zKeyIn,
  char *zKeyOut
){







|







38204
38205
38206
38207
38208
38209
38210
38211
38212
38213
38214
38215
38216
38217
38218
*/
static int kvstorageWrite(const char*, const char *zKey, const char *zData);
static int kvstorageDelete(const char*, const char *zKey);
static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
#define KVSTORAGE_KEY_SZ  32

/* Expand the key name with an appropriate prefix and put the result
** in zKeyOut[].  The zKeyOut[] buffer is assumed to hold at least
** KVSTORAGE_KEY_SZ bytes.
*/
static void kvstorageMakeKey(
  const char *zClass,
  const char *zKeyIn,
  char *zKeyOut
){
38188
38189
38190
38191
38192
38193
38194
38195
38196
38197


38198
38199
38200
38201
38202
38203
38204
38205
** by zClass and put the text data associated with that key in the first
** nBuf bytes of zBuf[].  The value might be truncated if zBuf is not large
** enough to hold it all.  The value put into zBuf must always be zero
** terminated, even if it gets truncated because nBuf is not large enough.
**
** Return the total number of bytes in the data, without truncation, and
** not counting the final zero terminator.   Return -1 if the key does
** not exist.
**
** If nBuf<=0 then this routine simply returns the size of the data without


** actually reading it.
*/
static int kvstorageRead(
  const char *zClass,
  const char *zKey,
  char *zBuf,
  int nBuf
){







|

|
>
>
|







38263
38264
38265
38266
38267
38268
38269
38270
38271
38272
38273
38274
38275
38276
38277
38278
38279
38280
38281
38282
** by zClass and put the text data associated with that key in the first
** nBuf bytes of zBuf[].  The value might be truncated if zBuf is not large
** enough to hold it all.  The value put into zBuf must always be zero
** terminated, even if it gets truncated because nBuf is not large enough.
**
** Return the total number of bytes in the data, without truncation, and
** not counting the final zero terminator.   Return -1 if the key does
** not exist or its key cannot be read.
**
** If nBuf<=0 then this routine simply returns the size of the data
** without actually reading it.  Similarly, if nBuf==1 then it
** zero-terminates zBuf at zBuf[0] and returns the size of the data
** without reading it.
*/
static int kvstorageRead(
  const char *zClass,
  const char *zKey,
  char *zBuf,
  int nBuf
){
38240
38241
38242
38243
38244
38245
38246
38247
38248
38249
38250
38251
38252
38253
38254
38255
38256
38257
38258
38259
38260
38261
38262
38263
38264
38265
38266
38267
38268
38269
38270
38271
38272
38273
38274
38275
38276
}

/*
** An internal level of indirection which enables us to replace the
** kvvfs i/o methods with JavaScript implementations in WASM builds.
** Maintenance reminder: if this struct changes in any way, the JSON
** rendering of its structure must be updated in
** sqlite3_wasm_enum_json(). There are no binary compatibility
** concerns, so it does not need an iVersion member. This file is
** necessarily always compiled together with sqlite3_wasm_enum_json(),
** and JS code dynamically creates the mapping of members based on
** that JSON description.
*/
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
struct sqlite3_kvvfs_methods {
  int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
  int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
  int (*xDelete)(const char *zClass, const char *zKey);
  const int nKeySize;
};

/*
** This object holds the kvvfs I/O methods which may be swapped out
** for JavaScript-side implementations in WASM builds. In such builds
** it cannot be const, but in native builds it should be so that
** the compiler can hopefully optimize this level of indirection out.
** That said, kvvfs is intended primarily for use in WASM builds.
**
** Note that this is not explicitly flagged as static because the
** amalgamation build will tag it with SQLITE_PRIVATE.
*/
#ifndef SQLITE_WASM
const
#endif
SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
kvstorageRead,
kvstorageWrite,







|
|
<
|
<
















|
|







38317
38318
38319
38320
38321
38322
38323
38324
38325

38326

38327
38328
38329
38330
38331
38332
38333
38334
38335
38336
38337
38338
38339
38340
38341
38342
38343
38344
38345
38346
38347
38348
38349
38350
38351
}

/*
** An internal level of indirection which enables us to replace the
** kvvfs i/o methods with JavaScript implementations in WASM builds.
** Maintenance reminder: if this struct changes in any way, the JSON
** rendering of its structure must be updated in
** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
** compatibility concerns, so it does not need an iVersion

** member.

*/
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
struct sqlite3_kvvfs_methods {
  int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
  int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
  int (*xDelete)(const char *zClass, const char *zKey);
  const int nKeySize;
};

/*
** This object holds the kvvfs I/O methods which may be swapped out
** for JavaScript-side implementations in WASM builds. In such builds
** it cannot be const, but in native builds it should be so that
** the compiler can hopefully optimize this level of indirection out.
** That said, kvvfs is intended primarily for use in WASM builds.
**
** This is not explicitly flagged as static because the amalgamation
** build will tag it with SQLITE_PRIVATE.
*/
#ifndef SQLITE_WASM
const
#endif
SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
kvstorageRead,
kvstorageWrite,
39435
39436
39437
39438
39439
39440
39441

39442
39443

39444
39445
39446
39447
39448
39449
39450
39451
39452
  { "pwrite64",     (sqlite3_syscall_ptr)0,          0  },
#endif
#define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off64_t))\
                    aSyscall[13].pCurrent)

#if defined(HAVE_FCHMOD)
  { "fchmod",       (sqlite3_syscall_ptr)fchmod,          0  },

#else
  { "fchmod",       (sqlite3_syscall_ptr)0,               0  },

#endif
#define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)

#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
#else
  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
#endif
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)







>


>

<







39510
39511
39512
39513
39514
39515
39516
39517
39518
39519
39520
39521

39522
39523
39524
39525
39526
39527
39528
  { "pwrite64",     (sqlite3_syscall_ptr)0,          0  },
#endif
#define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off64_t))\
                    aSyscall[13].pCurrent)

#if defined(HAVE_FCHMOD)
  { "fchmod",       (sqlite3_syscall_ptr)fchmod,          0  },
#define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)
#else
  { "fchmod",       (sqlite3_syscall_ptr)0,               0  },
#define osFchmod(FID,MODE) 0
#endif


#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
#else
  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
#endif
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
39696
39697
39698
39699
39700
39701
39702
39703
39704
39705
39706
39707
39708
39709
39710
39711
39712
#endif
  }
  return fd;
}

/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect the unixInodeInfo and
** vxworksFileId objects used by this file, all of which may be
** shared by multiple threads.
**
** Function unixMutexHeld() is used to assert() that the global mutex
** is held when required. This function is only used as part of assert()
** statements. e.g.
**
**   unixEnterMutex()
**     assert( unixMutexHeld() );







|
<
|







39772
39773
39774
39775
39776
39777
39778
39779

39780
39781
39782
39783
39784
39785
39786
39787
#endif
  }
  return fd;
}

/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect the unixInodeInfo objects used by

** this file, all of which may be shared by multiple threads.
**
** Function unixMutexHeld() is used to assert() that the global mutex
** is held when required. This function is only used as part of assert()
** statements. e.g.
**
**   unixEnterMutex()
**     assert( unixMutexHeld() );
39900
39901
39902
39903
39904
39905
39906

39907
39908
39909
39910
39911
39912
39913

#if OS_VXWORKS
/*
** All unique filenames are held on a linked list headed by this
** variable:
*/
static struct vxworksFileId *vxworksFileList = 0;


/*
** Simplify a filename into its canonical form
** by making the following changes:
**
**  * removing any trailing and duplicate /
**  * convert /./ into just /







>







39975
39976
39977
39978
39979
39980
39981
39982
39983
39984
39985
39986
39987
39988
39989

#if OS_VXWORKS
/*
** All unique filenames are held on a linked list headed by this
** variable:
*/
static struct vxworksFileId *vxworksFileList = 0;
static sqlite3_mutex *vxworksMutex = 0;

/*
** Simplify a filename into its canonical form
** by making the following changes:
**
**  * removing any trailing and duplicate /
**  * convert /./ into just /
39965
39966
39967
39968
39969
39970
39971
39972
39973
39974
39975
39976
39977
39978
39979
39980
39981
39982
39983
39984
39985
39986
39987
39988
39989
39990
39991
39992
39993
39994
39995
39996
39997
39998
39999
40000
40001
40002
40003
40004
40005
40006
40007
40008
40009
40010
40011
40012
40013
40014
40015
  memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
  n = vxworksSimplifyName(pNew->zCanonicalName, n);

  /* Search for an existing entry that matching the canonical name.
  ** If found, increment the reference count and return a pointer to
  ** the existing file ID.
  */
  unixEnterMutex();
  for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
    if( pCandidate->nName==n
     && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
    ){
       sqlite3_free(pNew);
       pCandidate->nRef++;
       unixLeaveMutex();
       return pCandidate;
    }
  }

  /* No match was found.  We will make a new file ID */
  pNew->nRef = 1;
  pNew->nName = n;
  pNew->pNext = vxworksFileList;
  vxworksFileList = pNew;
  unixLeaveMutex();
  return pNew;
}

/*
** Decrement the reference count on a vxworksFileId object.  Free
** the object when the reference count reaches zero.
*/
static void vxworksReleaseFileId(struct vxworksFileId *pId){
  unixEnterMutex();
  assert( pId->nRef>0 );
  pId->nRef--;
  if( pId->nRef==0 ){
    struct vxworksFileId **pp;
    for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
    assert( *pp==pId );
    *pp = pId->pNext;
    sqlite3_free(pId);
  }
  unixLeaveMutex();
}
#endif /* OS_VXWORKS */
/*************** End of Unique File ID Utility Used By VxWorks ****************
******************************************************************************/


/******************************************************************************







|






|









|








|









|







40041
40042
40043
40044
40045
40046
40047
40048
40049
40050
40051
40052
40053
40054
40055
40056
40057
40058
40059
40060
40061
40062
40063
40064
40065
40066
40067
40068
40069
40070
40071
40072
40073
40074
40075
40076
40077
40078
40079
40080
40081
40082
40083
40084
40085
40086
40087
40088
40089
40090
40091
  memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
  n = vxworksSimplifyName(pNew->zCanonicalName, n);

  /* Search for an existing entry that matching the canonical name.
  ** If found, increment the reference count and return a pointer to
  ** the existing file ID.
  */
  sqlite3_mutex_enter(vxworksMutex);
  for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
    if( pCandidate->nName==n
     && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
    ){
       sqlite3_free(pNew);
       pCandidate->nRef++;
       sqlite3_mutex_leave(vxworksMutex);
       return pCandidate;
    }
  }

  /* No match was found.  We will make a new file ID */
  pNew->nRef = 1;
  pNew->nName = n;
  pNew->pNext = vxworksFileList;
  vxworksFileList = pNew;
  sqlite3_mutex_leave(vxworksMutex);
  return pNew;
}

/*
** Decrement the reference count on a vxworksFileId object.  Free
** the object when the reference count reaches zero.
*/
static void vxworksReleaseFileId(struct vxworksFileId *pId){
  sqlite3_mutex_enter(vxworksMutex);
  assert( pId->nRef>0 );
  pId->nRef--;
  if( pId->nRef==0 ){
    struct vxworksFileId **pp;
    for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
    assert( *pp==pId );
    *pp = pId->pNext;
    sqlite3_free(pId);
  }
  sqlite3_mutex_leave(vxworksMutex);
}
#endif /* OS_VXWORKS */
/*************** End of Unique File ID Utility Used By VxWorks ****************
******************************************************************************/


/******************************************************************************
40389
40390
40391
40392
40393
40394
40395




40396
40397
40398
40399
40400
40401
40402
  */
  if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
    do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
    if( rc!=1 ){
      storeLastErrno(pFile, errno);
      return SQLITE_IOERR;
    }




    rc = osFstat(fd, &statbuf);
    if( rc!=0 ){
      storeLastErrno(pFile, errno);
      return SQLITE_IOERR;
    }
  }
#endif







>
>
>
>







40465
40466
40467
40468
40469
40470
40471
40472
40473
40474
40475
40476
40477
40478
40479
40480
40481
40482
  */
  if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
    do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
    if( rc!=1 ){
      storeLastErrno(pFile, errno);
      return SQLITE_IOERR;
    }
    if( fsync(fd) ){
      storeLastErrno(pFile, errno);
      return SQLITE_IOERR_FSYNC;
    }
    rc = osFstat(fd, &statbuf);
    if( rc!=0 ){
      storeLastErrno(pFile, errno);
      return SQLITE_IOERR;
    }
  }
#endif
40558
40559
40560
40561
40562
40563
40564


40565


40566
40567




40568
40569
40570



40571




40572



40573
40574


40575
40576







40577
40578
40579
40580
40581
40582
40583
# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
#else
static int osSetPosixAdvisoryLock(
  int h,                /* The file descriptor on which to take the lock */
  struct flock *pLock,  /* The description of the lock */
  unixFile *pFile       /* Structure holding timeout value */
){


  int tm = pFile->iBusyTimeout;


  int rc = osFcntl(h,F_SETLK,pLock);
  while( rc<0 && tm>0 ){




    /* On systems that support some kind of blocking file lock with a timeout,
    ** make appropriate changes here to invoke that blocking file lock.  On
    ** generic posix, however, there is no such API.  So we simply try the



    ** lock once every millisecond until either the timeout expires, or until




    ** the lock is obtained. */



    unixSleep(0,1000);
    rc = osFcntl(h,F_SETLK,pLock);


    tm--;
  }







  return rc;
}
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */


/*
** Attempt to set a system-lock on the file pFile.  The lock is







>
>
|
>
>
|
<
>
>
>
>
|
<
<
>
>
>
|
>
>
>
>
|
>
>
>
|
|
>
>
|
|
>
>
>
>
>
>
>







40638
40639
40640
40641
40642
40643
40644
40645
40646
40647
40648
40649
40650

40651
40652
40653
40654
40655


40656
40657
40658
40659
40660
40661
40662
40663
40664
40665
40666
40667
40668
40669
40670
40671
40672
40673
40674
40675
40676
40677
40678
40679
40680
40681
40682
40683
40684
40685
40686
40687
# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
#else
static int osSetPosixAdvisoryLock(
  int h,                /* The file descriptor on which to take the lock */
  struct flock *pLock,  /* The description of the lock */
  unixFile *pFile       /* Structure holding timeout value */
){
  int rc = 0;

  if( pFile->iBusyTimeout==0 ){
    /* unixFile->iBusyTimeout is set to 0. In this case, attempt a
    ** non-blocking lock. */
    rc = osFcntl(h,F_SETLK,pLock);

  }else{
    /* unixFile->iBusyTimeout is set to greater than zero. In this case,
    ** attempt a blocking-lock with a unixFile->iBusyTimeout ms timeout.
    **
    ** On systems that support some kind of blocking file lock operation,


    ** this block should be replaced by code to attempt a blocking lock
    ** with a timeout of unixFile->iBusyTimeout ms. The code below is
    ** placeholder code. If SQLITE_TEST is defined, the placeholder code
    ** retries the lock once every 1ms until it succeeds or the timeout
    ** is reached. Or, if SQLITE_TEST is not defined, the placeholder
    ** code attempts a non-blocking lock and sets unixFile->iBusyTimeout
    ** to 0. This causes the caller to return SQLITE_BUSY, instead of
    ** SQLITE_BUSY_TIMEOUT to SQLite - as required by a VFS that does not
    ** support blocking locks.
    */
#ifdef SQLITE_TEST
    int tm = pFile->iBusyTimeout;
    while( tm>0 ){
      rc = osFcntl(h,F_SETLK,pLock);
      if( rc==0 ) break;
      unixSleep(0,1000);
      tm--;
    }
#else
    rc = osFcntl(h,F_SETLK,pLock);
    pFile->iBusyTimeout = 0;
#endif
    /* End of code to replace with real blocking-locks code. */
  }

  return rc;
}
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */


/*
** Attempt to set a system-lock on the file pFile.  The lock is
44890
44891
44892
44893
44894
44895
44896

44897
44898


44899



44900

44901
44902
44903
44904
44905
44906
44907
    unixLeaveMutex();
  }
#endif

  storeLastErrno(pNew, 0);
#if OS_VXWORKS
  if( rc!=SQLITE_OK ){

    if( h>=0 ) robust_close(pNew, h, __LINE__);
    h = -1;


    osUnlink(zFilename);



    pNew->ctrlFlags |= UNIXFILE_DELETE;

  }
#endif
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pId->pMethods = pLockingStyle;
    OpenCounter(+1);







>
|
|
>
>
|
>
>
>
|
>







44994
44995
44996
44997
44998
44999
45000
45001
45002
45003
45004
45005
45006
45007
45008
45009
45010
45011
45012
45013
45014
45015
45016
45017
45018
    unixLeaveMutex();
  }
#endif

  storeLastErrno(pNew, 0);
#if OS_VXWORKS
  if( rc!=SQLITE_OK ){
    if( h>=0 ){
      robust_close(pNew, h, __LINE__);
      h = -1;
    }
    if( pNew->ctrlFlags & UNIXFILE_DELETE ){
      osUnlink(zFilename);
    }
    if( pNew->pId ){
      vxworksReleaseFileId(pNew->pId);
      pNew->pId = 0;
    }
  }
#endif
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pId->pMethods = pLockingStyle;
    OpenCounter(+1);
44937
44938
44939
44940
44941
44942
44943



44944
44945
44946
44947
44948
44949
44950
static const char *unixTempFileDir(void){
  unsigned int i = 0;
  struct stat buf;
  const char *zDir = sqlite3_temp_directory;

  while(1){
    if( zDir!=0



     && osStat(zDir, &buf)==0
     && S_ISDIR(buf.st_mode)
     && osAccess(zDir, 03)==0
    ){
      return zDir;
    }
    if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;







>
>
>







45048
45049
45050
45051
45052
45053
45054
45055
45056
45057
45058
45059
45060
45061
45062
45063
45064
static const char *unixTempFileDir(void){
  unsigned int i = 0;
  struct stat buf;
  const char *zDir = sqlite3_temp_directory;

  while(1){
    if( zDir!=0
#if OS_VXWORKS
     && zDir[0]=='/'
#endif
     && osStat(zDir, &buf)==0
     && S_ISDIR(buf.st_mode)
     && osAccess(zDir, 03)==0
    ){
      return zDir;
    }
    if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
45250
45251
45252
45253
45254
45255
45256






45257
45258
45259
45260
45261
45262
45263

  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_SUPER_JOURNAL
       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
  );







  /* Detect a pid change and reset the PRNG.  There is a race condition
  ** here such that two or more threads all trying to open databases at
  ** the same instant might all reset the PRNG.  But multiple resets
  ** are harmless.
  */
  if( randomnessPid!=osGetpid(0) ){







>
>
>
>
>
>







45364
45365
45366
45367
45368
45369
45370
45371
45372
45373
45374
45375
45376
45377
45378
45379
45380
45381
45382
45383

  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_SUPER_JOURNAL
       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
  );

#if OS_VXWORKS
  /* The file-ID mechanism used in Vxworks requires that all pathnames
  ** provided to unixOpen must be absolute pathnames. */
  if( zPath!=0 && zPath[0]!='/' ){ return SQLITE_CANTOPEN; }
#endif

  /* Detect a pid change and reset the PRNG.  There is a race condition
  ** here such that two or more threads all trying to open databases at
  ** the same instant might all reset the PRNG.  But multiple resets
  ** are harmless.
  */
  if( randomnessPid!=osGetpid(0) ){
45451
45452
45453
45454
45455
45456
45457
45458

45459


45460
45461
45462
45463
45464
45465
45466
        }
      }
      goto open_finished;
    }
  }
#endif

  assert( zPath==0 || zPath[0]=='/'

      || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL


  );
  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);

open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pPreallocatedUnused);
  }







|
>
|
>
>







45571
45572
45573
45574
45575
45576
45577
45578
45579
45580
45581
45582
45583
45584
45585
45586
45587
45588
45589
        }
      }
      goto open_finished;
    }
  }
#endif

  assert( zPath==0
       || zPath[0]=='/'
       || eType==SQLITE_OPEN_SUPER_JOURNAL
       || eType==SQLITE_OPEN_MAIN_JOURNAL
       || eType==SQLITE_OPEN_TEMP_JOURNAL
  );
  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);

open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pPreallocatedUnused);
  }
47181
47182
47183
47184
47185
47186
47187



47188
47189
47190
47191
47192
47193
47194
    sqlite3_vfs_register(&aVfs[i], i==0);
#endif
  }
#ifdef SQLITE_OS_KV_OPTIONAL
  sqlite3KvvfsInit();
#endif
  unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);




#ifndef SQLITE_OMIT_WAL
  /* Validate lock assumptions */
  assert( SQLITE_SHM_NLOCK==8 );  /* Number of available locks */
  assert( UNIX_SHM_BASE==120  );  /* Start of locking area */
  /* Locks:
  **    WRITE       UNIX_SHM_BASE      120







>
>
>







47304
47305
47306
47307
47308
47309
47310
47311
47312
47313
47314
47315
47316
47317
47318
47319
47320
    sqlite3_vfs_register(&aVfs[i], i==0);
#endif
  }
#ifdef SQLITE_OS_KV_OPTIONAL
  sqlite3KvvfsInit();
#endif
  unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#if OS_VXWORKS
  vxworksMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS2);
#endif

#ifndef SQLITE_OMIT_WAL
  /* Validate lock assumptions */
  assert( SQLITE_SHM_NLOCK==8 );  /* Number of available locks */
  assert( UNIX_SHM_BASE==120  );  /* Start of locking area */
  /* Locks:
  **    WRITE       UNIX_SHM_BASE      120
47215
47216
47217
47218
47219
47220
47221



47222
47223
47224
47225
47226
47227
47228
**
** Some operating systems might need to do some cleanup in this routine,
** to release dynamically allocated objects.  But not on unix.
** This routine is a no-op for unix.
*/
SQLITE_API int sqlite3_os_end(void){
  unixBigLock = 0;



  return SQLITE_OK;
}

#endif /* SQLITE_OS_UNIX */

/************** End of os_unix.c *********************************************/
/************** Begin file os_win.c ******************************************/







>
>
>







47341
47342
47343
47344
47345
47346
47347
47348
47349
47350
47351
47352
47353
47354
47355
47356
47357
**
** Some operating systems might need to do some cleanup in this routine,
** to release dynamically allocated objects.  But not on unix.
** This routine is a no-op for unix.
*/
SQLITE_API int sqlite3_os_end(void){
  unixBigLock = 0;
#if OS_VXWORKS
  vxworksMutex = 0;
#endif
  return SQLITE_OK;
}

#endif /* SQLITE_OS_UNIX */

/************** End of os_unix.c *********************************************/
/************** Begin file os_win.c ******************************************/
51347
51348
51349
51350
51351
51352
51353
51354

51355

51356
51357
51358
51359
51360
51361



51362
51363
51364
51365
51366
51367
51368
51369
51370

51371
51372
51373
51374
51375
51376

51377
51378
51379
51380
51381
51382
51383
51384
51385
51386
51387
51388

51389
51390
51391
51392
51393
51394
51395
51396
** Object used to represent a single file opened and mmapped to provide
** shared memory.  When multiple threads all reference the same
** log-summary, each thread has its own winFile object, but they all
** point to a single instance of this object.  In other words, each
** log-summary is opened only once per process.
**
** winShmMutexHeld() must be true when creating or destroying
** this object or while reading or writing the following fields:

**

**      nRef
**      pNext
**
** The following fields are read-only after the object is created:
**
**      zFilename



**
** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
** winShmMutexHeld() is true when reading or writing any other field
** in this structure.
**
** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate
** the *-shm file if the DMS-locking protocol demands it, and (c) map
** regions of the *-shm file into memory using MapViewOfFile() or
** similar. Other locks are taken by individual clients using the

** winShm.hShm handles.
*/
struct winShmNode {
  sqlite3_mutex *mutex;      /* Mutex to access this object */
  char *zFilename;           /* Name of the file */
  HANDLE hSharedShm;         /* File handle open on zFilename */


  int isUnlocked;            /* DMS lock has not yet been obtained */
  int isReadonly;            /* True if read-only */
  int szRegion;              /* Size of shared-memory regions */
  int nRegion;               /* Size of array apRegion */

  struct ShmRegion {
    HANDLE hMap;             /* File handle from CreateFileMapping */
    void *pMap;
  } *aRegion;
  DWORD lastErrno;           /* The Windows errno from the last I/O error */


  int nRef;                  /* Number of winShm objects pointing to this */
  winShmNode *pNext;         /* Next in list of all winShmNode objects */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
  u8 nextShmId;              /* Next available winShm.id value */
#endif
};

/*







|
>

>
|
<

|


>
>
>

|



|
|
|
|
>
|





>












>
|







51476
51477
51478
51479
51480
51481
51482
51483
51484
51485
51486
51487

51488
51489
51490
51491
51492
51493
51494
51495
51496
51497
51498
51499
51500
51501
51502
51503
51504
51505
51506
51507
51508
51509
51510
51511
51512
51513
51514
51515
51516
51517
51518
51519
51520
51521
51522
51523
51524
51525
51526
51527
51528
51529
51530
51531
51532
** Object used to represent a single file opened and mmapped to provide
** shared memory.  When multiple threads all reference the same
** log-summary, each thread has its own winFile object, but they all
** point to a single instance of this object.  In other words, each
** log-summary is opened only once per process.
**
** winShmMutexHeld() must be true when creating or destroying
** this object, or while editing the global linked list that starts
** at winShmNodeList.
**
** When reading or writing the linked list starting at winShmNode.pWinShmList,
** pShmNode->mutex must be held.

**
** The following fields are constant after the object is created:
**
**      zFilename
**      hSharedShm
**      mutex
**      bUseSharedLockHandle
**
** Either winShmNode.mutex must be held or winShmNode.pWinShmList==0 and
** winShmMutexHeld() is true when reading or writing any other field
** in this structure.
**
** File-handle hSharedShm is always used to (a) take the DMS lock, (b)
** truncate the *-shm file if the DMS-locking protocol demands it, and
** (c) map regions of the *-shm file into memory using MapViewOfFile()
** or similar. If bUseSharedLockHandle is true, then other locks are also
** taken on hSharedShm. Or, if bUseSharedLockHandle is false, then other
** locks are taken using each connection's winShm.hShm handles.
*/
struct winShmNode {
  sqlite3_mutex *mutex;      /* Mutex to access this object */
  char *zFilename;           /* Name of the file */
  HANDLE hSharedShm;         /* File handle open on zFilename */
  int bUseSharedLockHandle;  /* True to use hSharedShm for everything */

  int isUnlocked;            /* DMS lock has not yet been obtained */
  int isReadonly;            /* True if read-only */
  int szRegion;              /* Size of shared-memory regions */
  int nRegion;               /* Size of array apRegion */

  struct ShmRegion {
    HANDLE hMap;             /* File handle from CreateFileMapping */
    void *pMap;
  } *aRegion;
  DWORD lastErrno;           /* The Windows errno from the last I/O error */

  winShm *pWinShmList;       /* List of winShm objects with ptrs to this */

  winShmNode *pNext;         /* Next in list of all winShmNode objects */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
  u8 nextShmId;              /* Next available winShm.id value */
#endif
};

/*
51410
51411
51412
51413
51414
51415
51416

51417
51418
51419
51420
51421
51422
51423
51424
51425
51426
51427
51428
51429
51430
51431
51432
51433
51434
51435
51436
51437
51438
51439
51440
51441
51442
51443
51444
51445
51446
51447
51448
51449
51450
  u16 sharedMask;            /* Mask of shared locks held */
  u16 exclMask;              /* Mask of exclusive locks held */
  HANDLE hShm;               /* File-handle on *-shm file. For locking. */
  int bReadonly;             /* True if hShm is opened read-only */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
  u8 id;                     /* Id of this connection with its winShmNode */
#endif

};

/*
** Constants used for locking
*/
#define WIN_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
#define WIN_SHM_DMS    (WIN_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */

/* Forward references to VFS methods */
static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
static int winDelete(sqlite3_vfs *,const char*,int);

/*
** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
*/
static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
  winShmNode **pp;
  winShmNode *p;
  assert( winShmMutexHeld() );
  OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
           osGetCurrentProcessId(), deleteFlag));
  pp = &winShmNodeList;
  while( (p = *pp)!=0 ){
    if( p->nRef==0 ){
      int i;
      if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
      for(i=0; i<p->nRegion; i++){
        BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
        OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
        UNUSED_VARIABLE_VALUE(bRc);







>













|












|







51546
51547
51548
51549
51550
51551
51552
51553
51554
51555
51556
51557
51558
51559
51560
51561
51562
51563
51564
51565
51566
51567
51568
51569
51570
51571
51572
51573
51574
51575
51576
51577
51578
51579
51580
51581
51582
51583
51584
51585
51586
51587
  u16 sharedMask;            /* Mask of shared locks held */
  u16 exclMask;              /* Mask of exclusive locks held */
  HANDLE hShm;               /* File-handle on *-shm file. For locking. */
  int bReadonly;             /* True if hShm is opened read-only */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
  u8 id;                     /* Id of this connection with its winShmNode */
#endif
  winShm *pWinShmNext;       /* Next winShm object on same winShmNode */
};

/*
** Constants used for locking
*/
#define WIN_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
#define WIN_SHM_DMS    (WIN_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */

/* Forward references to VFS methods */
static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
static int winDelete(sqlite3_vfs *,const char*,int);

/*
** Purge the winShmNodeList list of all entries with winShmNode.pWinShmList==0.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
*/
static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
  winShmNode **pp;
  winShmNode *p;
  assert( winShmMutexHeld() );
  OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
           osGetCurrentProcessId(), deleteFlag));
  pp = &winShmNodeList;
  while( (p = *pp)!=0 ){
    if( p->pWinShmList==0 ){
      int i;
      if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
      for(i=0; i<p->nRegion; i++){
        BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
        OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
                 osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
        UNUSED_VARIABLE_VALUE(bRc);
51600
51601
51602
51603
51604
51605
51606






















































51607
51608
51609
51610
51611
51612
51613
 winopenfile_out:
  sqlite3_free(zConverted);
  *pbReadonly = bReadonly;
  *ph = h;
  return rc;
}
























































/*
** Open the shared-memory area associated with database file pDbFd.
*/
static int winOpenSharedMemory(winFile *pDbFd){
  struct winShm *p;                  /* The connection to be opened */
  winShmNode *pShmNode = 0;          /* The underlying mmapped file */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







51737
51738
51739
51740
51741
51742
51743
51744
51745
51746
51747
51748
51749
51750
51751
51752
51753
51754
51755
51756
51757
51758
51759
51760
51761
51762
51763
51764
51765
51766
51767
51768
51769
51770
51771
51772
51773
51774
51775
51776
51777
51778
51779
51780
51781
51782
51783
51784
51785
51786
51787
51788
51789
51790
51791
51792
51793
51794
51795
51796
51797
51798
51799
51800
51801
51802
51803
51804
 winopenfile_out:
  sqlite3_free(zConverted);
  *pbReadonly = bReadonly;
  *ph = h;
  return rc;
}

/*
** Close pDbFd's connection to shared-memory.  Delete the underlying
** *-shm file if deleteFlag is true.
*/
static int winCloseSharedMemory(winFile *pDbFd, int deleteFlag){
  winShm *p;            /* The connection to be closed */
  winShm **pp;          /* Iterator for pShmNode->pWinShmList */
  winShmNode *pShmNode; /* The underlying shared-memory file */

  p = pDbFd->pShm;
  if( p==0 ) return SQLITE_OK;
  if( p->hShm!=INVALID_HANDLE_VALUE ){
    osCloseHandle(p->hShm);
  }

  winShmEnterMutex();
  pShmNode = p->pShmNode;

  /* Remove this connection from the winShmNode.pWinShmList list */
  sqlite3_mutex_enter(pShmNode->mutex);
  for(pp=&pShmNode->pWinShmList; *pp!=p; pp=&(*pp)->pWinShmNext){}
  *pp = p->pWinShmNext;
  sqlite3_mutex_leave(pShmNode->mutex);

  winShmPurge(pDbFd->pVfs, deleteFlag);
  winShmLeaveMutex();

  /* Free the connection p */
  sqlite3_free(p);
  pDbFd->pShm = 0;
  return SQLITE_OK;
}

/*
** testfixture builds may set this global variable to true via a
** Tcl interface. This forces the VFS to use the locking normally
** only used for UNC paths for all files.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_win_test_unc_locking = 0;
#else
# define sqlite3_win_test_unc_locking 0
#endif

/*
** Return true if the string passed as the only argument is likely
** to be a UNC path. In other words, if it starts with "\\".
*/
static int winIsUNCPath(const char *zFile){
  if( zFile[0]=='\\' && zFile[1]=='\\' ){
    return 1;
  }
  return sqlite3_win_test_unc_locking;
}

/*
** Open the shared-memory area associated with database file pDbFd.
*/
static int winOpenSharedMemory(winFile *pDbFd){
  struct winShm *p;                  /* The connection to be opened */
  winShmNode *pShmNode = 0;          /* The underlying mmapped file */
51626
51627
51628
51629
51630
51631
51632

51633
51634
51635
51636
51637
51638
51639
51640
51641
51642
51643
51644
51645
51646
51647
51648
51649
51650
51651
51652
51653
51654
51655
51656
51657
51658
51659
51660
51661
51662
51663
51664
51665
51666
51667
51668
51669
  if( pNew==0 ){
    sqlite3_free(p);
    return SQLITE_IOERR_NOMEM_BKPT;
  }
  pNew->zFilename = (char*)&pNew[1];
  pNew->hSharedShm = INVALID_HANDLE_VALUE;
  pNew->isUnlocked = 1;

  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);

  /* Open a file-handle on the *-shm file for this connection. This file-handle
  ** is only used for locking. The mapping of the *-shm file is created using
  ** the shared file handle in winShmNode.hSharedShm.  */
  p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0);
  rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm);

  /* Look to see if there is an existing winShmNode that can be used.
  ** If no matching winShmNode currently exists, then create a new one.  */
  winShmEnterMutex();
  for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
    /* TBD need to come up with better match here.  Perhaps
    ** use FILE_ID_BOTH_DIR_INFO Structure.  */
    if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
  }
  if( pShmNode==0 ){
    pShmNode = pNew;

    /* Allocate a mutex for this winShmNode object, if one is required. */
    if( sqlite3GlobalConfig.bCoreMutex ){
      pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
      if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT;
    }

    /* Open a file-handle to use for mappings, and for the DMS lock. */
    if( rc==SQLITE_OK ){
      HANDLE h = INVALID_HANDLE_VALUE;
      pShmNode->isReadonly = p->bReadonly;
      rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h);
      pShmNode->hSharedShm = h;
    }

    /* If successful, link the new winShmNode into the global list. If an
    ** error occurred, free the object. */
    if( rc==SQLITE_OK ){







>



<
<
<
<
<
<




















|







51817
51818
51819
51820
51821
51822
51823
51824
51825
51826
51827






51828
51829
51830
51831
51832
51833
51834
51835
51836
51837
51838
51839
51840
51841
51842
51843
51844
51845
51846
51847
51848
51849
51850
51851
51852
51853
51854
51855
  if( pNew==0 ){
    sqlite3_free(p);
    return SQLITE_IOERR_NOMEM_BKPT;
  }
  pNew->zFilename = (char*)&pNew[1];
  pNew->hSharedShm = INVALID_HANDLE_VALUE;
  pNew->isUnlocked = 1;
  pNew->bUseSharedLockHandle = winIsUNCPath(pDbFd->zPath);
  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
  sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);







  /* Look to see if there is an existing winShmNode that can be used.
  ** If no matching winShmNode currently exists, then create a new one.  */
  winShmEnterMutex();
  for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
    /* TBD need to come up with better match here.  Perhaps
    ** use FILE_ID_BOTH_DIR_INFO Structure.  */
    if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
  }
  if( pShmNode==0 ){
    pShmNode = pNew;

    /* Allocate a mutex for this winShmNode object, if one is required. */
    if( sqlite3GlobalConfig.bCoreMutex ){
      pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
      if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT;
    }

    /* Open a file-handle to use for mappings, and for the DMS lock. */
    if( rc==SQLITE_OK ){
      HANDLE h = INVALID_HANDLE_VALUE;
      pShmNode->isReadonly = sqlite3_uri_boolean(pDbFd->zPath,"readonly_shm",0);
      rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h);
      pShmNode->hSharedShm = h;
    }

    /* If successful, link the new winShmNode into the global list. If an
    ** error occurred, free the object. */
    if( rc==SQLITE_OK ){
51677
51678
51679
51680
51681
51682
51683

51684

51685
51686
51687
51688
51689

51690
51691
51692
51693
51694
51695
51696
51697













51698
51699
51700
51701
51702
51703
51704
51705
51706
51707
51708
51709
51710
51711
51712
51713
51714
51715
51716
51717
51718
51719
51720
51721
51722
51723
51724
51725
51726
51727
51728
51729
51730
51731
51732
51733
51734
51735
51736
51737
51738
51739
51740
51741
51742
      }
    }
  }

  /* If no error has occurred, link the winShm object to the winShmNode and
  ** the winShm to pDbFd.  */
  if( rc==SQLITE_OK ){

    p->pShmNode = pShmNode;

    pShmNode->nRef++;
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
    p->id = pShmNode->nextShmId++;
#endif
    pDbFd->pShm = p;

  }else if( p ){
    winHandleClose(p->hShm);
    sqlite3_free(p);
  }

  assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 );
  winShmLeaveMutex();
  sqlite3_free(pNew);













  return rc;
}

/*
** Close a connection to shared-memory.  Delete the underlying
** storage if deleteFlag is true.
*/
static int winShmUnmap(
  sqlite3_file *fd,          /* Database holding shared memory */
  int deleteFlag             /* Delete after closing if true */
){
  winFile *pDbFd;       /* Database holding shared-memory */
  winShm *p;            /* The connection to be closed */
  winShmNode *pShmNode; /* The underlying shared-memory file */

  pDbFd = (winFile*)fd;
  p = pDbFd->pShm;
  if( p==0 ) return SQLITE_OK;
  if( p->hShm!=INVALID_HANDLE_VALUE ){
    osCloseHandle(p->hShm);
  }

  pShmNode = p->pShmNode;
  winShmEnterMutex();

  /* If pShmNode->nRef has reached 0, then close the underlying
  ** shared-memory file, too. */
  assert( pShmNode->nRef>0 );
  pShmNode->nRef--;
  if( pShmNode->nRef==0 ){
    winShmPurge(pDbFd->pVfs, deleteFlag);
  }
  winShmLeaveMutex();

  /* Free the connection p */
  sqlite3_free(p);
  pDbFd->pShm = 0;
  return SQLITE_OK;
}

/*
** Change the lock state for a shared-memory segment.
*/
static int winShmLock(
  sqlite3_file *fd,          /* Database file holding the shared memory */







>

>
|




>

<






>
>
>
>
>
>
>
>
>
>
>
>
>











<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







51863
51864
51865
51866
51867
51868
51869
51870
51871
51872
51873
51874
51875
51876
51877
51878
51879

51880
51881
51882
51883
51884
51885
51886
51887
51888
51889
51890
51891
51892
51893
51894
51895
51896
51897
51898
51899
51900
51901
51902
51903
51904
51905
51906
51907
51908
51909



51910























51911
51912
51913
51914
51915
51916
51917
      }
    }
  }

  /* If no error has occurred, link the winShm object to the winShmNode and
  ** the winShm to pDbFd.  */
  if( rc==SQLITE_OK ){
    sqlite3_mutex_enter(pShmNode->mutex);
    p->pShmNode = pShmNode;
    p->pWinShmNext = pShmNode->pWinShmList;
    pShmNode->pWinShmList = p;
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
    p->id = pShmNode->nextShmId++;
#endif
    pDbFd->pShm = p;
    sqlite3_mutex_leave(pShmNode->mutex);
  }else if( p ){

    sqlite3_free(p);
  }

  assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 );
  winShmLeaveMutex();
  sqlite3_free(pNew);

  /* Open a file-handle on the *-shm file for this connection. This file-handle
  ** is only used for locking. The mapping of the *-shm file is created using
  ** the shared file handle in winShmNode.hSharedShm.  */
  if( rc==SQLITE_OK && pShmNode->bUseSharedLockHandle==0 ){
    p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0);
    rc = winHandleOpen(pShmNode->zFilename, &p->bReadonly, &p->hShm);
    if( rc!=SQLITE_OK ){
      assert( p->hShm==INVALID_HANDLE_VALUE );
      winCloseSharedMemory(pDbFd, 0);
    }
  }

  return rc;
}

/*
** Close a connection to shared-memory.  Delete the underlying
** storage if deleteFlag is true.
*/
static int winShmUnmap(
  sqlite3_file *fd,          /* Database holding shared memory */
  int deleteFlag             /* Delete after closing if true */
){



  return winCloseSharedMemory((winFile*)fd, deleteFlag);























}

/*
** Change the lock state for a shared-memory segment.
*/
static int winShmLock(
  sqlite3_file *fd,          /* Database file holding the shared memory */
51797
51798
51799
51800
51801
51802
51803

51804
51805
51806
51807
51808
51809
51810
51811



















51812

51813
51814
51815
51816
51817
51818
51819
51820
51821
























51822

51823
51824
51825
51826
51827
51828
51829
  assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
       || 0==(p->exclMask & mask)
  );
  if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
   || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
   || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
  ){


    if( flags & SQLITE_SHM_UNLOCK ){
      /* Case (a) - unlock.  */

      assert( (p->exclMask & p->sharedMask)==0 );
      assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
      assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );




















      rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n);


      /* If successful, also clear the bits in sharedMask/exclMask */
      if( rc==SQLITE_OK ){
        p->exclMask = (p->exclMask & ~mask);
        p->sharedMask = (p->sharedMask & ~mask);
      }
    }else{
      int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0);
      DWORD nMs = winFileBusyTimeout(pDbFd);
























      rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs);

      if( rc==SQLITE_OK ){
        if( bExcl ){
          p->exclMask = (p->exclMask | mask);
        }else{
          p->sharedMask = (p->sharedMask | mask);
        }
      }







>








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>







51972
51973
51974
51975
51976
51977
51978
51979
51980
51981
51982
51983
51984
51985
51986
51987
51988
51989
51990
51991
51992
51993
51994
51995
51996
51997
51998
51999
52000
52001
52002
52003
52004
52005
52006
52007
52008
52009
52010
52011
52012
52013
52014
52015
52016
52017
52018
52019
52020
52021
52022
52023
52024
52025
52026
52027
52028
52029
52030
52031
52032
52033
52034
52035
52036
52037
52038
52039
52040
52041
52042
52043
52044
52045
52046
52047
52048
52049
52050
  assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
       || 0==(p->exclMask & mask)
  );
  if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
   || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
   || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
  ){
    HANDLE h = p->hShm;

    if( flags & SQLITE_SHM_UNLOCK ){
      /* Case (a) - unlock.  */

      assert( (p->exclMask & p->sharedMask)==0 );
      assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
      assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );

      assert( !(flags & SQLITE_SHM_SHARED) || n==1 );
      if( pShmNode->bUseSharedLockHandle ){
        h = pShmNode->hSharedShm;
        if( flags & SQLITE_SHM_SHARED ){
          winShm *pShm;
          sqlite3_mutex_enter(pShmNode->mutex);
          for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){
            if( pShm!=p && (pShm->sharedMask & mask) ){
              /* Another connection within this process is also holding this
              ** SHARED lock. So do not actually release the OS lock.  */
              h = INVALID_HANDLE_VALUE;
              break;
            }
          }
          sqlite3_mutex_leave(pShmNode->mutex);
        }
      }

      if( h!=INVALID_HANDLE_VALUE ){
        rc = winHandleUnlock(h, ofst+WIN_SHM_BASE, n);
      }

      /* If successful, also clear the bits in sharedMask/exclMask */
      if( rc==SQLITE_OK ){
        p->exclMask = (p->exclMask & ~mask);
        p->sharedMask = (p->sharedMask & ~mask);
      }
    }else{
      int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0);
      DWORD nMs = winFileBusyTimeout(pDbFd);

      if( pShmNode->bUseSharedLockHandle ){
        winShm *pShm;
        h = pShmNode->hSharedShm;
        sqlite3_mutex_enter(pShmNode->mutex);
        for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){
          if( bExcl ){
            if( (pShm->sharedMask|pShm->exclMask) & mask ){
              rc = SQLITE_BUSY;
              h = INVALID_HANDLE_VALUE;
            }
          }else{
            if( pShm->sharedMask & mask ){
              h = INVALID_HANDLE_VALUE;
            }else if( pShm->exclMask & mask ){
              rc = SQLITE_BUSY;
              h = INVALID_HANDLE_VALUE;
            }
          }
        }
        sqlite3_mutex_leave(pShmNode->mutex);
      }

      if( h!=INVALID_HANDLE_VALUE ){
        rc = winHandleLockTimeout(h, ofst+WIN_SHM_BASE, n, bExcl, nMs);
      }
      if( rc==SQLITE_OK ){
        if( bExcl ){
          p->exclMask = (p->exclMask | mask);
        }else{
          p->sharedMask = (p->sharedMask | mask);
        }
      }
61846
61847
61848
61849
61850
61851
61852
61853
61854
61855
61856
61857
61858
61859










61860



61861
61862
61863
61864
61865
61866
61867
** and FULL=3.
*/
SQLITE_PRIVATE void sqlite3PagerSetFlags(
  Pager *pPager,        /* The pager to set safety level for */
  unsigned pgFlags      /* Various flags */
){
  unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
  if( pPager->tempFile ){
    pPager->noSync = 1;
    pPager->fullSync = 0;
    pPager->extraSync = 0;
  }else{
    pPager->noSync =  level==PAGER_SYNCHRONOUS_OFF ?1:0;
    pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0;










    pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0;



  }
  if( pPager->noSync ){
    pPager->syncFlags = 0;
  }else if( pgFlags & PAGER_FULLFSYNC ){
    pPager->syncFlags = SQLITE_SYNC_FULL;
  }else{
    pPager->syncFlags = SQLITE_SYNC_NORMAL;







|




|

>
>
>
>
>
>
>
>
>
>
|
>
>
>







62067
62068
62069
62070
62071
62072
62073
62074
62075
62076
62077
62078
62079
62080
62081
62082
62083
62084
62085
62086
62087
62088
62089
62090
62091
62092
62093
62094
62095
62096
62097
62098
62099
62100
62101
** and FULL=3.
*/
SQLITE_PRIVATE void sqlite3PagerSetFlags(
  Pager *pPager,        /* The pager to set safety level for */
  unsigned pgFlags      /* Various flags */
){
  unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
  if( pPager->tempFile || level==PAGER_SYNCHRONOUS_OFF ){
    pPager->noSync = 1;
    pPager->fullSync = 0;
    pPager->extraSync = 0;
  }else{
    pPager->noSync =  0;
    pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0;

    /* Set Pager.extraSync if "PRAGMA synchronous=EXTRA" is requested, or
    ** if the file-system supports F2FS style atomic writes. If this flag
    ** is set, SQLite syncs the directory to disk immediately after deleting
    ** a journal file in "PRAGMA journal_mode=DELETE" mode.  */
    if( level==PAGER_SYNCHRONOUS_EXTRA
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
     || (sqlite3OsDeviceCharacteristics(pPager->fd) & SQLITE_IOCAP_BATCH_ATOMIC)
#endif
    ){
      pPager->extraSync = 1;
    }else{
      pPager->extraSync = 0;
    }
  }
  if( pPager->noSync ){
    pPager->syncFlags = 0;
  }else if( pgFlags & PAGER_FULLFSYNC ){
    pPager->syncFlags = SQLITE_SYNC_FULL;
  }else{
    pPager->syncFlags = SQLITE_SYNC_NORMAL;
65746
65747
65748
65749
65750
65751
65752
65753
65754
65755
65756
65757
65758
65759
65760
    ** sqlite3_wal_checkpoint() call, but it happens very rarely.
    ** https://sqlite.org/forum/forumpost/fd0f19d229156939
    */
    sqlite3_exec(db, "PRAGMA table_list",0,0,0);
  }
  if( pPager->pWal ){
    rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
        (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
        pPager->pBusyHandlerArg,
        pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
        pnLog, pnCkpt
    );
  }
  return rc;
}







|







65980
65981
65982
65983
65984
65985
65986
65987
65988
65989
65990
65991
65992
65993
65994
    ** sqlite3_wal_checkpoint() call, but it happens very rarely.
    ** https://sqlite.org/forum/forumpost/fd0f19d229156939
    */
    sqlite3_exec(db, "PRAGMA table_list",0,0,0);
  }
  if( pPager->pWal ){
    rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
        (eMode<=SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
        pPager->pBusyHandlerArg,
        pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
        pnLog, pnCkpt
    );
  }
  return rc;
}
70351
70352
70353
70354
70355
70356
70357

70358
70359
70360
70361
70362
70363
70364
70365
70366
70367
70368
70369
70370
70371
70372
70373
70374

70375
70376
70377
70378
70379
70380
70381
70382
70383
70384
70385
70386
70387
70388
70389
70390
70391
70392
70393
70394
70395
70396
70397
70398
70399



70400
70401
70402
70403
70404
70405
70406
70407
70408
70409
70410
70411
70412
70413
70414
70415
70416
70417
70418
70419
70420
70421
70422
70423
70424
70425
70426
70427
70428
70429
70430
  int (*xBusy2)(void*) = xBusy;   /* Busy handler for eMode2 */

  assert( pWal->ckptLock==0 );
  assert( pWal->writeLock==0 );

  /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
  ** in the SQLITE_CHECKPOINT_PASSIVE mode. */

  assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );

  if( pWal->readOnly ) return SQLITE_READONLY;
  WALTRACE(("WAL%p: checkpoint begins\n", pWal));

  /* Enable blocking locks, if possible. */
  sqlite3WalDb(pWal, db);
  if( xBusy2 ) (void)walEnableBlocking(pWal);

  /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
  ** "checkpoint" lock on the database file.
  ** EVIDENCE-OF: R-10421-19736 If any other process is running a
  ** checkpoint operation at the same time, the lock cannot be obtained and
  ** SQLITE_BUSY is returned.
  ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
  ** it will not be invoked in this case.
  */

  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  testcase( rc==SQLITE_BUSY );
  testcase( rc!=SQLITE_OK && xBusy2!=0 );
  if( rc==SQLITE_OK ){
    pWal->ckptLock = 1;

    /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
    ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
    ** file.
    **
    ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
    ** immediately, and a busy-handler is configured, it is invoked and the
    ** writer lock retried until either the busy-handler returns 0 or the
    ** lock is successfully obtained.
    */
    if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
      rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
      if( rc==SQLITE_OK ){
        pWal->writeLock = 1;
      }else if( rc==SQLITE_BUSY ){
        eMode2 = SQLITE_CHECKPOINT_PASSIVE;
        xBusy2 = 0;
        rc = SQLITE_OK;
      }
    }



  }


  /* Read the wal-index header. */
  SEH_TRY {
    if( rc==SQLITE_OK ){
      /* For a passive checkpoint, do not re-enable blocking locks after
      ** reading the wal-index header. A passive checkpoint should not block
      ** or invoke the busy handler. The only lock such a checkpoint may
      ** attempt to obtain is a lock on a read-slot, and it should give up
      ** immediately and do a partial checkpoint if it cannot obtain it. */
      walDisableBlocking(pWal);
      rc = walIndexReadHdr(pWal, &isChanged);
      if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal);
      if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
        sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
      }
    }

    /* Copy data from the log to the database file. */
    if( rc==SQLITE_OK ){
      if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
        rc = SQLITE_CORRUPT_BKPT;
      }else{
        rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf);
      }

      /* If no error occurred, set the output variables. */
      if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
        if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
        SEH_INJECT_FAULT;







>
|
















>
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>













|









|







70585
70586
70587
70588
70589
70590
70591
70592
70593
70594
70595
70596
70597
70598
70599
70600
70601
70602
70603
70604
70605
70606
70607
70608
70609
70610
70611
70612
70613
70614
70615
70616
70617
70618
70619
70620
70621
70622
70623
70624
70625
70626
70627
70628
70629
70630
70631
70632
70633
70634
70635
70636
70637
70638
70639
70640
70641
70642
70643
70644
70645
70646
70647
70648
70649
70650
70651
70652
70653
70654
70655
70656
70657
70658
70659
70660
70661
70662
70663
70664
70665
70666
70667
70668
70669
  int (*xBusy2)(void*) = xBusy;   /* Busy handler for eMode2 */

  assert( pWal->ckptLock==0 );
  assert( pWal->writeLock==0 );

  /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
  ** in the SQLITE_CHECKPOINT_PASSIVE mode. */
  assert( SQLITE_CHECKPOINT_NOOP<SQLITE_CHECKPOINT_PASSIVE );
  assert( eMode>SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );

  if( pWal->readOnly ) return SQLITE_READONLY;
  WALTRACE(("WAL%p: checkpoint begins\n", pWal));

  /* Enable blocking locks, if possible. */
  sqlite3WalDb(pWal, db);
  if( xBusy2 ) (void)walEnableBlocking(pWal);

  /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
  ** "checkpoint" lock on the database file.
  ** EVIDENCE-OF: R-10421-19736 If any other process is running a
  ** checkpoint operation at the same time, the lock cannot be obtained and
  ** SQLITE_BUSY is returned.
  ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
  ** it will not be invoked in this case.
  */
  if( eMode!=SQLITE_CHECKPOINT_NOOP ){
    rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
    testcase( rc==SQLITE_BUSY );
    testcase( rc!=SQLITE_OK && xBusy2!=0 );
    if( rc==SQLITE_OK ){
      pWal->ckptLock = 1;

      /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART
      ** and TRUNCATE modes also obtain the exclusive "writer" lock on the
      ** database file.
      **
      ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
      ** immediately, and a busy-handler is configured, it is invoked and the
      ** writer lock retried until either the busy-handler returns 0 or the
      ** lock is successfully obtained.
      */
      if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
        rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
        if( rc==SQLITE_OK ){
          pWal->writeLock = 1;
        }else if( rc==SQLITE_BUSY ){
          eMode2 = SQLITE_CHECKPOINT_PASSIVE;
          xBusy2 = 0;
          rc = SQLITE_OK;
        }
      }
    }
  }else{
    rc = SQLITE_OK;
  }


  /* Read the wal-index header. */
  SEH_TRY {
    if( rc==SQLITE_OK ){
      /* For a passive checkpoint, do not re-enable blocking locks after
      ** reading the wal-index header. A passive checkpoint should not block
      ** or invoke the busy handler. The only lock such a checkpoint may
      ** attempt to obtain is a lock on a read-slot, and it should give up
      ** immediately and do a partial checkpoint if it cannot obtain it. */
      walDisableBlocking(pWal);
      rc = walIndexReadHdr(pWal, &isChanged);
      if( eMode2>SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal);
      if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
        sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
      }
    }

    /* Copy data from the log to the database file. */
    if( rc==SQLITE_OK ){
      if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
        rc = SQLITE_CORRUPT_BKPT;
      }else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){
        rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf);
      }

      /* If no error occurred, set the output variables. */
      if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
        if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
        SEH_INJECT_FAULT;
91643
91644
91645
91646
91647
91648
91649
91650
91651
91652
91653
91654
91655
91656
91657
       || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1)
  );

  preupdate.v = v;
  preupdate.pCsr = pCsr;
  preupdate.op = op;
  preupdate.iNewReg = iReg;
  preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace;
  preupdate.pKeyinfo->db = db;
  preupdate.pKeyinfo->enc = ENC(db);
  preupdate.pKeyinfo->nKeyField = pTab->nCol;
  preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
  preupdate.iKey1 = iKey1;
  preupdate.iKey2 = iKey2;
  preupdate.pTab = pTab;







|







91882
91883
91884
91885
91886
91887
91888
91889
91890
91891
91892
91893
91894
91895
91896
       || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1)
  );

  preupdate.v = v;
  preupdate.pCsr = pCsr;
  preupdate.op = op;
  preupdate.iNewReg = iReg;
  preupdate.pKeyinfo = &preupdate.uKey.sKey;
  preupdate.pKeyinfo->db = db;
  preupdate.pKeyinfo->enc = ENC(db);
  preupdate.pKeyinfo->nKeyField = pTab->nCol;
  preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
  preupdate.iKey1 = iKey1;
  preupdate.iKey2 = iKey2;
  preupdate.pTab = pTab;
102526
102527
102528
102529
102530
102531
102532

102533
102534
102535
102536
102537
102538
102539
  assert( p->readOnly==0 );
  aRes[0] = 0;
  aRes[1] = aRes[2] = -1;
  assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
       || pOp->p2==SQLITE_CHECKPOINT_FULL
       || pOp->p2==SQLITE_CHECKPOINT_RESTART
       || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE

  );
  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
  if( rc ){
    if( rc!=SQLITE_BUSY ) goto abort_due_to_error;
    rc = SQLITE_OK;
    aRes[0] = 1;
  }







>







102765
102766
102767
102768
102769
102770
102771
102772
102773
102774
102775
102776
102777
102778
102779
  assert( p->readOnly==0 );
  aRes[0] = 0;
  aRes[1] = aRes[2] = -1;
  assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
       || pOp->p2==SQLITE_CHECKPOINT_FULL
       || pOp->p2==SQLITE_CHECKPOINT_RESTART
       || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE
       || pOp->p2==SQLITE_CHECKPOINT_NOOP
  );
  rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
  if( rc ){
    if( rc!=SQLITE_BUSY ) goto abort_due_to_error;
    rc = SQLITE_OK;
    aRes[0] = 1;
  }
110649
110650
110651
110652
110653
110654
110655


110656

110657
110658
110659
110660
110661

110662
110663
110664
110665
110666
110667
110668
110669
110670
  int type,        /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
  Expr *pExpr,     /* Expression to resolve.  May be NULL. */
  ExprList *pList  /* Expression list to resolve.  May be NULL. */
){
  SrcList *pSrc;                  /* Fake SrcList for pParse->pNewTable */
  NameContext sNC;                /* Name context for pParse->pNewTable */
  int rc;


  u8 srcSpace[SZ_SRCLIST_1];     /* Memory space for the fake SrcList */


  assert( type==0 || pTab!=0 );
  assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
          || type==NC_GenCol || pTab==0 );
  memset(&sNC, 0, sizeof(sNC));

  pSrc = (SrcList*)srcSpace;
  memset(pSrc, 0, SZ_SRCLIST_1);
  if( pTab ){
    pSrc->nSrc = 1;
    pSrc->a[0].zName = pTab->zName;
    pSrc->a[0].pSTab = pTab;
    pSrc->a[0].iCursor = -1;
    if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
      /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP







>
>
|
>





>
|
<







110889
110890
110891
110892
110893
110894
110895
110896
110897
110898
110899
110900
110901
110902
110903
110904
110905
110906

110907
110908
110909
110910
110911
110912
110913
  int type,        /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
  Expr *pExpr,     /* Expression to resolve.  May be NULL. */
  ExprList *pList  /* Expression list to resolve.  May be NULL. */
){
  SrcList *pSrc;                  /* Fake SrcList for pParse->pNewTable */
  NameContext sNC;                /* Name context for pParse->pNewTable */
  int rc;
  union {
    SrcList sSrc;
    u8 srcSpace[SZ_SRCLIST_1];     /* Memory space for the fake SrcList */
  } uSrc;

  assert( type==0 || pTab!=0 );
  assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
          || type==NC_GenCol || pTab==0 );
  memset(&sNC, 0, sizeof(sNC));
  memset(&uSrc, 0, sizeof(uSrc));
  pSrc = &uSrc.sSrc;

  if( pTab ){
    pSrc->nSrc = 1;
    pSrc->a[0].zName = pTab->zName;
    pSrc->a[0].pSTab = pTab;
    pSrc->a[0].iCursor = -1;
    if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
      /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
111919
111920
111921
111922
111923
111924
111925





111926
111927
111928
111929
111930
111931
111932
    return;
  }
  if( IsWindowFunc(pExpr) ){
    sqlite3ExprOrderByAggregateError(pParse, pExpr);
    sqlite3ExprListDelete(db, pOrderBy);
    return;
  }






  pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0);
  if( pOB==0 ){
    sqlite3ExprListDelete(db, pOrderBy);
    return;
  }
  pOB->x.pList = pOrderBy;







>
>
>
>
>







112162
112163
112164
112165
112166
112167
112168
112169
112170
112171
112172
112173
112174
112175
112176
112177
112178
112179
112180
    return;
  }
  if( IsWindowFunc(pExpr) ){
    sqlite3ExprOrderByAggregateError(pParse, pExpr);
    sqlite3ExprListDelete(db, pOrderBy);
    return;
  }
  if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
    sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
    sqlite3ExprListDelete(db, pOrderBy);
    return;
  }

  pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0);
  if( pOB==0 ){
    sqlite3ExprListDelete(db, pOrderBy);
    return;
  }
  pOB->x.pList = pOrderBy;
113115
113116
113117
113118
113119
113120
113121
113122
113123
113124
113125
113126
113127
113128
113129
113130
113131
    r2 = 0; /* Silence a false-positive uninit-var warning in MSVC */
    addrIsNull = 0;
  }
  r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pFree1);
  if( addrIsNull==0 ){
    /*
    ** If the right operand contains a subquery and the left operand does not
    ** and the left operand might be NULL, then check the left operand do
    ** an IsNull check on the left operand before computing the right
    ** operand.
    */
    if( ExprHasProperty(pExpr->pRight, EP_Subquery)
     && sqlite3ExprCanBeNull(pExpr->pLeft)
    ){
      addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r1);
      VdbeComment((v, "skip right operand"));
      VdbeCoverage(v);







|
|
<







113363
113364
113365
113366
113367
113368
113369
113370
113371

113372
113373
113374
113375
113376
113377
113378
    r2 = 0; /* Silence a false-positive uninit-var warning in MSVC */
    addrIsNull = 0;
  }
  r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pFree1);
  if( addrIsNull==0 ){
    /*
    ** If the right operand contains a subquery and the left operand does not
    ** and the left operand might be NULL, then do an IsNull check
    ** check on the left operand before computing the right operand.

    */
    if( ExprHasProperty(pExpr->pRight, EP_Subquery)
     && sqlite3ExprCanBeNull(pExpr->pLeft)
    ){
      addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r1);
      VdbeComment((v, "skip right operand"));
      VdbeCoverage(v);
114681
114682
114683
114684
114685
114686
114687
114688
114689
114690
114691
114692
114693
114694
114695
  Expr *pExpr,          /* The IN expression */
  int destIfFalse,      /* Jump here if LHS is not contained in the RHS */
  int destIfNull        /* Jump here if the results are unknown due to NULLs */
){
  int rRhsHasNull = 0;  /* Register that is true if RHS contains NULL values */
  int eType;            /* Type of the RHS */
  int rLhs;             /* Register(s) holding the LHS values */
  int rLhsOrig;         /* LHS values prior to reordering by aiMap[] */
  Vdbe *v;              /* Statement under construction */
  int *aiMap = 0;       /* Map from vector field to index column */
  char *zAff = 0;       /* Affinity string for comparisons */
  int nVector;          /* Size of vectors for this IN operator */
  int iDummy;           /* Dummy parameter to exprCodeVector() */
  Expr *pLeft;          /* The LHS of the IN operator */
  int i;                /* loop counter */







<







114928
114929
114930
114931
114932
114933
114934

114935
114936
114937
114938
114939
114940
114941
  Expr *pExpr,          /* The IN expression */
  int destIfFalse,      /* Jump here if LHS is not contained in the RHS */
  int destIfNull        /* Jump here if the results are unknown due to NULLs */
){
  int rRhsHasNull = 0;  /* Register that is true if RHS contains NULL values */
  int eType;            /* Type of the RHS */
  int rLhs;             /* Register(s) holding the LHS values */

  Vdbe *v;              /* Statement under construction */
  int *aiMap = 0;       /* Map from vector field to index column */
  char *zAff = 0;       /* Affinity string for comparisons */
  int nVector;          /* Size of vectors for this IN operator */
  int iDummy;           /* Dummy parameter to exprCodeVector() */
  Expr *pLeft;          /* The LHS of the IN operator */
  int i;                /* loop counter */
114744
114745
114746
114747
114748
114749
114750
114751
114752
114753
114754
114755
114756
114757
114758
114759
114760
114761
114762
114763
114764
114765
114766
114767
114768
114769
114770
114771
114772
114773
114774
114775
114776
114777

114778
114779
114780
114781
114782
114783
114784
  ** the field order that matches the RHS index.
  **
  ** Avoid factoring the LHS of the IN(...) expression out of the loop,
  ** even if it is constant, as OP_Affinity may be used on the register
  ** by code generated below.  */
  assert( pParse->okConstFactor==okConstFactor );
  pParse->okConstFactor = 0;
  rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
  pParse->okConstFactor = okConstFactor;
  for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
  if( i==nVector ){
    /* LHS fields are not reordered */
    rLhs = rLhsOrig;
  }else{
    /* Need to reorder the LHS fields according to aiMap */
    rLhs = sqlite3GetTempRange(pParse, nVector);
    for(i=0; i<nVector; i++){
      sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0);
    }
  }

  /* If sqlite3FindInIndex() did not find or create an index that is
  ** suitable for evaluating the IN operator, then evaluate using a
  ** sequence of comparisons.
  **
  ** This is step (1) in the in-operator.md optimized algorithm.
  */
  if( eType==IN_INDEX_NOOP ){
    ExprList *pList;
    CollSeq *pColl;
    int labelOk = sqlite3VdbeMakeLabel(pParse);
    int r2, regToFree;
    int regCkNull = 0;
    int ii;

    assert( ExprUseXList(pExpr) );
    pList = pExpr->x.pList;
    pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    if( destIfNull!=destIfFalse ){
      regCkNull = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
    }







|

<
<
<
<
<
<
<
<
<
<
<














>







114990
114991
114992
114993
114994
114995
114996
114997
114998











114999
115000
115001
115002
115003
115004
115005
115006
115007
115008
115009
115010
115011
115012
115013
115014
115015
115016
115017
115018
115019
115020
  ** the field order that matches the RHS index.
  **
  ** Avoid factoring the LHS of the IN(...) expression out of the loop,
  ** even if it is constant, as OP_Affinity may be used on the register
  ** by code generated below.  */
  assert( pParse->okConstFactor==okConstFactor );
  pParse->okConstFactor = 0;
  rLhs = exprCodeVector(pParse, pLeft, &iDummy);
  pParse->okConstFactor = okConstFactor;












  /* If sqlite3FindInIndex() did not find or create an index that is
  ** suitable for evaluating the IN operator, then evaluate using a
  ** sequence of comparisons.
  **
  ** This is step (1) in the in-operator.md optimized algorithm.
  */
  if( eType==IN_INDEX_NOOP ){
    ExprList *pList;
    CollSeq *pColl;
    int labelOk = sqlite3VdbeMakeLabel(pParse);
    int r2, regToFree;
    int regCkNull = 0;
    int ii;
    assert( nVector==1 );
    assert( ExprUseXList(pExpr) );
    pList = pExpr->x.pList;
    pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    if( destIfNull!=destIfFalse ){
      regCkNull = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
    }
114811
114812
114813
114814
114815
114816
114817




















114818
114819
114820
114821
114822
114823
114824
      sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
      sqlite3VdbeGoto(v, destIfFalse);
    }
    sqlite3VdbeResolveLabel(v, labelOk);
    sqlite3ReleaseTempReg(pParse, regCkNull);
    goto sqlite3ExprCodeIN_finished;
  }





















  /* Step 2: Check to see if the LHS contains any NULL columns.  If the
  ** LHS does contain NULLs then the result must be either FALSE or NULL.
  ** We will then skip the binary search of the RHS.
  */
  if( destIfNull==destIfFalse ){
    destStep2 = destIfFalse;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







115047
115048
115049
115050
115051
115052
115053
115054
115055
115056
115057
115058
115059
115060
115061
115062
115063
115064
115065
115066
115067
115068
115069
115070
115071
115072
115073
115074
115075
115076
115077
115078
115079
115080
      sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
      sqlite3VdbeGoto(v, destIfFalse);
    }
    sqlite3VdbeResolveLabel(v, labelOk);
    sqlite3ReleaseTempReg(pParse, regCkNull);
    goto sqlite3ExprCodeIN_finished;
  }

  if( eType!=IN_INDEX_ROWID ){
    /* If this IN operator will use an index, then the order of columns in the
    ** vector might be different from the order in the index.  In that case,
    ** we need to reorder the LHS values to be in index order.  Run Affinity
    ** before reordering the columns, so that the affinity is correct.
    */
    sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
    for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
    if( i!=nVector ){
      /* Need to reorder the LHS fields according to aiMap */
      int rLhsOrig = rLhs;
      rLhs = sqlite3GetTempRange(pParse, nVector);
      for(i=0; i<nVector; i++){
        sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0);
      }
      sqlite3ReleaseTempReg(pParse, rLhsOrig);
    }
  }


  /* Step 2: Check to see if the LHS contains any NULL columns.  If the
  ** LHS does contain NULLs then the result must be either FALSE or NULL.
  ** We will then skip the binary search of the RHS.
  */
  if( destIfNull==destIfFalse ){
    destStep2 = destIfFalse;
114838
114839
114840
114841
114842
114843
114844

114845
114846
114847
114848
114849
114850
114851
114852
114853
114854
114855
114856
  ** of the RHS using the LHS as a probe.  If found, the result is
  ** true.
  */
  if( eType==IN_INDEX_ROWID ){
    /* In this case, the RHS is the ROWID of table b-tree and so we also
    ** know that the RHS is non-NULL.  Hence, we combine steps 3 and 4
    ** into a single opcode. */

    sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs);
    VdbeCoverage(v);
    addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto);  /* Return True */
  }else{
    sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
    if( destIfFalse==destIfNull ){
      /* Combine Step 3 and Step 5 into a single opcode */
      if( ExprHasProperty(pExpr, EP_Subrtn) ){
        const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
        assert( pOp->opcode==OP_Once || pParse->nErr );
        if( pOp->opcode==OP_Once && pOp->p3>0 ){  /* tag-202407032019 */
          assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );







>




<







115094
115095
115096
115097
115098
115099
115100
115101
115102
115103
115104
115105

115106
115107
115108
115109
115110
115111
115112
  ** of the RHS using the LHS as a probe.  If found, the result is
  ** true.
  */
  if( eType==IN_INDEX_ROWID ){
    /* In this case, the RHS is the ROWID of table b-tree and so we also
    ** know that the RHS is non-NULL.  Hence, we combine steps 3 and 4
    ** into a single opcode. */
    assert( nVector==1 );
    sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs);
    VdbeCoverage(v);
    addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto);  /* Return True */
  }else{

    if( destIfFalse==destIfNull ){
      /* Combine Step 3 and Step 5 into a single opcode */
      if( ExprHasProperty(pExpr, EP_Subrtn) ){
        const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
        assert( pOp->opcode==OP_Once || pParse->nErr );
        if( pOp->opcode==OP_Once && pOp->p3>0 ){  /* tag-202407032019 */
          assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
114920
114921
114922
114923
114924
114925
114926
114927
114928
114929
114930
114931
114932
114933
114934
    sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
  }

  /* Jumps here in order to return true. */
  sqlite3VdbeJumpHere(v, addrTruthOp);

sqlite3ExprCodeIN_finished:
  if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs);
  VdbeComment((v, "end IN expr"));
sqlite3ExprCodeIN_oom_error:
  sqlite3DbFree(pParse->db, aiMap);
  sqlite3DbFree(pParse->db, zAff);
}
#endif /* SQLITE_OMIT_SUBQUERY */








<







115176
115177
115178
115179
115180
115181
115182

115183
115184
115185
115186
115187
115188
115189
    sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
  }

  /* Jumps here in order to return true. */
  sqlite3VdbeJumpHere(v, addrTruthOp);

sqlite3ExprCodeIN_finished:

  VdbeComment((v, "end IN expr"));
sqlite3ExprCodeIN_oom_error:
  sqlite3DbFree(pParse->db, aiMap);
  sqlite3DbFree(pParse->db, zAff);
}
#endif /* SQLITE_OMIT_SUBQUERY */

115478
115479
115480
115481
115482
115483
115484








































































115485
115486
115487
115488
115489
115490
115491
      }
      return ret;
    }
  }
  return 0;
}










































































/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".
** Return the register where results are stored.
**
** With this routine, there is no guarantee that results will







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







115733
115734
115735
115736
115737
115738
115739
115740
115741
115742
115743
115744
115745
115746
115747
115748
115749
115750
115751
115752
115753
115754
115755
115756
115757
115758
115759
115760
115761
115762
115763
115764
115765
115766
115767
115768
115769
115770
115771
115772
115773
115774
115775
115776
115777
115778
115779
115780
115781
115782
115783
115784
115785
115786
115787
115788
115789
115790
115791
115792
115793
115794
115795
115796
115797
115798
115799
115800
115801
115802
115803
115804
115805
115806
115807
115808
115809
115810
115811
115812
115813
115814
115815
115816
115817
115818
      }
      return ret;
    }
  }
  return 0;
}

/*
** Generate code that evaluates an AND or OR operator leaving a
** boolean result in a register.  pExpr is the AND/OR expression.
** Store the result in the "target" register.  Use short-circuit
** evaluation to avoid computing both operands, if possible.
**
** The code generated might require the use of a temporary register.
** If it does, then write the number of that temporary register
** into *pTmpReg.  If not, leave *pTmpReg unchanged.
*/
static SQLITE_NOINLINE int exprCodeTargetAndOr(
  Parse *pParse,     /* Parsing context */
  Expr *pExpr,       /* AND or OR expression to be coded */
  int target,        /* Put result in this register, guaranteed */
  int *pTmpReg       /* Write a temporary register here */
){
  int op;            /* The opcode.  TK_AND or TK_OR */
  int skipOp;        /* Opcode for the branch that skips one operand */
  int addrSkip;      /* Branch instruction that skips one of the operands */
  int regSS = 0;     /* Register holding computed operand when other omitted */
  int r1, r2;        /* Registers for left and right operands, respectively */
  Expr *pAlt;        /* Alternative, simplified expression */
  Vdbe *v;           /* statement being coded */

  assert( pExpr!=0 );
  op = pExpr->op;
  assert( op==TK_AND || op==TK_OR );
  assert( TK_AND==OP_And );            testcase( op==TK_AND );
  assert( TK_OR==OP_Or );              testcase( op==TK_OR );
  pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
  if( pAlt!=pExpr ){
    return sqlite3ExprCodeTarget(pParse, pAlt, target);
  }
  assert( pParse->pVdbe!=0 );
  v = pParse->pVdbe;
  skipOp = op==TK_AND ? OP_IfNot : OP_If;
  if( exprEvalRhsFirst(pExpr) ){
    /* Compute the right operand first.  Skip the computation of the left
    ** operand if the right operand fully determines the result */
    r2 = regSS = sqlite3ExprCodeTarget(pParse, pExpr->pRight, target);
    addrSkip = sqlite3VdbeAddOp1(v, skipOp, r2);
    VdbeComment((v, "skip left operand"));
    VdbeCoverage(v);
    r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pTmpReg);
  }else{
    /* Compute the left operand first */
    r1 = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
    if( ExprHasProperty(pExpr->pRight, EP_Subquery) ){
      /* Skip over the computation of the right operand if the right
      ** operand is a subquery and the left operand completely determines
      ** the result */
      regSS = r1;
      addrSkip = sqlite3VdbeAddOp1(v, skipOp, r1);
      VdbeComment((v, "skip right operand"));
      VdbeCoverage(v);
    }else{
      addrSkip = regSS = 0;
    }
    r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pTmpReg);
  }
  sqlite3VdbeAddOp3(v, op, r2, r1, target);
  testcase( (*pTmpReg)==0 );
  if( addrSkip ){
    sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
    sqlite3VdbeJumpHere(v, addrSkip);
    sqlite3VdbeAddOp3(v, OP_Or, regSS, regSS, target);
    VdbeComment((v, "short-circut value"));
  }
  return target;
}



/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".
** Return the register where results are stored.
**
** With this routine, there is no guarantee that results will
115766
115767
115768
115769
115770
115771
115772
115773
115774
115775
115776
115777
115778



115779
115780
115781
115782
115783
115784
115785
115786
115787
115788
115789
115790
115791
115792
115793
115794
115795
115796
115797
115798
            sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
            sqlite3VdbeJumpHere(v, addrIsNull);
            sqlite3VdbeAddOp2(v, OP_Null, 0, inReg);
          }
        }
        testcase( regFree1==0 );
        testcase( regFree2==0 );

      }
      break;
    }
    case TK_AND:
    case TK_OR:



    case TK_PLUS:
    case TK_STAR:
    case TK_MINUS:
    case TK_REM:
    case TK_BITAND:
    case TK_BITOR:
    case TK_SLASH:
    case TK_LSHIFT:
    case TK_RSHIFT:
    case TK_CONCAT: {
      int addrIsNull;
      assert( TK_AND==OP_And );            testcase( op==TK_AND );
      assert( TK_OR==OP_Or );              testcase( op==TK_OR );
      assert( TK_PLUS==OP_Add );           testcase( op==TK_PLUS );
      assert( TK_MINUS==OP_Subtract );     testcase( op==TK_MINUS );
      assert( TK_REM==OP_Remainder );      testcase( op==TK_REM );
      assert( TK_BITAND==OP_BitAnd );      testcase( op==TK_BITAND );
      assert( TK_BITOR==OP_BitOr );        testcase( op==TK_BITOR );
      assert( TK_SLASH==OP_Divide );       testcase( op==TK_SLASH );
      assert( TK_LSHIFT==OP_ShiftLeft );   testcase( op==TK_LSHIFT );







<




|
>
>
>











<
<







116093
116094
116095
116096
116097
116098
116099

116100
116101
116102
116103
116104
116105
116106
116107
116108
116109
116110
116111
116112
116113
116114
116115
116116
116117
116118


116119
116120
116121
116122
116123
116124
116125
            sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
            sqlite3VdbeJumpHere(v, addrIsNull);
            sqlite3VdbeAddOp2(v, OP_Null, 0, inReg);
          }
        }
        testcase( regFree1==0 );
        testcase( regFree2==0 );

      }
      break;
    }
    case TK_AND:
    case TK_OR: {
      inReg = exprCodeTargetAndOr(pParse, pExpr, target, &regFree1);
      break;
    }
    case TK_PLUS:
    case TK_STAR:
    case TK_MINUS:
    case TK_REM:
    case TK_BITAND:
    case TK_BITOR:
    case TK_SLASH:
    case TK_LSHIFT:
    case TK_RSHIFT:
    case TK_CONCAT: {
      int addrIsNull;


      assert( TK_PLUS==OP_Add );           testcase( op==TK_PLUS );
      assert( TK_MINUS==OP_Subtract );     testcase( op==TK_MINUS );
      assert( TK_REM==OP_Remainder );      testcase( op==TK_REM );
      assert( TK_BITAND==OP_BitAnd );      testcase( op==TK_BITAND );
      assert( TK_BITOR==OP_BitOr );        testcase( op==TK_BITOR );
      assert( TK_SLASH==OP_Divide );       testcase( op==TK_SLASH );
      assert( TK_LSHIFT==OP_ShiftLeft );   testcase( op==TK_LSHIFT );
124571
124572
124573
124574
124575
124576
124577
124578
124579
124580
124581
124582
124583
124584
124585
** find the (first) offset of that column in index pIdx.  Or return -1
** if column iCol is not used in index pIdx.
*/
SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
  int i;
  i16 iCol16;
  assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
  assert( pIdx->nColumn<=SQLITE_MAX_COLUMN+1 );
  iCol16 = iCol;
  for(i=0; i<pIdx->nColumn; i++){
    if( iCol16==pIdx->aiColumn[i] ){
      return i;
    }
  }
  return -1;







|







124898
124899
124900
124901
124902
124903
124904
124905
124906
124907
124908
124909
124910
124911
124912
** find the (first) offset of that column in index pIdx.  Or return -1
** if column iCol is not used in index pIdx.
*/
SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
  int i;
  i16 iCol16;
  assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
  assert( pIdx->nColumn<=SQLITE_MAX_COLUMN*2 );
  iCol16 = iCol;
  for(i=0; i<pIdx->nColumn; i++){
    if( iCol16==pIdx->aiColumn[i] ){
      return i;
    }
  }
  return -1;
124868
124869
124870
124871
124872
124873
124874



124875
124876
124877
124878
124879
124880
124881
    }
    sqlite3OpenSchemaTable(pParse, iDb);
    sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
    sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC);
    sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite3VdbeAddOp0(v, OP_Close);



  }

  /* Normal (non-error) return. */
  return;

  /* If an error occurs, we jump here */
begin_table_error:







>
>
>







125195
125196
125197
125198
125199
125200
125201
125202
125203
125204
125205
125206
125207
125208
125209
125210
125211
    }
    sqlite3OpenSchemaTable(pParse, iDb);
    sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
    sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC);
    sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite3VdbeAddOp0(v, OP_Close);
  }else if( db->init.imposterTable ){
    pTable->tabFlags |= TF_Imposter;
    if( db->init.imposterTable>=2 ) pTable->tabFlags |= TF_Readonly;
  }

  /* Normal (non-error) return. */
  return;

  /* If an error occurs, we jump here */
begin_table_error:
129163
129164
129165
129166
129167
129168
129169
129170


129171
129172
129173
129174
129175
129176
129177



129178
129179
129180
129181
129182
129183
129184
      pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
                        sqlite3LocateCollSeq(pParse, zColl);
      pKey->aSortFlags[i] = pIdx->aSortOrder[i];
      assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) );
    }
    if( pParse->nErr ){
      assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
      if( pIdx->bNoQuery==0 ){


        /* Deactivate the index because it contains an unknown collating
        ** sequence.  The only way to reactive the index is to reload the
        ** schema.  Adding the missing collating sequence later does not
        ** reactive the index.  The application had the chance to register
        ** the missing index using the collation-needed callback.  For
        ** simplicity, SQLite will not give the application a second chance.
        */



        pIdx->bNoQuery = 1;
        pParse->rc = SQLITE_ERROR_RETRY;
      }
      sqlite3KeyInfoUnref(pKey);
      pKey = 0;
    }
  }







|
>
>






|
>
>
>







129493
129494
129495
129496
129497
129498
129499
129500
129501
129502
129503
129504
129505
129506
129507
129508
129509
129510
129511
129512
129513
129514
129515
129516
129517
129518
129519
      pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
                        sqlite3LocateCollSeq(pParse, zColl);
      pKey->aSortFlags[i] = pIdx->aSortOrder[i];
      assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) );
    }
    if( pParse->nErr ){
      assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
      if( pIdx->bNoQuery==0
       && sqlite3HashFind(&pIdx->pSchema->idxHash, pIdx->zName)
      ){
        /* Deactivate the index because it contains an unknown collating
        ** sequence.  The only way to reactive the index is to reload the
        ** schema.  Adding the missing collating sequence later does not
        ** reactive the index.  The application had the chance to register
        ** the missing index using the collation-needed callback.  For
        ** simplicity, SQLite will not give the application a second chance.
        **
        ** Except, do not do this if the index is not in the schema hash
        ** table. In this case the index is currently being constructed
        ** by a CREATE INDEX statement, and retrying will not help.  */
        pIdx->bNoQuery = 1;
        pParse->rc = SQLITE_ERROR_RETRY;
      }
      sqlite3KeyInfoUnref(pKey);
      pKey = 0;
    }
  }
139245
139246
139247
139248
139249
139250
139251


139252
139253
139254
139255
139256
139257
139258
  /* Version 3.43.0 and later */
  int (*stmt_explain)(sqlite3_stmt*,int);
  /* Version 3.44.0 and later */
  void *(*get_clientdata)(sqlite3*,const char*);
  int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
  /* Version 3.50.0 and later */
  int (*setlk_timeout)(sqlite3*,int,int);


};

/*
** This is the function signature used for all extension entry points.  It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(







>
>







139580
139581
139582
139583
139584
139585
139586
139587
139588
139589
139590
139591
139592
139593
139594
139595
  /* Version 3.43.0 and later */
  int (*stmt_explain)(sqlite3_stmt*,int);
  /* Version 3.44.0 and later */
  void *(*get_clientdata)(sqlite3*,const char*);
  int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
  /* Version 3.50.0 and later */
  int (*setlk_timeout)(sqlite3*,int,int);
  /* Version 3.51.0 and later */
  int (*set_errmsg)(sqlite3*,int,const char*);
};

/*
** This is the function signature used for all extension entry points.  It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
139580
139581
139582
139583
139584
139585
139586


139587
139588
139589
139590
139591
139592
139593
/* Version 3.43.0 and later */
#define sqlite3_stmt_explain           sqlite3_api->stmt_explain
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata         sqlite3_api->get_clientdata
#define sqlite3_set_clientdata         sqlite3_api->set_clientdata
/* Version 3.50.0 and later */
#define sqlite3_setlk_timeout          sqlite3_api->setlk_timeout


#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */

#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
  /* This case when the file really is being compiled as a loadable
  ** extension */
# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;







>
>







139917
139918
139919
139920
139921
139922
139923
139924
139925
139926
139927
139928
139929
139930
139931
139932
/* Version 3.43.0 and later */
#define sqlite3_stmt_explain           sqlite3_api->stmt_explain
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata         sqlite3_api->get_clientdata
#define sqlite3_set_clientdata         sqlite3_api->set_clientdata
/* Version 3.50.0 and later */
#define sqlite3_setlk_timeout          sqlite3_api->setlk_timeout
/* Version 3.51.0 and later */
#define sqlite3_set_errmsg             sqlite3_api->set_errmsg
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */

#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
  /* This case when the file really is being compiled as a loadable
  ** extension */
# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
140103
140104
140105
140106
140107
140108
140109
140110


140111
140112
140113
140114
140115
140116
140117
  sqlite3_is_interrupted,
  /* Version 3.43.0 and later */
  sqlite3_stmt_explain,
  /* Version 3.44.0 and later */
  sqlite3_get_clientdata,
  sqlite3_set_clientdata,
  /* Version 3.50.0 and later */
  sqlite3_setlk_timeout


};

/* True if x is the directory separator character
*/
#if SQLITE_OS_WIN
# define DirSep(X)  ((X)=='/'||(X)=='\\')
#else







|
>
>







140442
140443
140444
140445
140446
140447
140448
140449
140450
140451
140452
140453
140454
140455
140456
140457
140458
  sqlite3_is_interrupted,
  /* Version 3.43.0 and later */
  sqlite3_stmt_explain,
  /* Version 3.44.0 and later */
  sqlite3_get_clientdata,
  sqlite3_set_clientdata,
  /* Version 3.50.0 and later */
  sqlite3_setlk_timeout,
  /* Version 3.51.0 and later */
  sqlite3_set_errmsg
};

/* True if x is the directory separator character
*/
#if SQLITE_OS_WIN
# define DirSep(X)  ((X)=='/'||(X)=='\\')
#else
141564
141565
141566
141567
141568
141569
141570
















141571
141572
141573
141574
141575
141576
141577
  int addr;
  sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
  addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
  VdbeCoverage(v);
  sqlite3VdbeAddOp0(v, OP_Halt);
  return addr;
}

















/*
** Process a pragma statement.
**
** Pragmas are of this form:
**
**      PRAGMA [schema.]id [= value]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







141905
141906
141907
141908
141909
141910
141911
141912
141913
141914
141915
141916
141917
141918
141919
141920
141921
141922
141923
141924
141925
141926
141927
141928
141929
141930
141931
141932
141933
141934
  int addr;
  sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
  addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
  VdbeCoverage(v);
  sqlite3VdbeAddOp0(v, OP_Halt);
  return addr;
}

/*
** Should table pTab be skipped when doing an integrity_check?
** Return true or false.
**
** If pObjTab is not null, the return true if pTab matches pObjTab.
**
** If pObjTab is null, then return true only if pTab is an imposter table.
*/
static int tableSkipIntegrityCheck(const Table *pTab, const Table *pObjTab){
  if( pObjTab ){
    return pTab!=pObjTab;
  }else{
    return (pTab->tabFlags & TF_Imposter)!=0;
  }
}

/*
** Process a pragma statement.
**
** Pragmas are of this form:
**
**      PRAGMA [schema.]id [= value]
142910
142911
142912
142913
142914
142915
142916
142917
142918
142919
142920
142921
142922
142923
142924
142925
142926
142927
142928
142929
142930
142931
142932
142933
142934
142935
142936
142937
      */
      assert( sqlite3SchemaMutexHeld(db, i, 0) );
      pTbls = &db->aDb[i].pSchema->tblHash;
      for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);  /* Current table */
        Index *pIdx;                      /* An index on pTab */
        int nIdx;                         /* Number of indexes on pTab */
        if( pObjTab && pObjTab!=pTab ) continue;
        if( HasRowid(pTab) ) cnt++;
        for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
      }
      if( cnt==0 ) continue;
      if( pObjTab ) cnt++;
      aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
      if( aRoot==0 ) break;
      cnt = 0;
      if( pObjTab ) aRoot[++cnt] = 0;
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        if( pObjTab && pObjTab!=pTab ) continue;
        if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum;
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
          aRoot[++cnt] = pIdx->tnum;
        }
      }
      aRoot[0] = cnt;








|












|







143267
143268
143269
143270
143271
143272
143273
143274
143275
143276
143277
143278
143279
143280
143281
143282
143283
143284
143285
143286
143287
143288
143289
143290
143291
143292
143293
143294
      */
      assert( sqlite3SchemaMutexHeld(db, i, 0) );
      pTbls = &db->aDb[i].pSchema->tblHash;
      for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);  /* Current table */
        Index *pIdx;                      /* An index on pTab */
        int nIdx;                         /* Number of indexes on pTab */
        if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
        if( HasRowid(pTab) ) cnt++;
        for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
      }
      if( cnt==0 ) continue;
      if( pObjTab ) cnt++;
      aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
      if( aRoot==0 ) break;
      cnt = 0;
      if( pObjTab ) aRoot[++cnt] = 0;
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
        if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum;
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
          aRoot[++cnt] = pIdx->tnum;
        }
      }
      aRoot[0] = cnt;

142954
142955
142956
142957
142958
142959
142960
142961
142962
142963
142964
142965
142966
142967
142968
      /* Check that the indexes all have the right number of rows */
      cnt = pObjTab ? 1 : 0;
      sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        int iTab = 0;
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        if( pObjTab && pObjTab!=pTab ) continue;
        if( HasRowid(pTab) ){
          iTab = cnt++;
        }else{
          iTab = cnt;
          for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){
            if( IsPrimaryKeyIndex(pIdx) ) break;
            iTab++;







|







143311
143312
143313
143314
143315
143316
143317
143318
143319
143320
143321
143322
143323
143324
143325
      /* Check that the indexes all have the right number of rows */
      cnt = pObjTab ? 1 : 0;
      sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        int iTab = 0;
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
        if( HasRowid(pTab) ){
          iTab = cnt++;
        }else{
          iTab = cnt;
          for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){
            if( IsPrimaryKeyIndex(pIdx) ) break;
            iTab++;
142990
142991
142992
142993
142994
142995
142996
142997
142998
142999
143000
143001
143002
143003
143004
        int loopTop;
        int iDataCur, iIdxCur;
        int r1 = -1;
        int bStrict;            /* True for a STRICT table */
        int r2;                 /* Previous key for WITHOUT ROWID tables */
        int mxCol;              /* Maximum non-virtual column number */

        if( pObjTab && pObjTab!=pTab ) continue;
        if( !IsOrdinaryTable(pTab) ) continue;
        if( isQuick || HasRowid(pTab) ){
          pPk = 0;
          r2 = 0;
        }else{
          pPk = sqlite3PrimaryKeyIndex(pTab);
          r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);







|







143347
143348
143349
143350
143351
143352
143353
143354
143355
143356
143357
143358
143359
143360
143361
        int loopTop;
        int iDataCur, iIdxCur;
        int r1 = -1;
        int bStrict;            /* True for a STRICT table */
        int r2;                 /* Previous key for WITHOUT ROWID tables */
        int mxCol;              /* Maximum non-virtual column number */

        if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
        if( !IsOrdinaryTable(pTab) ) continue;
        if( isQuick || HasRowid(pTab) ){
          pPk = 0;
          r2 = 0;
        }else{
          pPk = sqlite3PrimaryKeyIndex(pTab);
          r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);
143314
143315
143316
143317
143318
143319
143320
143321
143322
143323
143324
143325
143326
143327
143328
      /* Second pass to invoke the xIntegrity method on all virtual
      ** tables.
      */
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        sqlite3_vtab *pVTab;
        int a1;
        if( pObjTab && pObjTab!=pTab ) continue;
        if( IsOrdinaryTable(pTab) ) continue;
        if( !IsVirtual(pTab) ) continue;
        if( pTab->nCol<=0 ){
          const char *zMod = pTab->u.vtab.azArg[0];
          if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
        }
        sqlite3ViewGetColumnNames(pParse, pTab);







|







143671
143672
143673
143674
143675
143676
143677
143678
143679
143680
143681
143682
143683
143684
143685
      /* Second pass to invoke the xIntegrity method on all virtual
      ** tables.
      */
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        sqlite3_vtab *pVTab;
        int a1;
        if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
        if( IsOrdinaryTable(pTab) ) continue;
        if( !IsVirtual(pTab) ) continue;
        if( pTab->nCol<=0 ){
          const char *zMod = pTab->u.vtab.azArg[0];
          if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
        }
        sqlite3ViewGetColumnNames(pParse, pTab);
143546
143547
143548
143549
143550
143551
143552


143553
143554
143555
143556
143557
143558
143559
    if( zRight ){
      if( sqlite3StrICmp(zRight, "full")==0 ){
        eMode = SQLITE_CHECKPOINT_FULL;
      }else if( sqlite3StrICmp(zRight, "restart")==0 ){
        eMode = SQLITE_CHECKPOINT_RESTART;
      }else if( sqlite3StrICmp(zRight, "truncate")==0 ){
        eMode = SQLITE_CHECKPOINT_TRUNCATE;


      }
    }
    pParse->nMem = 3;
    sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
    sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
  }
  break;







>
>







143903
143904
143905
143906
143907
143908
143909
143910
143911
143912
143913
143914
143915
143916
143917
143918
    if( zRight ){
      if( sqlite3StrICmp(zRight, "full")==0 ){
        eMode = SQLITE_CHECKPOINT_FULL;
      }else if( sqlite3StrICmp(zRight, "restart")==0 ){
        eMode = SQLITE_CHECKPOINT_RESTART;
      }else if( sqlite3StrICmp(zRight, "truncate")==0 ){
        eMode = SQLITE_CHECKPOINT_TRUNCATE;
      }else if( sqlite3StrICmp(zRight, "noop")==0 ){
        eMode = SQLITE_CHECKPOINT_NOOP;
      }
    }
    pParse->nMem = 3;
    sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
    sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
  }
  break;
145112
145113
145114
145115
145116
145117
145118

145119
145120
145121

145122
145123
145124
145125
145126
145127
145128
  do{
    /* Make multiple attempts to compile the SQL, until it either succeeds
    ** or encounters a permanent error.  A schema problem after one schema
    ** reset is considered a permanent error. */
    rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
    assert( rc==SQLITE_OK || *ppStmt==0 );
    if( rc==SQLITE_OK || db->mallocFailed ) break;

  }while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
       || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
  sqlite3BtreeLeaveAll(db);

  rc = sqlite3ApiExit(db, rc);
  assert( (rc&db->errMask)==rc );
  db->busyHandler.nBusy = 0;
  sqlite3_mutex_leave(db->mutex);
  assert( rc==SQLITE_OK || (*ppStmt)==0 );
  return rc;
}







>
|
|

>







145471
145472
145473
145474
145475
145476
145477
145478
145479
145480
145481
145482
145483
145484
145485
145486
145487
145488
145489
  do{
    /* Make multiple attempts to compile the SQL, until it either succeeds
    ** or encounters a permanent error.  A schema problem after one schema
    ** reset is considered a permanent error. */
    rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
    assert( rc==SQLITE_OK || *ppStmt==0 );
    if( rc==SQLITE_OK || db->mallocFailed ) break;
    cnt++;
  }while( (rc==SQLITE_ERROR_RETRY && ALWAYS(cnt<=SQLITE_MAX_PREPARE_RETRY))
       || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt)==1) );
  sqlite3BtreeLeaveAll(db);
  assert( rc!=SQLITE_ERROR_RETRY );
  rc = sqlite3ApiExit(db, rc);
  assert( (rc&db->errMask)==rc );
  db->busyHandler.nBusy = 0;
  sqlite3_mutex_leave(db->mutex);
  assert( rc==SQLITE_OK || (*ppStmt)==0 );
  return rc;
}
145788
145789
145790
145791
145792
145793
145794
145795
145796
145797
145798
145799
145800
145801
145802
145803
SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
  assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON );
  while( p ){
    ExprSetProperty(p, joinFlag);
    assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
    ExprSetVVAProperty(p, EP_NoReduce);
    p->w.iJoin = iTable;
    if( p->op==TK_FUNCTION ){
      assert( ExprUseXList(p) );
      if( p->x.pList ){
        int i;
        for(i=0; i<p->x.pList->nExpr; i++){
          sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag);
        }
      }
    }







<
|







146149
146150
146151
146152
146153
146154
146155

146156
146157
146158
146159
146160
146161
146162
146163
SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
  assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON );
  while( p ){
    ExprSetProperty(p, joinFlag);
    assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
    ExprSetVVAProperty(p, EP_NoReduce);
    p->w.iJoin = iTable;

    if( ExprUseXList(p) ){
      if( p->x.pList ){
        int i;
        for(i=0; i<p->x.pList->nExpr; i++){
          sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag);
        }
      }
    }
146005
146006
146007
146008
146009
146010
146011

146012
146013
146014
146015
146016
146017
146018
    ** an AND operator.
    */
    else if( pRight->u3.pOn ){
      sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType);
      p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn);
      pRight->u3.pOn = 0;
      pRight->fg.isOn = 1;

    }
  }
  return 0;
}

/*
** An instance of this object holds information (beyond pParse and pSelect)







>







146365
146366
146367
146368
146369
146370
146371
146372
146373
146374
146375
146376
146377
146378
146379
    ** an AND operator.
    */
    else if( pRight->u3.pOn ){
      sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType);
      p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn);
      pRight->u3.pOn = 0;
      pRight->fg.isOn = 1;
      p->selFlags |= SF_OnToWhere;
    }
  }
  return 0;
}

/*
** An instance of this object holds information (beyond pParse and pSelect)
146891
146892
146893
146894
146895
146896
146897



146898
146899
146900
146901
146902
146903
146904
146905

/*
** Allocate a KeyInfo object sufficient for an index of N key columns and
** X extra columns.
*/
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
  int nExtra = (N+X)*(sizeof(CollSeq*)+1);



  KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
  if( p ){
    p->aSortFlags = (u8*)&p->aColl[N+X];
    p->nKeyField = (u16)N;
    p->nAllField = (u16)(N+X);
    p->enc = ENC(db);
    p->db = db;
    p->nRef = 1;







>
>
>
|







147252
147253
147254
147255
147256
147257
147258
147259
147260
147261
147262
147263
147264
147265
147266
147267
147268
147269

/*
** Allocate a KeyInfo object sufficient for an index of N key columns and
** X extra columns.
*/
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
  int nExtra = (N+X)*(sizeof(CollSeq*)+1);
  KeyInfo *p;
  assert( X>=0 );
  if( NEVER(N+X>0xffff) ) return (KeyInfo*)sqlite3OomFault(db);
  p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
  if( p ){
    p->aSortFlags = (u8*)&p->aColl[N+X];
    p->nKeyField = (u16)N;
    p->nAllField = (u16)(N+X);
    p->enc = ENC(db);
    p->db = db;
    p->nRef = 1;
149210
149211
149212
149213
149214
149215
149216
149217
149218
149219
149220
149221
149222
149223
149224
**
** All references to columns in table iTable are to be replaced by corresponding
** expressions in pEList.
**
** ## About "isOuterJoin":
**
** The isOuterJoin column indicates that the replacement will occur into a
** position in the parent that NULL-able due to an OUTER JOIN.  Either the
** target slot in the parent is the right operand of a LEFT JOIN, or one of
** the left operands of a RIGHT JOIN.  In either case, we need to potentially
** bypass the substituted expression with OP_IfNullRow.
**
** Suppose the original expression is an integer constant. Even though the table
** has the nullRow flag set, because the expression is an integer constant,
** it will not be NULLed out.  So instead, we insert an OP_IfNullRow opcode







|







149574
149575
149576
149577
149578
149579
149580
149581
149582
149583
149584
149585
149586
149587
149588
**
** All references to columns in table iTable are to be replaced by corresponding
** expressions in pEList.
**
** ## About "isOuterJoin":
**
** The isOuterJoin column indicates that the replacement will occur into a
** position in the parent that is NULL-able due to an OUTER JOIN.  Either the
** target slot in the parent is the right operand of a LEFT JOIN, or one of
** the left operands of a RIGHT JOIN.  In either case, we need to potentially
** bypass the substituted expression with OP_IfNullRow.
**
** Suppose the original expression is an integer constant. Even though the table
** has the nullRow flag set, because the expression is an integer constant,
** it will not be NULLed out.  So instead, we insert an OP_IfNullRow opcode
150048
150049
150050
150051
150052
150053
150054
150055
150056
150057
150058
150059
150060
150061
150062
150063
150064
150065
150066
150067
150068
150069
150070
150071
150072
150073
150074
150075
150076
150077
150078
150079
150080
150081
150082
150083
150084

150085
150086
150087
150088
150089
150090
150091
150092
150093
150094
150095
150096
150097
150098
150099
150100
150101
150102
150103
150104
150105
150106
150107
150108
150109
150110
  ** will scan expressions looking for iParent references and replace
  ** those references with expressions that resolve to the subquery FROM
  ** elements we are now copying in.
  */
  pSub = pSub1;
  for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
    int nSubSrc;
    u8 jointype = 0;
    u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ;
    assert( pSub!=0 );
    pSubSrc = pSub->pSrc;     /* FROM clause of subquery */
    nSubSrc = pSubSrc->nSrc;  /* Number of terms in subquery FROM clause */
    pSrc = pParent->pSrc;     /* FROM clause of the outer query */

    if( pParent==p ){
      jointype = pSubitem->fg.jointype;     /* First time through the loop */
    }

    /* The subquery uses a single slot of the FROM clause of the outer
    ** query.  If the subquery has more than one element in its FROM clause,
    ** then expand the outer query to make space for it to hold all elements
    ** of the subquery.
    **
    ** Example:
    **
    **    SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
    **
    ** The outer query has 3 slots in its FROM clause.  One slot of the
    ** outer query (the middle slot) is used by the subquery.  The next
    ** block of code will expand the outer query FROM clause to 4 slots.
    ** The middle slot is expanded to two slots in order to make space
    ** for the two elements in the FROM clause of the subquery.
    */
    if( nSubSrc>1 ){
      pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
      if( pSrc==0 ) break;
      pParent->pSrc = pSrc;

    }

    /* Transfer the FROM clause terms from the subquery into the
    ** outer query.
    */
    iNewParent = pSubSrc->a[0].iCursor;
    for(i=0; i<nSubSrc; i++){
      SrcItem *pItem = &pSrc->a[i+iFrom];
      assert( pItem->fg.isTabFunc==0 );
      assert( pItem->fg.isSubquery
           || pItem->fg.fixedSchema
           || pItem->u4.zDatabase==0 );
      if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
      *pItem = pSubSrc->a[i];
      pItem->fg.jointype |= ltorj;
      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
    }
    pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
    pSrc->a[iFrom].fg.jointype |= jointype | ltorj;

    /* Now begin substituting subquery result set expressions for
    ** references to the iParent in the outer query.
    **
    ** Example:
    **
    **   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;







|
<





<
<
<
<



















>














|


<
|







150412
150413
150414
150415
150416
150417
150418
150419

150420
150421
150422
150423
150424




150425
150426
150427
150428
150429
150430
150431
150432
150433
150434
150435
150436
150437
150438
150439
150440
150441
150442
150443
150444
150445
150446
150447
150448
150449
150450
150451
150452
150453
150454
150455
150456
150457
150458
150459
150460
150461

150462
150463
150464
150465
150466
150467
150468
150469
  ** will scan expressions looking for iParent references and replace
  ** those references with expressions that resolve to the subquery FROM
  ** elements we are now copying in.
  */
  pSub = pSub1;
  for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
    int nSubSrc;
    u8 jointype = pSubitem->fg.jointype;

    assert( pSub!=0 );
    pSubSrc = pSub->pSrc;     /* FROM clause of subquery */
    nSubSrc = pSubSrc->nSrc;  /* Number of terms in subquery FROM clause */
    pSrc = pParent->pSrc;     /* FROM clause of the outer query */





    /* The subquery uses a single slot of the FROM clause of the outer
    ** query.  If the subquery has more than one element in its FROM clause,
    ** then expand the outer query to make space for it to hold all elements
    ** of the subquery.
    **
    ** Example:
    **
    **    SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
    **
    ** The outer query has 3 slots in its FROM clause.  One slot of the
    ** outer query (the middle slot) is used by the subquery.  The next
    ** block of code will expand the outer query FROM clause to 4 slots.
    ** The middle slot is expanded to two slots in order to make space
    ** for the two elements in the FROM clause of the subquery.
    */
    if( nSubSrc>1 ){
      pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
      if( pSrc==0 ) break;
      pParent->pSrc = pSrc;
      pSubitem = &pSrc->a[iFrom];
    }

    /* Transfer the FROM clause terms from the subquery into the
    ** outer query.
    */
    iNewParent = pSubSrc->a[0].iCursor;
    for(i=0; i<nSubSrc; i++){
      SrcItem *pItem = &pSrc->a[i+iFrom];
      assert( pItem->fg.isTabFunc==0 );
      assert( pItem->fg.isSubquery
           || pItem->fg.fixedSchema
           || pItem->u4.zDatabase==0 );
      if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
      *pItem = pSubSrc->a[i];
      pItem->fg.jointype |= (jointype & JT_LTORJ);
      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
    }

    pSubitem->fg.jointype |= jointype;

    /* Now begin substituting subquery result set expressions for
    ** references to the iParent in the outer query.
    **
    ** Example:
    **
    **   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
152836
152837
152838
152839
152840
152841
152842













































































































152843
152844
152845
152846
152847
152848
152849
        }
#endif
        existsToJoin(pParse, p, pSubWhere);
      }
    }
  }
}














































































































/*
** Generate byte-code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







153195
153196
153197
153198
153199
153200
153201
153202
153203
153204
153205
153206
153207
153208
153209
153210
153211
153212
153213
153214
153215
153216
153217
153218
153219
153220
153221
153222
153223
153224
153225
153226
153227
153228
153229
153230
153231
153232
153233
153234
153235
153236
153237
153238
153239
153240
153241
153242
153243
153244
153245
153246
153247
153248
153249
153250
153251
153252
153253
153254
153255
153256
153257
153258
153259
153260
153261
153262
153263
153264
153265
153266
153267
153268
153269
153270
153271
153272
153273
153274
153275
153276
153277
153278
153279
153280
153281
153282
153283
153284
153285
153286
153287
153288
153289
153290
153291
153292
153293
153294
153295
153296
153297
153298
153299
153300
153301
153302
153303
153304
153305
153306
153307
153308
153309
153310
153311
153312
153313
153314
153315
153316
153317
        }
#endif
        existsToJoin(pParse, p, pSubWhere);
      }
    }
  }
}

/*
** Type used for Walker callbacks by selectCheckOnClauses().
*/
typedef struct CheckOnCtx CheckOnCtx;
struct CheckOnCtx {
  SrcList *pSrc;                  /* SrcList for this context */
  int iJoin;                      /* Cursor numbers must be =< than this */
  CheckOnCtx *pParent;            /* Parent context */
};

/*
** True if the SrcList passed as the only argument contains at least
** one RIGHT or FULL JOIN. False otherwise.
*/
#define hasRightJoin(pSrc) (((pSrc)->a[0].fg.jointype & JT_LTORJ)!=0)

/*
** The xExpr callback for the search of invalid ON clause terms.
*/
static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
  CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;

  /* Check if pExpr is root or near-root of an ON clause constraint that needs
  ** to be checked to ensure that it does not refer to tables in its FROM
  ** clause to the right of itself. i.e. it is either:
  **
  **   + an ON clause on an OUTER join, or
  **   + an ON clause on an INNER join within a FROM that features at
  **     least one RIGHT or FULL join.
  */
  if( (ExprHasProperty(pExpr, EP_OuterON))
   || (ExprHasProperty(pExpr, EP_InnerON) && hasRightJoin(pCtx->pSrc))
  ){
    /* If CheckOnCtx.iJoin is already set, then fall through and process
    ** this expression node as normal. Or, if CheckOnCtx.iJoin is still 0,
    ** set it to the cursor number of the RHS of the join to which this
    ** ON expression was attached and then iterate through the entire
    ** expression.  */
    assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin );
    if( pCtx->iJoin==0 ){
      pCtx->iJoin = pExpr->w.iJoin;
      sqlite3WalkExprNN(pWalker, pExpr);
      pCtx->iJoin = 0;
      return WRC_Prune;
    }
  }

  if( pExpr->op==TK_COLUMN ){
    /* A column expression. Find the SrcList (if any) to which it refers.
    ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an
    ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it
    ** does not refer to a table to the right of CheckOnCtx.iJoin. */
    do {
      SrcList *pSrc = pCtx->pSrc;
      int iTab = pExpr->iTable;
      if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
        if( pCtx->iJoin && iTab>pCtx->iJoin ){
          sqlite3ErrorMsg(pWalker->pParse,
              "ON clause references tables to its right");
          return WRC_Abort;
        }
        break;
      }
      pCtx = pCtx->pParent;
    }while( pCtx );
  }
  return WRC_Continue;
}

/*
** The xSelect callback for the search of invalid ON clause terms.
*/
static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
  CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;
  if( pSelect->pSrc==pCtx->pSrc || pSelect->pSrc->nSrc==0 ){
    return WRC_Continue;
  }else{
    CheckOnCtx sCtx;
    memset(&sCtx, 0, sizeof(sCtx));
    sCtx.pSrc = pSelect->pSrc;
    sCtx.pParent = pCtx;
    pWalker->u.pCheckOnCtx = &sCtx;
    sqlite3WalkSelect(pWalker, pSelect);
    pWalker->u.pCheckOnCtx = pCtx;
    pSelect->selFlags &= ~SF_OnToWhere;
    return WRC_Prune;
  }
}

/*
** Check all ON clauses in pSelect to verify that they do not reference
** columns to the right.
*/
static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
  Walker w;
  CheckOnCtx sCtx;
  assert( pSelect->selFlags & SF_OnToWhere );
  assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 );
  memset(&w, 0, sizeof(w));
  w.pParse = pParse;
  w.xExprCallback = selectCheckOnClausesExpr;
  w.xSelectCallback = selectCheckOnClausesSelect;
  w.u.pCheckOnCtx = &sCtx;
  memset(&sCtx, 0, sizeof(sCtx));
  sCtx.pSrc = pSelect->pSrc;
  sqlite3WalkExprNN(&w, pSelect->pWhere);
  pSelect->selFlags &= ~SF_OnToWhere;
}

/*
** Generate byte-code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
**
152963
152964
152965
152966
152967
152968
152969












152970
152971
152972
152973
152974
152975
152976
  assert( p->pEList!=0 );
#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x10 ){
    TREETRACE(0x10,pParse,p, ("after name resolution:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif













  /* If the SF_UFSrcCheck flag is set, then this function is being called
  ** as part of populating the temp table for an UPDATE...FROM statement.
  ** In this case, it is an error if the target object (pSrc->a[0]) name
  ** or alias is duplicated within FROM clause (pSrc->a[1..n]).
  **
  ** Postgres disallows this case too. The reason is that some other







>
>
>
>
>
>
>
>
>
>
>
>







153431
153432
153433
153434
153435
153436
153437
153438
153439
153440
153441
153442
153443
153444
153445
153446
153447
153448
153449
153450
153451
153452
153453
153454
153455
153456
  assert( p->pEList!=0 );
#if TREETRACE_ENABLED
  if( sqlite3TreeTrace & 0x10 ){
    TREETRACE(0x10,pParse,p, ("after name resolution:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif

  /* If the SELECT statement contains ON clauses that were moved into
  ** the WHERE clause, go through and verify that none of the terms
  ** in the ON clauses reference tables to the right of the ON clause.
  ** Do this now, after name resolution, but before query flattening
  */
  if( p->selFlags & SF_OnToWhere ){
    selectCheckOnClauses(pParse, p);
    if( pParse->nErr ){
      goto select_end;
    }
  }

  /* If the SF_UFSrcCheck flag is set, then this function is being called
  ** as part of populating the temp table for an UPDATE...FROM statement.
  ** In this case, it is an error if the target object (pSrc->a[0]) name
  ** or alias is duplicated within FROM clause (pSrc->a[1..n]).
  **
  ** Postgres disallows this case too. The reason is that some other
155529
155530
155531
155532
155533
155534
155535


155536

155537
155538
155539
155540
155541
155542
155543
155544
155545
155546
155547
155548
155549
155550
155551

155552
155553
155554
155555
155556
155557
155558
155559
155560
){
  Vdbe *v = pParse->pVdbe;
  sqlite3 *db = pParse->db;
  ExprList *pNew;
  Returning *pReturning;
  Select sSelect;
  SrcList *pFrom;


  u8 fromSpace[SZ_SRCLIST_1];


  assert( v!=0 );
  if( !pParse->bReturning ){
    /* This RETURNING trigger must be for a different statement as
    ** this statement lacks a RETURNING clause. */
    return;
  }
  assert( db->pParse==pParse );
  assert( !pParse->isCreate );
  pReturning = pParse->u1.d.pReturning;
  if( pTrigger != &(pReturning->retTrig) ){
    /* This RETURNING trigger is for a different statement */
    return;
  }
  memset(&sSelect, 0, sizeof(sSelect));

  pFrom = (SrcList*)fromSpace;
  memset(pFrom, 0, SZ_SRCLIST_1);
  sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
  sSelect.pSrc = pFrom;
  pFrom->nSrc = 1;
  pFrom->a[0].pSTab = pTab;
  pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */
  pFrom->a[0].iCursor = -1;
  sqlite3SelectPrep(pParse, &sSelect, 0);







>
>
|
>















>
|
<







156009
156010
156011
156012
156013
156014
156015
156016
156017
156018
156019
156020
156021
156022
156023
156024
156025
156026
156027
156028
156029
156030
156031
156032
156033
156034
156035
156036

156037
156038
156039
156040
156041
156042
156043
){
  Vdbe *v = pParse->pVdbe;
  sqlite3 *db = pParse->db;
  ExprList *pNew;
  Returning *pReturning;
  Select sSelect;
  SrcList *pFrom;
  union {
    SrcList sSrc;
    u8 fromSpace[SZ_SRCLIST_1];
  } uSrc;

  assert( v!=0 );
  if( !pParse->bReturning ){
    /* This RETURNING trigger must be for a different statement as
    ** this statement lacks a RETURNING clause. */
    return;
  }
  assert( db->pParse==pParse );
  assert( !pParse->isCreate );
  pReturning = pParse->u1.d.pReturning;
  if( pTrigger != &(pReturning->retTrig) ){
    /* This RETURNING trigger is for a different statement */
    return;
  }
  memset(&sSelect, 0, sizeof(sSelect));
  memset(&uSrc, 0, sizeof(uSrc));
  pFrom = &uSrc.sSrc;

  sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
  sSelect.pSrc = pFrom;
  pFrom->nSrc = 1;
  pFrom->a[0].pSTab = pTab;
  pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */
  pFrom->a[0].iCursor = -1;
  sqlite3SelectPrep(pParse, &sSelect, 0);
163077
163078
163079
163080
163081
163082
163083


163084

163085
163086
163087
163088
163089
163090
163091
  WhereRightJoin *pRJ = pLevel->pRJ;
  Expr *pSubWhere = 0;
  WhereClause *pWC = &pWInfo->sWC;
  WhereInfo *pSubWInfo;
  WhereLoop *pLoop = pLevel->pWLoop;
  SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  SrcList *pFrom;


  u8 fromSpace[SZ_SRCLIST_1];

  Bitmask mAll = 0;
  int k;

  ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
  sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
                                  pRJ->regReturn);
  for(k=0; k<iLevel; k++){







>
>
|
>







163560
163561
163562
163563
163564
163565
163566
163567
163568
163569
163570
163571
163572
163573
163574
163575
163576
163577
  WhereRightJoin *pRJ = pLevel->pRJ;
  Expr *pSubWhere = 0;
  WhereClause *pWC = &pWInfo->sWC;
  WhereInfo *pSubWInfo;
  WhereLoop *pLoop = pLevel->pWLoop;
  SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  SrcList *pFrom;
  union {
    SrcList sSrc;
    u8 fromSpace[SZ_SRCLIST_1];
  } uSrc;
  Bitmask mAll = 0;
  int k;

  ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
  sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
                                  pRJ->regReturn);
  for(k=0; k<iLevel; k++){
163121
163122
163123
163124
163125
163126
163127
163128
163129
163130
163131
163132
163133
163134
163135
      }
      if( pTerm->prereqAll & ~mAll ) continue;
      if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
      pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
                                 sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
    }
  }
  pFrom = (SrcList*)fromSpace;
  pFrom->nSrc = 1;
  pFrom->nAlloc = 1;
  memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
  pFrom->a[0].fg.jointype = 0;
  assert( pParse->withinRJSubrtn < 100 );
  pParse->withinRJSubrtn++;
  pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,







|







163607
163608
163609
163610
163611
163612
163613
163614
163615
163616
163617
163618
163619
163620
163621
      }
      if( pTerm->prereqAll & ~mAll ) continue;
      if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
      pSubWhere = sqlite3ExprAnd(pParse, pSubWhere,
                                 sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
    }
  }
  pFrom = &uSrc.sSrc;
  pFrom->nSrc = 1;
  pFrom->nAlloc = 1;
  memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
  pFrom->a[0].fg.jointype = 0;
  assert( pParse->withinRJSubrtn < 100 );
  pParse->withinRJSubrtn++;
  pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,
164338
164339
164340
164341
164342
164343
164344
164345
164346
164347
164348
164349
164350
164351
164352
164353
164354
164355
164356
164357
164358
164359
164360
164361
164362
164363
164364
164365
164366

  if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){
    Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin);
    if( ExprHasProperty(pExpr, EP_OuterON) ){
      prereqAll |= x;
      extraRight = x-1;  /* ON clause terms may not be used with an index
                         ** on left table of a LEFT JOIN.  Ticket #3015 */
      if( (prereqAll>>1)>=x ){
        sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
        return;
      }
    }else if( (prereqAll>>1)>=x ){
      /* The ON clause of an INNER JOIN references a table to its right.
      ** Most other SQL database engines raise an error.  But SQLite versions
      ** 3.0 through 3.38 just put the ON clause constraint into the WHERE
      ** clause and carried on.   Beginning with 3.39, raise an error only
      ** if there is a RIGHT or FULL JOIN in the query.  This makes SQLite
      ** more like other systems, and also preserves legacy. */
      if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
        sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
        return;
      }
      ExprClearProperty(pExpr, EP_InnerON);
    }
  }
  pTerm->prereqAll = prereqAll;
  pTerm->leftCursor = -1;
  pTerm->iParent = -1;
  pTerm->eOperator = 0;







<
<
<
<

<
<
<
<
<
<
<
<
<
<







164824
164825
164826
164827
164828
164829
164830




164831










164832
164833
164834
164835
164836
164837
164838

  if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){
    Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin);
    if( ExprHasProperty(pExpr, EP_OuterON) ){
      prereqAll |= x;
      extraRight = x-1;  /* ON clause terms may not be used with an index
                         ** on left table of a LEFT JOIN.  Ticket #3015 */




    }else if( (prereqAll>>1)>=x ){










      ExprClearProperty(pExpr, EP_InnerON);
    }
  }
  pTerm->prereqAll = prereqAll;
  pTerm->leftCursor = -1;
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
170214
170215
170216
170217
170218
170219
170220




170221
170222
170223
170224
170225
170226
170227
      pLoop = pLast;
    }
    if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
      if( pLoop->u.vtab.isOrdered
       && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
      ){
        obSat = obDone;




      }
      break;
    }
    iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;

    /* Mark off any ORDER BY term X that is a column in the table of
    ** the current loop for which there is term in the WHERE







>
>
>
>







170686
170687
170688
170689
170690
170691
170692
170693
170694
170695
170696
170697
170698
170699
170700
170701
170702
170703
      pLoop = pLast;
    }
    if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
      if( pLoop->u.vtab.isOrdered
       && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
      ){
        obSat = obDone;
      }else{
        /* No further ORDER BY terms may be matched. So this call should
        ** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */
        isOrderDistinct = 0;
      }
      break;
    }
    iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;

    /* Mark off any ORDER BY term X that is a column in the table of
    ** the current loop for which there is term in the WHERE
171117
171118
171119
171120
171121
171122
171123

171124
171125
171126
171127
171128
171129
171130
171131
171132
171133
171134
171135
171136
171137
171138
171139
171140
171141
171142

    /* Swap the roles of aFrom and aTo for the next generation */
    pFrom = aTo;
    aTo = aFrom;
    aFrom = pFrom;
    nFrom = nTo;
  }


  if( nFrom==0 ){
    sqlite3ErrorMsg(pParse, "no query solution");
    sqlite3StackFreeNN(pParse->db, pSpace);
    return SQLITE_ERROR;
  }

  /* Find the lowest cost path.  pFrom will be left pointing to that path */
  pFrom = aFrom;
  for(ii=1; ii<nFrom; ii++){
    if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
  }
  assert( pWInfo->nLevel==nLoop );
  /* Load the lowest cost path into pWInfo */
  for(iLoop=0; iLoop<nLoop; iLoop++){
    WhereLevel *pLevel = pWInfo->a + iLoop;
    pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop];
    pLevel->iFrom = pWLoop->iTab;
    pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;







>






<
<

<
<
<







171593
171594
171595
171596
171597
171598
171599
171600
171601
171602
171603
171604
171605
171606


171607



171608
171609
171610
171611
171612
171613
171614

    /* Swap the roles of aFrom and aTo for the next generation */
    pFrom = aTo;
    aTo = aFrom;
    aFrom = pFrom;
    nFrom = nTo;
  }
  assert( nFrom==0 || nFrom==1 );

  if( nFrom==0 ){
    sqlite3ErrorMsg(pParse, "no query solution");
    sqlite3StackFreeNN(pParse->db, pSpace);
    return SQLITE_ERROR;
  }


  pFrom = aFrom;



  assert( pWInfo->nLevel==nLoop );
  /* Load the lowest cost path into pWInfo */
  for(iLoop=0; iLoop<nLoop; iLoop++){
    WhereLevel *pLevel = pWInfo->a + iLoop;
    pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop];
    pLevel->iFrom = pWLoop->iTab;
    pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
171261
171262
171263
171264
171265
171266
171267
171268



171269
171270
171271
171272
171273
171274
171275
  int i;
#ifdef WHERETRACE_ENABLED
  int once = 0;
#endif
  for(i=0; i<pWInfo->nLevel; i++){
    WhereLoop *p = pWInfo->a[i].pWLoop;
    if( p==0 ) break;
    if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue;



    if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
      u8 iTab = p->iTab;
      WhereLoop *pLoop;
      for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){
        if( pLoop->iTab!=iTab ) continue;
        if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){
          /* Auto-index and index-constrained loops allowed to remain */







|
>
>
>







171733
171734
171735
171736
171737
171738
171739
171740
171741
171742
171743
171744
171745
171746
171747
171748
171749
171750
  int i;
#ifdef WHERETRACE_ENABLED
  int once = 0;
#endif
  for(i=0; i<pWInfo->nLevel; i++){
    WhereLoop *p = pWInfo->a[i].pWLoop;
    if( p==0 ) break;
    if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
      /* Treat a vtab scan as similar to a full-table scan */
      break;
    }
    if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
      u8 iTab = p->iTab;
      WhereLoop *pLoop;
      for(pLoop=pWInfo->pLoops; pLoop; pLoop=pLoop->pNextLoop){
        if( pLoop->iTab!=iTab ) continue;
        if( (pLoop->wsFlags & (WHERE_CONSTRAINT|WHERE_AUTO_INDEX))!=0 ){
          /* Auto-index and index-constrained loops allowed to remain */
175374
175375
175376
175377
175378
175379
175380
175381
175382
175383
175384
175385
175386
175387
175388
**         AGGSTEP
**       }
**       RETURN_ROW
**
**
**   ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
**     ... loop started by sqlite3WhereBegin() ...
**     if( new partition ){
**       Gosub flush
**     }
**     Insert new row into eph table.
**     if( first row of partition ){
**       Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**       regEnd = <expr2>







|







175849
175850
175851
175852
175853
175854
175855
175856
175857
175858
175859
175860
175861
175862
175863
**         AGGSTEP
**       }
**       RETURN_ROW
**
**
**   ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
**   ... loop started by sqlite3WhereBegin() ...
**     if( new partition ){
**       Gosub flush
**     }
**     Insert new row into eph table.
**     if( first row of partition ){
**       Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
**       regEnd = <expr2>
175892
175893
175894
175895
175896
175897
175898






175899
175900
175901
175902
175903
175904
175905
    }else
    if( pMWin->eEnd==TK_UNBOUNDED ){
      addrStart = sqlite3VdbeCurrentAddr(v);
      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1);
      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1);
    }else{
      assert( pMWin->eEnd==TK_FOLLOWING );






      addrStart = sqlite3VdbeCurrentAddr(v);
      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1);
      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1);
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
    sqlite3VdbeJumpHere(v, addrBreak2);
    addrStart = sqlite3VdbeCurrentAddr(v);







>
>
>
>
>
>







176367
176368
176369
176370
176371
176372
176373
176374
176375
176376
176377
176378
176379
176380
176381
176382
176383
176384
176385
176386
    }else
    if( pMWin->eEnd==TK_UNBOUNDED ){
      addrStart = sqlite3VdbeCurrentAddr(v);
      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1);
      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1);
    }else{
      assert( pMWin->eEnd==TK_FOLLOWING );
      /* assert( regStart>=0 );
      ** regEnd = regEnd - regStart;
      ** regStart = 0;   */
      sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, regStart);

      addrStart = sqlite3VdbeCurrentAddr(v);
      addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1);
      addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1);
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart);
    sqlite3VdbeJumpHere(v, addrBreak2);
    addrStart = sqlite3VdbeCurrentAddr(v);
184837
184838
184839
184840
184841
184842
184843



184844
184845
184846
184847
184848
184849
184850
  const char *zName = 0;
  int i, origRc = rc;
  for(i=0; i<2 && zName==0; i++, rc &= 0xff){
    switch( rc ){
      case SQLITE_OK:                 zName = "SQLITE_OK";                break;
      case SQLITE_ERROR:              zName = "SQLITE_ERROR";             break;
      case SQLITE_ERROR_SNAPSHOT:     zName = "SQLITE_ERROR_SNAPSHOT";    break;



      case SQLITE_INTERNAL:           zName = "SQLITE_INTERNAL";          break;
      case SQLITE_PERM:               zName = "SQLITE_PERM";              break;
      case SQLITE_ABORT:              zName = "SQLITE_ABORT";             break;
      case SQLITE_ABORT_ROLLBACK:     zName = "SQLITE_ABORT_ROLLBACK";    break;
      case SQLITE_BUSY:               zName = "SQLITE_BUSY";              break;
      case SQLITE_BUSY_RECOVERY:      zName = "SQLITE_BUSY_RECOVERY";     break;
      case SQLITE_BUSY_SNAPSHOT:      zName = "SQLITE_BUSY_SNAPSHOT";     break;







>
>
>







185318
185319
185320
185321
185322
185323
185324
185325
185326
185327
185328
185329
185330
185331
185332
185333
185334
  const char *zName = 0;
  int i, origRc = rc;
  for(i=0; i<2 && zName==0; i++, rc &= 0xff){
    switch( rc ){
      case SQLITE_OK:                 zName = "SQLITE_OK";                break;
      case SQLITE_ERROR:              zName = "SQLITE_ERROR";             break;
      case SQLITE_ERROR_SNAPSHOT:     zName = "SQLITE_ERROR_SNAPSHOT";    break;
      case SQLITE_ERROR_RETRY:        zName = "SQLITE_ERROR_RETRY";       break;
      case SQLITE_ERROR_MISSING_COLLSEQ:
                                zName = "SQLITE_ERROR_MISSING_COLLSEQ";   break;
      case SQLITE_INTERNAL:           zName = "SQLITE_INTERNAL";          break;
      case SQLITE_PERM:               zName = "SQLITE_PERM";              break;
      case SQLITE_ABORT:              zName = "SQLITE_ABORT";             break;
      case SQLITE_ABORT_ROLLBACK:     zName = "SQLITE_ABORT_ROLLBACK";    break;
      case SQLITE_BUSY:               zName = "SQLITE_BUSY";              break;
      case SQLITE_BUSY_RECOVERY:      zName = "SQLITE_BUSY_RECOVERY";     break;
      case SQLITE_BUSY_SNAPSHOT:      zName = "SQLITE_BUSY_SNAPSHOT";     break;
186017
186018
186019
186020
186021
186022
186023























186024
186025
186026
186027
186028
186029
186030
    if( z==0 ){
      z = sqlite3ErrStr(db->errCode);
    }
  }
  sqlite3_mutex_leave(db->mutex);
  return z;
}
























/*
** Return the byte offset of the most recent error
*/
SQLITE_API int sqlite3_error_offset(sqlite3 *db){
  int iOffset = -1;
  if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







186501
186502
186503
186504
186505
186506
186507
186508
186509
186510
186511
186512
186513
186514
186515
186516
186517
186518
186519
186520
186521
186522
186523
186524
186525
186526
186527
186528
186529
186530
186531
186532
186533
186534
186535
186536
186537
    if( z==0 ){
      z = sqlite3ErrStr(db->errCode);
    }
  }
  sqlite3_mutex_leave(db->mutex);
  return z;
}

/*
** Set the error code and error message associated with the database handle.
**
** This routine is intended to be called by outside extensions (ex: the
** Session extension). Internal logic should invoke sqlite3Error() or
** sqlite3ErrorWithMsg() directly.
*/
SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zMsg){
  int rc = SQLITE_OK;
  if( !sqlite3SafetyCheckSickOrOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);
  if( zMsg ){
    sqlite3ErrorWithMsg(db, errcode, "%s", zMsg);
  }else{
    sqlite3Error(db, errcode);
  }
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

/*
** Return the byte offset of the most recent error
*/
SQLITE_API int sqlite3_error_offset(sqlite3 *db){
  int iOffset = -1;
  if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
187842
187843
187844
187845
187846
187847
187848
187849
187850
187851
187852
187853



187854
187855
187856
187857
187858
187859
187860
187861
187862
    ** not.
    */
    case SQLITE_TESTCTRL_ISINIT: {
      if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
    **
    ** This test control is used to create imposter tables.  "db" is a pointer
    ** to the database connection.  dbName is the database name (ex: "main" or
    ** "temp") which will receive the imposter.  "onOff" turns imposter mode on



    ** or off.  "tnum" is the root page of the b-tree to which the imposter
    ** table should connect.
    **
    ** Enable imposter mode only when the schema has already been parsed.  Then
    ** run a single CREATE TABLE statement to construct the imposter table in
    ** the parsed schema.  Then turn imposter mode back off again.
    **
    ** If onOff==0 and tnum>0 then reset the schema for all databases, causing
    ** the schema to be reparsed the next time it is needed.  This has the







|



|
>
>
>
|
<







188349
188350
188351
188352
188353
188354
188355
188356
188357
188358
188359
188360
188361
188362
188363
188364

188365
188366
188367
188368
188369
188370
188371
    ** not.
    */
    case SQLITE_TESTCTRL_ISINIT: {
      if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, mode, tnum);
    **
    ** This test control is used to create imposter tables.  "db" is a pointer
    ** to the database connection.  dbName is the database name (ex: "main" or
    ** "temp") which will receive the imposter.  "mode" turns imposter mode on
    ** or off.  mode==0 means imposter mode is off.  mode==1 means imposter mode
    ** is on.  mode==2 means imposter mode is on but results in an imposter
    ** table that is read-only unless writable_schema is on.  "tnum" is the
    ** root page of the b-tree to which the imposter table should connect.

    **
    ** Enable imposter mode only when the schema has already been parsed.  Then
    ** run a single CREATE TABLE statement to construct the imposter table in
    ** the parsed schema.  Then turn imposter mode back off again.
    **
    ** If onOff==0 and tnum>0 then reset the schema for all databases, causing
    ** the schema to be reparsed the next time it is needed.  This has the
189085
189086
189087
189088
189089
189090
189091







189092
189093
189094
189095
189096
189097
189098
189099
189100
189101
189102
189103
189104
189105
189106
189107
189108
189109
**
******************************************************************************
**
*/
#ifndef _FTSINT_H
#define _FTSINT_H








/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stddef.h> */
/* #include <stdio.h> */
/* #include <string.h> */
/* #include <stdarg.h> */

#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif

/* FTS3/FTS4 require virtual tables */
#ifdef SQLITE_OMIT_VIRTUALTABLE
# undef SQLITE_ENABLE_FTS3
# undef SQLITE_ENABLE_FTS4
#endif

/*







>
>
>
>
>
>
>







<
<
<
<







189594
189595
189596
189597
189598
189599
189600
189601
189602
189603
189604
189605
189606
189607
189608
189609
189610
189611
189612
189613
189614




189615
189616
189617
189618
189619
189620
189621
**
******************************************************************************
**
*/
#ifndef _FTSINT_H
#define _FTSINT_H

/*
** Activate assert() only if SQLITE_TEST is enabled.
*/
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif

/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stddef.h> */
/* #include <stdio.h> */
/* #include <string.h> */
/* #include <stdarg.h> */





/* FTS3/FTS4 require virtual tables */
#ifdef SQLITE_OMIT_VIRTUALTABLE
# undef SQLITE_ENABLE_FTS3
# undef SQLITE_ENABLE_FTS4
#endif

/*
189538
189539
189540
189541
189542
189543
189544
189545
189546
189547
189548
189549
189550
189551
189552
189553
189554
189555
189556
189557
189558
typedef sqlite3_int64 i64;        /* 8-byte signed integer */

/*
** Macro used to suppress compiler warnings for unused parameters.
*/
#define UNUSED_PARAMETER(x) (void)(x)

/*
** Activate assert() only if SQLITE_TEST is enabled.
*/
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif

/*
** The TESTONLY macro is used to enclose variable declarations or
** other bits of code that are needed to support the arguments
** within testcase() and assert() macros.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
# define TESTONLY(X)  X







<
<
<
<
<
<
<







190050
190051
190052
190053
190054
190055
190056







190057
190058
190059
190060
190061
190062
190063
typedef sqlite3_int64 i64;        /* 8-byte signed integer */

/*
** Macro used to suppress compiler warnings for unused parameters.
*/
#define UNUSED_PARAMETER(x) (void)(x)








/*
** The TESTONLY macro is used to enclose variable declarations or
** other bits of code that are needed to support the arguments
** within testcase() and assert() macros.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
# define TESTONLY(X)  X
203819
203820
203821
203822
203823
203824
203825
203826
203827
203828
203829
203830
203831
203832
203833
203834
};

/*
** An object of this type contains the state required to create or append
** to an appendable b-tree segment.
*/
struct IncrmergeWriter {
  int nLeafEst;                   /* Space allocated for leaf blocks */
  int nWork;                      /* Number of leaf pages flushed */
  sqlite3_int64 iAbsLevel;        /* Absolute level of input segments */
  int iIdx;                       /* Index of *output* segment in iAbsLevel+1 */
  sqlite3_int64 iStart;           /* Block number of first allocated block */
  sqlite3_int64 iEnd;             /* Block number of last allocated block */
  sqlite3_int64 nLeafData;        /* Bytes of leaf page data so far */
  u8 bNoLeafData;                 /* If true, store 0 for segment size */
  NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];







|
|







204324
204325
204326
204327
204328
204329
204330
204331
204332
204333
204334
204335
204336
204337
204338
204339
};

/*
** An object of this type contains the state required to create or append
** to an appendable b-tree segment.
*/
struct IncrmergeWriter {
  i64 nLeafEst;                   /* Space allocated for leaf blocks */
  i64 nWork;                      /* Number of leaf pages flushed */
  sqlite3_int64 iAbsLevel;        /* Absolute level of input segments */
  int iIdx;                       /* Index of *output* segment in iAbsLevel+1 */
  sqlite3_int64 iStart;           /* Block number of first allocated block */
  sqlite3_int64 iEnd;             /* Block number of last allocated block */
  sqlite3_int64 nLeafData;        /* Bytes of leaf page data so far */
  u8 bNoLeafData;                 /* If true, store 0 for segment size */
  NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
204566
204567
204568
204569
204570
204571
204572
204573
204574
204575
204576
204577
204578
204579
204580
204581
204582
204583
204584
204585
204586
204587
204588
204589
204590
  sqlite3_int64 iAbsLevel,        /* Absolute level of input segments */
  int iIdx,                       /* Index of new output segment */
  Fts3MultiSegReader *pCsr,       /* Cursor that data will be read from */
  IncrmergeWriter *pWriter        /* Populate this object */
){
  int rc;                         /* Return Code */
  int i;                          /* Iterator variable */
  int nLeafEst = 0;               /* Blocks allocated for leaf nodes */
  sqlite3_stmt *pLeafEst = 0;     /* SQL used to determine nLeafEst */
  sqlite3_stmt *pFirstBlock = 0;  /* SQL used to determine first block */

  /* Calculate nLeafEst. */
  rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0);
  if( rc==SQLITE_OK ){
    sqlite3_bind_int64(pLeafEst, 1, iAbsLevel);
    sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment);
    if( SQLITE_ROW==sqlite3_step(pLeafEst) ){
      nLeafEst = sqlite3_column_int(pLeafEst, 0);
    }
    rc = sqlite3_reset(pLeafEst);
  }
  if( rc!=SQLITE_OK ) return rc;

  /* Calculate the first block to use in the output segment */
  rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0);







|









|







205071
205072
205073
205074
205075
205076
205077
205078
205079
205080
205081
205082
205083
205084
205085
205086
205087
205088
205089
205090
205091
205092
205093
205094
205095
  sqlite3_int64 iAbsLevel,        /* Absolute level of input segments */
  int iIdx,                       /* Index of new output segment */
  Fts3MultiSegReader *pCsr,       /* Cursor that data will be read from */
  IncrmergeWriter *pWriter        /* Populate this object */
){
  int rc;                         /* Return Code */
  int i;                          /* Iterator variable */
  i64 nLeafEst = 0;               /* Blocks allocated for leaf nodes */
  sqlite3_stmt *pLeafEst = 0;     /* SQL used to determine nLeafEst */
  sqlite3_stmt *pFirstBlock = 0;  /* SQL used to determine first block */

  /* Calculate nLeafEst. */
  rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0);
  if( rc==SQLITE_OK ){
    sqlite3_bind_int64(pLeafEst, 1, iAbsLevel);
    sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment);
    if( SQLITE_ROW==sqlite3_step(pLeafEst) ){
      nLeafEst = sqlite3_column_int64(pLeafEst, 0);
    }
    rc = sqlite3_reset(pLeafEst);
  }
  if( rc!=SQLITE_OK ) return rc;

  /* Calculate the first block to use in the output segment */
  rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0);
228351
228352
228353
228354
228355
228356
228357
228358
228359
228360
228361
228362
228363
228364
228365
228366
    && !defined(SQLITE_OMIT_VIRTUALTABLE)

typedef struct DbpageTable DbpageTable;
typedef struct DbpageCursor DbpageCursor;

struct DbpageCursor {
  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
  int pgno;                       /* Current page number */
  int mxPgno;                     /* Last page to visit on this scan */
  Pager *pPager;                  /* Pager being read/written */
  DbPage *pPage1;                 /* Page 1 of the database */
  int iDb;                        /* Index of database to analyze */
  int szPage;                     /* Size of each page in bytes */
};

struct DbpageTable {







|
|







228856
228857
228858
228859
228860
228861
228862
228863
228864
228865
228866
228867
228868
228869
228870
228871
    && !defined(SQLITE_OMIT_VIRTUALTABLE)

typedef struct DbpageTable DbpageTable;
typedef struct DbpageCursor DbpageCursor;

struct DbpageCursor {
  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
  Pgno pgno;                      /* Current page number */
  Pgno mxPgno;                    /* Last page to visit on this scan */
  Pager *pPager;                  /* Pager being read/written */
  DbPage *pPage1;                 /* Page 1 of the database */
  int iDb;                        /* Index of database to analyze */
  int szPage;                     /* Size of each page in bytes */
};

struct DbpageTable {
228489
228490
228491
228492
228493
228494
228495
228496
228497
228498
228499
228500
228501
228502
228503

  pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor));
  if( pCsr==0 ){
    return SQLITE_NOMEM_BKPT;
  }else{
    memset(pCsr, 0, sizeof(DbpageCursor));
    pCsr->base.pVtab = pVTab;
    pCsr->pgno = -1;
  }

  *ppCursor = (sqlite3_vtab_cursor *)pCsr;
  return SQLITE_OK;
}

/*







|







228994
228995
228996
228997
228998
228999
229000
229001
229002
229003
229004
229005
229006
229007
229008

  pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor));
  if( pCsr==0 ){
    return SQLITE_NOMEM_BKPT;
  }else{
    memset(pCsr, 0, sizeof(DbpageCursor));
    pCsr->base.pVtab = pVTab;
    pCsr->pgno = 0;
  }

  *ppCursor = (sqlite3_vtab_cursor *)pCsr;
  return SQLITE_OK;
}

/*
228589
228590
228591
228592
228593
228594
228595
228596
228597
228598
228599
228600
228601
228602
228603
228604
228605
228606
228607
228608
  sqlite3_context *ctx,
  int i
){
  DbpageCursor *pCsr = (DbpageCursor *)pCursor;
  int rc = SQLITE_OK;
  switch( i ){
    case 0: {           /* pgno */
      sqlite3_result_int(ctx, pCsr->pgno);
      break;
    }
    case 1: {           /* data */
      DbPage *pDbPage = 0;
      if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){
        /* The pending byte page. Assume it is zeroed out. Attempting to
        ** request this page from the page is an SQLITE_CORRUPT error. */
        sqlite3_result_zeroblob(ctx, pCsr->szPage);
      }else{
        rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
        if( rc==SQLITE_OK ){
          sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,







|




|







229094
229095
229096
229097
229098
229099
229100
229101
229102
229103
229104
229105
229106
229107
229108
229109
229110
229111
229112
229113
  sqlite3_context *ctx,
  int i
){
  DbpageCursor *pCsr = (DbpageCursor *)pCursor;
  int rc = SQLITE_OK;
  switch( i ){
    case 0: {           /* pgno */
      sqlite3_result_int64(ctx, (sqlite3_int64)pCsr->pgno);
      break;
    }
    case 1: {           /* data */
      DbPage *pDbPage = 0;
      if( pCsr->pgno==(Pgno)((PENDING_BYTE/pCsr->szPage)+1) ){
        /* The pending byte page. Assume it is zeroed out. Attempting to
        ** request this page from the page is an SQLITE_CORRUPT error. */
        sqlite3_result_zeroblob(ctx, pCsr->szPage);
      }else{
        rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
        if( rc==SQLITE_OK ){
          sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
228668
228669
228670
228671
228672
228673
228674
228675
228676
228677
228678
228679
228680
228681
228682
228683
228684
228685
    goto update_fail;
  }
  if( argc==1 ){
    zErr = "cannot delete";
    goto update_fail;
  }
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
    pgno = (Pgno)sqlite3_value_int(argv[2]);
    isInsert = 1;
  }else{
    pgno = sqlite3_value_int(argv[0]);
    if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
      zErr = "cannot insert";
      goto update_fail;
    }
    isInsert = 0;
  }
  if( sqlite3_value_type(argv[4])==SQLITE_NULL ){







|


|







229173
229174
229175
229176
229177
229178
229179
229180
229181
229182
229183
229184
229185
229186
229187
229188
229189
229190
    goto update_fail;
  }
  if( argc==1 ){
    zErr = "cannot delete";
    goto update_fail;
  }
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
    pgno = (Pgno)sqlite3_value_int64(argv[2]);
    isInsert = 1;
  }else{
    pgno = (Pgno)sqlite3_value_int64(argv[0]);
    if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
      zErr = "cannot insert";
      goto update_fail;
    }
    isInsert = 0;
  }
  if( sqlite3_value_type(argv[4])==SQLITE_NULL ){
231623
231624
231625
231626
231627
231628
231629













231630
231631
231632
231633
231634
231635
231636
      }
    }
    assert( (a - p->aRecord)==p->nRecord );
  }

  return rc;
}














/*
** Formulate and prepare a SELECT statement to retrieve a row from table
** zTab in database zDb based on its primary key. i.e.
**
**   SELECT *, <noop-test> FROM zDb.zTab WHERE (pk1, pk2,...) IS (?1, ?2,...)
**







>
>
>
>
>
>
>
>
>
>
>
>
>







232128
232129
232130
232131
232132
232133
232134
232135
232136
232137
232138
232139
232140
232141
232142
232143
232144
232145
232146
232147
232148
232149
232150
232151
232152
232153
232154
      }
    }
    assert( (a - p->aRecord)==p->nRecord );
  }

  return rc;
}

static int sessionPrepare(
  sqlite3 *db,
  sqlite3_stmt **pp,
  char **pzErrmsg,
  const char *zSql
){
  int rc = sqlite3_prepare_v2(db, zSql, -1, pp, 0);
  if( pzErrmsg && rc!=SQLITE_OK ){
    *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
  }
  return rc;
}

/*
** Formulate and prepare a SELECT statement to retrieve a row from table
** zTab in database zDb based on its primary key. i.e.
**
**   SELECT *, <noop-test> FROM zDb.zTab WHERE (pk1, pk2,...) IS (?1, ?2,...)
**
231645
231646
231647
231648
231649
231650
231651
231652

231653
231654
231655
231656
231657
231658
231659
231660
231661
231662
231663
231664
  int bIgnoreNoop,
  const char *zDb,                /* Database name */
  const char *zTab,               /* Table name */
  int bRowid,
  int nCol,                       /* Number of columns in table */
  const char **azCol,             /* Names of table columns */
  u8 *abPK,                       /* PRIMARY KEY  array */
  sqlite3_stmt **ppStmt           /* OUT: Prepared SELECT statement */

){
  int rc = SQLITE_OK;
  char *zSql = 0;
  const char *zSep = "";
  int nSql = -1;
  int i;

  SessionBuffer cols = {0, 0, 0};
  SessionBuffer nooptest = {0, 0, 0};
  SessionBuffer pkfield = {0, 0, 0};
  SessionBuffer pkvar = {0, 0, 0};








|
>




<







232163
232164
232165
232166
232167
232168
232169
232170
232171
232172
232173
232174
232175

232176
232177
232178
232179
232180
232181
232182
  int bIgnoreNoop,
  const char *zDb,                /* Database name */
  const char *zTab,               /* Table name */
  int bRowid,
  int nCol,                       /* Number of columns in table */
  const char **azCol,             /* Names of table columns */
  u8 *abPK,                       /* PRIMARY KEY  array */
  sqlite3_stmt **ppStmt,          /* OUT: Prepared SELECT statement */
  char **pzErrmsg                 /* OUT: Error message */
){
  int rc = SQLITE_OK;
  char *zSql = 0;
  const char *zSep = "";

  int i;

  SessionBuffer cols = {0, 0, 0};
  SessionBuffer nooptest = {0, 0, 0};
  SessionBuffer pkfield = {0, 0, 0};
  SessionBuffer pkvar = {0, 0, 0};

231730
231731
231732
231733
231734
231735
231736
231737
231738
231739
231740
231741
231742
231743
231744
    }
    zSql = (char*)buf.aBuf;
    nSql = buf.nBuf;
  }
#endif

  if( rc==SQLITE_OK ){
    rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0);
  }
  sqlite3_free(zSql);
  sqlite3_free(nooptest.aBuf);
  sqlite3_free(pkfield.aBuf);
  sqlite3_free(pkvar.aBuf);
  sqlite3_free(cols.aBuf);
  return rc;







|







232248
232249
232250
232251
232252
232253
232254
232255
232256
232257
232258
232259
232260
232261
232262
    }
    zSql = (char*)buf.aBuf;
    nSql = buf.nBuf;
  }
#endif

  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, ppStmt, pzErrmsg, zSql);
  }
  sqlite3_free(zSql);
  sqlite3_free(nooptest.aBuf);
  sqlite3_free(pkfield.aBuf);
  sqlite3_free(pkvar.aBuf);
  sqlite3_free(cols.aBuf);
  return rc;
231894
231895
231896
231897
231898
231899
231900
231901
231902
231903
231904
231905
231906
231907
231908

      /* Write a table header */
      sessionAppendTableHdr(&buf, bPatchset, pTab, &rc);

      /* Build and compile a statement to execute: */
      if( rc==SQLITE_OK ){
        rc = sessionSelectStmt(db, 0, pSession->zDb,
            zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel
        );
      }

      nNoop = buf.nBuf;
      for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){
        SessionChange *p;         /* Used to iterate through changes */








|







232412
232413
232414
232415
232416
232417
232418
232419
232420
232421
232422
232423
232424
232425
232426

      /* Write a table header */
      sessionAppendTableHdr(&buf, bPatchset, pTab, &rc);

      /* Build and compile a statement to execute: */
      if( rc==SQLITE_OK ){
        rc = sessionSelectStmt(db, 0, pSession->zDb,
            zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel, 0
        );
      }

      nNoop = buf.nBuf;
      for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){
        SessionChange *p;         /* Used to iterate through changes */

233103
233104
233105
233106
233107
233108
233109

233110
233111
233112
233113
233114
233115
233116
  int bInvertConstraints;         /* Invert when iterating constraints buffer */
  SessionBuffer constraints;      /* Deferred constraints are stored here */
  SessionBuffer rebase;           /* Rebase information (if any) here */
  u8 bRebaseStarted;              /* If table header is already in rebase */
  u8 bRebase;                     /* True to collect rebase information */
  u8 bIgnoreNoop;                 /* True to ignore no-op conflicts */
  int bRowid;

};

/* Number of prepared UPDATE statements to cache. */
#define SESSION_UPDATE_CACHE_SZ 12

/*
** Find a prepared UPDATE statement suitable for the UPDATE step currently







>







233621
233622
233623
233624
233625
233626
233627
233628
233629
233630
233631
233632
233633
233634
233635
  int bInvertConstraints;         /* Invert when iterating constraints buffer */
  SessionBuffer constraints;      /* Deferred constraints are stored here */
  SessionBuffer rebase;           /* Rebase information (if any) here */
  u8 bRebaseStarted;              /* If table header is already in rebase */
  u8 bRebase;                     /* True to collect rebase information */
  u8 bIgnoreNoop;                 /* True to ignore no-op conflicts */
  int bRowid;
  char *zErr;                     /* Error message, if any */
};

/* Number of prepared UPDATE statements to cache. */
#define SESSION_UPDATE_CACHE_SZ 12

/*
** Find a prepared UPDATE statement suitable for the UPDATE step currently
233328
233329
233330
233331
233332
233333
233334
233335
233336
233337
233338
233339
233340
233341
233342
        zSep = "AND ";
      }
    }
    sessionAppendStr(&buf, ")", &rc);
  }

  if( rc==SQLITE_OK ){
    rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0);
  }
  sqlite3_free(buf.aBuf);

  return rc;
}

/*







|







233847
233848
233849
233850
233851
233852
233853
233854
233855
233856
233857
233858
233859
233860
233861
        zSep = "AND ";
      }
    }
    sessionAppendStr(&buf, ")", &rc);
  }

  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pDelete, &p->zErr, (char*)buf.aBuf);
  }
  sqlite3_free(buf.aBuf);

  return rc;
}

/*
233355
233356
233357
233358
233359
233360
233361
233362
233363
233364
233365
233366
233367
233368
233369
static int sessionSelectRow(
  sqlite3 *db,                    /* Database handle */
  const char *zTab,               /* Table name */
  SessionApplyCtx *p              /* Session changeset-apply context */
){
  /* TODO */
  return sessionSelectStmt(db, p->bIgnoreNoop,
      "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect
  );
}

/*
** Formulate and prepare an INSERT statement to add a record to table zTab.
** For example:
**







|







233874
233875
233876
233877
233878
233879
233880
233881
233882
233883
233884
233885
233886
233887
233888
static int sessionSelectRow(
  sqlite3 *db,                    /* Database handle */
  const char *zTab,               /* Table name */
  SessionApplyCtx *p              /* Session changeset-apply context */
){
  /* TODO */
  return sessionSelectStmt(db, p->bIgnoreNoop,
      "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect, &p->zErr
  );
}

/*
** Formulate and prepare an INSERT statement to add a record to table zTab.
** For example:
**
233392
233393
233394
233395
233396
233397
233398
233399
233400
233401
233402
233403
233404
233405
233406
233407
233408
233409
233410
233411
233412
233413
233414
233415
233416
233417
233418
233419
233420
233421
233422
233423
233424
233425
233426
233427
233428
233429
233430
233431
233432
  sessionAppendStr(&buf, ") VALUES(?", &rc);
  for(i=1; i<p->nCol; i++){
    sessionAppendStr(&buf, ", ?", &rc);
  }
  sessionAppendStr(&buf, ")", &rc);

  if( rc==SQLITE_OK ){
    rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0);
  }
  sqlite3_free(buf.aBuf);
  return rc;
}

static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){
  return sqlite3_prepare_v2(db, zSql, -1, pp, 0);
}

/*
** Prepare statements for applying changes to the sqlite_stat1 table.
** These are similar to those created by sessionSelectRow(),
** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for
** other tables.
*/
static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){
  int rc = sessionSelectRow(db, "sqlite_stat1", p);
  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pInsert,
        "INSERT INTO main.sqlite_stat1 VALUES(?1, "
        "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, "
        "?3)"
    );
  }
  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pDelete,
        "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
        "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END "
        "AND (?4 OR stat IS ?3)"
    );
  }
  return rc;
}







|





<
<
<
<









|






|







233911
233912
233913
233914
233915
233916
233917
233918
233919
233920
233921
233922
233923




233924
233925
233926
233927
233928
233929
233930
233931
233932
233933
233934
233935
233936
233937
233938
233939
233940
233941
233942
233943
233944
233945
233946
233947
  sessionAppendStr(&buf, ") VALUES(?", &rc);
  for(i=1; i<p->nCol; i++){
    sessionAppendStr(&buf, ", ?", &rc);
  }
  sessionAppendStr(&buf, ")", &rc);

  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pInsert, &p->zErr, (char*)buf.aBuf);
  }
  sqlite3_free(buf.aBuf);
  return rc;
}





/*
** Prepare statements for applying changes to the sqlite_stat1 table.
** These are similar to those created by sessionSelectRow(),
** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for
** other tables.
*/
static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){
  int rc = sessionSelectRow(db, "sqlite_stat1", p);
  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pInsert, 0,
        "INSERT INTO main.sqlite_stat1 VALUES(?1, "
        "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, "
        "?3)"
    );
  }
  if( rc==SQLITE_OK ){
    rc = sessionPrepare(db, &p->pDelete, 0,
        "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
        "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END "
        "AND (?4 OR stat IS ?3)"
    );
  }
  return rc;
}
233642
233643
233644
233645
233646
233647
233648
233649
233650
233651
233652
233653
233654
233655
233656
233657
233658
233659
233660
233661
233662
233663
233664
233665
233666
233667
233668
233669
233670
233671
233672
233673
233674
233675
233676
233677
233678
233679
233680
233681
233682
233683
233684
233685
233686
233687
233688


233689
233690
233691
233692
233693
233694
233695
  int eType,                      /* Either CHANGESET_DATA or CONFLICT */
  SessionApplyCtx *p,             /* changeset_apply() context */
  sqlite3_changeset_iter *pIter,  /* Changeset iterator */
  int(*xConflict)(void *, int, sqlite3_changeset_iter*),
  void *pCtx,                     /* First argument for conflict handler */
  int *pbReplace                  /* OUT: Set to true if PK row is found */
){
  int res = 0;                    /* Value returned by conflict handler */
  int rc;
  int nCol;
  int op;
  const char *zDummy;

  sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0);

  assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA );
  assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT );
  assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND );

  /* Bind the new.* PRIMARY KEY values to the SELECT statement. */
  if( pbReplace ){
    rc = sessionSeekToRow(pIter, p);
  }else{
    rc = SQLITE_OK;
  }

  if( rc==SQLITE_ROW ){
    /* There exists another row with the new.* primary key. */
    if( p->bIgnoreNoop
     && sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1)
    ){
      res = SQLITE_CHANGESET_OMIT;
    }else{
      pIter->pConflict = p->pSelect;
      res = xConflict(pCtx, eType, pIter);
      pIter->pConflict = 0;
    }
    rc = sqlite3_reset(p->pSelect);
  }else if( rc==SQLITE_OK ){
    if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){
      /* Instead of invoking the conflict handler, append the change blob
      ** to the SessionApplyCtx.constraints buffer. */
      u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
      int nBlob = pIter->in.iNext - pIter->in.iCurrent;
      sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
      return SQLITE_OK;
    }else{


      /* No other row with the new.* primary key. */
      res = xConflict(pCtx, eType+1, pIter);
      if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE;
    }
  }

  if( rc==SQLITE_OK ){







|




















|
|

<
<













|
>
>







234157
234158
234159
234160
234161
234162
234163
234164
234165
234166
234167
234168
234169
234170
234171
234172
234173
234174
234175
234176
234177
234178
234179
234180
234181
234182
234183
234184
234185
234186
234187


234188
234189
234190
234191
234192
234193
234194
234195
234196
234197
234198
234199
234200
234201
234202
234203
234204
234205
234206
234207
234208
234209
234210
  int eType,                      /* Either CHANGESET_DATA or CONFLICT */
  SessionApplyCtx *p,             /* changeset_apply() context */
  sqlite3_changeset_iter *pIter,  /* Changeset iterator */
  int(*xConflict)(void *, int, sqlite3_changeset_iter*),
  void *pCtx,                     /* First argument for conflict handler */
  int *pbReplace                  /* OUT: Set to true if PK row is found */
){
  int res = SQLITE_CHANGESET_OMIT;/* Value returned by conflict handler */
  int rc;
  int nCol;
  int op;
  const char *zDummy;

  sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0);

  assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA );
  assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT );
  assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND );

  /* Bind the new.* PRIMARY KEY values to the SELECT statement. */
  if( pbReplace ){
    rc = sessionSeekToRow(pIter, p);
  }else{
    rc = SQLITE_OK;
  }

  if( rc==SQLITE_ROW ){
    /* There exists another row with the new.* primary key. */
    if( 0==p->bIgnoreNoop
     || 0==sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1)
    ){


      pIter->pConflict = p->pSelect;
      res = xConflict(pCtx, eType, pIter);
      pIter->pConflict = 0;
    }
    rc = sqlite3_reset(p->pSelect);
  }else if( rc==SQLITE_OK ){
    if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){
      /* Instead of invoking the conflict handler, append the change blob
      ** to the SessionApplyCtx.constraints buffer. */
      u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
      int nBlob = pIter->in.iNext - pIter->in.iCurrent;
      sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
      return SQLITE_OK;
    }else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
           || eType==SQLITE_CHANGESET_CONFLICT
    ){
      /* No other row with the new.* primary key. */
      res = xConflict(pCtx, eType+1, pIter);
      if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE;
    }
  }

  if( rc==SQLITE_OK ){
233779
233780
233781
233782
233783
233784
233785
233786
233787
233788
233789
233790
233791
233792
233793
    if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){
      rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK));
    }
    if( rc!=SQLITE_OK ) return rc;

    sqlite3_step(p->pDelete);
    rc = sqlite3_reset(p->pDelete);
    if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 && p->bIgnoreNoop==0 ){
      rc = sessionConflictHandler(
          SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry
      );
    }else if( (rc&0xff)==SQLITE_CONSTRAINT ){
      rc = sessionConflictHandler(
          SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0
      );







|







234294
234295
234296
234297
234298
234299
234300
234301
234302
234303
234304
234305
234306
234307
234308
    if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){
      rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK));
    }
    if( rc!=SQLITE_OK ) return rc;

    sqlite3_step(p->pDelete);
    rc = sqlite3_reset(p->pDelete);
    if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){
      rc = sessionConflictHandler(
          SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry
      );
    }else if( (rc&0xff)==SQLITE_CONSTRAINT ){
      rc = sessionConflictHandler(
          SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0
      );
234201
234202
234203
234204
234205
234206
234207





234208
234209
234210
234211
234212
234213
234214
  sqlite3_free((char*)sApply.rebase.aBuf);

  if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
    assert( db->flags & SQLITE_FkNoAction );
    db->flags &= ~((u64)SQLITE_FkNoAction);
    db->aDb[0].pSchema->schema_cookie -= 32;
  }





  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  return rc;
}

/*
** This function is called by all six sqlite3changeset_apply() variants:
**







>
>
>
>
>







234716
234717
234718
234719
234720
234721
234722
234723
234724
234725
234726
234727
234728
234729
234730
234731
234732
234733
234734
  sqlite3_free((char*)sApply.rebase.aBuf);

  if( (flags & SQLITE_CHANGESETAPPLY_FKNOACTION) && savedFlag==0 ){
    assert( db->flags & SQLITE_FkNoAction );
    db->flags &= ~((u64)SQLITE_FkNoAction);
    db->aDb[0].pSchema->schema_cookie -= 32;
  }

  assert( rc!=SQLITE_OK || sApply.zErr==0 );
  sqlite3_set_errmsg(db, rc, sApply.zErr);
  sqlite3_free(sApply.zErr);

  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  return rc;
}

/*
** This function is called by all six sqlite3changeset_apply() variants:
**
236410
236411
236412
236413
236414
236415
236416
236417





236418
236419
236420
236421
236422
236423
236424
236425
236426
236427
236428
236429
236430
236431
236432
236433
236434
236435
236436
236437
236438

/*
** Constants for the largest and smallest possible 64-bit signed integers.
*/
# define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)

/* The uptr type is an unsigned integer large enough to hold a pointer





*/
#if defined(HAVE_STDINT_H)
  typedef uintptr_t uptr;
#elif SQLITE_PTRSIZE==4
  typedef u32 uptr;
#else
  typedef u64 uptr;
#endif

#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
# define EIGHT_BYTE_ALIGNMENT(X)   ((((uptr)(X) - (uptr)0)&3)==0)
#else
# define EIGHT_BYTE_ALIGNMENT(X)   ((((uptr)(X) - (uptr)0)&7)==0)
#endif

/*
** Macros needed to provide flexible arrays in a portable way
*/
#ifndef offsetof
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif







|
>
>
>
>
>

<
<
<
<
<
<
<
<
<
|
<
<
<







236930
236931
236932
236933
236934
236935
236936
236937
236938
236939
236940
236941
236942
236943









236944



236945
236946
236947
236948
236949
236950
236951

/*
** Constants for the largest and smallest possible 64-bit signed integers.
*/
# define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)

/*
** This macro is used in a single assert() within fts5 to check that an
** allocation is aligned to an 8-byte boundary. But it is a complicated
** macro to get right for multiple platforms without generating warnings.
** So instead of reproducing the entire definition from sqliteInt.h, we
** just do without this assert() for the rare non-amalgamation builds.
*/









#define EIGHT_BYTE_ALIGNMENT(x) 1




/*
** Macros needed to provide flexible arrays in a portable way
*/
#ifndef offsetof
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
237172
237173
237174
237175
237176
237177
237178
237179
237180
237181
237182
237183
237184
237185
237186
**     rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
**     rc = sqlite3Fts5ExprNext(pExpr)
** ){
**   // The document with rowid iRowid matches the expression!
**   i64 iRowid = sqlite3Fts5ExprRowid(pExpr);
** }
*/
static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc);
static int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax);
static int sqlite3Fts5ExprEof(Fts5Expr*);
static i64 sqlite3Fts5ExprRowid(Fts5Expr*);

static void sqlite3Fts5ExprFree(Fts5Expr*);
static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2);








|







237685
237686
237687
237688
237689
237690
237691
237692
237693
237694
237695
237696
237697
237698
237699
**     rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
**     rc = sqlite3Fts5ExprNext(pExpr)
** ){
**   // The document with rowid iRowid matches the expression!
**   i64 iRowid = sqlite3Fts5ExprRowid(pExpr);
** }
*/
static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, i64, int bDesc);
static int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax);
static int sqlite3Fts5ExprEof(Fts5Expr*);
static i64 sqlite3Fts5ExprRowid(Fts5Expr*);

static void sqlite3Fts5ExprFree(Fts5Expr*);
static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2);

242741
242742
242743
242744
242745
242746
242747
242748






242749
242750
242751
242752
242753
242754
242755
242756
242757
242758
242759
242760
242761
242762
242763
242764
242765
242766
242767
242768



242769
242770
242771
242772
242773
242774
242775
** to parameter iFirst. Or, if iterating in ascending order (bDesc==1),
** then the first document visited must have a rowid smaller than or
** equal to iFirst.
**
** Return SQLITE_OK if successful, or an SQLite error code otherwise. It
** is not considered an error if the query does not match any documents.
*/
static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){






  Fts5ExprNode *pRoot = p->pRoot;
  int rc;                         /* Return code */

  p->pIndex = pIdx;
  p->bDesc = bDesc;
  rc = fts5ExprNodeFirst(p, pRoot);

  /* If not at EOF but the current rowid occurs earlier than iFirst in
  ** the iteration order, move to document iFirst or later. */
  if( rc==SQLITE_OK
   && 0==pRoot->bEof
   && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0
  ){
    rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
  }

  /* If the iterator is not at a real match, skip forward until it is. */
  while( pRoot->bNomatch && rc==SQLITE_OK ){
    assert( pRoot->bEof==0 );
    rc = fts5ExprNodeNext(p, pRoot, 0, 0);



  }
  return rc;
}

/*
** Move to the next document
**







|
>
>
>
>
>
>




















>
>
>







243254
243255
243256
243257
243258
243259
243260
243261
243262
243263
243264
243265
243266
243267
243268
243269
243270
243271
243272
243273
243274
243275
243276
243277
243278
243279
243280
243281
243282
243283
243284
243285
243286
243287
243288
243289
243290
243291
243292
243293
243294
243295
243296
243297
** to parameter iFirst. Or, if iterating in ascending order (bDesc==1),
** then the first document visited must have a rowid smaller than or
** equal to iFirst.
**
** Return SQLITE_OK if successful, or an SQLite error code otherwise. It
** is not considered an error if the query does not match any documents.
*/
static int sqlite3Fts5ExprFirst(
  Fts5Expr *p,
  Fts5Index *pIdx,
  i64 iFirst,
  i64 iLast,
  int bDesc
){
  Fts5ExprNode *pRoot = p->pRoot;
  int rc;                         /* Return code */

  p->pIndex = pIdx;
  p->bDesc = bDesc;
  rc = fts5ExprNodeFirst(p, pRoot);

  /* If not at EOF but the current rowid occurs earlier than iFirst in
  ** the iteration order, move to document iFirst or later. */
  if( rc==SQLITE_OK
   && 0==pRoot->bEof
   && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0
  ){
    rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
  }

  /* If the iterator is not at a real match, skip forward until it is. */
  while( pRoot->bNomatch && rc==SQLITE_OK ){
    assert( pRoot->bEof==0 );
    rc = fts5ExprNodeNext(p, pRoot, 0, 0);
  }
  if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){
    pRoot->bEof = 1;
  }
  return rc;
}

/*
** Move to the next document
**
251883
251884
251885
251886
251887
251888
251889


251890

251891
251892
251893
251894
251895
251896
251897
251898
251899
251900
/*
** The %_data table is completely empty when this function is called. This
** function populates it with the initial structure objects for each index,
** and the initial version of the "averages" record (a zero-byte blob).
*/
static int sqlite3Fts5IndexReinit(Fts5Index *p){
  Fts5Structure *pTmp;


  u8 tmpSpace[SZ_FTS5STRUCTURE(1)];

  fts5StructureInvalidate(p);
  fts5IndexDiscardData(p);
  pTmp = (Fts5Structure*)tmpSpace;
  memset(pTmp, 0, SZ_FTS5STRUCTURE(1));
  if( p->pConfig->bContentlessDelete ){
    pTmp->nOriginCntr = 1;
  }
  fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
  fts5StructureWrite(p, pTmp);
  return fts5IndexReturn(p);







>
>
|
>


|







252405
252406
252407
252408
252409
252410
252411
252412
252413
252414
252415
252416
252417
252418
252419
252420
252421
252422
252423
252424
252425
/*
** The %_data table is completely empty when this function is called. This
** function populates it with the initial structure objects for each index,
** and the initial version of the "averages" record (a zero-byte blob).
*/
static int sqlite3Fts5IndexReinit(Fts5Index *p){
  Fts5Structure *pTmp;
  union {
    Fts5Structure sFts;
    u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
  } uFts;
  fts5StructureInvalidate(p);
  fts5IndexDiscardData(p);
  pTmp = &uFts.sFts;
  memset(pTmp, 0, SZ_FTS5STRUCTURE(1));
  if( p->pConfig->bContentlessDelete ){
    pTmp->nOriginCntr = 1;
  }
  fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
  fts5StructureWrite(p, pTmp);
  return fts5IndexReturn(p);
255107
255108
255109
255110
255111
255112
255113











255114
255115
255116
255117
255118
255119
255120
  if( sqlite3_libversion_number()>=3008012 )
#endif
  {
    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
  }
#endif
}












static int fts5UsePatternMatch(
  Fts5Config *pConfig,
  struct sqlite3_index_constraint *p
){
  assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
  assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );







>
>
>
>
>
>
>
>
>
>
>







255632
255633
255634
255635
255636
255637
255638
255639
255640
255641
255642
255643
255644
255645
255646
255647
255648
255649
255650
255651
255652
255653
255654
255655
255656
  if( sqlite3_libversion_number()>=3008012 )
#endif
  {
    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
  }
#endif
}

static void fts5SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
#if SQLITE_VERSION_NUMBER>=3008002
#ifndef SQLITE_CORE
  if( sqlite3_libversion_number()>=3008002 )
#endif
  {
    pIdxInfo->estimatedRows = nRow;
  }
#endif
}

static int fts5UsePatternMatch(
  Fts5Config *pConfig,
  struct sqlite3_index_constraint *p
){
  assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
  assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
255243
255244
255245
255246
255247
255248
255249
255250
255251
255252
255253
255254
255255
255256
255257
255258
255259
255260
255261
255262
255263
255264
255265
255266
255267
255268

255269
255270
255271
255272
255273
255274
255275
          if( bSeenRank ) continue;
          idxStr[iIdxStr++] = 'r';
          bSeenRank = 1;
        }else{
          nSeenMatch++;
          idxStr[iIdxStr++] = 'M';
          sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
          idxStr += strlen(&idxStr[iIdxStr]);
          assert( idxStr[iIdxStr]=='\0' );
        }
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        pInfo->aConstraintUsage[i].omit = 1;
      }
    }else if( p->usable ){
      if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
        assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
        idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
        sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
        idxStr += strlen(&idxStr[iIdxStr]);
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        assert( idxStr[iIdxStr]=='\0' );
        nSeenMatch++;
      }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
        idxStr[iIdxStr++] = '=';
        bSeenEq = 1;
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;

      }
    }
  }

  if( bSeenEq==0 ){
    for(i=0; i<pInfo->nConstraint; i++){
      struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];







|


















>







255779
255780
255781
255782
255783
255784
255785
255786
255787
255788
255789
255790
255791
255792
255793
255794
255795
255796
255797
255798
255799
255800
255801
255802
255803
255804
255805
255806
255807
255808
255809
255810
255811
255812
          if( bSeenRank ) continue;
          idxStr[iIdxStr++] = 'r';
          bSeenRank = 1;
        }else{
          nSeenMatch++;
          idxStr[iIdxStr++] = 'M';
          sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
          iIdxStr += (int)strlen(&idxStr[iIdxStr]);
          assert( idxStr[iIdxStr]=='\0' );
        }
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        pInfo->aConstraintUsage[i].omit = 1;
      }
    }else if( p->usable ){
      if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
        assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
        idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
        sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
        idxStr += strlen(&idxStr[iIdxStr]);
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        assert( idxStr[iIdxStr]=='\0' );
        nSeenMatch++;
      }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
        idxStr[iIdxStr++] = '=';
        bSeenEq = 1;
        pInfo->aConstraintUsage[i].argvIndex = ++iCons;
        pInfo->aConstraintUsage[i].omit = 1;
      }
    }
  }

  if( bSeenEq==0 ){
    for(i=0; i<pInfo->nConstraint; i++){
      struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
255309
255310
255311
255312
255313
255314
255315
255316
255317


255318
255319
255320
255321
255322
255323
255324
255325
255326


255327
255328
255329
255330
255331
255332
255333
        idxFlags |= FTS5_BI_ORDER_DESC;
      }
    }
  }

  /* Calculate the estimated cost based on the flags set in idxFlags. */
  if( bSeenEq ){
    pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
    if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);


  }else if( bSeenLt && bSeenGt ){
    pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
  }else if( bSeenLt || bSeenGt ){
    pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
  }else{
    pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
  }
  for(i=1; i<nSeenMatch; i++){
    pInfo->estimatedCost *= 0.4;


  }

  pInfo->idxNum = idxFlags;
  return SQLITE_OK;
}

static int fts5NewTransaction(Fts5FullTable *pTab){







|
|
>
>
|
|
|
|
|
|
|
|
|
>
>







255846
255847
255848
255849
255850
255851
255852
255853
255854
255855
255856
255857
255858
255859
255860
255861
255862
255863
255864
255865
255866
255867
255868
255869
255870
255871
255872
255873
255874
        idxFlags |= FTS5_BI_ORDER_DESC;
      }
    }
  }

  /* Calculate the estimated cost based on the flags set in idxFlags. */
  if( bSeenEq ){
    pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0;
    fts5SetUniqueFlag(pInfo);
    fts5SetEstimatedRows(pInfo, 1);
  }else{
    if( bSeenLt && bSeenGt ){
      pInfo->estimatedCost = nSeenMatch ? 5000.0 :   750000.0;
    }else if( bSeenLt || bSeenGt ){
      pInfo->estimatedCost = nSeenMatch ? 7500.0 :  2250000.0;
    }else{
      pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0;
    }
    for(i=1; i<nSeenMatch; i++){
      pInfo->estimatedCost *= 0.4;
    }
    fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0));
  }

  pInfo->idxNum = idxFlags;
  return SQLITE_OK;
}

static int fts5NewTransaction(Fts5FullTable *pTab){
255518
255519
255520
255521
255522
255523
255524
255525


255526
255527
255528
255529
255530
255531
255532
  int rc = SQLITE_OK;
  assert( *pbSkip==0 );
  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
    Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
    int bDesc = pCsr->bDesc;
    i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);

    rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);


    if( rc==SQLITE_OK &&  iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
      *pbSkip = 1;
    }

    CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
    fts5CsrNewrow(pCsr);
    if( sqlite3Fts5ExprEof(pCsr->pExpr) ){







|
>
>







256059
256060
256061
256062
256063
256064
256065
256066
256067
256068
256069
256070
256071
256072
256073
256074
256075
  int rc = SQLITE_OK;
  assert( *pbSkip==0 );
  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
    Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
    int bDesc = pCsr->bDesc;
    i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);

    rc = sqlite3Fts5ExprFirst(
        pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc
    );
    if( rc==SQLITE_OK &&  iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
      *pbSkip = 1;
    }

    CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
    fts5CsrNewrow(pCsr);
    if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
255690
255691
255692
255693
255694
255695
255696
255697


255698
255699
255700
255701
255702
255703
255704

  return rc;
}

static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
  int rc;
  Fts5Expr *pExpr = pCsr->pExpr;
  rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);


  if( sqlite3Fts5ExprEof(pExpr) ){
    CsrFlagSet(pCsr, FTS5CSR_EOF);
  }
  fts5CsrNewrow(pCsr);
  return rc;
}








|
>
>







256233
256234
256235
256236
256237
256238
256239
256240
256241
256242
256243
256244
256245
256246
256247
256248
256249

  return rc;
}

static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
  int rc;
  Fts5Expr *pExpr = pCsr->pExpr;
  rc = sqlite3Fts5ExprFirst(
      pExpr, pTab->p.pIndex, pCsr->iFirstRowid, pCsr->iLastRowid, bDesc
  );
  if( sqlite3Fts5ExprEof(pExpr) ){
    CsrFlagSet(pCsr, FTS5CSR_EOF);
  }
  fts5CsrNewrow(pCsr);
  return rc;
}

258175
258176
258177
258178
258179
258180
258181
258182
258183
258184
258185
258186
258187
258188
258189
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2025-07-30 16:17:14 cf7163f82ca380958a79350473b2c5a2cebda7496d6d575fa2835c362010fea1", -1, SQLITE_TRANSIENT);
}

/*
** Implementation of fts5_locale(LOCALE, TEXT) function.
**
** If parameter LOCALE is NULL, or a zero-length string, then a copy of
** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as







|







258720
258721
258722
258723
258724
258725
258726
258727
258728
258729
258730
258731
258732
258733
258734
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2025-09-24 19:10:58 821cc0e421bc14a68ebaee507e38a900e0c84ff6ba7ee95bf796cad387755232", -1, SQLITE_TRANSIENT);
}

/*
** Implementation of fts5_locale(LOCALE, TEXT) function.
**
** If parameter LOCALE is NULL, or a zero-length string, then a copy of
** TEXT is returned. Otherwise, both LOCALE and TEXT are interpreted as
Changes to extsrc/sqlite3.h.
144
145
146
147
148
149
150
151



152
153
154
155
156
157
158
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.51.0"
#define SQLITE_VERSION_NUMBER 3051000
#define SQLITE_SOURCE_ID      "2025-07-30 16:17:14 cf7163f82ca380958a79350473b2c5a2cebda7496d6d575fa2835c362010fea1"




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







|
>
>
>







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.51.0"
#define SQLITE_VERSION_NUMBER 3051000
#define SQLITE_SOURCE_ID      "2025-09-24 19:10:58 821cc0e421bc14a68ebaee507e38a900e0c84ff6ba7ee95bf796cad387755232"
#define SQLITE_SCM_BRANCH     "trunk"
#define SQLITE_SCM_TAGS       ""
#define SQLITE_SCM_DATETIME   "2025-09-24T19:10:58.215Z"

/*
** 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
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347

2348
2349

2350
2351

2352
2353

2354
2355
2356
2357
2358
2359
2360
** SQLite version 3.35.0, TEMP views are still allowed even if
** this option is off.  So, in other words, this option now only disables
** views in the main database schema or in the schemas of ATTACH-ed
** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There must be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or

** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.

** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled

** following this call.  The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd>

**
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].







|
|
|
|
|
>
|
<
>
|
|
>
|
|
>







2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352

2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
** SQLite version 3.35.0, TEMP views are still allowed even if
** this option is off.  So, in other words, this option now only disables
** views in the main database schema or in the schemas of ATTACH-ed
** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable using the
** [fts3_tokenizer()] function - part of the [FTS3] full-text search engine
** extension - without using bound parameters as the parameters. Doing so
** is disabled by default. There must be two additional arguments. The first
** argument is an integer. If it is passed 0, then using fts3_tokenizer()
** without bound parameters is disabled. If it is passed a positive value,
** then calling fts3_tokenizer without bound parameters is enabled. If it

** is passed a negative value, this setting is not modified - this can be
** used to query for the current setting. The second parameter is a pointer
** to an integer into which is written 0 or 1 to indicate the current value
** of this setting (after it is modified, if applicable).  The second
** parameter may be a NULL pointer, in which case the value of the setting
** is not reported back. Refer to [FTS3] documentation for further details.
** </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
4196
4197
4198
4199
4200
4201
4202




























4203
4204
4205
4206
4207
4208
4209
SQLITE_API int sqlite3_errcode(sqlite3 *db);
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *sqlite3_errstr(int);
SQLITE_API int sqlite3_error_offset(sqlite3 *db);





























/*
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement that
** has been compiled into binary form and is ready to be evaluated.
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
SQLITE_API int sqlite3_errcode(sqlite3 *db);
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *sqlite3_errstr(int);
SQLITE_API int sqlite3_error_offset(sqlite3 *db);

/*
** CAPI3REF: Set Error Codes And Message
** METHOD: sqlite3
**
** Set the error code of the database handle passed as the first argument
** to errcode, and the error message to a copy of nul-terminated string
** zErrMsg. If zErrMsg is passed NULL, then the error message is set to
** the default message associated with the supplied error code.  Subsequent
** calls to [sqlite3_errcode()] and [sqlite3_errmsg()] and similar will
** return the values set by this routine in place of what was previously
** set by SQLite itself.
**
** This function returns SQLITE_OK if the error code and error message are
** successfully set, SQLITE_NOMEM if an OOM occurs, and SQLITE_MISUSE if
** the database handle is NULL or invalid.
**
** The error code and message set by this routine remains in effect until
** they are changed, either by another call to this routine or until they are
** changed to by SQLite itself to reflect the result of some subsquent
** API call.
**
** This function is intended for use by SQLite extensions or wrappers.  The
** idea is that an extension or wrapper can use this routine to set error
** messages and error codes and thus behave more like a core SQLite
** feature from the point of view of an application.
*/
SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zErrMsg);

/*
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement that
** has been compiled into binary form and is ready to be evaluated.
**
6206
6207
6208
6209
6210
6211
6212

6213
6214
6215
6216
6217
6218
6219
** with a [database connection].
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
** to be attached to [database connection] D using name N.  Subsequent
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
** or a NULL pointer if there were no prior calls to
** sqlite3_set_clientdata() with the same values of D and N.
** Names are compared using strcmp() and are thus case sensitive.

**
** If P and X are both non-NULL, then the destructor X is invoked with
** argument P on the first of the following occurrences:
** <ul>
** <li> An out-of-memory error occurs during the call to
**      sqlite3_set_clientdata() which attempts to register pointer P.
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made







>







6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
** with a [database connection].
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
** to be attached to [database connection] D using name N.  Subsequent
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
** or a NULL pointer if there were no prior calls to
** sqlite3_set_clientdata() with the same values of D and N.
** Names are compared using strcmp() and are thus case sensitive.
** It returns 0 on success and SQLITE_NOMEM on allocation failure.
**
** If P and X are both non-NULL, then the destructor X is invoked with
** argument P on the first of the following occurrences:
** <ul>
** <li> An out-of-memory error occurs during the call to
**      sqlite3_set_clientdata() which attempts to register pointer P.
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794



9795

9796
9797
9798









9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831

9832
9833
9834
9835
9836
9837
9838
9839
9840
** is a copy of the third parameter passed to sqlite3_wal_hook() when
** registering the callback. ^The second is a copy of the database handle.
** ^The third parameter is the name of the database that was written to -
** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
** is the number of pages currently in the write-ahead log file,
** including those that were just committed.
**
** The callback function should normally return [SQLITE_OK].  ^If an error
** code is returned, that error will propagate back up through the
** SQLite code base to cause the statement that provoked the callback
** to report an error, though the commit will have still occurred. If the
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
** that does not correspond to any valid SQLite error code, the results
** are undefined.
**
** A single database handle may have at most a single write-ahead log callback
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
** previously registered write-ahead log callback. ^The return value is



** a copy of the third parameter from the previous call, if any, or 0.

** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
** overwrite any prior [sqlite3_wal_hook()] settings.









*/
SQLITE_API void *sqlite3_wal_hook(
  sqlite3*,
  int(*)(void *,sqlite3*,const char*,int),
  void*
);

/*
** CAPI3REF: Configure an auto-checkpoint
** METHOD: sqlite3
**
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
** [sqlite3_wal_hook()] that causes any database on [database connection] D
** to automatically [checkpoint]
** after committing a transaction if there are N or
** more frames in the [write-ahead log] file.  ^Passing zero or
** a negative value as the nFrame parameter disables automatic
** checkpoints entirely.
**
** ^The callback registered by this function replaces any existing callback
** registered using [sqlite3_wal_hook()].  ^Likewise, registering a callback
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
** configured by this function.
**
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.
**
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages.  The use of this interface

** is only necessary if the default setting is found to be suboptimal
** for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);

/*
** CAPI3REF: Checkpoint a database
** METHOD: sqlite3
**







|







|
|
|
>
>
>
|
>
|
|
|
>
>
>
>
>
>
>
>
>
















|















|
>
|
|







9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
** is a copy of the third parameter passed to sqlite3_wal_hook() when
** registering the callback. ^The second is a copy of the database handle.
** ^The third parameter is the name of the database that was written to -
** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
** is the number of pages currently in the write-ahead log file,
** including those that were just committed.
**
** ^The callback function should normally return [SQLITE_OK].  ^If an error
** code is returned, that error will propagate back up through the
** SQLite code base to cause the statement that provoked the callback
** to report an error, though the commit will have still occurred. If the
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
** that does not correspond to any valid SQLite error code, the results
** are undefined.
**
** ^A single database handle may have at most a single write-ahead log
** callback registered at one time. ^Calling [sqlite3_wal_hook()]
** replaces the default behavior or previously registered write-ahead
** log callback.
**
** ^The return value is a copy of the third parameter from the
** previous call, if any, or 0.
**
** ^The [sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and
** will overwrite any prior [sqlite3_wal_hook()] settings.
**
** ^If a write-ahead log callback is set using this function then
** [sqlite3_wal_checkpoint_v2()] or [PRAGMA wal_checkpoint]
** should be invoked periodically to keep the write-ahead log file
** from growing without bound.
**
** ^Passing a NULL pointer for the callback disables automatic
** checkpointing entirely. To re-enable the default behavior, call
** sqlite3_wal_autocheckpoint(db,1000) or use [PRAGMA wal_checkpoint].
*/
SQLITE_API void *sqlite3_wal_hook(
  sqlite3*,
  int(*)(void *,sqlite3*,const char*,int),
  void*
);

/*
** CAPI3REF: Configure an auto-checkpoint
** METHOD: sqlite3
**
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
** [sqlite3_wal_hook()] that causes any database on [database connection] D
** to automatically [checkpoint]
** after committing a transaction if there are N or
** more frames in the [write-ahead log] file.  ^Passing zero or
** a negative value as the N parameter disables automatic
** checkpoints entirely.
**
** ^The callback registered by this function replaces any existing callback
** registered using [sqlite3_wal_hook()].  ^Likewise, registering a callback
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
** configured by this function.
**
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.
**
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages.
**
** ^The use of this interface is only necessary if the default setting
** is found to be suboptimal for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);

/*
** CAPI3REF: Checkpoint a database
** METHOD: sqlite3
**
9891
9892
9893
9894
9895
9896
9897





9898
9899
9900
9901
9902
9903
9904
**   ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
**   database writer attempts while it is pending, but does not impede readers.
**
** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
**   ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
**   addition that it also truncates the log file to zero bytes just prior
**   to a successful return.





** </dl>
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
** the log file or to -1 if the checkpoint could not run because
** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
** log file (including any that were already checkpointed before the function







>
>
>
>
>







9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
**   ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
**   database writer attempts while it is pending, but does not impede readers.
**
** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
**   ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
**   addition that it also truncates the log file to zero bytes just prior
**   to a successful return.
**
** <dt>SQLITE_CHECKPOINT_NOOP<dd>
**   ^This mode always checkpoints zero frames. The only reason to invoke
**   a NOOP checkpoint is to access the values returned by
**   sqlite3_wal_checkpoint_v2() via output parameters *pnLog and *pnCkpt.
** </dl>
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
** the log file or to -1 if the checkpoint could not run because
** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
** log file (including any that were already checkpointed before the function
9961
9962
9963
9964
9965
9966
9967

9968
9969
9970
9971
9972
9973
9974
** KEYWORDS: {checkpoint mode}
**
** These constants define all valid values for the "checkpoint mode" passed
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/

#define SQLITE_CHECKPOINT_PASSIVE  0  /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL     1  /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3  /* Like RESTART but also truncate WAL */

/*
** CAPI3REF: Virtual Table Interface Configuration







>







10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
** KEYWORDS: {checkpoint mode}
**
** These constants define all valid values for the "checkpoint mode" passed
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/
#define SQLITE_CHECKPOINT_NOOP    -1  /* Do no work at all */
#define SQLITE_CHECKPOINT_PASSIVE  0  /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL     1  /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3  /* Like RESTART but also truncate WAL */

/*
** CAPI3REF: Virtual Table Interface Configuration
10788
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800
10801
10802
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
** to avoid a memory leak.
**
** The [sqlite3_snapshot_get()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot **ppSnapshot
);

/*
** CAPI3REF: Start a read transaction on an historical snapshot







|







10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
** to avoid a memory leak.
**
** The [sqlite3_snapshot_get()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API int sqlite3_snapshot_get(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot **ppSnapshot
);

/*
** CAPI3REF: Start a read transaction on an historical snapshot
10837
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
** after the most recent I/O on the database connection.)^
** (Hint: Run "[PRAGMA application_id]" against a newly opened
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot *pSnapshot
);

/*
** CAPI3REF: Destroy a snapshot
** DESTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
** The application must eventually free every [sqlite3_snapshot] object
** using this routine to avoid a memory leak.
**
** The [sqlite3_snapshot_free()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);

/*
** CAPI3REF: Compare the ages of two snapshot handles.
** METHOD: sqlite3_snapshot
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
** of two valid snapshot handles.







|
















|







10892
10893
10894
10895
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
** after the most recent I/O on the database connection.)^
** (Hint: Run "[PRAGMA application_id]" against a newly opened
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API int sqlite3_snapshot_open(
  sqlite3 *db,
  const char *zSchema,
  sqlite3_snapshot *pSnapshot
);

/*
** CAPI3REF: Destroy a snapshot
** DESTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
** The application must eventually free every [sqlite3_snapshot] object
** using this routine to avoid a memory leak.
**
** The [sqlite3_snapshot_free()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*);

/*
** CAPI3REF: Compare the ages of two snapshot handles.
** METHOD: sqlite3_snapshot
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
** of two valid snapshot handles.
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890
10891
10892
10893
10894
10895
** Otherwise, this API returns a negative value if P1 refers to an older
** snapshot than P2, zero if the two handles refer to the same database
** snapshot, and a positive value if P1 is a newer snapshot than P2.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
  sqlite3_snapshot *p1,
  sqlite3_snapshot *p2
);

/*
** CAPI3REF: Recover snapshots from a wal file
** METHOD: sqlite3_snapshot







|







10936
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947
10948
10949
10950
** Otherwise, this API returns a negative value if P1 refers to an older
** snapshot than P2, zero if the two handles refer to the same database
** snapshot, and a positive value if P1 is a newer snapshot than P2.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API int sqlite3_snapshot_cmp(
  sqlite3_snapshot *p1,
  sqlite3_snapshot *p2
);

/*
** CAPI3REF: Recover snapshots from a wal file
** METHOD: sqlite3_snapshot
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);

/*
** CAPI3REF: Serialize a database
**
** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
** memory that is a serialization of the S database on
** [database connection] D.  If S is a NULL pointer, the main database is used.







|







10964
10965
10966
10967
10968
10969
10970
10971
10972
10973
10974
10975
10976
10977
10978
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);

/*
** CAPI3REF: Serialize a database
**
** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
** memory that is a serialization of the S database on
** [database connection] D.  If S is a NULL pointer, the main database is used.
10983
10984
10985
10986
10987
10988
10989
10990

10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
#define SQLITE_SERIALIZE_NOCOPY 0x001   /* Do no memory allocations */

/*
** CAPI3REF: Deserialize a database
**
** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
** [database connection] D to disconnect from database S and then
** reopen S as an in-memory database based on the serialization contained

** in P.  The serialized database P is N bytes in size.  M is the size of
** the buffer P, which might be larger than N.  If M is larger than N, and
** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
** permitted to add content to the in-memory database as long as the total
** size does not exceed M bytes.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
** connection closes.  If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
** SQLite will try to increase the buffer size using sqlite3_realloc64()
** if writes on the database cause it to grow larger than M bytes.
**







|
>
|
|
|
|
|







11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
#define SQLITE_SERIALIZE_NOCOPY 0x001   /* Do no memory allocations */

/*
** CAPI3REF: Deserialize a database
**
** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
** [database connection] D to disconnect from database S and then
** reopen S as an in-memory database based on the serialization
** contained in P.  If S is a NULL pointer, the main database is
** used. The serialized database P is N bytes in size.  M is the size
** of the buffer P, which might be larger than N.  If M is larger than
** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
** SQLite is permitted to add content to the in-memory database as
** long as the total size does not exceed M bytes.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
** connection closes.  If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
** SQLite will try to increase the buffer size using sqlite3_realloc64()
** if writes on the database cause it to grow larger than M bytes.
**
12313
12314
12315
12316
12317
12318
12319









12320
12321
12322
12323
12324
12325
12326

/*
** CAPI3REF: Apply A Changeset To A Database
**
** Apply a changeset or patchset to a database. These functions attempt to
** update the "main" database attached to handle db with the changes found in
** the changeset passed via the second and third arguments.









**
** The fourth argument (xFilter) passed to these functions is the "filter
** callback". This may be passed NULL, in which case all changes in the
** changeset are applied to the database. For sqlite3changeset_apply() and
** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once
** for each table affected by at least one change in the changeset. In this
** case the table name is passed as the second argument, and a copy of







>
>
>
>
>
>
>
>
>







12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391

/*
** CAPI3REF: Apply A Changeset To A Database
**
** Apply a changeset or patchset to a database. These functions attempt to
** update the "main" database attached to handle db with the changes found in
** the changeset passed via the second and third arguments.
**
** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned. Additionally, starting with version 3.51.0,
** an error code and error message that may be accessed using the
** [sqlite3_errcode()] and [sqlite3_errmsg()] APIs are left in the database
** handle.
**
** The fourth argument (xFilter) passed to these functions is the "filter
** callback". This may be passed NULL, in which case all changes in the
** changeset are applied to the database. For sqlite3changeset_apply() and
** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once
** for each table affected by at least one change in the changeset. In this
** case the table name is passed as the second argument, and a copy of
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
** </dl>
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
** This can be used to further customize the application's conflict
** resolution strategy.
**
** All changes made by these functions are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
**
** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
** may set (*ppRebase) to point to a "rebase" that may be used with the
** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
** is set to the size of the buffer in bytes. It is the responsibility of the
** caller to eventually free any such buffer using sqlite3_free(). The buffer
** is only allocated and populated if one or more conflicts were encountered







<
<
<
<
<
<







12516
12517
12518
12519
12520
12521
12522






12523
12524
12525
12526
12527
12528
12529
** </dl>
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
** This can be used to further customize the application's conflict
** resolution strategy.
**






** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
** may set (*ppRebase) to point to a "rebase" that may be used with the
** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
** is set to the size of the buffer in bytes. It is the responsibility of the
** caller to eventually free any such buffer using sqlite3_free(). The buffer
** is only allocated and populated if one or more conflicts were encountered
Changes to src/browse.c.
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
*/
static const char zComputeFileAgeSetup[] =
@ CREATE TABLE IF NOT EXISTS temp.fileage(
@   fnid INTEGER PRIMARY KEY,
@   fid INTEGER,
@   mid INTEGER,
@   mtime DATETIME,
@   pathname TEXT

@ );
@ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;
;

static const char zComputeFileAgeRun[] =
@ WITH RECURSIVE
@  ckin(x) AS (VALUES(:ckin)
@              UNION
@              SELECT plink.pid
@                FROM ckin, plink
@               WHERE plink.cid=ckin.x)
@ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname)
@   SELECT filename.fnid, mlink.fid, mlink.mid, event.mtime, filename.name

@     FROM foci, filename, blob, mlink, event
@    WHERE foci.checkinID=:ckin
@      AND foci.filename GLOB :glob
@      AND filename.name=foci.filename
@      AND blob.uuid=foci.uuid
@      AND mlink.fid=blob.rid
@      AND mlink.fid!=mlink.pid







|
>











|
|
>







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
*/
static const char zComputeFileAgeSetup[] =
@ CREATE TABLE IF NOT EXISTS temp.fileage(
@   fnid INTEGER PRIMARY KEY,
@   fid INTEGER,
@   mid INTEGER,
@   mtime DATETIME,
@   pathname TEXT,
@   uuid TEXT
@ );
@ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;
;

static const char zComputeFileAgeRun[] =
@ WITH RECURSIVE
@  ckin(x) AS (VALUES(:ckin)
@              UNION
@              SELECT plink.pid
@                FROM ckin, plink
@               WHERE plink.cid=ckin.x)
@ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname, uuid)
@   SELECT filename.fnid, mlink.fid, mlink.mid, event.mtime, filename.name,
@          foci.uuid
@     FROM foci, filename, blob, mlink, event
@    WHERE foci.checkinID=:ckin
@      AND foci.filename GLOB :glob
@      AND filename.name=foci.filename
@      AND blob.uuid=foci.uuid
@      AND mlink.fid=blob.rid
@      AND mlink.fid!=mlink.pid
Changes to src/cgi.c.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260


261
262
263
264
265
266
267
268
  cgi_combine_header_and_body();
  return blob_buffer(&cgiContent[0]);
}

/*
** Additional information used to form the HTTP reply
*/
static const char *zContentType = "text/html";   /* Content type of the reply */
static const char *zReplyStatus = "OK";          /* Reply status description */
static int iReplyStatus = 200;               /* Reply status code */
static Blob extraHeader = BLOB_INITIALIZER;  /* Extra header text */
static int rangeStart = 0;                   /* Start of Range: */
static int rangeEnd = 0;                     /* End of Range: plus 1 */

/*
** Set the reply content type.
**
** The reply content type defaults to "text/html".  It only needs to be
** changed (by calling this routine) in the exceptional case where some
** other content type is being returned.
*/
void cgi_set_content_type(const char *zType){


  zContentType = fossil_strdup(zType);
}

/*
** Erase any existing reply content.  Replace is with a pNewContent.
**
** This routine erases pNewContent.  In other words, it move pNewContent
** into the content buffer.







|














>
>
|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  cgi_combine_header_and_body();
  return blob_buffer(&cgiContent[0]);
}

/*
** Additional information used to form the HTTP reply
*/
static const char *zReplyMimeType = "text/html"; /* Content type of the reply */
static const char *zReplyStatus = "OK";          /* Reply status description */
static int iReplyStatus = 200;               /* Reply status code */
static Blob extraHeader = BLOB_INITIALIZER;  /* Extra header text */
static int rangeStart = 0;                   /* Start of Range: */
static int rangeEnd = 0;                     /* End of Range: plus 1 */

/*
** Set the reply content type.
**
** The reply content type defaults to "text/html".  It only needs to be
** changed (by calling this routine) in the exceptional case where some
** other content type is being returned.
*/
void cgi_set_content_type(const char *zType){
  int i;
  for(i=0; zType[i]>='+' && zType[i]<='z'; i++){}
  zReplyMimeType = fossil_strndup(zType, i);
}

/*
** Erase any existing reply content.  Replace is with a pNewContent.
**
** This routine erases pNewContent.  In other words, it move pNewContent
** into the content buffer.
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
*/
static int is_gzippable(void){
  if( g.fNoHttpCompress ) return 0;
  if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
  /* Maintenance note: this oddball structure is intended to make
  ** adding new mimetypes to this list less of a performance hit than
  ** doing a strcmp/glob over a growing set of compressible types. */
  switch(zContentType ? *zContentType : 0){
    case (int)'a':
      if(0==fossil_strncmp("application/",zContentType,12)){
        const char * z = &zContentType[12];
        switch(*z){
          case (int)'j':
            return fossil_strcmp("javascript", z)==0
                || fossil_strcmp("json", z)==0;
          case (int)'w': return fossil_strcmp("wasm", z)==0;
          case (int)'x':
            return fossil_strcmp("x-tcl", z)==0
                || fossil_strcmp("x-tar", z)==0;
          default:
            return sqlite3_strglob("*xml", z)==0;
        }
      }
      break;
    case (int)'i':
      return fossil_strcmp(zContentType, "image/svg+xml")==0
        || fossil_strcmp(zContentType, "image/vnd.microsoft.icon")==0;
    case (int)'t':
      return fossil_strncmp(zContentType, "text/", 5)==0;
  }
  return 0;
}


/*
** The following routines read or write content from/to the wire for







|

|
|














|
|

|







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
*/
static int is_gzippable(void){
  if( g.fNoHttpCompress ) return 0;
  if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
  /* Maintenance note: this oddball structure is intended to make
  ** adding new mimetypes to this list less of a performance hit than
  ** doing a strcmp/glob over a growing set of compressible types. */
  switch(zReplyMimeType ? *zReplyMimeType : 0){
    case (int)'a':
      if(0==fossil_strncmp("application/",zReplyMimeType,12)){
        const char * z = &zReplyMimeType[12];
        switch(*z){
          case (int)'j':
            return fossil_strcmp("javascript", z)==0
                || fossil_strcmp("json", z)==0;
          case (int)'w': return fossil_strcmp("wasm", z)==0;
          case (int)'x':
            return fossil_strcmp("x-tcl", z)==0
                || fossil_strcmp("x-tar", z)==0;
          default:
            return sqlite3_strglob("*xml", z)==0;
        }
      }
      break;
    case (int)'i':
      return fossil_strcmp(zReplyMimeType, "image/svg+xml")==0
        || fossil_strcmp(zReplyMimeType, "image/vnd.microsoft.icon")==0;
    case (int)'t':
      return fossil_strncmp(zReplyMimeType, "text/", 5)==0;
  }
  return 0;
}


/*
** The following routines read or write content from/to the wire for
400
401
402
403
404
405
406


407
408
409
410
411
412
413
  if( !g.httpUseSSL ){
    return fread(ptr, 1, nmemb, g.httpIn);
  }
#ifdef FOSSIL_ENABLE_SSL
  return ssl_read_server(g.httpSSLConn, ptr, nmemb, 1);
#else
  fossil_fatal("SSL not available");


#endif
}

/* Works like feof():
**
** Return true if end-of-input has been reached.
*/







>
>







402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  if( !g.httpUseSSL ){
    return fread(ptr, 1, nmemb, g.httpIn);
  }
#ifdef FOSSIL_ENABLE_SSL
  return ssl_read_server(g.httpSSLConn, ptr, nmemb, 1);
#else
  fossil_fatal("SSL not available");
  /* NOT REACHED */
  return 0;
#endif
}

/* Works like feof():
**
** Return true if end-of-input has been reached.
*/
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
    fflush(g.httpOut);
  }
}

/*
** Given a Content-Type value, returns a string suitable for appending
** to the Content-Type header for adding (or not) the "; charset=..."
** part. It returns an empty string for most types or if zContentType
** is NULL.
**
** See forum post f60dece061c364d1 for the discussions which lead to
** this. Previously we always appended the charset, but WASM loaders
** are pedantic and refuse to load any responses which have a
** charset. Also, adding a charset is not strictly appropriate for
** most types (and not required for many others which may ostensibly
** benefit from one, as detailed in that forum post).
*/
static const char * content_type_charset(const char *zContentType){
  if(0==fossil_strncmp(zContentType,"text/",5)){
    return "; charset=utf-8";
  }
  return "";
}

/*
** Generate the reply to a web request.  The output might be an







|









|
|







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
    fflush(g.httpOut);
  }
}

/*
** Given a Content-Type value, returns a string suitable for appending
** to the Content-Type header for adding (or not) the "; charset=..."
** part. It returns an empty string for most types or if zReplyMimeType
** is NULL.
**
** See forum post f60dece061c364d1 for the discussions which lead to
** this. Previously we always appended the charset, but WASM loaders
** are pedantic and refuse to load any responses which have a
** charset. Also, adding a charset is not strictly appropriate for
** most types (and not required for many others which may ostensibly
** benefit from one, as detailed in that forum post).
*/
static const char * content_type_charset(const char *zReplyMimeType){
  if(0==fossil_strncmp(zReplyMimeType,"text/",5)){
    return "; charset=utf-8";
  }
  return "";
}

/*
** Generate the reply to a web request.  The output might be an
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
    blob_appendf(&hdr, "X-UA-Compatible: IE=edge\r\n");
  }else{
    assert( rangeEnd==0 );
    blob_appendf(&hdr, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }
  if( etag_tag()[0]!=0
   && iReplyStatus==200
   && strcmp(zContentType,"text/html")!=0
  ){
    /* Do not cache HTML replies as those will have been generated and
    ** will likely, therefore, contains a nonce and we want that nonce to
    ** be different every time. */
    blob_appendf(&hdr, "ETag: \"%s\"\r\n", etag_tag());
    blob_appendf(&hdr, "Cache-Control: max-age=%d\r\n", etag_maxage());
    if( etag_mtime()>0 ){







|







502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
    blob_appendf(&hdr, "X-UA-Compatible: IE=edge\r\n");
  }else{
    assert( rangeEnd==0 );
    blob_appendf(&hdr, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }
  if( etag_tag()[0]!=0
   && iReplyStatus==200
   && strcmp(zReplyMimeType,"text/html")!=0
  ){
    /* Do not cache HTML replies as those will have been generated and
    ** will likely, therefore, contains a nonce and we want that nonce to
    ** be different every time. */
    blob_appendf(&hdr, "ETag: \"%s\"\r\n", etag_tag());
    blob_appendf(&hdr, "Cache-Control: max-age=%d\r\n", etag_maxage());
    if( etag_mtime()>0 ){
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
  ** highlighter scripts.
  **
  ** These headers are probably best added by the web server hosting fossil as
  ** a CGI script.
  */

  if( iReplyStatus!=304 ) {
    blob_appendf(&hdr, "Content-Type: %s%s\r\n", zContentType,
                 content_type_charset(zContentType));
    if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
      cgi_combine_header_and_body();
      blob_compress(&cgiContent[0], &cgiContent[0]);
    }

    if( is_gzippable() && iReplyStatus!=206 ){
      int i;
      gzip_begin(0);







|
|
|







544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  ** highlighter scripts.
  **
  ** These headers are probably best added by the web server hosting fossil as
  ** a CGI script.
  */

  if( iReplyStatus!=304 ) {
    blob_appendf(&hdr, "Content-Type: %s%s\r\n", zReplyMimeType,
                 content_type_charset(zReplyMimeType));
    if( fossil_strcmp(zReplyMimeType,"application/x-fossil")==0 ){
      cgi_combine_header_and_body();
      blob_compress(&cgiContent[0], &cgiContent[0]);
    }

    if( is_gzippable() && iReplyStatus!=206 ){
      int i;
      gzip_begin(0);
942
943
944
945
946
947
948










949
950
951
952
953
954
955
/*
** Add an environment varaible value to the parameter set.  The zName
** portion is fixed but a copy is be made of zValue.
*/
void cgi_setenv(const char *zName, const char *zValue){
  cgi_set_parameter_nocopy(zName, fossil_strdup(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
** VALUE may be url-encoded ("+" for space, "%HH" for other special
** characters).  But this routine assumes that NAME contains no







>
>
>
>
>
>
>
>
>
>







946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
/*
** Add an environment varaible value to the parameter set.  The zName
** portion is fixed but a copy is be made of zValue.
*/
void cgi_setenv(const char *zName, const char *zValue){
  cgi_set_parameter_nocopy(zName, fossil_strdup(zValue), 0);
}

/*
** Returns true if NUL-terminated z contains any non-NUL
** control characters (<0x20, 32d).
*/
static int contains_ctrl(const char *z){
  assert(z);
  for( ; *z>=0x20; ++z ){}
  return 0!=*z;
}

/*
** 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
** VALUE may be url-encoded ("+" for space, "%HH" for other special
** characters).  But this routine assumes that NAME contains no
972
973
974
975
976
977
978




979
980
981
982
983
984
985
986
987
**
** Parameters are separated by the "terminator" character.  Whitespace
** 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++; }







>
>
>
>

|







986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
**
** Parameters are separated by the "terminator" character.  Whitespace
** 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.
**
** If bPermitCtrl is false and the decoded value of any entry in z
** contains control characters (<0x20, 32d) then that key/value pair
** are skipped.
*/
static void add_param_list(char *z, int terminator, int bPermitCtrl){
  int isQP = terminator=='&';
  while( *z ){
    char *zName;
    char *zValue;
    while( fossil_isspace(*z) ){ z++; }
    zName = z;
    while( *z && *z!='=' && *z!=terminator ){ z++; }
996
997
998
999
1000
1001
1002



1003
1004
1005
1006
1007
1008
1009
1010
      }
      dehttpize(zValue);
    }else{
      if( *z ){ *z++ = 0; }
      zValue = "";
    }
    if( zName[0] && fossil_no_strange_characters(zName+1) ){



      if( fossil_islower(zName[0]) ){
        cgi_set_parameter_nocopy(zName, zValue, isQP);
      }else if( fossil_isupper(zName[0]) ){
        cgi_set_parameter_nocopy_tolower(zName, zValue, isQP);
      }
    }
#ifdef FOSSIL_ENABLE_JSON
    json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );







>
>
>
|







1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
      }
      dehttpize(zValue);
    }else{
      if( *z ){ *z++ = 0; }
      zValue = "";
    }
    if( zName[0] && fossil_no_strange_characters(zName+1) ){
      if( 0==bPermitCtrl && contains_ctrl(zValue) ){
        continue /* Reject it. An argument could be made
                 ** for break instead of continue. */;
      }else if( fossil_islower(zName[0]) ){
        cgi_set_parameter_nocopy(zName, zValue, isQP);
      }else if( fossil_isupper(zName[0]) ){
        cgi_set_parameter_nocopy_tolower(zName, zValue, isQP);
      }
    }
#ifdef FOSSIL_ENABLE_JSON
    json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
*/
int cgi_setup_query_string(void){
  int rc = 0;
  char * z = (char*)P("QUERY_STRING");
  if( z ){
    rc = 0x01;
    z = fossil_strdup(z);
    add_param_list(z, '&');
    z = (char*)P("skin");
    if( z ){
      char *zErr = skin_use_alternative(z, 2, SKIN_FROM_QPARAM);
      rc |= 0x02;
      if( !zErr && P("once")==0 ){
        cookie_write_parameter("skin","skin",z);
        /* Per /chat discussion, passing ?skin=... without "once"







|







1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
*/
int cgi_setup_query_string(void){
  int rc = 0;
  char * z = (char*)P("QUERY_STRING");
  if( z ){
    rc = 0x01;
    z = fossil_strdup(z);
    add_param_list(z, '&', 0);
    z = (char*)P("skin");
    if( z ){
      char *zErr = skin_use_alternative(z, 2, SKIN_FROM_QPARAM);
      rc |= 0x02;
      if( !zErr && P("once")==0 ){
        cookie_write_parameter("skin","skin",z);
        /* Per /chat discussion, passing ?skin=... without "once"
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
    assert(!g.json.isJsonMode &&
           "Internal misconfiguration of g.json.isJsonMode");
  }
#endif
  z = (char*)P("HTTP_COOKIE");
  if( z ){
    z = fossil_strdup(z);
    add_param_list(z, ';');
    z = (char*)cookie_value("skin",0);
    if(z){
      skin_use_alternative(z, 2, SKIN_FROM_COOKIE);
    }
  }

  cgi_setup_query_string();







|







1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
    assert(!g.json.isJsonMode &&
           "Internal misconfiguration of g.json.isJsonMode");
  }
#endif
  z = (char*)P("HTTP_COOKIE");
  if( z ){
    z = fossil_strdup(z);
    add_param_list(z, ';', 0);
    z = (char*)cookie_value("skin",0);
    if(z){
      skin_use_alternative(z, 2, SKIN_FROM_COOKIE);
    }
  }

  cgi_setup_query_string();
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
  if( len==0 ) return;
  if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
   || fossil_strncmp(g.zContentType,"multipart/form-data",19)==0
  ){
    char *z = blob_str(&g.cgiIn);
    cgi_trace(z);
    if( g.zContentType[0]=='a' ){
      add_param_list(z, '&');
    }else{
      process_multipart_form_data(z, len);
    }
    blob_init(&g.cgiIn, 0, 0);
  }
}








|







1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
  if( len==0 ) return;
  if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
   || fossil_strncmp(g.zContentType,"multipart/form-data",19)==0
  ){
    char *z = blob_str(&g.cgiIn);
    cgi_trace(z);
    if( g.zContentType[0]=='a' ){
      add_param_list(z, '&', 1);
    }else{
      process_multipart_form_data(z, len);
    }
    blob_init(&g.cgiIn, 0, 0);
  }
}

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
static NORETURN void malformed_request(const char *zMsg, ...){
  va_list ap;
  char *z;
  va_start(ap, zMsg);
  z = vmprintf(zMsg, ap);
  va_end(ap);
  cgi_set_status(400, "Bad Request");
  zContentType = "text/plain";
  if( g.zReqType==0 ) g.zReqType = "WWW";
  if( g.zReqType[0]=='C' && PD("SERVER_SOFTWARE",0)!=0 ){
    const char *zServer = PD("SERVER_SOFTWARE","");
    cgi_printf("Bad CGI Request from \"%s\": %s\n",zServer,z);
  }else{
    cgi_printf("Bad %s Request: %s\n", g.zReqType, z);
  }







|







2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
static NORETURN void malformed_request(const char *zMsg, ...){
  va_list ap;
  char *z;
  va_start(ap, zMsg);
  z = vmprintf(zMsg, ap);
  va_end(ap);
  cgi_set_status(400, "Bad Request");
  zReplyMimeType = "text/plain";
  if( g.zReqType==0 ) g.zReqType = "WWW";
  if( g.zReqType[0]=='C' && PD("SERVER_SOFTWARE",0)!=0 ){
    const char *zServer = PD("SERVER_SOFTWARE","");
    cgi_printf("Bad CGI Request from \"%s\": %s\n",zServer,z);
  }else{
    cgi_printf("Bad %s Request: %s\n", g.zReqType, z);
  }
Changes to src/chat.c.
387
388
389
390
391
392
393















394
395
396
397
398
399
400
  if(fAsMessageList){
    CX("}]}");
  }else{
    CX("}");
  }
  fossil_free(zTime);
}
















/*
** WEBPAGE: chat-send hidden loadavg-exempt
**
** This page receives (via XHR) a new chat-message and/or a new file
** to be entered into the chat history.
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  if(fAsMessageList){
    CX("}]}");
  }else{
    CX("}");
  }
  fossil_free(zTime);
}

/*
** Like chat_emit_permissions_error() but emits a single
** /chat-message-format JSON object about a CSRF violation.
*/
static void chat_emit_csrf_error(void){
  char * zTime = cgi_iso8601_datestamp();
  cgi_set_content_type("application/json");
  CX("{");
  CX("\"isError\": true, \"xfrom\": null,");
  CX("\"mtime\": %!j, \"lmtime\": %!j,", zTime, zTime);
  CX("\"xmsg\": \"CSRF validation failure.\"");
  CX("}");
  fossil_free(zTime);
}

/*
** WEBPAGE: chat-send hidden loadavg-exempt
**
** This page receives (via XHR) a new chat-message and/or a new file
** to be entered into the chat history.
**
419
420
421
422
423
424
425



426
427
428
429
430
431
432
void chat_send_webpage(void){
  int nByte;
  const char *zMsg;
  const char *zUserName;
  login_check_credentials();
  if( 0==g.perm.Chat ) {
    chat_emit_permissions_error(0);



    return;
  }
  zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
  nByte = atoi(PD("file:bytes","0"));
  zMsg = PD("msg","");
  db_begin_write();
  db_unprotect(PROTECT_READONLY);







>
>
>







434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
void chat_send_webpage(void){
  int nByte;
  const char *zMsg;
  const char *zUserName;
  login_check_credentials();
  if( 0==g.perm.Chat ) {
    chat_emit_permissions_error(0);
    return;
  }else if( 0==cgi_csrf_safe(1) ){
    chat_emit_csrf_error();
    return;
  }
  zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
  nByte = atoi(PD("file:bytes","0"));
  zMsg = PD("msg","");
  db_begin_write();
  db_unprotect(PROTECT_READONLY);
Changes to src/checkin.c.
716
717
718
719
720
721
722

723
724
725
726
727
728
729
/*
** Take care of -r version of ls command
*/
static void ls_cmd_rev(
  const char *zRev,  /* Revision string given */
  int verboseFlag,   /* Verbose flag given */
  int showAge,       /* Age flag given */

  int timeOrder,     /* Order by time flag given */
  int treeFmt        /* Show output in the tree format */
){
  Stmt q;
  char *zOrderBy = "pathname COLLATE nocase";
  char *zName;
  Blob where;







>







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
/*
** Take care of -r version of ls command
*/
static void ls_cmd_rev(
  const char *zRev,  /* Revision string given */
  int verboseFlag,   /* Verbose flag given */
  int showAge,       /* Age flag given */
  int showHash,      /* Show hash flag given */
  int timeOrder,     /* Order by time flag given */
  int treeFmt        /* Show output in the tree format */
){
  Stmt q;
  char *zOrderBy = "pathname COLLATE nocase";
  char *zName;
  Blob where;
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
  if( timeOrder ){
    zOrderBy = "mtime DESC";
  }

  compute_fileage(rid,0);
  db_prepare(&q,
    "SELECT datetime(fileage.mtime, toLocal()), fileage.pathname,\n"
    "       blob.size\n"
    "  FROM fileage, blob\n"
    " WHERE blob.rid=fileage.fid %s\n"
    " ORDER BY %s;", blob_sql_text(&where), zOrderBy /*safe-for-%s*/
  );
  blob_reset(&where);
  if( treeFmt ) blob_init(&out, 0, 0);

  while( db_step(&q)==SQLITE_ROW ){
    const char *zTime = db_column_text(&q,0);
    const char *zFile = db_column_text(&q,1);
    int size = db_column_int(&q,2);
    if( treeFmt ){
      blob_appendf(&out, "%s\n", zFile);
    }else if( verboseFlag ){

      fossil_print("%s  %7d  %s\n", zTime, size, zFile);
    }else if( showAge ){
      fossil_print("%s  %s\n", zTime, zFile);
    }else{
      fossil_print("%s\n", zFile);
    }
  }
  db_finalize(&q);







|














>
|







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
  if( timeOrder ){
    zOrderBy = "mtime DESC";
  }

  compute_fileage(rid,0);
  db_prepare(&q,
    "SELECT datetime(fileage.mtime, toLocal()), fileage.pathname,\n"
    "       blob.size, fileage.uuid\n"
    "  FROM fileage, blob\n"
    " WHERE blob.rid=fileage.fid %s\n"
    " ORDER BY %s;", blob_sql_text(&where), zOrderBy /*safe-for-%s*/
  );
  blob_reset(&where);
  if( treeFmt ) blob_init(&out, 0, 0);

  while( db_step(&q)==SQLITE_ROW ){
    const char *zTime = db_column_text(&q,0);
    const char *zFile = db_column_text(&q,1);
    int size = db_column_int(&q,2);
    if( treeFmt ){
      blob_appendf(&out, "%s\n", zFile);
    }else if( verboseFlag ){
      const char *zUuid = mprintf("[%S]  ", db_column_text(&q,3));
      fossil_print("%s  %7d  %s%s\n", zTime, size, showHash ? zUuid :"", zFile);
    }else if( showAge ){
      fossil_print("%s  %s\n", zTime, zFile);
    }else{
      fossil_print("%s\n", zFile);
    }
  }
  db_finalize(&q);
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823

824
825
826
827
828
829
830
** option as well, as explained below.
**
** The --age option displays file commit times.  Like -r, --age has the
** side effect of making -t sort by commit time, not modification time.
**
** The -v option provides extra information about each file.  Without -r,
** -v displays the change status, in the manner of the changes command.
** With -r, -v shows the commit time and size of the checked-in files.

**
** The -t option changes the sort order.  Without -t, files are sorted by
** path and name (case insensitive sort if -r).  If neither --age nor -r
** are used, -t sorts by modification time, otherwise by commit time.
**
** Options:
**   --age                 Show when each file was committed

**   --hash                With -v, verify file status using hashing
**                         rather than relying on file sizes and mtimes
**   -r VERSION            The specific check-in to list
**   -R|--repository REPO  Extract info from repository REPO
**   -t                    Sort output in time order
**   --tree                Tree format
**   -v|--verbose          Provide extra information about each file







|
>







>







811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
** option as well, as explained below.
**
** The --age option displays file commit times.  Like -r, --age has the
** side effect of making -t sort by commit time, not modification time.
**
** The -v option provides extra information about each file.  Without -r,
** -v displays the change status, in the manner of the changes command.
** With -r, -v shows the commit time and size of the checked-in files; in
** this combination, it additionally shows file hashes with -h.
**
** The -t option changes the sort order.  Without -t, files are sorted by
** path and name (case insensitive sort if -r).  If neither --age nor -r
** are used, -t sorts by modification time, otherwise by commit time.
**
** Options:
**   --age                 Show when each file was committed
**   -h                    With -v and -r, show file hashes
**   --hash                With -v, verify file status using hashing
**                         rather than relying on file sizes and mtimes
**   -r VERSION            The specific check-in to list
**   -R|--repository REPO  Extract info from repository REPO
**   -t                    Sort output in time order
**   --tree                Tree format
**   -v|--verbose          Provide extra information about each file
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
  int showAge;
  int treeFmt;
  int timeOrder;
  char *zOrderBy = "pathname";
  Blob where;
  int i;
  int useHash = 0;

  const char *zName;
  const char *zRev;

  verboseFlag = find_option("verbose","v", 0)!=0;
  if( !verboseFlag ){
    verboseFlag = find_option("l","l", 0)!=0; /* deprecated */
  }
  showAge = find_option("age",0,0)!=0;
  zRev = find_option("r","r",1);
  timeOrder = find_option("t","t",0)!=0;
  if( verboseFlag ){
    useHash = find_option("hash",0,0)!=0;

  }
  treeFmt = find_option("tree",0,0)!=0;
  if( treeFmt ){
    if( zRev==0 ) zRev = "current";
  }

  if( zRev!=0 ){
    db_find_and_open_repository(0, 0);
    verify_all_options();
    ls_cmd_rev(zRev,verboseFlag,showAge,timeOrder,treeFmt);
    return;
  }else if( find_option("R",0,1)!=0 ){
    fossil_fatal("the -r is required in addition to -R");
  }

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);







>












>









|







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
  int showAge;
  int treeFmt;
  int timeOrder;
  char *zOrderBy = "pathname";
  Blob where;
  int i;
  int useHash = 0;
  int showHash = 0;
  const char *zName;
  const char *zRev;

  verboseFlag = find_option("verbose","v", 0)!=0;
  if( !verboseFlag ){
    verboseFlag = find_option("l","l", 0)!=0; /* deprecated */
  }
  showAge = find_option("age",0,0)!=0;
  zRev = find_option("r","r",1);
  timeOrder = find_option("t","t",0)!=0;
  if( verboseFlag ){
    useHash = find_option("hash",0,0)!=0;
    showHash = find_option("h","h",0)!=0;
  }
  treeFmt = find_option("tree",0,0)!=0;
  if( treeFmt ){
    if( zRev==0 ) zRev = "current";
  }

  if( zRev!=0 ){
    db_find_and_open_repository(0, 0);
    verify_all_options();
    ls_cmd_rev(zRev,verboseFlag,showAge,showHash,timeOrder,treeFmt);
    return;
  }else if( find_option("R",0,1)!=0 ){
    fossil_fatal("the -r is required in addition to -R");
  }

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
void tree_cmd(void){
  const char *zRev;

  zRev = find_option("r","r",1);
  if( zRev==0 ) zRev = "current";
  db_find_and_open_repository(0, 0);
  verify_all_options();
  ls_cmd_rev(zRev,0,0,0,1);
}

/*
** COMMAND: extras
**
** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
**







|







988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
void tree_cmd(void){
  const char *zRev;

  zRev = find_option("r","r",1);
  if( zRev==0 ) zRev = "current";
  db_find_and_open_repository(0, 0);
  verify_all_options();
  ls_cmd_rev(zRev,0,0,0,0,1);
}

/*
** COMMAND: extras
**
** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
**
Changes to src/comformat.c.
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  }
  switch( cchUTF8 ){
    case 4:
      *pUtf32 =
        ( (z[0] & 0x0f)<<18 ) |
        ( (z[1] & 0x3f)<<12 ) |
        ( (z[2] & 0x3f)<< 6 ) |
        ( (z[4] & 0x3f)<< 0 ) ;
      break;
    case 3:
      *pUtf32 =
        ( (z[0] & 0x0f)<<12 ) | 
        ( (z[1] & 0x3f)<< 6 ) | 
        ( (z[2] & 0x3f)<< 0 ) ;
      break;







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  }
  switch( cchUTF8 ){
    case 4:
      *pUtf32 =
        ( (z[0] & 0x0f)<<18 ) |
        ( (z[1] & 0x3f)<<12 ) |
        ( (z[2] & 0x3f)<< 6 ) |
        ( (z[3] & 0x3f)<< 0 ) ;
      break;
    case 3:
      *pUtf32 =
        ( (z[0] & 0x0f)<<12 ) | 
        ( (z[1] & 0x3f)<< 6 ) | 
        ( (z[2] & 0x3f)<< 0 ) ;
      break;
Changes to src/cookies.c.
254
255
256
257
258
259
260


261
262
263
264
265
266
267
268
  for(i=0; cgi_param_info(i, &zName, &zValue, &isQP); i++){
    char *zDel;
    if( isQP ) continue;
    if( fossil_isupper(zName[0]) ) continue;
    if( bFDSonly && strcmp(zName, "fossil_display_settings")!=0 ) continue;
    zDel = mprintf("del%s",zName);
    if( P(zDel)!=0 ){


      cgi_set_cookie(zName, "", 0, -1);
      cgi_redirect(g.zPath);
    }
    nCookie++;
    @ <li><p><b>%h(zName)</b>: %h(zValue)
    @ <input type="submit" name="%h(zDel)" value="Delete">
    if( fossil_strcmp(zName, DISPLAY_SETTINGS_COOKIE)==0  && cookies.nParam>0 ){
      int j;







>
>
|







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  for(i=0; cgi_param_info(i, &zName, &zValue, &isQP); i++){
    char *zDel;
    if( isQP ) continue;
    if( fossil_isupper(zName[0]) ) continue;
    if( bFDSonly && strcmp(zName, "fossil_display_settings")!=0 ) continue;
    zDel = mprintf("del%s",zName);
    if( P(zDel)!=0 ){
      const char *zPath = fossil_strcmp(ROBOT_COOKIE,zName)==0
        ? "/" : 0;
      cgi_set_cookie(zName, "", zPath, -1);
      cgi_redirect(g.zPath);
    }
    nCookie++;
    @ <li><p><b>%h(zName)</b>: %h(zValue)
    @ <input type="submit" name="%h(zDel)" value="Delete">
    if( fossil_strcmp(zName, DISPLAY_SETTINGS_COOKIE)==0  && cookies.nParam>0 ){
      int j;
Changes to src/default.css.
572
573
574
575
576
577
578

579
580
581
582
583
584
585

/* Rules governing diff layout and colors */
table.diff {
  width: 100%;
  border-spacing: 0;
  border-radius: 5px;
  border: 1px solid black;

  font-size: 80%;
}
table.diff td.diffln{
  padding: 0;
}
table.diff td.diffln > pre{
  padding: 0 0.25em 0 0.5em;







>







572
573
574
575
576
577
578
579
580
581
582
583
584
585
586

/* Rules governing diff layout and colors */
table.diff {
  width: 100%;
  border-spacing: 0;
  border-radius: 5px;
  border: 1px solid black;
  overflow: hidden; /* Prevent background from overlapping rounded borders. */
  font-size: 80%;
}
table.diff td.diffln{
  padding: 0;
}
table.diff td.diffln > pre{
  padding: 0 0.25em 0 0.5em;
Changes to src/fossil.dom.js.
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  dom.createElemFactoryWithOptionalParent = function(childType){
    return function(parent){
      const e = this.create(childType);
      if(parent) parent.appendChild(e);
      return e;
    };
  };
  
  dom.table = dom.createElemFactory('table');
  dom.thead = dom.createElemFactoryWithOptionalParent('thead');
  dom.tbody = dom.createElemFactoryWithOptionalParent('tbody');
  dom.tfoot = dom.createElemFactoryWithOptionalParent('tfoot');
  dom.tr = dom.createElemFactoryWithOptionalParent('tr');
  dom.td = dom.createElemFactoryWithOptionalParent('td');
  dom.th = dom.createElemFactoryWithOptionalParent('th');







|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  dom.createElemFactoryWithOptionalParent = function(childType){
    return function(parent){
      const e = this.create(childType);
      if(parent) parent.appendChild(e);
      return e;
    };
  };

  dom.table = dom.createElemFactory('table');
  dom.thead = dom.createElemFactoryWithOptionalParent('thead');
  dom.tbody = dom.createElemFactoryWithOptionalParent('tbody');
  dom.tfoot = dom.createElemFactoryWithOptionalParent('tfoot');
  dom.tr = dom.createElemFactoryWithOptionalParent('tr');
  dom.td = dom.createElemFactoryWithOptionalParent('td');
  dom.th = dom.createElemFactoryWithOptionalParent('th');
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
     Internal impl for addClass(), removeClass().
  */
  const domAddRemoveClass = function f(action,e){
    if(!f.rxSPlus){
      f.rxSPlus = /\s+/;
      f.applyAction = function(e,a,v){
        if(!e || !v
           /*silently skip empty strings/flasy
             values, for user convenience*/) return;
        else if(e.forEach){
          e.forEach((E)=>E.classList[a](v));
        }else{
          e.classList[a](v);
        }
      };
    }







|
|







379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
     Internal impl for addClass(), removeClass().
  */
  const domAddRemoveClass = function f(action,e){
    if(!f.rxSPlus){
      f.rxSPlus = /\s+/;
      f.applyAction = function(e,a,v){
        if(!e || !v
           /*silently skip empty strings/falsy
             values, for usage convenience*/) return;
        else if(e.forEach){
          e.forEach((E)=>E.classList[a](v));
        }else{
          e.classList[a](v);
        }
      };
    }
582
583
584
585
586
587
588

589
590
591
592
593
594
595
      }else{
        e.setAttribute(key,val);
      }
    }
    return e;
  };


  const enableDisable = function f(enable){
    var i = 1, n = arguments.length;
    for( ; i < n; ++i ){
      let e = arguments[i];
      if(e.forEach){
        e.forEach((x)=>f(enable,x));
      }else{







>







582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
      }else{
        e.setAttribute(key,val);
      }
    }
    return e;
  };

  /* Impl for dom.enable() and dom.disable(). */
  const enableDisable = function f(enable){
    var i = 1, n = arguments.length;
    for( ; i < n; ++i ){
      let e = arguments[i];
      if(e.forEach){
        e.forEach((x)=>f(enable,x));
      }else{
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
  };

  /**
     Parses a string as HTML.

     Usages:

     Array (htmlString)
     DOMElement (DOMElement target, htmlString)

     The first form parses the string as HTML and returns an Array of
     all elements parsed from it. If string is falsy then it returns
     an empty array.

     The second form parses the HTML string and appends all elements
     to the given target element using dom.append(), then returns the







|
|







842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
  };

  /**
     Parses a string as HTML.

     Usages:

     Array parseHtml(htmlString)
     DOMElement parseHtml(DOMElement target, htmlString)

     The first form parses the string as HTML and returns an Array of
     all elements parsed from it. If string is falsy then it returns
     an empty array.

     The second form parses the HTML string and appends all elements
     to the given target element using dom.append(), then returns the
Changes to src/info.c.
399
400
401
402
403
404
405


406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
      @ Changes to %h(zName).
    }
    @ </span></div>
    if( pCfg ){
      append_diff(zOld, zNew, pCfg);
    }
  }else{


    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
          @ Renamed and modified
          @ %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zOldName,zOld,zCkin))\
          @ %h(zOldName)</a>
          @ %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>
          @ to %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zName,zNew,zCkin))\
          @ %h(zName)</a>
          @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
        }else{
          @ Modified %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zName,zNew,zCkin))\
          @ %h(zName)</a>
          @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>
          @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
        }
      }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
        @ Name change
        @ from %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zOldName,zOld,zCkin))\
        @ %h(zOldName)</a>
        @ to %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zName,zNew,zCkin))\
        @ %h(zName)</a>.
      }else{
        @ %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zName,zNew,zCkin))\
        @ %h(zName)</a> became
        if( mperm==PERM_EXE ){
          @ executable with contents
        }else if( mperm==PERM_LNK ){
          @ a symlink with target
        }else{
          @ a regular file with contents
        }
        @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
      }
    }else if( zOld ){
      @ Deleted %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zName,zOld,zCkin))\
      @ %h(zName)</a> version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>.
    }else{
      @ Added %z(href("%R/finfo?name=%T&m=%!S&ci=%!S",zName,zNew,zCkin))\
      @ %h(zName)</a> version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
    }
    if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      if( pCfg ){
        @ </span></div>
        append_diff(zOld, zNew, pCfg);
      }else{







>
>




|


|



|






|

|


|











|


|







399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
      @ Changes to %h(zName).
    }
    @ </span></div>
    if( pCfg ){
      append_diff(zOld, zNew, pCfg);
    }
  }else{
    const char *zCkin2 =
      mprintf(validate16(zCkin, -1) ? "%!S" : "%T"/*works-like:"%s"*/, zCkin);
    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
          @ Renamed and modified
          @ %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zOldName,zOld,zCkin2))\
          @ %h(zOldName)</a>
          @ %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>
          @ to %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zName,zNew,zCkin2))\
          @ %h(zName)</a>
          @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
        }else{
          @ Modified %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zName,zNew,zCkin2))\
          @ %h(zName)</a>
          @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>
          @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
        }
      }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
        @ Name change
        @ from %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zOldName,zOld,zCkin2))\
        @ %h(zOldName)</a>
        @ to %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zName,zNew,zCkin2))\
        @ %h(zName)</a>.
      }else{
        @ %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zName,zNew,zCkin2))\
        @ %h(zName)</a> became
        if( mperm==PERM_EXE ){
          @ executable with contents
        }else if( mperm==PERM_LNK ){
          @ a symlink with target
        }else{
          @ a regular file with contents
        }
        @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
      }
    }else if( zOld ){
      @ Deleted %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zName,zOld,zCkin2))\
      @ %h(zName)</a> version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>.
    }else{
      @ Added %z(href("%R/finfo?name=%T&m=%!S&ci=%s",zName,zNew,zCkin2))\
      @ %h(zName)</a> version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>.
    }
    if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      if( pCfg ){
        @ </span></div>
        append_diff(zOld, zNew, pCfg);
      }else{
641
642
643
644
645
646
647


648
649
650
651
652
653
654
    vid
  );
  if( DCfg.diffFlags & DIFF_SIDEBYSIDE ){
    DCfg.diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
  }else{
    DCfg.diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
  }


  @ <div class="sectionmenu info-changes-menu">
  zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
  if( diffType!=1 ){
    @ %z(chref("button","%R?diff=1%s",zW))Unified&nbsp;Diff</a>
  }
  if( diffType!=2 ){
    @ %z(chref("button","%R?diff=2%s",zW))Side-by-Side&nbsp;Diff</a>







>
>







643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
    vid
  );
  if( DCfg.diffFlags & DIFF_SIDEBYSIDE ){
    DCfg.diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
  }else{
    DCfg.diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
  }
  @ <div class="section" id="changes_section">Changes</div>
  DCfg.diffFlags |= DIFF_NUMSTAT; /* Show stats in the 'Changes' section */
  @ <div class="sectionmenu info-changes-menu">
  zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
  if( diffType!=1 ){
    @ %z(chref("button","%R?diff=1%s",zW))Unified&nbsp;Diff</a>
  }
  if( diffType!=2 ){
    @ %z(chref("button","%R?diff=2%s",zW))Side-by-Side&nbsp;Diff</a>
716
717
718
719
720
721
722






723
724
725
726
727
728
729
      blob_read_from_file(&new, zTreename, ExtFILE);
      text_diff(&old, &new, cgi_output_blob(), pCfg);
      blob_reset(&old);
      blob_reset(&new);
    }
  }
  db_finalize(&q);






  append_diff_javascript(diffType);
}

/*
** Render a web-page diff of the changes in the working check-out to
** an external reference.
*/







>
>
>
>
>
>







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
      blob_read_from_file(&new, zTreename, ExtFILE);
      text_diff(&old, &new, cgi_output_blob(), pCfg);
      blob_reset(&old);
      blob_reset(&new);
    }
  }
  db_finalize(&q);
  @ <script nonce='%h(style_nonce())'>;/* info.c:%d(__LINE__) */
  @ document.getElementById('changes_section').textContent =  'Changes ' +
  @   '(%d(g.diffCnt[0]) file' + (%d(g.diffCnt[0])===1 ? '' : 's') + ': ' +
  @   '+%d(g.diffCnt[1]) ' +
  @   '−%d(g.diffCnt[2]))'
  @ </script>
  append_diff_javascript(diffType);
}

/*
** Render a web-page diff of the changes in the working check-out to
** an external reference.
*/
739
740
741
742
743
744
745


746
747
748
749
750
751
752
    "SELECT pathname FROM vfile WHERE vid=%d ORDER BY pathname", vid
  );
  if( DCfg.diffFlags & DIFF_SIDEBYSIDE ){
    DCfg.diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
  }else{
    DCfg.diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
  }


  @ <div class="sectionmenu info-changes-menu">
  zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
  if( diffType!=1 ){
    @ %z(chref("button","%R?diff=1&exbase=%h%s",zExBase,zW))\
    @ Unified&nbsp;Diff</a>
  }
  if( diffType!=2 ){







>
>







749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
    "SELECT pathname FROM vfile WHERE vid=%d ORDER BY pathname", vid
  );
  if( DCfg.diffFlags & DIFF_SIDEBYSIDE ){
    DCfg.diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
  }else{
    DCfg.diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
  }
  @ <div class="section" id="changes_section">Changes</div>
  DCfg.diffFlags |= DIFF_NUMSTAT; /* Show stats in the 'Changes' section */
  @ <div class="sectionmenu info-changes-menu">
  zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
  if( diffType!=1 ){
    @ %z(chref("button","%R?diff=1&exbase=%h%s",zExBase,zW))\
    @ Unified&nbsp;Diff</a>
  }
  if( diffType!=2 ){
801
802
803
804
805
806
807






808
809
810
811
812
813
814
      blob_reset(&lhs);
      blob_reset(&rhs);
    }
    fossil_free(zLhs);
    fossil_free(zRhs);
  }
  db_finalize(&q);






  append_diff_javascript(diffType);
}

/*
** WEBPAGE: ckout
**
** Show information about the current checkout.  This page only functions







>
>
>
>
>
>







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
      blob_reset(&lhs);
      blob_reset(&rhs);
    }
    fossil_free(zLhs);
    fossil_free(zRhs);
  }
  db_finalize(&q);
  @ <script nonce='%h(style_nonce())'>;/* info.c:%d(__LINE__) */
  @ document.getElementById('changes_section').textContent =  'Changes ' +
  @   '(%d(g.diffCnt[0]) file' + (%d(g.diffCnt[0])===1 ? '' : 's') + ': ' +
  @   '+%d(g.diffCnt[1]) ' +
  @   '−%d(g.diffCnt[2]))'
  @ </script>
  append_diff_javascript(diffType);
}

/*
** WEBPAGE: ckout
**
** Show information about the current checkout.  This page only functions
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
*/
int preferred_diff_type(void){
  int dflt;
  int res;
  int isBot;
  static char zDflt[2]
    /*static b/c cookie_link_parameter() does not copy it!*/;
  if( client_might_be_a_robot() ){
    dflt = 0;
    isBot = 1;
  }else{
    dflt = db_get_int("preferred-diff-type",-99);
    if( dflt<=0 ) dflt = user_agent_is_likely_mobile() ? 1 : 2;
    isBot = 0;
  }







|







1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
*/
int preferred_diff_type(void){
  int dflt;
  int res;
  int isBot;
  static char zDflt[2]
    /*static b/c cookie_link_parameter() does not copy it!*/;
  if( client_might_be_a_robot() && robot_restrict_has_tag("diff") ){
    dflt = 0;
    isBot = 1;
  }else{
    dflt = db_get_int("preferred-diff-type",-99);
    if( dflt<=0 ) dflt = user_agent_is_likely_mobile() ? 1 : 2;
    isBot = 0;
  }
2937
2938
2939
2940
2941
2942
2943
2944

2945
2946
2947
2948
2949
2950
2951
      const char *zDate = db_column_text(&q,1);
      const char *zIp = db_column_text(&q,2);
      @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
    }
    db_finalize(&q);
  }
  if( !docOnly ){
    style_submenu_element("Download", "%R/raw/%s?at=%T",zUuid,file_tail(zName));

    if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
      style_submenu_element("Check-ins Using", "%R/timeline?uf=%s", zUuid);
    }
  }
  if( zMime ){
    if( fossil_strcmp(zMime, "text/html")==0 ){
      if( asText ){







|
>







2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
      const char *zDate = db_column_text(&q,1);
      const char *zIp = db_column_text(&q,2);
      @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
    }
    db_finalize(&q);
  }
  if( !docOnly ){
    style_submenu_element("Download", "%R/raw/%s?at=%T",
                zUuid, file_tail(blob_str(&downloadName)));
    if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
      style_submenu_element("Check-ins Using", "%R/timeline?uf=%s", zUuid);
    }
  }
  if( zMime ){
    if( fossil_strcmp(zMime, "text/html")==0 ){
      if( asText ){
Changes to src/manifest.c.
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
          zUuid = fossil_strdup(zTagUuid);
        }
      }
      zName = p->aTag[i].zName;
      zValue = p->aTag[i].zValue;
      if( strcmp(zName, "*branch")==0 ){
        blob_appendf(&comment,
           " Move to branch [/timeline?r=%h&nd&dp=%!S&unhide | %h].",
           zValue, zTagUuid, zValue);
        branchMove = 1;
        continue;
      }else if( strcmp(zName, "*bgcolor")==0 ){
        blob_appendf(&comment,
           " Change branch background color to \"%h\".", zValue);
        continue;







|







2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
          zUuid = fossil_strdup(zTagUuid);
        }
      }
      zName = p->aTag[i].zName;
      zValue = p->aTag[i].zValue;
      if( strcmp(zName, "*branch")==0 ){
        blob_appendf(&comment,
           " Move to branch [/timeline?r=%t&nd&dp=%!S&unhide | %h].",
           zValue, zTagUuid, zValue);
        branchMove = 1;
        continue;
      }else if( strcmp(zName, "*bgcolor")==0 ){
        blob_appendf(&comment,
           " Change branch background color to \"%h\".", zValue);
        continue;
Changes to src/regexp.c.
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
** Usage: %fossil test-grep REGEXP [FILE...]
**
** Run a regular expression match over the named disk files, or against
** standard input if no disk files are named on the command-line.
**
** Options:
**   -i|--ignore-case    Ignore case

*/
void re_test_grep(void){
  ReCompiled *pRe;
  const char *zErr;

  int ignoreCase = find_option("ignore-case","i",0)!=0;










  if( g.argc<3 ){
    usage("REGEXP [FILE...]");
  }
  zErr = re_compile(&pRe, g.argv[2], ignoreCase);

  if( zErr ) fossil_fatal("%s", zErr);
  if( g.argc==3 ){
    grep_file(pRe, "-", stdin);
  }else{
    int i;
    for(i=3; i<g.argc; i++){
      FILE *in = fossil_fopen(g.argv[i], "rb");
      if( in==0 ){
        fossil_warning("cannot open \"%s\"", g.argv[i]);
      }else{
        grep_file(pRe, g.argv[i], in);
        fclose(in);
      }







>




>

>
>
>
>
>
>
>
>
>
>
|
|
|
|
>

|



|







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
** Usage: %fossil test-grep REGEXP [FILE...]
**
** Run a regular expression match over the named disk files, or against
** standard input if no disk files are named on the command-line.
**
** Options:
**   -i|--ignore-case    Ignore case
**   --robot-exception   Use the robot-exception setting as the REGEXP
*/
void re_test_grep(void){
  ReCompiled *pRe;
  const char *zErr;
  int iFileList = 3;
  int ignoreCase = find_option("ignore-case","i",0)!=0;
  int bRobot = find_option("robot-exception",0,0)!=0;
  if( bRobot ){
    const char *zRe;
    db_find_and_open_repository(0,0);
    verify_all_options();
    zRe = db_get("robot-exception","^$");
    zErr = re_compile(&pRe, zRe, ignoreCase);
    iFileList = 2;
  }else{
    verify_all_options();
    if( g.argc<3 ){
      usage("REGEXP [FILE...]");
    }
    zErr = re_compile(&pRe, g.argv[2], ignoreCase);
  }
  if( zErr ) fossil_fatal("%s", zErr);
  if( g.argc==iFileList ){
    grep_file(pRe, "-", stdin);
  }else{
    int i;
    for(i=iFileList; i<g.argc; i++){
      FILE *in = fossil_fopen(g.argv[i], "rb");
      if( in==0 ){
        fossil_warning("cannot open \"%s\"", g.argv[i]);
      }else{
        grep_file(pRe, g.argv[i], in);
        fclose(in);
      }
1014
1015
1016
1017
1018
1019
1020

















































































    if( bInvert ){
      fossil_print("%d\n", nSearch-nMatch);
    }else{
      fossil_print("%d\n", nMatch);
    }
  }
}
























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
    if( bInvert ){
      fossil_print("%d\n", nSearch-nMatch);
    }else{
      fossil_print("%d\n", nMatch);
    }
  }
}

/*
** WEBPAGE: re_rules
**
** Show a summary of the regular expression matching rules for Fossil.
*/
void re_rules_page(void){
  style_set_current_feature("wiki");
  style_header("Regular Expression Syntax");
  @ <p>Syntax rules for regular expression matching in Fossil:</p>
  @ 
  @ <table border="0" cellpadding="0" cellspacing="0">
  @ <tr><th>&emsp;&emsp;&emsp;<th>Pattern
  @     <th>&emsp;&emsp;&emsp;<th align="left">Match
  @ <tr><td><td><i>X</i><b>*</b>
  @     <td><td>Zero or more occurrences of <i>X</i>
  @ <tr><td><td><i>X</i><b>+</b>
  @     <td><td>One or more occurrences of <i>X</i>
  @ <tr><td><td><i>X</i><b>?</b>
  @     <td><td>Zero or one occurrences of <i>X</i>
  @ <tr><td><td><i>X</i><b>{</b><i>P</i><b>,</b><i>Q</i><b>}</b>
  @     <td><td>Between P and Q occurrences of <i>X</i>
  @ <tr><td><td><b>(</b><i>X</i><b>)</b>
  @     <td><td><i>X</i>
  @ <tr><td><td><i>X</i><b>|</b><i>Y</i>
  @     <td><td><i>X</i> or <i>Y</i>
  @ <tr><td><td><b>^</b><i>X</i>
  @     <td><td><i>X</i> at the beginning of the string
  @ <tr><td><td><i>X</i><b>$</b>
  @     <td><td><i>X</i> at the end of the string
  @ <tr><td><td><b>.</b>
  @     <td><td>Any single character
  @ <tr><td><td><b>\</b><i>C</i>
  @     <td><td>Character <i>C</i> if <i>C</i> is one of: <b>\{}()[]|*+?</b>
  @ <tr><td><td><b>\</b><i>C</i>
  @     <td><td>C-language escapes if <i>C</i> is one of: <b>afnrtv</b>
  @ <tr><td><td><b>\u</b><i>HHHH</i>
  @     <td><td>Unicode character U+HHHH where <i>HHHH</i> is four hex digits
  @ <tr><td><td><b>\</b><i>HH</i>
  @     <td><td>Unicode character U+00HH where <i>HH</i> is two hex digits
  @ <tr><td><td><b>[</b><i>abc</i><b>]</b>
  @     <td><td>Any single character from <i>abc</i>
  @ <tr><td><td><b>[^</b><i>abc</i><b>]</b>
  @     <td><td>Any single character not in <i>abc</i>
  @ <tr><td><td><b>[</b><i>a-z</i><b>]</b>
  @     <td><td>Any single character between <i>a</i> and <i>z</i>, inclusive
  @ <tr><td><td><b>[^</b><i>a-z</i><b>]</b>
  @     <td><td>Any single character not between <i>a</i> and <i>z</i>
  @ <tr><td><td><b>\b</b>
  @     <td><td>Word boundary
  @ <tr><td><td><b>\w</b>
  @     <td><td>A word character: a-zA-Z0-9 or _
  @ <tr><td><td><b>\W</b>
  @     <td><td>A non-word character
  @ <tr><td><td><b>\d</b>
  @     <td><td>A digit.  0-9
  @ <tr><td><td><b>\D</b>
  @     <td><td>A non-digit character
  @ <tr><td><td><b>\s</b>
  @     <td><td>A whitespace character
  @ <tr><td><td><b>\S</b>
  @     <td><td>A non-whitespace character
  @ </table>
  @ 
  @ <p>In the "Pattern" column of the table above:</p>
  @ <ul>
  @ <li> "<i>X</i>" and "<i>Y</i>" mean any subpattern
  @ <li> "<i>P</i>" and "<i>Q</i>" mean integers
  @ <li> "<i>C</i>" means a single character
  @ <li> "<i>H</i>" means a hexadecimal digit
  @ <li> "<i>abc</i>" means any sequences of one or more characters
  @ <li> "<i>a-z</i>" means any single character, a single "<b>-</b>"
  @      character, and then one additional character.
  @ <li> All other symbols in the patterns are literal text
  @ </ul>
  @ 
  @ <p>The "<i>X</i><b>|</b><i>Y</i>" pattern has lower precedence
  @ than the others.  Use "<b>(</b>...<b>)</b>" for grouping, as
  @ necessary.
  style_finish_page();
}
Changes to src/robot.c.
240
241
242
243
244
245
246





247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268


















269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291







































































292
293
294
295
296
297
298
299
300
301
302
303
304
305
306



307

308
309
310
311
312
313
314
315
  p2 = robot.h1-p1;
  p3 = p2%k2;
  p4 = (p2/k2)%k3;
  p5 = p2/(k2*k3);
  @ function ccc(a,b,c){return (a*%u(k3)+b)*%u(k2)+c;}\
  @ window.addEventListener('load',function(){\
  @ bbb(ccc(%u(p5),%u(p4),%u(p3)),%u(k));},false);





  @ </script>
  style_finish_page();
}

/*
** SETTING: robot-restrict                width=40 block-text
** The VALUE of this setting is a list of GLOB patterns that match
** pages for which complex HTTP requests from unauthenicated clients
** should be disallowed.  "Unauthenticated" means the user is "nobody".
** The recommended value for this setting is:
**
**     timelineX,diff,annotate,zip,fileage,file,finfo
**
** The "diff" tag covers all diffing pages such as /vdiff, /fdiff, and
** /vpatch.  The "annotate" tag also covers /blame and /praise.  "zip"
** also covers /tarball and /sqlar.  If a tag has an "X" character appended,
** then it only applies if query parameters are such that the page is
** particularly difficult to compute. In all other case, the tag should
** exactly match the page name.
**
** Change this setting "off" to disable all robot restrictions.
*/



















/*
** Return the default restriction GLOB
*/
const char *robot_restrict_default(void){
  return "timelineX,diff,annotate,zip,fileage,file,finfo";
}

/*
** Return true if zTag matches one of the tags in the robot-restrict
** setting.
*/
int robot_restrict_has_tag(const char *zTag){
  static const char *zGlob = 0;
  if( zGlob==0 ){
    zGlob = db_get("robot-restrict",robot_restrict_default());
    if( zGlob==0 ) zGlob = "";
  }
  if( zGlob[0]==0 || fossil_strcmp(zGlob, "off")==0 ){
    return 0;
  }
  return glob_multi_match(zGlob,zTag);
}








































































/*
** Check to see if the page named in the argument is on the
** robot-restrict list.  If it is on the list and if the user
** is "nobody" then bring up a captcha to test to make sure that
** client is not a robot.
**
** This routine returns true if a captcha was rendered and if subsequent
** page generation should be aborted.  It returns false if the page
** should not be restricted and should be rendered normally.
*/
int robot_restrict(const char *zTag){
  if( robot.resultCache==KNOWN_NOT_ROBOT ) return 0;
  if( !robot_restrict_has_tag(zTag) ) return 0;
  if( !client_might_be_a_robot() ) return 0;





  /* Generate the proof-of-work captcha */   
  ask_for_proof_that_client_is_not_robot();
  return 1;
}

/*
** WEBPAGE: test-robotck
**







>
>
>
>
>











|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















>
>
>
|
>
|







240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  p2 = robot.h1-p1;
  p3 = p2%k2;
  p4 = (p2/k2)%k3;
  p5 = p2/(k2*k3);
  @ function ccc(a,b,c){return (a*%u(k3)+b)*%u(k2)+c;}\
  @ window.addEventListener('load',function(){\
  @ bbb(ccc(%u(p5),%u(p4),%u(p3)),%u(k));},false);
  /* Prevent successfully completed robot checks from reappearing and force
  ** incomplete checks to start over when navigating back and forward. More
  ** information: <https://stackoverflow.com/a/43043658>. */
  @ window.addEventListener('pageshow',function(e){if(e.persisted)\
    @ window.location.reload();});
  @ </script>
  style_finish_page();
}

/*
** SETTING: robot-restrict                width=40 block-text
** The VALUE of this setting is a list of GLOB patterns that match
** pages for which complex HTTP requests from unauthenicated clients
** should be disallowed.  "Unauthenticated" means the user is "nobody".
** The recommended value for this setting is:
**
**     timelineX,diff,annotate,zip,fileage,file,finfo,reports
**
** The "diff" tag covers all diffing pages such as /vdiff, /fdiff, and
** /vpatch.  The "annotate" tag also covers /blame and /praise.  "zip"
** also covers /tarball and /sqlar.  If a tag has an "X" character appended,
** then it only applies if query parameters are such that the page is
** particularly difficult to compute. In all other case, the tag should
** exactly match the page name.
**
** Change this setting "off" to disable all robot restrictions.
*/
/*
** SETTING: robot-exception              width=40 block-text
**
** The value of this setting should be a regular expression.
** If it matches the REQUEST_URI without the SCRIPT_NAME prefix
** matches this regular expression, then the request is an exception
** to anti-robot defenses and should be allowed through.  For
** example, to allow robots to download tarballs or ZIP archives
** for named versions and releases, you could use an expression like
** this:
**
**     ^/(tarball|zip)\\b*\\b(version-|release)\\b
**
** This setting can hold multiple regular expressions, one
** regular expression per line.  The input URL is exempted from
** anti-robot defenses if any of the multiple regular expressions
** matches.
*/

/*
** Return the default restriction GLOB
*/
const char *robot_restrict_default(void){
  return "timelineX,diff,annotate,zip,fileage,file,finfo,reports";
}

/*
** Return true if zTag matches one of the tags in the robot-restrict
** setting.
*/
int robot_restrict_has_tag(const char *zTag){
  static const char *zGlob = 0;
  if( zGlob==0 ){
    zGlob = db_get("robot-restrict",robot_restrict_default());
    if( zGlob==0 ) zGlob = "";
  }
  if( zGlob[0]==0 || fossil_strcmp(zGlob, "off")==0 ){
    return 0;
  }
  return glob_multi_match(zGlob,zTag);
}

/*
** Check the request URI to see if it matches one of the URI
** exceptions listed in the robot-exception setting.  Return true
** if it does.  Return false if it does not.
**
** For the purposes of this routine, the "request URI" means
** the REQUEST_URI value with the SCRIPT_NAME prefix removed and
** with QUERY_STRING appended with a "?" separator if QUERY_STRING
** is not empty.
**
** If the robot-exception setting does not exist or is an empty
** string, then return false.
*/
int robot_exception(void){
  const char *zRE = db_get("robot-exception",0);
  const char *zQS;    /* QUERY_STRING */
  const char *zURI;   /* REQUEST_URI */
  const char *zSN;    /* SCRIPT_NAME */
  const char *zNL;    /* Next newline character */
  char *zRequest;     /* REQUEST_URL w/o SCRIPT_NAME prefix + QUERY_STRING */
  int nRequest;       /* Length of zRequest in bytes */
  size_t nURI, nSN;   /* Length of zURI and zSN */
  int bMatch = 0;     /* True if there is a match */

  if( zRE==0 ) return 0;
  if( zRE[0]==0 ) return 0;
  zURI = PD("REQUEST_URI","");
  nURI = strlen(zURI);
  zSN = PD("SCRIPT_NAME","");
  nSN = strlen(zSN);
  if( nSN<=nURI ) zURI += nSN;
  zQS = P("QUERY_STRING");
  if( zQS && zQS[0] ){
    zRequest = mprintf("%s?%s", zURI, zQS);
  }else{
    zRequest = fossil_strdup(zURI);
  }
  nRequest = (int)strlen(zRequest);
  while( zRE[0] && bMatch==0 ){
    char *z;
    const char *zErr;
    size_t n;
    ReCompiled *pRe;
    zNL = strchr(zRE,'\n');
    if( zNL ){
      n = (size_t)(zNL - zRE)+1;
      while( zNL>zRE && fossil_isspace(zNL[0]) ) zNL--;
      if( zNL==zRE ){
        zRE += n;
        continue;
      }
    }else{
      n = strlen(zRE);
    }
    z = mprintf("%.*s", (int)(zNL - zRE)+1, zRE);
    zRE += n;
    zErr = re_compile(&pRe, z, 0);
    if( zErr ){
      fossil_warning("robot-exception error \"%s\" in expression \"%s\"\n",
                     zErr, z);
      fossil_free(z);
      continue;
    }
    fossil_free(z);
    bMatch = re_match(pRe, (const unsigned char*)zRequest, nRequest);
    re_free(pRe);
  }
  fossil_free(zRequest);
  return bMatch;
}

/*
** Check to see if the page named in the argument is on the
** robot-restrict list.  If it is on the list and if the user
** is "nobody" then bring up a captcha to test to make sure that
** client is not a robot.
**
** This routine returns true if a captcha was rendered and if subsequent
** page generation should be aborted.  It returns false if the page
** should not be restricted and should be rendered normally.
*/
int robot_restrict(const char *zTag){
  if( robot.resultCache==KNOWN_NOT_ROBOT ) return 0;
  if( !robot_restrict_has_tag(zTag) ) return 0;
  if( !client_might_be_a_robot() ) return 0;
  if( robot_exception() ){
    robot.resultCache = KNOWN_NOT_ROBOT;
    return 0;
  }

  /* Generate the proof-of-work captcha */
  ask_for_proof_that_client_is_not_robot();
  return 1;
}

/*
** WEBPAGE: test-robotck
**
Changes to src/security_audit.c.
952
953
954
955
956
957
958
959


960
961
962
963
964
965
966
  }
  while( fgets(z, sizeof(z), in) ){
    if( prevWasTime ){
      if( strncmp(z,"possible hack attempt - 418 ", 27)==0 ){
        bOutput = (eType & 0x01)!=0;
        nHack++;
      }else
      if( (strncmp(z,"panic: ", 7)==0 || strstr(z," assertion fault ")!=0) ){


        bOutput = (eType & 0x02)!=0;
        nPanic++;
      }else
      if( strncmp(z,"SMTP:", 5)==0 ){
        bOutput = (eType & 0x20)!=0;
        nSmtp++;
      }else







|
>
>







952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
  }
  while( fgets(z, sizeof(z), in) ){
    if( prevWasTime ){
      if( strncmp(z,"possible hack attempt - 418 ", 27)==0 ){
        bOutput = (eType & 0x01)!=0;
        nHack++;
      }else
      if( (strncmp(z,"panic: ", 7)==0 && strncmp(z+7,"Timeout",7)!=0)
       || strstr(z," assertion fault ")!=0
      ){
        bOutput = (eType & 0x02)!=0;
        nPanic++;
      }else
      if( strncmp(z,"SMTP:", 5)==0 ){
        bOutput = (eType & 0x20)!=0;
        nSmtp++;
      }else
Changes to src/setup.c.
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
  @ <p>The settings on this page are intended to help site administrators
  @ defend the site against robots.
  @
  @ <form action="%R/setup_robot" method="post"><div>
  login_insert_csrf_secret();
  @ <input type="submit"  name="submit" value="Apply Changes"></p>
  @ <hr>
  @ <p><b>Do not allow robots access to these pages.</b>
  @ <p> If the page name matches the GLOB pattern of this setting, and the
  @ users is "nobody", and the client has not previously passed a captcha
  @ test to show that it is not a robot, then the page is not displayed.
  @ A captcha test is is rendered instead.
  @ The recommended value for this setting is:
  @ <p>
  @ &emsp;&emsp;&emsp;<tt>%h(robot_restrict_default())</tt>
  @ <p>
  @ The "diff" tag covers all diffing pages such as /vdiff, /fdiff, and 
  @ /vpatch.  The "annotate" tag covers /annotate and also /blame and
  @ /praise.  The "zip" covers itself and also /tarball and /sqlar. If a
  @ tag has an "X" character appended, then it only applies if query
  @ parameters are such that the page is particularly difficult to compute.
  @ In all other case, the tag should exactly match the page name.
  @
  @ To disable robot restrictions, change this setting to "off".
  @ (Property: robot-restrict)
  @ <br>
  textarea_attribute("", 2, 80,
      "robot-restrict", "rbrestrict", robot_restrict_default(), 0);
















  @ <hr>
  addAutoHyperlinkSettings();

  @ <hr>
  entry_attribute("Anonymous Login Validity", 11, "anon-cookie-lifespan",
                  "anoncookls", "840", 0);
  @ <p>The number of minutes for which an anonymous login cookie is valid.







|
|




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
  @ <p>The settings on this page are intended to help site administrators
  @ defend the site against robots.
  @
  @ <form action="%R/setup_robot" method="post"><div>
  login_insert_csrf_secret();
  @ <input type="submit"  name="submit" value="Apply Changes"></p>
  @ <hr>
  @ <p><b>Do not allow robots access to these pages.</b><br>
  @ If the page name matches the GLOB pattern of this setting, and the
  @ users is "nobody", and the client has not previously passed a captcha
  @ test to show that it is not a robot, then the page is not displayed.
  @ A captcha test is is rendered instead.
  @ The recommended value for this setting is:
  @ <p>
  @ &emsp;&emsp;&emsp;<tt>%h(robot_restrict_default())</tt>
  @ <p>
  @ The "diff" tag covers all diffing pages such as /vdiff, /fdiff, and 
  @ /vpatch.  The "annotate" tag covers /annotate and also /blame and
  @ /praise.  The "zip" covers itself and also /tarball and /sqlar. If a
  @ tag has an "X" character appended, then it only applies if query
  @ parameters are such that the page is particularly difficult to compute.
  @ In all other case, the tag should exactly match the page name.
  @
  @ To disable robot restrictions, change this setting to "off".
  @ (Property: robot-restrict)
  @ <br>
  textarea_attribute("", 2, 80,
      "robot-restrict", "rbrestrict", robot_restrict_default(), 0);

  @ <hr>
  @ <p><b>Exceptions to anti-robot restrictions</b><br>
  @ The entry below is a list of regular expressions, one per line.
  @ If any of these regular expressions match the input URL, then the
  @ request is exempt from anti-robot defenses.  Use this, for example,
  @ to allow scripts to download release tarballs using a pattern
  @ like:</p>
  @ <p>
  @ &emsp;&emsp;<tt>^/tarball\b.*\b(version-|release)\b</tt>
  @ <p>The pattern should match against the REQUEST_URI with the
  @ SCRIPT_NAME prefix removed, and with QUERY_STRING appended following
  @ a "?" if QUERY_STRING exists.  (Property: robot-exception)<br>
  textarea_attribute("", 3, 80,
      "robot-exception", "rbexcept", "", 0);

  @ <hr>
  addAutoHyperlinkSettings();

  @ <hr>
  entry_attribute("Anonymous Login Validity", 11, "anon-cookie-lifespan",
                  "anoncookls", "840", 0);
  @ <p>The number of minutes for which an anonymous login cookie is valid.
Changes to src/timeline.c.
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
  }
  if( (!g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki && !g.perm.RdForum)
   || (bisectLocal && !g.perm.Setup)
  ){
    login_needed(g.anon.Read && g.anon.RdTkt && g.anon.RdWiki);
    return;
  }
  if( zBefore && robot_restrict("timelineX") ) return;
  if( !bisectLocal ){
    etag_check(ETAG_QUERY|ETAG_COOKIE|ETAG_DATA|ETAG_CONFIG, 0);
  }
  cookie_read_parameter("y","y");
  zType = P("y");
  if( zType==0 ){
    zType = g.perm.Read ? "ci" : "all";







|







1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
  }
  if( (!g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki && !g.perm.RdForum)
   || (bisectLocal && !g.perm.Setup)
  ){
    login_needed(g.anon.Read && g.anon.RdTkt && g.anon.RdWiki);
    return;
  }
  if( (zBefore || zCirca) && robot_restrict("timelineX") ) return;
  if( !bisectLocal ){
    etag_check(ETAG_QUERY|ETAG_COOKIE|ETAG_DATA|ETAG_CONFIG, 0);
  }
  cookie_read_parameter("y","y");
  zType = P("y");
  if( zType==0 ){
    zType = g.perm.Read ? "ci" : "all";
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
        blob_appendf(&desc,
                    "Check-in %z%h</a> only (%z%h</a> does not precede it)",
                     href("%R/info?name=%h",zBaseName), zBaseName,
                     href("%R/info?name=%h",zBackTo), zBackTo);
      }else{
        blob_appendf(&desc, " back to %z%h</a>%s",
                     href("%R/info?name=%h",zBackTo), zBackTo,
                     bBackAdded ? " (not a direct anscestor)" : "");
        if( ridFwdTo && zFwdTo ){
          blob_appendf(&desc, " and up to %z%h</a>%s",
                     href("%R/info?name=%h",zFwdTo), zFwdTo,
                     bFwdAdded ? " (not a direct descendant)" : "");
        }
      }
    }else if( ridFwdTo ){







|







2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
        blob_appendf(&desc,
                    "Check-in %z%h</a> only (%z%h</a> does not precede it)",
                     href("%R/info?name=%h",zBaseName), zBaseName,
                     href("%R/info?name=%h",zBackTo), zBackTo);
      }else{
        blob_appendf(&desc, " back to %z%h</a>%s",
                     href("%R/info?name=%h",zBackTo), zBackTo,
                     bBackAdded ? " (not a direct ancestor)" : "");
        if( ridFwdTo && zFwdTo ){
          blob_appendf(&desc, " and up to %z%h</a>%s",
                     href("%R/info?name=%h",zFwdTo), zFwdTo,
                     bFwdAdded ? " (not a direct descendant)" : "");
        }
      }
    }else if( ridFwdTo ){
Changes to www/changes.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>Change Log</title>

<h2 id='v2_27'>Changes for version 2.27 (pending)</h2><ol>
  <li> Fix a SQL injection on the [/help?cmd=/file|/file page].  Thanks to
       additional defenses built into Fossil, as well as good luck, this injection
       is not exploitable for either data exfiltration or privilege escalation.  The
       only possible result of invoking the injection is a harmless SQL syntax error.
       (The [https://en.wikipedia.org/wiki/Swiss_cheese_model|holes in the Swiss cheese]
       did not line up!)












  <li> Enhance the chng= query parameter on the [/help?cmd=/timeline|timeline page]
       so that it works with other query parameters like p=, d=, from=, and to=.
  <li> Always include nodes identify by sel1= and sel2= in the /timeline display.


  <li> Enable the --editor option on the [/help?cmd=amend|fossil amend] command.
  <li> Require at least an anonymous login to access the /blame page and similar,
       to help prevent robots from soaking up excess CPU time on such pages.
  <li> When walking the filesystem looking for Fossil repositories, avoid descending
       into directories named "/proc".
  <li> Reduce memory requirements for sending authenticated sync protocol
       messages.

  <li> Add the [/help?cmd=stash | stash rename] subcommand.
  </ol>

<h2 id='v2_26'>Changes for version 2.26 (2025-04-30)</h2><ol>
 <li>Enhancements to [/help?cmd=diff|fossil diff] and similar:
     <ol type="a">
     <li> The argument to the --from option can be a directory name, causing









>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>

<
<




>







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
<title>Change Log</title>

<h2 id='v2_27'>Changes for version 2.27 (pending)</h2><ol>
  <li> Fix a SQL injection on the [/help?cmd=/file|/file page].  Thanks to
       additional defenses built into Fossil, as well as good luck, this injection
       is not exploitable for either data exfiltration or privilege escalation.  The
       only possible result of invoking the injection is a harmless SQL syntax error.
       (The [https://en.wikipedia.org/wiki/Swiss_cheese_model|holes in the Swiss cheese]
       did not line up!)
  <li> Strengthen robot defenses to help prevent public-facing servers from being
       overwhelmed by the latest generation of AI spiders.
  <ol type="a">
    <li> New javascript captcha used to restrict access by user "nobody" to pages
         listed in the [/help?cmd=robot-restrict|robot-restrict setting].
    <li> The [/help?cmd=robot-exception|robot-exception setting] is available to allow
         access to pages that match a regular expression.  Use this, for example, to
         allow curl scripts and similar to download release tarballs.
    <li> Require at least an anonymous login to access the /blame page and similar.
  </ol>
  <li> [/help?cmd=/timeline|Timeline] enhancements:
  <ol type="a">
    <li> The chng= query parameter on the [/help?cmd=/timeline|timeline page]
         so that it works with other query parameters like p=, d=, from=, and to=.
    <li> Always include nodes identify by sel1= and sel2= in the /timeline display.
    <li> Improved title when p= and d= are different.
  </ol>
  <li> Enable the --editor option on the [/help?cmd=amend|fossil amend] command.


  <li> When walking the filesystem looking for Fossil repositories, avoid descending
       into directories named "/proc".
  <li> Reduce memory requirements for sending authenticated sync protocol
       messages.
  <li> Show numstat-style change statistics in the /info and /ckout pages.
  <li> Add the [/help?cmd=stash | stash rename] subcommand.
  </ol>

<h2 id='v2_26'>Changes for version 2.26 (2025-04-30)</h2><ol>
 <li>Enhancements to [/help?cmd=diff|fossil diff] and similar:
     <ol type="a">
     <li> The argument to the --from option can be a directory name, causing
Changes to www/relatedwork.md.
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
[ChiselApp]:     https://chiselapp.com/
[CLion]:         https://www.jetbrains.com/clion/
[corec66]:       https://corecursive.com/066-sqlite-with-richard-hipp/
[Darcs]:         http://darcs.net/
[db2w]:          https://youtu.be/2eaQzahCeh4
[emacsfsl]:      https://chiselapp.com/user/venks/repository/emacs-fossil/doc/tip/README.md
[floss26]:       https://twit.tv/shows/floss-weekly/episodes/26
[fnc]:           https://fnc.bsdbox.org
[fsl]:           http://fossil.0branch.com/fsl
[Fuel]:          https://fuel-scm.org/fossil/index
[Git]:           https://git-scm.com
[GoLand]:        https://www.jetbrains.com/go/
[got]:           https://gameoftrees.org
[Inskinerator]:  https://tangentsoft.com/inskinerator
[IntelliJ]:      https://www.jetbrains.com/idea/







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
[ChiselApp]:     https://chiselapp.com/
[CLion]:         https://www.jetbrains.com/clion/
[corec66]:       https://corecursive.com/066-sqlite-with-richard-hipp/
[Darcs]:         http://darcs.net/
[db2w]:          https://youtu.be/2eaQzahCeh4
[emacsfsl]:      https://chiselapp.com/user/venks/repository/emacs-fossil/doc/tip/README.md
[floss26]:       https://twit.tv/shows/floss-weekly/episodes/26
[fnc]:           https://fnc.sh
[fsl]:           http://fossil.0branch.com/fsl
[Fuel]:          https://fuel-scm.org/fossil/index
[Git]:           https://git-scm.com
[GoLand]:        https://www.jetbrains.com/go/
[got]:           https://gameoftrees.org
[Inskinerator]:  https://tangentsoft.com/inskinerator
[IntelliJ]:      https://www.jetbrains.com/idea/