Fossil

Check-in [ef298b282a]
Login

Check-in [ef298b282a]

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

Overview
Comment:Sync with trunk.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | diff-word-wrap
Files: files | file ages | folders
SHA3-256: ef298b282a22b59b061bcba1afbbd0ac82bca4b5fec7e2448b020ab246f11475
User & Date: florian 2024-09-20 03:50:00.000
Context
2024-09-20
03:57
Try dynamic calculation of the top and bottom paddings of inserted and deleted text so that the background color extends exactly to the line height (using the `calc()' CSS function). In Chromium, `overflow-y: hidden' is required so that the table cell containing the diff line doesn't display vertical scrollbars (without otherwise changing the visual result). ... (check-in: db04882760 user: florian tags: diff-word-wrap)
03:50
Sync with trunk. ... (check-in: ef298b282a user: florian tags: diff-word-wrap)
2024-09-19
12:05
Merge diff-web-noise-reduction branch to trunk, change that try to skip diff processing/rendering upfront where no useful diff output can be done. ... (check-in: 8b73fbbd1a user: mgagnon tags: trunk)
2024-09-17
06:15
Sync with trunk and resolve the merge conflicts in the 'fossil.diff.js' script. ... (check-in: ac3d7c9b4f user: florian tags: diff-word-wrap)
Changes
Unified Diff Ignore Whitespace Patch
Changes to extsrc/shell.c.
1210
1211
1212
1213
1214
1215
1216




1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227



1228
1229
1230
1231
1232
1233
1234
      nbo += dwno;
    }
    ++rv;
  }
  return rv;
}





SQLITE_INTERNAL_LINKAGE char *
cfGets(char *cBuf, int n, FILE *pf){
  int nci = 0;
  struct FileAltIds fai = altIdsOfFile(pf);
  int fmode = _setmode(fai.fd, _O_BINARY);
  BOOL eatCR = (fmode & _O_TEXT)!=0;
  _setmode(fai.fd, fmode);
  while( nci < n-1 ){
    DWORD nr;
    if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
    if( nr>0 && (!eatCR || cBuf[nci]!='\r') ) nci += nr;



  }
  if( nci < n ) cBuf[nci] = 0;
  return (nci>0)? cBuf : 0;
}
# else
#  define cfWrite(b,os,no,f) fwrite(b,os,no,f)
#  define cfGets(b,n,f) fgets(b,n,f)







>
>
>
>










|
>
>
>







1210
1211
1212
1213
1214
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
      nbo += dwno;
    }
    ++rv;
  }
  return rv;
}

/* An fgets() equivalent, using Win32 file API for actual input.
** Input ends when given buffer is filled or a newline is read.
** If the FILE object is in text mode, swallows 0x0D. (ASCII CR)
*/
SQLITE_INTERNAL_LINKAGE char *
cfGets(char *cBuf, int n, FILE *pf){
  int nci = 0;
  struct FileAltIds fai = altIdsOfFile(pf);
  int fmode = _setmode(fai.fd, _O_BINARY);
  BOOL eatCR = (fmode & _O_TEXT)!=0;
  _setmode(fai.fd, fmode);
  while( nci < n-1 ){
    DWORD nr;
    if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
    if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){
      nci += nr;
      if( cBuf[nci-nr]=='\n' ) break;
    }
  }
  if( nci < n ) cBuf[nci] = 0;
  return (nci>0)? cBuf : 0;
}
# else
#  define cfWrite(b,os,no,f) fwrite(b,os,no,f)
#  define cfGets(b,n,f) fgets(b,n,f)
3781
3782
3783
3784
3785
3786
3787




























































































































































































































































































































































































































3788
3789
3790
3791
3792
3793
3794
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                      0, sha3QueryFunc, 0, 0);
  }
  return rc;
}

/************************* End ../ext/misc/shathree.c ********************/




























































































































































































































































































































































































































/************************* Begin ../ext/misc/uint.c ******************/
/*
** 2020-04-14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**







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







3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
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
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                      0, sha3QueryFunc, 0, 0);
  }
  return rc;
}

/************************* End ../ext/misc/shathree.c ********************/
/************************* Begin ../ext/misc/sha1.c ******************/
/*
** 2017-01-27
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This SQLite extension implements functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
**     sha1(X)
**     sha1_query(Y)
**
** The sha1(X) function computes the SHA1 hash of the input X, or NULL if
** X is NULL.
**
** The sha1_query(Y) function evalutes all queries in the SQL statements of Y
** and returns a hash of their results.
*/
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>

/******************************************************************************
** The Hash Engine
*/
/* Context for the SHA1 hash */
typedef struct SHA1Context SHA1Context;
struct SHA1Context {
  unsigned int state[5];
  unsigned int count[2];
  unsigned char buffer[64];
};

#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)

#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
    |(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
    ^block[(i+2)&15]^block[i&15],1))

/*
 * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
 *
 * Rl0() for little-endian and Rb0() for big-endian.  Endianness is
 * determined at run-time.
 */
#define Rl0(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
    z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
    z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
    z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
    z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);

/*
 * Hash a single 512-bit block. This is the core of the algorithm.
 */
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
  unsigned int qq[5]; /* a, b, c, d, e; */
  static int one = 1;
  unsigned int block[16];
  memcpy(block, buffer, 64);
  memcpy(qq,state,5*sizeof(unsigned int));

#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]

  /* Copy p->state[] to working vars */
  /*
  a = state[0];
  b = state[1];
  c = state[2];
  d = state[3];
  e = state[4];
  */

  /* 4 rounds of 20 operations each. Loop unrolled. */
  if( 1 == *(unsigned char*)&one ){
    Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
    Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
    Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
    Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
  }else{
    Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
    Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
    Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
    Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
  }
  R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
  R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
  R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
  R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
  R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
  R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
  R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
  R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
  R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
  R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
  R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
  R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
  R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
  R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
  R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
  R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);

  /* Add the working vars back into context.state[] */
  state[0] += a;
  state[1] += b;
  state[2] += c;
  state[3] += d;
  state[4] += e;

#undef a
#undef b
#undef c
#undef d
#undef e
}


/* Initialize a SHA1 context */
static void hash_init(SHA1Context *p){
  /* SHA1 initialization constants */
  p->state[0] = 0x67452301;
  p->state[1] = 0xEFCDAB89;
  p->state[2] = 0x98BADCFE;
  p->state[3] = 0x10325476;
  p->state[4] = 0xC3D2E1F0;
  p->count[0] = p->count[1] = 0;
}

/* Add new content to the SHA1 hash */
static void hash_step(
  SHA1Context *p,                 /* Add content to this context */
  const unsigned char *data,      /* Data to be added */
  unsigned int len                /* Number of bytes in data */
){
  unsigned int i, j;

  j = p->count[0];
  if( (p->count[0] += len << 3) < j ){
    p->count[1] += (len>>29)+1;
  }
  j = (j >> 3) & 63;
  if( (j + len) > 63 ){
    (void)memcpy(&p->buffer[j], data, (i = 64-j));
    SHA1Transform(p->state, p->buffer);
    for(; i + 63 < len; i += 64){
      SHA1Transform(p->state, &data[i]);
    }
    j = 0;
  }else{
    i = 0;
  }
  (void)memcpy(&p->buffer[j], &data[i], len - i);
}

/* Compute a string using sqlite3_vsnprintf() and hash it */
static void hash_step_vformat(
  SHA1Context *p,                 /* Add content to this context */
  const char *zFormat,
  ...
){
  va_list ap;
  int n;
  char zBuf[50];
  va_start(ap, zFormat);
  sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
  va_end(ap);
  n = (int)strlen(zBuf);
  hash_step(p, (unsigned char*)zBuf, n);
}


/* Add padding and compute the message digest.  Render the
** message digest as lower-case hexadecimal and put it into
** zOut[].  zOut[] must be at least 41 bytes long. */
static void hash_finish(
  SHA1Context *p,           /* The SHA1 context to finish and render */
  char *zOut,               /* Store hex or binary hash here */
  int bAsBinary             /* 1 for binary hash, 0 for hex hash */
){
  unsigned int i;
  unsigned char finalcount[8];
  unsigned char digest[20];
  static const char zEncode[] = "0123456789abcdef";

  for (i = 0; i < 8; i++){
    finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
       >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
  }
  hash_step(p, (const unsigned char *)"\200", 1);
  while ((p->count[0] & 504) != 448){
    hash_step(p, (const unsigned char *)"\0", 1);
  }
  hash_step(p, finalcount, 8);  /* Should cause a SHA1Transform() */
  for (i = 0; i < 20; i++){
    digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
  }
  if( bAsBinary ){
    memcpy(zOut, digest, 20);
  }else{
    for(i=0; i<20; i++){
      zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
      zOut[i*2+1] = zEncode[digest[i] & 0xf];
    }
    zOut[i*2]= 0;
  }
}
/* End of the hashing logic
*****************************************************************************/

/*
** Implementation of the sha1(X) function.
**
** Return a lower-case hexadecimal rendering of the SHA1 hash of the
** argument X.  If X is a BLOB, it is hashed as is.  For all other
** types of input, X is converted into a UTF-8 string and the string
** is hash without the trailing 0x00 terminator.  The hash of a NULL
** value is NULL.
*/
static void sha1Func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  SHA1Context cx;
  int eType = sqlite3_value_type(argv[0]);
  int nByte = sqlite3_value_bytes(argv[0]);
  char zOut[44];

  assert( argc==1 );
  if( eType==SQLITE_NULL ) return;
  hash_init(&cx);
  if( eType==SQLITE_BLOB ){
    hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
  }else{
    hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
  }
  if( sqlite3_user_data(context)!=0 ){
    hash_finish(&cx, zOut, 1);
    sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT);
  }else{
    hash_finish(&cx, zOut, 0);
    sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT);
  }
}

/*
** Implementation of the sha1_query(SQL) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using SHA1 and that hash is returned.
**
** The original SQL text is included as part of the hash.
**
** The hash is not just a concatenation of the outputs.  Each query
** is delimited and each row and value within the query is delimited,
** with all values being marked with their datatypes.
*/
static void sha1QueryFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  sqlite3_stmt *pStmt = 0;
  int nCol;                   /* Number of columns in the result set */
  int i;                      /* Loop counter */
  int rc;
  int n;
  const char *z;
  SHA1Context cx;
  char zOut[44];

  assert( argc==1 );
  if( zSql==0 ) return;
  hash_init(&cx);
  while( zSql[0] ){
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
    if( rc ){
      char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
                                   zSql, sqlite3_errmsg(db));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    if( !sqlite3_stmt_readonly(pStmt) ){
      char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
      sqlite3_finalize(pStmt);
      sqlite3_result_error(context, zMsg, -1);
      sqlite3_free(zMsg);
      return;
    }
    nCol = sqlite3_column_count(pStmt);
    z = sqlite3_sql(pStmt);
    n = (int)strlen(z);
    hash_step_vformat(&cx,"S%d:",n);
    hash_step(&cx,(unsigned char*)z,n);

    /* Compute a hash over the result of the query */
    while( SQLITE_ROW==sqlite3_step(pStmt) ){
      hash_step(&cx,(const unsigned char*)"R",1);
      for(i=0; i<nCol; i++){
        switch( sqlite3_column_type(pStmt,i) ){
          case SQLITE_NULL: {
            hash_step(&cx, (const unsigned char*)"N",1);
            break;
          }
          case SQLITE_INTEGER: {
            sqlite3_uint64 u;
            int j;
            unsigned char x[9];
            sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
            memcpy(&u, &v, 8);
            for(j=8; j>=1; j--){
              x[j] = u & 0xff;
              u >>= 8;
            }
            x[0] = 'I';
            hash_step(&cx, x, 9);
            break;
          }
          case SQLITE_FLOAT: {
            sqlite3_uint64 u;
            int j;
            unsigned char x[9];
            double r = sqlite3_column_double(pStmt,i);
            memcpy(&u, &r, 8);
            for(j=8; j>=1; j--){
              x[j] = u & 0xff;
              u >>= 8;
            }
            x[0] = 'F';
            hash_step(&cx,x,9);
            break;
          }
          case SQLITE_TEXT: {
            int n2 = sqlite3_column_bytes(pStmt, i);
            const unsigned char *z2 = sqlite3_column_text(pStmt, i);
            hash_step_vformat(&cx,"T%d:",n2);
            hash_step(&cx, z2, n2);
            break;
          }
          case SQLITE_BLOB: {
            int n2 = sqlite3_column_bytes(pStmt, i);
            const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
            hash_step_vformat(&cx,"B%d:",n2);
            hash_step(&cx, z2, n2);
            break;
          }
        }
      }
    }
    sqlite3_finalize(pStmt);
  }
  hash_finish(&cx, zOut, 0);
  sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}


#ifdef _WIN32

#endif
int sqlite3_sha_init(
  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  static int one = 1;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sha1", 1, 
                       SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                                0, sha1Func, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha1b", 1, 
                       SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                          (void*)&one, sha1Func, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha1_query", 1, 
                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                 sha1QueryFunc, 0, 0);
  }
  return rc;
}

/************************* End ../ext/misc/sha1.c ********************/
/************************* Begin ../ext/misc/uint.c ******************/
/*
** 2020-04-14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
    p->a[p->nUsed++] = y;
    p->bSorted = 1;
  }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
    p->a[p->nUsed++] = y;
  }else if( p->bKeepSorted ){
    int i;
    i = percentBinarySearch(p, y, 0);
    if( i<p->nUsed ){
      memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
    }
    p->a[i] = y;
    p->nUsed++;
  }else{
    p->a[p->nUsed++] = y;
    p->bSorted = 0;







|







5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
    p->a[p->nUsed++] = y;
    p->bSorted = 1;
  }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
    p->a[p->nUsed++] = y;
  }else if( p->bKeepSorted ){
    int i;
    i = percentBinarySearch(p, y, 0);
    if( i<(int)p->nUsed ){
      memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
    }
    p->a[i] = y;
    p->nUsed++;
  }else{
    p->a[p->nUsed++] = y;
    p->bSorted = 0;
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
  }
  p->bKeepSorted = 1;

  /* Find and remove the row */
  i = percentBinarySearch(p, y, 1);
  if( i>=0 ){
    p->nUsed--;
    if( i<p->nUsed ){
      memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
    }
  }
}

/*
** Compute the final output of percentile().  Clean up all allocated







|







5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
  }
  p->bKeepSorted = 1;

  /* Find and remove the row */
  i = percentBinarySearch(p, y, 1);
  if( i>=0 ){
    p->nUsed--;
    if( i<(int)p->nUsed ){
      memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
    }
  }
}

/*
** Compute the final output of percentile().  Clean up all allocated
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
#endif
int sqlite3_percentile_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  int i;
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
  (void)pApi;      /* Unused parameter */
#else
  SQLITE_EXTENSION_INIT2(pApi);
#endif
  (void)pzErrMsg;  /* Unused parameter */
  for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){







|







5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
#endif
int sqlite3_percentile_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  unsigned int i;
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
  (void)pApi;      /* Unused parameter */
#else
  SQLITE_EXTENSION_INIT2(pApi);
#endif
  (void)pzErrMsg;  /* Unused parameter */
  for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
16209
16210
16211
16212
16213
16214
16215






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































16216
16217
16218
16219
16220
16221
16222
    rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
                                 stmtrandFunc, 0, 0);
  }
  return rc;
}

/************************* End ../ext/misc/stmtrand.c ********************/































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
#else
#define SQLITE_SHELL_HAVE_RECOVER 0
#endif
#if SQLITE_SHELL_HAVE_RECOVER







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







16628
16629
16630
16631
16632
16633
16634
16635
16636
16637
16638
16639
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650
16651
16652
16653
16654
16655
16656
16657
16658
16659
16660
16661
16662
16663
16664
16665
16666
16667
16668
16669
16670
16671
16672
16673
16674
16675
16676
16677
16678
16679
16680
16681
16682
16683
16684
16685
16686
16687
16688
16689
16690
16691
16692
16693
16694
16695
16696
16697
16698
16699
16700
16701
16702
16703
16704
16705
16706
16707
16708
16709
16710
16711
16712
16713
16714
16715
16716
16717
16718
16719
16720
16721
16722
16723
16724
16725
16726
16727
16728
16729
16730
16731
16732
16733
16734
16735
16736
16737
16738
16739
16740
16741
16742
16743
16744
16745
16746
16747
16748
16749
16750
16751
16752
16753
16754
16755
16756
16757
16758
16759
16760
16761
16762
16763
16764
16765
16766
16767
16768
16769
16770
16771
16772
16773
16774
16775
16776
16777
16778
16779
16780
16781
16782
16783
16784
16785
16786
16787
16788
16789
16790
16791
16792
16793
16794
16795
16796
16797
16798
16799
16800
16801
16802
16803
16804
16805
16806
16807
16808
16809
16810
16811
16812
16813
16814
16815
16816
16817
16818
16819
16820
16821
16822
16823
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834
16835
16836
16837
16838
16839
16840
16841
16842
16843
16844
16845
16846
16847
16848
16849
16850
16851
16852
16853
16854
16855
16856
16857
16858
16859
16860
16861
16862
16863
16864
16865
16866
16867
16868
16869
16870
16871
16872
16873
16874
16875
16876
16877
16878
16879
16880
16881
16882
16883
16884
16885
16886
16887
16888
16889
16890
16891
16892
16893
16894
16895
16896
16897
16898
16899
16900
16901
16902
16903
16904
16905
16906
16907
16908
16909
16910
16911
16912
16913
16914
16915
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950
16951
16952
16953
16954
16955
16956
16957
16958
16959
16960
16961
16962
16963
16964
16965
16966
16967
16968
16969
16970
16971
16972
16973
16974
16975
16976
16977
16978
16979
16980
16981
16982
16983
16984
16985
16986
16987
16988
16989
16990
16991
16992
16993
16994
16995
16996
16997
16998
16999
17000
17001
17002
17003
17004
17005
17006
17007
17008
17009
17010
17011
17012
17013
17014
17015
17016
17017
17018
17019
17020
17021
17022
17023
17024
17025
17026
17027
17028
17029
17030
17031
17032
17033
17034
17035
17036
17037
17038
17039
17040
17041
17042
17043
17044
17045
17046
17047
17048
17049
17050
17051
17052
17053
17054
17055
17056
17057
17058
17059
17060
17061
17062
17063
17064
17065
17066
17067
17068
17069
17070
17071
17072
17073
17074
17075
17076
17077
17078
17079
17080
17081
17082
17083
17084
17085
17086
17087
17088
17089
17090
17091
17092
17093
17094
17095
17096
17097
17098
17099
17100
17101
17102
17103
17104
17105
17106
17107
17108
17109
17110
17111
17112
17113
17114
17115
17116
17117
17118
17119
17120
17121
17122
17123
17124
17125
17126
17127
17128
17129
17130
17131
17132
17133
17134
17135
17136
17137
17138
17139
17140
17141
17142
17143
17144
17145
17146
17147
17148
17149
17150
17151
17152
17153
17154
17155
17156
17157
17158
17159
17160
17161
17162
17163
17164
17165
17166
17167
17168
17169
17170
17171
17172
17173
17174
17175
17176
17177
17178
17179
17180
17181
17182
17183
17184
17185
17186
17187
17188
17189
17190
17191
17192
17193
17194
17195
17196
17197
17198
17199
17200
17201
17202
17203
17204
17205
17206
17207
17208
17209
17210
17211
17212
17213
17214
17215
17216
17217
17218
17219
17220
17221
17222
17223
17224
17225
17226
17227
17228
17229
17230
17231
17232
17233
17234
17235
17236
17237
17238
17239
17240
17241
17242
17243
17244
17245
17246
17247
17248
17249
17250
17251
17252
17253
17254
17255
17256
17257
17258
17259
17260
17261
17262
17263
17264
17265
17266
17267
17268
17269
17270
17271
17272
17273
17274
17275
17276
17277
17278
17279
17280
17281
17282
17283
17284
17285
17286
17287
17288
17289
17290
17291
17292
17293
17294
17295
17296
17297
17298
17299
17300
17301
17302
17303
17304
17305
17306
17307
17308
17309
17310
17311
17312
17313
17314
17315
17316
17317
17318
17319
17320
17321
17322
17323
17324
17325
17326
17327
17328
17329
17330
17331
17332
17333
17334
17335
17336
17337
17338
17339
17340
17341
17342
17343
17344
17345
17346
17347
17348
17349
17350
17351
17352
17353
17354
17355
17356
17357
17358
17359
17360
17361
17362
17363
17364
17365
17366
17367
17368
17369
17370
17371
17372
17373
17374
17375
17376
17377
17378
17379
17380
17381
17382
17383
17384
17385
17386
17387
17388
17389
17390
17391
17392
17393
17394
17395
17396
17397
17398
17399
17400
17401
17402
17403
17404
17405
17406
17407
17408
17409
17410
17411
17412
17413
17414
17415
17416
17417
17418
17419
17420
17421
17422
17423
17424
17425
17426
17427
17428
17429
17430
17431
17432
17433
17434
17435
17436
17437
17438
17439
17440
17441
17442
17443
17444
17445
17446
17447
17448
17449
17450
17451
17452
17453
17454
17455
17456
17457
17458
17459
17460
17461
17462
17463
17464
17465
17466
17467
17468
17469
17470
17471
17472
17473
17474
17475
17476
17477
17478
17479
17480
17481
17482
17483
17484
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495
17496
17497
17498
17499
17500
17501
17502
17503
17504
17505
17506
17507
17508
17509
17510
17511
17512
17513
17514
17515
17516
17517
17518
17519
17520
17521
17522
17523
17524
17525
17526
17527
17528
17529
17530
17531
17532
17533
17534
17535
17536
17537
17538
17539
17540
17541
17542
17543
17544
17545
17546
17547
17548
17549
17550
17551
17552
17553
17554
17555
17556
17557
17558
17559
17560
17561
17562
17563
17564
17565
17566
17567
17568
17569
17570
17571
17572
17573
17574
17575
17576
17577
17578
17579
17580
17581
17582
17583
17584
17585
17586
17587
17588
17589
17590
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610
17611
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626
17627
17628
17629
17630
17631
    rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
                                 stmtrandFunc, 0, 0);
  }
  return rc;
}

/************************* End ../ext/misc/stmtrand.c ********************/
/************************* Begin ../ext/misc/vfstrace.c ******************/
/*
** 2011 March 16
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code implements a VFS shim that writes diagnostic
** output for each VFS call, similar to "strace".
**
** USAGE:
**
** This source file exports a single symbol which is the name of a
** function:
**
**   int vfstrace_register(
**     const char *zTraceName,         // Name of the newly constructed VFS
**     const char *zOldVfsName,        // Name of the underlying VFS
**     int (*xOut)(const char*,void*), // Output routine.  ex: fputs
**     void *pOutArg,                  // 2nd argument to xOut.  ex: stderr
**     int makeDefault                 // Make the new VFS the default
**   );
**
** Applications that want to trace their VFS usage must provide a callback
** function with this prototype:
**
**   int traceOutput(const char *zMessage, void *pAppData);
**
** This function will "output" the trace messages, where "output" can
** mean different things to different applications.  The traceOutput function
** for the command-line shell (see shell.c) is "fputs" from the standard
** library, which means that all trace output is written on the stream
** specified by the second argument.  In the case of the command-line shell
** the second argument is stderr.  Other applications might choose to output
** trace information to a file, over a socket, or write it into a buffer.
**
** The vfstrace_register() function creates a new "shim" VFS named by
** the zTraceName parameter.  A "shim" VFS is an SQLite backend that does
** not really perform the duties of a true backend, but simply filters or
** interprets VFS calls before passing them off to another VFS which does
** the actual work.  In this case the other VFS - the one that does the
** real work - is identified by the second parameter, zOldVfsName.  If
** the 2nd parameter is NULL then the default VFS is used.  The common
** case is for the 2nd parameter to be NULL.
**
** The third and fourth parameters are the pointer to the output function
** and the second argument to the output function.  For the SQLite
** command-line shell, when the -vfstrace option is used, these parameters
** are fputs and stderr, respectively.
**
** The fifth argument is true (non-zero) to cause the newly created VFS
** to become the default VFS.  The common case is for the fifth parameter
** to be true.
**
** The call to vfstrace_register() simply creates the shim VFS that does
** tracing.  The application must also arrange to use the new VFS for
** all database connections that are created and for which tracing is 
** desired.  This can be done by specifying the trace VFS using URI filename
** notation, or by specifying the trace VFS as the 4th parameter to
** sqlite3_open_v2() or by making the trace VFS be the default (by setting
** the 5th parameter of vfstrace_register() to 1).
**
**
** ENABLING VFSTRACE IN A COMMAND-LINE SHELL
**
** The SQLite command line shell implemented by the shell.c source file
** can be used with this module.  To compile in -vfstrace support, first
** gather this file (test_vfstrace.c), the shell source file (shell.c),
** and the SQLite amalgamation source files (sqlite3.c, sqlite3.h) into
** the working directory.  Then compile using a command like the following:
**
**    gcc -o sqlite3 -Os -I. -DSQLITE_ENABLE_VFSTRACE \
**        -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \
**        -DHAVE_READLINE -DHAVE_USLEEP=1 \
**        shell.c test_vfstrace.c sqlite3.c -ldl -lreadline -lncurses
**
** The gcc command above works on Linux and provides (in addition to the
** -vfstrace option) support for FTS3 and FTS4, RTREE, and command-line
** editing using the readline library.  The command-line shell does not
** use threads so we added -DSQLITE_THREADSAFE=0 just to make the code
** run a little faster.   For compiling on a Mac, you'll probably need
** to omit the -DHAVE_READLINE, the -lreadline, and the -lncurses options.
** The compilation could be simplified to just this:
**
**    gcc -DSQLITE_ENABLE_VFSTRACE \
**         shell.c test_vfstrace.c sqlite3.c -ldl -lpthread
**
** In this second example, all unnecessary options have been removed
** Note that since the code is now threadsafe, we had to add the -lpthread
** option to pull in the pthreads library.
**
** To cross-compile for windows using MinGW, a command like this might
** work:
**
**    /opt/mingw/bin/i386-mingw32msvc-gcc -o sqlite3.exe -Os -I \
**         -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_VFSTRACE \
**         shell.c test_vfstrace.c sqlite3.c
**
** Similar compiler commands will work on different systems.  The key
** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
** the shell.c source file will know to include the -vfstrace command-line
** option and (2) you must compile and link the three source files
** shell,c, test_vfstrace.c, and sqlite3.c.  
*/
#include <stdlib.h>
#include <string.h>
/* #include "sqlite3.h" */

/*
** An instance of this structure is attached to the each trace VFS to
** provide auxiliary information.
*/
typedef struct vfstrace_info vfstrace_info;
struct vfstrace_info {
  sqlite3_vfs *pRootVfs;              /* The underlying real VFS */
  int (*xOut)(const char*, void*);    /* Send output here */
  void *pOutArg;                      /* First argument to xOut */
  const char *zVfsName;               /* Name of this trace-VFS */
  sqlite3_vfs *pTraceVfs;             /* Pointer back to the trace VFS */
};

/*
** The sqlite3_file object for the trace VFS
*/
typedef struct vfstrace_file vfstrace_file;
struct vfstrace_file {
  sqlite3_file base;        /* Base class.  Must be first */
  vfstrace_info *pInfo;     /* The trace-VFS to which this file belongs */
  const char *zFName;       /* Base name of the file */
  sqlite3_file *pReal;      /* The real underlying file */
};

/*
** Method declarations for vfstrace_file.
*/
static int vfstraceClose(sqlite3_file*);
static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int vfstraceWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
static int vfstraceTruncate(sqlite3_file*, sqlite3_int64 size);
static int vfstraceSync(sqlite3_file*, int flags);
static int vfstraceFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int vfstraceLock(sqlite3_file*, int);
static int vfstraceUnlock(sqlite3_file*, int);
static int vfstraceCheckReservedLock(sqlite3_file*, int *);
static int vfstraceFileControl(sqlite3_file*, int op, void *pArg);
static int vfstraceSectorSize(sqlite3_file*);
static int vfstraceDeviceCharacteristics(sqlite3_file*);
static int vfstraceShmLock(sqlite3_file*,int,int,int);
static int vfstraceShmMap(sqlite3_file*,int,int,int, void volatile **);
static void vfstraceShmBarrier(sqlite3_file*);
static int vfstraceShmUnmap(sqlite3_file*,int);

/*
** Method declarations for vfstrace_vfs.
*/
static int vfstraceOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int vfstraceDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int vfstraceAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int vfstraceFullPathname(sqlite3_vfs*, const char *zName, int, char *);
static void *vfstraceDlOpen(sqlite3_vfs*, const char *zFilename);
static void vfstraceDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*vfstraceDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
static void vfstraceDlClose(sqlite3_vfs*, void*);
static int vfstraceRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int vfstraceSleep(sqlite3_vfs*, int microseconds);
static int vfstraceCurrentTime(sqlite3_vfs*, double*);
static int vfstraceGetLastError(sqlite3_vfs*, int, char*);
static int vfstraceCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int vfstraceSetSystemCall(sqlite3_vfs*,const char*, sqlite3_syscall_ptr);
static sqlite3_syscall_ptr vfstraceGetSystemCall(sqlite3_vfs*, const char *);
static const char *vfstraceNextSystemCall(sqlite3_vfs*, const char *zName);

/*
** Return a pointer to the tail of the pathname.  Examples:
**
**     /home/drh/xyzzy.txt -> xyzzy.txt
**     xyzzy.txt           -> xyzzy.txt
*/
static const char *fileTail(const char *z){
  size_t i;
  if( z==0 ) return 0;
  i = strlen(z)-1;
  while( i>0 && z[i-1]!='/' ){ i--; }
  return &z[i];
}

/*
** Send trace output defined by zFormat and subsequent arguments.
*/
static void vfstrace_printf(
  vfstrace_info *pInfo,
  const char *zFormat,
  ...
){
  va_list ap;
  char *zMsg;
  va_start(ap, zFormat);
  zMsg = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  pInfo->xOut(zMsg, pInfo->pOutArg);
  sqlite3_free(zMsg);
}

/*
** Try to convert an error code into a symbolic name for that error code.
*/
static const char *vfstrace_errcode_name(int rc ){
  const char *zVal = 0;
  switch( rc ){
    case SQLITE_OK:                 zVal = "SQLITE_OK";                 break;
    case SQLITE_INTERNAL:           zVal = "SQLITE_INTERNAL";           break;
    case SQLITE_ERROR:              zVal = "SQLITE_ERROR";              break;
    case SQLITE_PERM:               zVal = "SQLITE_PERM";               break;
    case SQLITE_ABORT:              zVal = "SQLITE_ABORT";              break;
    case SQLITE_BUSY:               zVal = "SQLITE_BUSY";               break;
    case SQLITE_LOCKED:             zVal = "SQLITE_LOCKED";             break;
    case SQLITE_NOMEM:              zVal = "SQLITE_NOMEM";              break;
    case SQLITE_READONLY:           zVal = "SQLITE_READONLY";           break;
    case SQLITE_INTERRUPT:          zVal = "SQLITE_INTERRUPT";          break;
    case SQLITE_IOERR:              zVal = "SQLITE_IOERR";              break;
    case SQLITE_CORRUPT:            zVal = "SQLITE_CORRUPT";            break;
    case SQLITE_NOTFOUND:           zVal = "SQLITE_NOTFOUND";           break;
    case SQLITE_FULL:               zVal = "SQLITE_FULL";               break;
    case SQLITE_CANTOPEN:           zVal = "SQLITE_CANTOPEN";           break;
    case SQLITE_PROTOCOL:           zVal = "SQLITE_PROTOCOL";           break;
    case SQLITE_EMPTY:              zVal = "SQLITE_EMPTY";              break;
    case SQLITE_SCHEMA:             zVal = "SQLITE_SCHEMA";             break;
    case SQLITE_TOOBIG:             zVal = "SQLITE_TOOBIG";             break;
    case SQLITE_CONSTRAINT:         zVal = "SQLITE_CONSTRAINT";         break;
    case SQLITE_MISMATCH:           zVal = "SQLITE_MISMATCH";           break;
    case SQLITE_MISUSE:             zVal = "SQLITE_MISUSE";             break;
    case SQLITE_NOLFS:              zVal = "SQLITE_NOLFS";              break;
    case SQLITE_IOERR_READ:         zVal = "SQLITE_IOERR_READ";         break;
    case SQLITE_IOERR_SHORT_READ:   zVal = "SQLITE_IOERR_SHORT_READ";   break;
    case SQLITE_IOERR_WRITE:        zVal = "SQLITE_IOERR_WRITE";        break;
    case SQLITE_IOERR_FSYNC:        zVal = "SQLITE_IOERR_FSYNC";        break;
    case SQLITE_IOERR_DIR_FSYNC:    zVal = "SQLITE_IOERR_DIR_FSYNC";    break;
    case SQLITE_IOERR_TRUNCATE:     zVal = "SQLITE_IOERR_TRUNCATE";     break;
    case SQLITE_IOERR_FSTAT:        zVal = "SQLITE_IOERR_FSTAT";        break;
    case SQLITE_IOERR_UNLOCK:       zVal = "SQLITE_IOERR_UNLOCK";       break;
    case SQLITE_IOERR_RDLOCK:       zVal = "SQLITE_IOERR_RDLOCK";       break;
    case SQLITE_IOERR_DELETE:       zVal = "SQLITE_IOERR_DELETE";       break;
    case SQLITE_IOERR_BLOCKED:      zVal = "SQLITE_IOERR_BLOCKED";      break;
    case SQLITE_IOERR_NOMEM:        zVal = "SQLITE_IOERR_NOMEM";        break;
    case SQLITE_IOERR_ACCESS:       zVal = "SQLITE_IOERR_ACCESS";       break;
    case SQLITE_IOERR_CHECKRESERVEDLOCK:
                               zVal = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE_IOERR_LOCK:         zVal = "SQLITE_IOERR_LOCK";         break;
    case SQLITE_IOERR_CLOSE:        zVal = "SQLITE_IOERR_CLOSE";        break;
    case SQLITE_IOERR_DIR_CLOSE:    zVal = "SQLITE_IOERR_DIR_CLOSE";    break;
    case SQLITE_IOERR_SHMOPEN:      zVal = "SQLITE_IOERR_SHMOPEN";      break;
    case SQLITE_IOERR_SHMSIZE:      zVal = "SQLITE_IOERR_SHMSIZE";      break;
    case SQLITE_IOERR_SHMLOCK:      zVal = "SQLITE_IOERR_SHMLOCK";      break;
    case SQLITE_IOERR_SHMMAP:       zVal = "SQLITE_IOERR_SHMMAP";       break;
    case SQLITE_IOERR_SEEK:         zVal = "SQLITE_IOERR_SEEK";         break;
    case SQLITE_IOERR_GETTEMPPATH:  zVal = "SQLITE_IOERR_GETTEMPPATH";  break;
    case SQLITE_IOERR_CONVPATH:     zVal = "SQLITE_IOERR_CONVPATH";     break;
    case SQLITE_READONLY_DBMOVED:   zVal = "SQLITE_READONLY_DBMOVED";   break;
    case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break;
    case SQLITE_BUSY_RECOVERY:      zVal = "SQLITE_BUSY_RECOVERY";      break;
    case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break;
  }
  return zVal;
}

/*
** Convert value rc into a string and print it using zFormat.  zFormat
** should have exactly one %s
*/
static void vfstrace_print_errcode(
  vfstrace_info *pInfo,
  const char *zFormat,
  int rc
){
  const char *zVal;
  char zBuf[50];
  zVal = vfstrace_errcode_name(rc);
  if( zVal==0 ){
    zVal = vfstrace_errcode_name(rc&0xff);
    if( zVal ){
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%s | 0x%x", zVal, rc&0xffff00);
    }else{
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%d (0x%x)", rc, rc);
    }
    zVal = zBuf;
  }
  vfstrace_printf(pInfo, zFormat, zVal);
}

/*
** Append to a buffer.
*/
static void strappend(char *z, int *pI, const char *zAppend){
  int i = *pI;
  while( zAppend[0] ){ z[i++] = *(zAppend++); }
  z[i] = 0;
  *pI = i;
}

/*
** Close an vfstrace-file.
*/
static int vfstraceClose(sqlite3_file *pFile){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
  rc = p->pReal->pMethods->xClose(p->pReal);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  if( rc==SQLITE_OK ){
    sqlite3_free((void*)p->base.pMethods);
    p->base.pMethods = 0;
  }
  return rc;
}

/*
** Read data from an vfstrace-file.
*/
static int vfstraceRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
                  pInfo->zVfsName, p->zFName, iAmt, iOfst);
  rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}

/*
** Write data to an vfstrace-file.
*/
static int vfstraceWrite(
  sqlite3_file *pFile, 
  const void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
                  pInfo->zVfsName, p->zFName, iAmt, iOfst);
  rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}

/*
** Truncate an vfstrace-file.
*/
static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
                  size);
  rc = p->pReal->pMethods->xTruncate(p->pReal, size);
  vfstrace_printf(pInfo, " -> %d\n", rc);
  return rc;
}

/*
** Sync an vfstrace-file.
*/
static int vfstraceSync(sqlite3_file *pFile, int flags){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  int i;
  char zBuf[100];
  memcpy(zBuf, "|0", 3);
  i = 0;
  if( flags & SQLITE_SYNC_FULL )        strappend(zBuf, &i, "|FULL");
  else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL");
  if( flags & SQLITE_SYNC_DATAONLY )    strappend(zBuf, &i, "|DATAONLY");
  if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
    sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
  }
  vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
                  &zBuf[1]);
  rc = p->pReal->pMethods->xSync(p->pReal, flags);
  vfstrace_printf(pInfo, " -> %d\n", rc);
  return rc;
}

/*
** Return the current file-size of an vfstrace-file.
*/
static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
  rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
  vfstrace_print_errcode(pInfo, " -> %s,", rc);
  vfstrace_printf(pInfo, " size=%lld\n", *pSize);
  return rc;
}

/*
** Return the name of a lock.
*/
static const char *lockName(int eLock){
  const char *azLockNames[] = {
     "NONE", "SHARED", "RESERVED", "PENDING", "EXCLUSIVE"
  };
  if( eLock<0 || eLock>=sizeof(azLockNames)/sizeof(azLockNames[0]) ){
    return "???";
  }else{
    return azLockNames[eLock];
  }
}

/*
** Lock an vfstrace-file.
*/
static int vfstraceLock(sqlite3_file *pFile, int eLock){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
                  lockName(eLock));
  rc = p->pReal->pMethods->xLock(p->pReal, eLock);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}

/*
** Unlock an vfstrace-file.
*/
static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
                  lockName(eLock));
  rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}

/*
** Check if another file-handle holds a RESERVED lock on an vfstrace-file.
*/
static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)", 
                  pInfo->zVfsName, p->zFName);
  rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
  vfstrace_print_errcode(pInfo, " -> %s", rc);
  vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
  return rc;
}

/*
** File control method. For custom operations on an vfstrace-file.
*/
static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  char zBuf[100];
  char zBuf2[100];
  char *zOp;
  char *zRVal = 0;
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE:           zOp = "LOCKSTATE";           break;
    case SQLITE_GET_LOCKPROXYFILE:         zOp = "GET_LOCKPROXYFILE";   break;
    case SQLITE_SET_LOCKPROXYFILE:         zOp = "SET_LOCKPROXYFILE";   break;
    case SQLITE_LAST_ERRNO:                zOp = "LAST_ERRNO";          break;
    case SQLITE_FCNTL_SIZE_HINT: {
      sqlite3_snprintf(sizeof(zBuf), zBuf, "SIZE_HINT,%lld",
                       *(sqlite3_int64*)pArg);
      zOp = zBuf;
      break;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg);
      zOp = zBuf;
      break;
    }
    case SQLITE_FCNTL_FILE_POINTER:        zOp = "FILE_POINTER";        break;
    case SQLITE_FCNTL_WIN32_AV_RETRY:      zOp = "WIN32_AV_RETRY";      break;
    case SQLITE_FCNTL_PERSIST_WAL: {
       sqlite3_snprintf(sizeof(zBuf), zBuf, "PERSIST_WAL,%d", *(int*)pArg);
       zOp = zBuf;
       break;
    }
    case SQLITE_FCNTL_OVERWRITE:           zOp = "OVERWRITE";           break;
    case SQLITE_FCNTL_VFSNAME:             zOp = "VFSNAME";             break;
    case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
    case SQLITE_FCNTL_PRAGMA: {
      const char *const* a = (const char*const*)pArg;
      sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
      zOp = zBuf;
      break;
    }
    case SQLITE_FCNTL_BUSYHANDLER:         zOp = "BUSYHANDLER";         break;
    case SQLITE_FCNTL_TEMPFILENAME:        zOp = "TEMPFILENAME";        break;
    case SQLITE_FCNTL_MMAP_SIZE: {
      sqlite3_int64 iMMap = *(sqlite3_int64*)pArg;
      sqlite3_snprintf(sizeof(zBuf), zBuf, "MMAP_SIZE,%lld",iMMap);
      zOp = zBuf;
      break;
    }
    case SQLITE_FCNTL_TRACE:               zOp = "TRACE";               break;
    case SQLITE_FCNTL_HAS_MOVED:           zOp = "HAS_MOVED";           break;
    case SQLITE_FCNTL_SYNC:                zOp = "SYNC";                break;
    case SQLITE_FCNTL_COMMIT_PHASETWO:     zOp = "COMMIT_PHASETWO";     break;
    case SQLITE_FCNTL_WIN32_SET_HANDLE:    zOp = "WIN32_SET_HANDLE";    break;
    case SQLITE_FCNTL_WAL_BLOCK:           zOp = "WAL_BLOCK";           break;
    case SQLITE_FCNTL_ZIPVFS:              zOp = "ZIPVFS";              break; 
    case SQLITE_FCNTL_RBU:                 zOp = "RBU";                 break;
    case SQLITE_FCNTL_VFS_POINTER:         zOp = "VFS_POINTER";         break;
    case SQLITE_FCNTL_JOURNAL_POINTER:     zOp = "JOURNAL_POINTER";     break;
    case SQLITE_FCNTL_WIN32_GET_HANDLE:    zOp = "WIN32_GET_HANDLE";    break;
    case SQLITE_FCNTL_PDB:                 zOp = "PDB";                 break;
    case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE:  zOp = "BEGIN_ATOMIC_WRITE";  break;
    case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: zOp = "COMMIT_ATOMIC_WRITE"; break;
    case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
       zOp = "ROLLBACK_ATOMIC_WRITE";
       break;
    }
    case SQLITE_FCNTL_LOCK_TIMEOUT: {
       sqlite3_snprintf(sizeof(zBuf), zBuf, "LOCK_TIMEOUT,%d", *(int*)pArg);
       zOp = zBuf;
       break;
    }
    case SQLITE_FCNTL_DATA_VERSION:        zOp = "DATA_VERSION";        break;
    case SQLITE_FCNTL_SIZE_LIMIT:          zOp = "SIZE_LIMIT";          break;
    case SQLITE_FCNTL_CKPT_DONE:           zOp = "CKPT_DONE";           break;
    case SQLITE_FCNTL_RESERVE_BYTES:       zOp = "RESERVED_BYTES";      break;
    case SQLITE_FCNTL_CKPT_START:          zOp = "CKPT_START";          break;
    case SQLITE_FCNTL_EXTERNAL_READER:     zOp = "EXTERNAL_READER";     break;
    case SQLITE_FCNTL_CKSM_FILE:           zOp = "CKSM_FILE";           break;
    case SQLITE_FCNTL_RESET_CACHE:         zOp = "RESET_CACHE";         break;
    case 0xca093fa0:                       zOp = "DB_UNCHANGED";        break;
    default: {
      sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
      zOp = zBuf;
      break;
    }
  }
  vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)",
                  pInfo->zVfsName, p->zFName, zOp);
  rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
  if( rc==SQLITE_OK ){
    switch( op ){
      case SQLITE_FCNTL_VFSNAME: {
        *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
                                    pInfo->zVfsName, *(char**)pArg);
        zRVal = *(char**)pArg;
        break;
      }
      case SQLITE_FCNTL_MMAP_SIZE: {
        sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%lld", *(sqlite3_int64*)pArg);
        zRVal = zBuf2;
        break;
      }
      case SQLITE_FCNTL_HAS_MOVED:
      case SQLITE_FCNTL_PERSIST_WAL: {
        sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%d", *(int*)pArg);
        zRVal = zBuf2;
        break;
      }
      case SQLITE_FCNTL_PRAGMA:
      case SQLITE_FCNTL_TEMPFILENAME: {
        zRVal = *(char**)pArg;
        break;
      }
    }
  }
  if( zRVal ){
    vfstrace_print_errcode(pInfo, " -> %s", rc);
    vfstrace_printf(pInfo, ", %s\n", zRVal);
  }else{
    vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  }
  return rc;
}

/*
** Return the sector-size in bytes for an vfstrace-file.
*/
static int vfstraceSectorSize(sqlite3_file *pFile){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
  rc = p->pReal->pMethods->xSectorSize(p->pReal);
  vfstrace_printf(pInfo, " -> %d\n", rc);
  return rc;
}

/*
** Return the device characteristic flags supported by an vfstrace-file.
*/
static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
                  pInfo->zVfsName, p->zFName);
  rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
  vfstrace_printf(pInfo, " -> 0x%08x\n", rc);
  return rc;
}

/*
** Shared-memory operations.
*/
static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  char zLck[100];
  int i = 0;
  memcpy(zLck, "|0", 3);
  if( flags & SQLITE_SHM_UNLOCK )    strappend(zLck, &i, "|UNLOCK");
  if( flags & SQLITE_SHM_LOCK )      strappend(zLck, &i, "|LOCK");
  if( flags & SQLITE_SHM_SHARED )    strappend(zLck, &i, "|SHARED");
  if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE");
  if( flags & ~(0xf) ){
     sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
  }
  vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)",
                  pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]);
  rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}
static int vfstraceShmMap(
  sqlite3_file *pFile, 
  int iRegion, 
  int szRegion, 
  int isWrite, 
  void volatile **pp
){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
                  pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
  rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}
static void vfstraceShmBarrier(sqlite3_file *pFile){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
  p->pReal->pMethods->xShmBarrier(p->pReal);
}
static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = p->pInfo;
  int rc;
  vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
                  pInfo->zVfsName, p->zFName, delFlag);
  rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}



/*
** Open an vfstrace file handle.
*/
static int vfstraceOpen(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_file *pFile,
  int flags,
  int *pOutFlags
){
  int rc;
  vfstrace_file *p = (vfstrace_file *)pFile;
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  p->pInfo = pInfo;
  p->zFName = zName ? fileTail(zName) : "<temp>";
  p->pReal = (sqlite3_file *)&p[1];
  rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
  vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
                  pInfo->zVfsName, p->zFName, flags);
  if( p->pReal->pMethods ){
    sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) );
    const sqlite3_io_methods *pSub = p->pReal->pMethods;
    memset(pNew, 0, sizeof(*pNew));
    pNew->iVersion = pSub->iVersion;
    pNew->xClose = vfstraceClose;
    pNew->xRead = vfstraceRead;
    pNew->xWrite = vfstraceWrite;
    pNew->xTruncate = vfstraceTruncate;
    pNew->xSync = vfstraceSync;
    pNew->xFileSize = vfstraceFileSize;
    pNew->xLock = vfstraceLock;
    pNew->xUnlock = vfstraceUnlock;
    pNew->xCheckReservedLock = vfstraceCheckReservedLock;
    pNew->xFileControl = vfstraceFileControl;
    pNew->xSectorSize = vfstraceSectorSize;
    pNew->xDeviceCharacteristics = vfstraceDeviceCharacteristics;
    if( pNew->iVersion>=2 ){
      pNew->xShmMap = pSub->xShmMap ? vfstraceShmMap : 0;
      pNew->xShmLock = pSub->xShmLock ? vfstraceShmLock : 0;
      pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0;
      pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0;
    }
    pFile->pMethods = pNew;
  }
  vfstrace_print_errcode(pInfo, " -> %s", rc);
  if( pOutFlags ){
    vfstrace_printf(pInfo, ", outFlags=0x%x\n", *pOutFlags);
  }else{
    vfstrace_printf(pInfo, "\n");
  }
  return rc;
}

/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  int rc;
  vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
                  pInfo->zVfsName, zPath, dirSync);
  rc = pRoot->xDelete(pRoot, zPath, dirSync);
  vfstrace_print_errcode(pInfo, " -> %s\n", rc);
  return rc;
}

/*
** Test for access permissions. Return true if the requested permission
** is available, or false otherwise.
*/
static int vfstraceAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  int rc;
  vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
                  pInfo->zVfsName, zPath, flags);
  rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
  vfstrace_print_errcode(pInfo, " -> %s", rc);
  vfstrace_printf(pInfo, ", out=%d\n", *pResOut);
  return rc;
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
*/
static int vfstraceFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  int rc;
  vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
                  pInfo->zVfsName, zPath);
  rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
  vfstrace_print_errcode(pInfo, " -> %s", rc);
  vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut);
  return rc;
}

/*
** Open the dynamic library located at zPath and return a handle.
*/
static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
  return pRoot->xDlOpen(pRoot, zPath);
}

/*
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
** utf-8 string describing the most recent error encountered associated 
** with dynamic libraries.
*/
static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
  pRoot->xDlError(pRoot, nByte, zErrMsg);
  vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
}

/*
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
*/
static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  vfstrace_printf(pInfo, "%s.xDlSym(\"%s\")\n", pInfo->zVfsName, zSym);
  return pRoot->xDlSym(pRoot, p, zSym);
}

/*
** Close the dynamic library handle pHandle.
*/
static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
  pRoot->xDlClose(pRoot, pHandle);
}

/*
** Populate the buffer pointed to by zBufOut with nByte bytes of 
** random data.
*/
static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
  return pRoot->xRandomness(pRoot, nByte, zBufOut);
}

/*
** Sleep for nMicro microseconds. Return the number of microseconds 
** actually slept.
*/
static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  return pRoot->xSleep(pRoot, nMicro);
}

/*
** Return the current time as a Julian Day number in *pTimeOut.
*/
static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  return pRoot->xCurrentTime(pRoot, pTimeOut);
}
static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
}

/*
** Return th3 most recent error code and message
*/
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  return pRoot->xGetLastError(pRoot, iErr, zErr);
}

/*
** Override system calls.
*/
static int vfstraceSetSystemCall(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_syscall_ptr pFunc
){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  return pRoot->xSetSystemCall(pRoot, zName, pFunc);
}
static sqlite3_syscall_ptr vfstraceGetSystemCall(
  sqlite3_vfs *pVfs,
  const char *zName
){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  return pRoot->xGetSystemCall(pRoot, zName);
}
static const char *vfstraceNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
  vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
  sqlite3_vfs *pRoot = pInfo->pRootVfs;
  return pRoot->xNextSystemCall(pRoot, zName);
}


/*
** Clients invoke this routine to construct a new trace-vfs shim.
**
** Return SQLITE_OK on success.  
**
** SQLITE_NOMEM is returned in the case of a memory allocation error.
** SQLITE_NOTFOUND is returned if zOldVfsName does not exist.
*/
int vfstrace_register(
   const char *zTraceName,           /* Name of the newly constructed VFS */
   const char *zOldVfsName,          /* Name of the underlying VFS */
   int (*xOut)(const char*,void*),   /* Output routine.  ex: fputs */
   void *pOutArg,                    /* 2nd argument to xOut.  ex: stderr */
   int makeDefault                   /* True to make the new VFS the default */
){
  sqlite3_vfs *pNew;
  sqlite3_vfs *pRoot;
  vfstrace_info *pInfo;
  size_t nName;
  size_t nByte;

  pRoot = sqlite3_vfs_find(zOldVfsName);
  if( pRoot==0 ) return SQLITE_NOTFOUND;
  nName = strlen(zTraceName);
  nByte = sizeof(*pNew) + sizeof(*pInfo) + nName + 1;
  pNew = sqlite3_malloc64( nByte );
  if( pNew==0 ) return SQLITE_NOMEM;
  memset(pNew, 0, nByte);
  pInfo = (vfstrace_info*)&pNew[1];
  pNew->iVersion = pRoot->iVersion;
  pNew->szOsFile = pRoot->szOsFile + sizeof(vfstrace_file);
  pNew->mxPathname = pRoot->mxPathname;
  pNew->zName = (char*)&pInfo[1];
  memcpy((char*)&pInfo[1], zTraceName, nName+1);
  pNew->pAppData = pInfo;
  pNew->xOpen = vfstraceOpen;
  pNew->xDelete = vfstraceDelete;
  pNew->xAccess = vfstraceAccess;
  pNew->xFullPathname = vfstraceFullPathname;
  pNew->xDlOpen = pRoot->xDlOpen==0 ? 0 : vfstraceDlOpen;
  pNew->xDlError = pRoot->xDlError==0 ? 0 : vfstraceDlError;
  pNew->xDlSym = pRoot->xDlSym==0 ? 0 : vfstraceDlSym;
  pNew->xDlClose = pRoot->xDlClose==0 ? 0 : vfstraceDlClose;
  pNew->xRandomness = vfstraceRandomness;
  pNew->xSleep = vfstraceSleep;
  pNew->xCurrentTime = vfstraceCurrentTime;
  pNew->xGetLastError = pRoot->xGetLastError==0 ? 0 : vfstraceGetLastError;
  if( pNew->iVersion>=2 ){
    pNew->xCurrentTimeInt64 = pRoot->xCurrentTimeInt64==0 ? 0 :
                                   vfstraceCurrentTimeInt64;
    if( pNew->iVersion>=3 ){
      pNew->xSetSystemCall = pRoot->xSetSystemCall==0 ? 0 : 
                                   vfstraceSetSystemCall;
      pNew->xGetSystemCall = pRoot->xGetSystemCall==0 ? 0 : 
                                   vfstraceGetSystemCall;
      pNew->xNextSystemCall = pRoot->xNextSystemCall==0 ? 0 : 
                                   vfstraceNextSystemCall;
    }
  }
  pInfo->pRootVfs = pRoot;
  pInfo->xOut = xOut;
  pInfo->pOutArg = pOutArg;
  pInfo->zVfsName = pNew->zName;
  pInfo->pTraceVfs = pNew;
  vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
       pInfo->zVfsName, pRoot->zName);
  return sqlite3_vfs_register(pNew, makeDefault);
}

/*
** Look for the named VFS.  If it is a TRACEVFS, then unregister it
** and delete it.
*/
void vfstrace_unregister(const char *zTraceName){
  sqlite3_vfs *pVfs = sqlite3_vfs_find(zTraceName);
  if( pVfs==0 ) return;
  if( pVfs->xOpen!=vfstraceOpen ) return;
  sqlite3_vfs_unregister(pVfs);
  sqlite3_free(pVfs);
}

/************************* End ../ext/misc/vfstrace.c ********************/

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
#else
#define SQLITE_SHELL_HAVE_RECOVER 0
#endif
#if SQLITE_SHELL_HAVE_RECOVER
24509
24510
24511
24512
24513
24514
24515

24516
24517
24518
24519
24520
24521
24522
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_TRUSTED_SCHEMA, testmode_on,0);
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, !testmode_on,0);
    }

#ifndef SQLITE_OMIT_LOAD_EXTENSION
    sqlite3_enable_load_extension(p->db, 1);
#endif

    sqlite3_shathree_init(p->db, 0, 0);
    sqlite3_uint_init(p->db, 0, 0);
    sqlite3_stmtrand_init(p->db, 0, 0);
    sqlite3_decimal_init(p->db, 0, 0);
    sqlite3_percentile_init(p->db, 0, 0);
    sqlite3_base64_init(p->db, 0, 0);
    sqlite3_base85_init(p->db, 0, 0);







>







25918
25919
25920
25921
25922
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_TRUSTED_SCHEMA, testmode_on,0);
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, !testmode_on,0);
    }

#ifndef SQLITE_OMIT_LOAD_EXTENSION
    sqlite3_enable_load_extension(p->db, 1);
#endif
    sqlite3_sha_init(p->db, 0, 0);
    sqlite3_shathree_init(p->db, 0, 0);
    sqlite3_uint_init(p->db, 0, 0);
    sqlite3_stmtrand_init(p->db, 0, 0);
    sqlite3_decimal_init(p->db, 0, 0);
    sqlite3_percentile_init(p->db, 0, 0);
    sqlite3_base64_init(p->db, 0, 0);
    sqlite3_base85_init(p->db, 0, 0);
31372
31373
31374
31375
31376
31377
31378
31379
31380
31381
31382
31383
31384
31385
31386
31387
31388
#endif
  "   -stats               print memory stats before each finalize\n"
  "   -table               set output mode to 'table'\n"
  "   -tabs                set output mode to 'tabs'\n"
  "   -unsafe-testing      allow unsafe commands and modes for testing\n"
  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
  "   -vfstrace            enable tracing of all VFS calls\n"
#endif
#ifdef SQLITE_HAVE_ZLIB
  "   -zip                 open the file as a ZIP Archive\n"
#endif
;
static void usage(int showDetail){
  eputf("Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
       "FILENAME is the name of an SQLite database. A new database is created\n"







<

<







32782
32783
32784
32785
32786
32787
32788

32789

32790
32791
32792
32793
32794
32795
32796
#endif
  "   -stats               print memory stats before each finalize\n"
  "   -table               set output mode to 'table'\n"
  "   -tabs                set output mode to 'tabs'\n"
  "   -unsafe-testing      allow unsafe commands and modes for testing\n"
  "   -version             show SQLite version\n"
  "   -vfs NAME            use NAME as the default VFS\n"

  "   -vfstrace            enable tracing of all VFS calls\n"

#ifdef SQLITE_HAVE_ZLIB
  "   -zip                 open the file as a ZIP Archive\n"
#endif
;
static void usage(int showDetail){
  eputf("Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
       "FILENAME is the name of an SQLite database. A new database is created\n"
31500
31501
31502
31503
31504
31505
31506

31507
31508
31509
31510
31511
31512
31513
  const char *zInitFile = 0;
  int i;
  int rc = 0;
  int warnInmemoryDb = 0;
  int readStdin = 1;
  int nCmd = 0;
  int nOptsEnd = argc;

  char **azCmd = 0;
  const char *zVfs = 0;           /* Value of -vfs command-line option */
#if !SQLITE_SHELL_IS_UTF8
  char **argvToFree = 0;
  int argcToFree = 0;
#endif
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */







>







32908
32909
32910
32911
32912
32913
32914
32915
32916
32917
32918
32919
32920
32921
32922
  const char *zInitFile = 0;
  int i;
  int rc = 0;
  int warnInmemoryDb = 0;
  int readStdin = 1;
  int nCmd = 0;
  int nOptsEnd = argc;
  int bEnableVfstrace = 0;
  char **azCmd = 0;
  const char *zVfs = 0;           /* Value of -vfs command-line option */
#if !SQLITE_SHELL_IS_UTF8
  char **argvToFree = 0;
  int argcToFree = 0;
#endif
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
31694
31695
31696
31697
31698
31699
31700
31701
31702
31703
31704
31705
31706
31707
31708
31709
31710
31711

31712
31713
31714
31715
31716
31717
31718
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      verify_uninitialized();
      switch( n ){
         case 0:  sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);  break;
         case 2:  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);   break;
         default: sqlite3_config(SQLITE_CONFIG_SERIALIZED);    break;
      }
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
         const char *zOldVfsName,
         int (*xOut)(const char*,void*),
         void *pOutArg,
         int makeDefault
      );
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif

#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiplex_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif
    }else if( cli_strcmp(z,"-mmap")==0 ){
      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));







<

<
<
<
<
<
<
<

<
>







33103
33104
33105
33106
33107
33108
33109

33110







33111

33112
33113
33114
33115
33116
33117
33118
33119
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      verify_uninitialized();
      switch( n ){
         case 0:  sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);  break;
         case 2:  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);   break;
         default: sqlite3_config(SQLITE_CONFIG_SERIALIZED);    break;
      }

    }else if( cli_strcmp(z,"-vfstrace")==0 ){







      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);

      bEnableVfstrace = 1;
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiplex_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif
    }else if( cli_strcmp(z,"-mmap")==0 ){
      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
31760
31761
31762
31763
31764
31765
31766
31767
31768
31769
31770
31771
31772
31773
31774
    }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
      ShellSetFlag(&data,SHFLG_TestingMode);
    }else if( cli_strcmp(z,"-safe")==0 ){
      /* no-op - catch this on the second pass */
    }
  }
#ifndef SQLITE_SHELL_FIDDLE
  verify_uninitialized();
#endif


#ifdef SQLITE_SHELL_INIT_PROC
  {
    /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
    ** of a C-function that will perform initialization actions on SQLite that







|







33161
33162
33163
33164
33165
33166
33167
33168
33169
33170
33171
33172
33173
33174
33175
    }else if( cli_strcmp(z,"-unsafe-testing")==0 ){
      ShellSetFlag(&data,SHFLG_TestingMode);
    }else if( cli_strcmp(z,"-safe")==0 ){
      /* no-op - catch this on the second pass */
    }
  }
#ifndef SQLITE_SHELL_FIDDLE
  if( !bEnableVfstrace ) verify_uninitialized();
#endif


#ifdef SQLITE_SHELL_INIT_PROC
  {
    /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
    ** of a C-function that will perform initialization actions on SQLite that
31949
31950
31951
31952
31953
31954
31955
31956
31957
31958
31959
31960
31961
31962
31963
31964
31965
31966
      i++;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    }else if( cli_strcmp(z,"-sorterref")==0 ){
      i++;
#endif
    }else if( cli_strcmp(z,"-vfs")==0 ){
      i++;
#ifdef SQLITE_ENABLE_VFSTRACE
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      i++;
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      i++;
#endif
    }else if( cli_strcmp(z,"-help")==0 ){
      usage(1);
    }else if( cli_strcmp(z,"-cmd")==0 ){







<


<







33350
33351
33352
33353
33354
33355
33356

33357
33358

33359
33360
33361
33362
33363
33364
33365
      i++;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
    }else if( cli_strcmp(z,"-sorterref")==0 ){
      i++;
#endif
    }else if( cli_strcmp(z,"-vfs")==0 ){
      i++;

    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      i++;

#ifdef SQLITE_ENABLE_MULTIPLEX
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      i++;
#endif
    }else if( cli_strcmp(z,"-help")==0 ){
      usage(1);
    }else if( cli_strcmp(z,"-cmd")==0 ){
32120
32121
32122
32123
32124
32125
32126



32127
32128
32129
32130
32131
32132
32133
  free(argvToFree);
#endif
  free(data.colWidth);
  free(data.zNonce);
  /* Clear the global data structure so that valgrind will detect memory
  ** leaks */
  memset(&data, 0, sizeof(data));



#ifdef SQLITE_DEBUG
  if( sqlite3_memory_used()>mem_main_enter ){
    eputf("Memory leaked: %u bytes\n",
          (unsigned int)(sqlite3_memory_used()-mem_main_enter));
  }
#endif
#else /* SQLITE_SHELL_FIDDLE... */







>
>
>







33519
33520
33521
33522
33523
33524
33525
33526
33527
33528
33529
33530
33531
33532
33533
33534
33535
  free(argvToFree);
#endif
  free(data.colWidth);
  free(data.zNonce);
  /* Clear the global data structure so that valgrind will detect memory
  ** leaks */
  memset(&data, 0, sizeof(data));
  if( bEnableVfstrace ){
    vfstrace_unregister("trace");
  }
#ifdef SQLITE_DEBUG
  if( sqlite3_memory_used()>mem_main_enter ){
    eputf("Memory leaked: %u bytes\n",
          (unsigned int)(sqlite3_memory_used()-mem_main_enter));
  }
#endif
#else /* SQLITE_SHELL_FIDDLE... */
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
** 7891a266c4425722ae8b9231397ef9e42e24.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif
/************** Begin file sqliteInt.h ***************************************/







|







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
** a63e412b6b2939422ecfa99d91fccb7a9c61.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif
/************** Begin file sqliteInt.h ***************************************/
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.47.0"
#define SQLITE_VERSION_NUMBER 3047000
#define SQLITE_SOURCE_ID      "2024-09-02 21:59:31 7891a266c4425722ae8b9231397ef9e42e2432be9e6b70632dfaf9ff15300d2c"

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







|







460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.47.0"
#define SQLITE_VERSION_NUMBER 3047000
#define SQLITE_SOURCE_ID      "2024-09-17 22:57:08 a63e412b6b2939422ecfa99d91fccb7a9c61e1533bb0db20ff12f3815ef41a2c"

/*
** 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
29283
29284
29285
29286
29287
29288
29289



29290
29291





29292
29293
29294
29295





29296
29297
29298
29299
29300
29301
29302
29303
29304
29305
29306
  }
}

#ifndef NDEBUG
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.



*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){





  assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
  return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){





  assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
  return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
#endif

#endif /* !defined(SQLITE_MUTEX_OMIT) */

/************** End of mutex.c ***********************************************/
/************** Begin file mutex_noop.c **************************************/
/*
** 2008 October 07







>
>
>


>
>
>
>
>




>
>
>
>
>



|







29283
29284
29285
29286
29287
29288
29289
29290
29291
29292
29293
29294
29295
29296
29297
29298
29299
29300
29301
29302
29303
29304
29305
29306
29307
29308
29309
29310
29311
29312
29313
29314
29315
29316
29317
29318
29319
  }
}

#ifndef NDEBUG
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
**
** Because these routines raise false-positive alerts in TSAN, disable
** them (make them always return 1) when compiling with TSAN.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
# if defined(__has_feature)
#   if __has_feature(thread_sanitizer)
      p = 0;
#   endif
# endif
  assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
  return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
# if defined(__has_feature)
#   if __has_feature(thread_sanitizer)
      p = 0;
#   endif
# endif
  assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
  return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
#endif /* NDEBUG */

#endif /* !defined(SQLITE_MUTEX_OMIT) */

/************** End of mutex.c ***********************************************/
/************** Begin file mutex_noop.c **************************************/
/*
** 2008 October 07
65169
65170
65171
65172
65173
65174
65175
65176
65177
65178
65179
65180
65181
65182
65183
**    12: Checkpoint sequence number
**    16: Salt-1, random integer incremented with each checkpoint
**    20: Salt-2, a different random integer changing with each ckpt
**    24: Checksum-1 (first part of checksum for first 24 bytes of header).
**    28: Checksum-2 (second part of checksum for first 24 bytes of header).
**
** Immediately following the wal-header are zero or more frames. Each
** frame consists of a 24-byte frame-header followed by a <page-size> bytes
** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
**     0: Page number.
**     4: For commit records, the size of the database image in pages
**        after the commit. For all other records, zero.
**     8: Salt-1 (copied from the header)







|







65182
65183
65184
65185
65186
65187
65188
65189
65190
65191
65192
65193
65194
65195
65196
**    12: Checkpoint sequence number
**    16: Salt-1, random integer incremented with each checkpoint
**    20: Salt-2, a different random integer changing with each ckpt
**    24: Checksum-1 (first part of checksum for first 24 bytes of header).
**    28: Checksum-2 (second part of checksum for first 24 bytes of header).
**
** Immediately following the wal-header are zero or more frames. Each
** frame consists of a 24-byte frame-header followed by <page-size> bytes
** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
**     0: Page number.
**     4: For commit records, the size of the database image in pages
**        after the commit. For all other records, zero.
**     8: Salt-1 (copied from the header)
92228
92229
92230
92231
92232
92233
92234











92235
92236
92237
92238
92239
92240
92241
** out of range, then SQLITE_RANGE is returned. Otherwise SQLITE_OK.
**
** A successful evaluation of this routine acquires the mutex on p.
** the mutex is released if any kind of error occurs.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.











*/
static int vdbeUnbind(Vdbe *p, unsigned int i){
  Mem *pVar;
  if( vdbeSafetyNotNull(p) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(p->db->mutex);







>
>
>
>
>
>
>
>
>
>
>







92241
92242
92243
92244
92245
92246
92247
92248
92249
92250
92251
92252
92253
92254
92255
92256
92257
92258
92259
92260
92261
92262
92263
92264
92265
** out of range, then SQLITE_RANGE is returned. Otherwise SQLITE_OK.
**
** A successful evaluation of this routine acquires the mutex on p.
** the mutex is released if any kind of error occurs.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
**
** (tag-20240917-01) If  vdbeUnbind(p,(u32)(i-1))  returns SQLITE_OK,
** that means all of the the following will be true:
**
**     p!=0
**     p->pVar!=0
**     i>0
**     i<=p->nVar
**
** An assert() is normally added after vdbeUnbind() to help static analyzers
** realize this.
*/
static int vdbeUnbind(Vdbe *p, unsigned int i){
  Mem *pVar;
  if( vdbeSafetyNotNull(p) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(p->db->mutex);
92285
92286
92287
92288
92289
92290
92291

92292
92293
92294
92295
92296
92297
92298
){
  Vdbe *p = (Vdbe *)pStmt;
  Mem *pVar;
  int rc;

  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){

    if( zData!=0 ){
      pVar = &p->aVar[i-1];
      rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
      if( rc==SQLITE_OK && encoding!=0 ){
        rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
      }
      if( rc ){







>







92309
92310
92311
92312
92313
92314
92315
92316
92317
92318
92319
92320
92321
92322
92323
){
  Vdbe *p = (Vdbe *)pStmt;
  Mem *pVar;
  int rc;

  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    if( zData!=0 ){
      pVar = &p->aVar[i-1];
      rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
      if( rc==SQLITE_OK && encoding!=0 ){
        rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
      }
      if( rc ){
92334
92335
92336
92337
92338
92339
92340

92341
92342
92343
92344
92345
92346
92347
92348
92349
92350
92351
92352
92353

92354
92355
92356
92357
92358
92359
92360
92361
92362
92363

92364
92365
92366
92367
92368
92369
92370
92371
92372
92373
92374
92375
92376
92377
92378

92379
92380
92381
92382
92383
92384
92385
  return bindText(pStmt, i, zData, nData, xDel, 0);
}
SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){

    sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
  return sqlite3_bind_int64(p, i, (i64)iValue);
}
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){

    sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){

    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE_API int sqlite3_bind_pointer(
  sqlite3_stmt *pStmt,
  int i,
  void *pPtr,
  const char *zPTtype,
  void (*xDestructor)(void*)
){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){

    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
    sqlite3_mutex_leave(p->db->mutex);
  }else if( xDestructor ){
    xDestructor(pPtr);
  }
  return rc;
}







>













>










>















>







92359
92360
92361
92362
92363
92364
92365
92366
92367
92368
92369
92370
92371
92372
92373
92374
92375
92376
92377
92378
92379
92380
92381
92382
92383
92384
92385
92386
92387
92388
92389
92390
92391
92392
92393
92394
92395
92396
92397
92398
92399
92400
92401
92402
92403
92404
92405
92406
92407
92408
92409
92410
92411
92412
92413
92414
  return bindText(pStmt, i, zData, nData, xDel, 0);
}
SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
  return sqlite3_bind_int64(p, i, (i64)iValue);
}
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE_API int sqlite3_bind_pointer(
  sqlite3_stmt *pStmt,
  int i,
  void *pPtr,
  const char *zPTtype,
  void (*xDestructor)(void*)
){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
    sqlite3_mutex_leave(p->db->mutex);
  }else if( xDestructor ){
    xDestructor(pPtr);
  }
  return rc;
}
92453
92454
92455
92456
92457
92458
92459

92460
92461
92462
92463
92464
92465
92466
  return rc;
}
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){

#ifndef SQLITE_OMIT_INCRBLOB
    sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
    rc = sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#endif
    sqlite3_mutex_leave(p->db->mutex);
  }







>







92482
92483
92484
92485
92486
92487
92488
92489
92490
92491
92492
92493
92494
92495
92496
  return rc;
}
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
#ifndef SQLITE_OMIT_INCRBLOB
    sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
    rc = sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#endif
    sqlite3_mutex_leave(p->db->mutex);
  }
169138
169139
169140
169141
169142
169143
169144

169145
169146
169147
169148
169149
169150
169151
    tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy);
  }
  hasRightJoin = (pWInfo->pTabList->a[0].fg.jointype & JT_LTORJ)!=0;
  for(i=pWInfo->nLevel-1; i>=1; i--){
    WhereTerm *pTerm, *pEnd;
    SrcItem *pItem;
    WhereLoop *pLoop;

    pLoop = pWInfo->a[i].pWLoop;
    pItem = &pWInfo->pTabList->a[pLoop->iTab];
    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
    if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0
     && (pLoop->wsFlags & WHERE_ONEROW)==0
    ){
      continue;







>







169168
169169
169170
169171
169172
169173
169174
169175
169176
169177
169178
169179
169180
169181
169182
    tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy);
  }
  hasRightJoin = (pWInfo->pTabList->a[0].fg.jointype & JT_LTORJ)!=0;
  for(i=pWInfo->nLevel-1; i>=1; i--){
    WhereTerm *pTerm, *pEnd;
    SrcItem *pItem;
    WhereLoop *pLoop;
    Bitmask m1;
    pLoop = pWInfo->a[i].pWLoop;
    pItem = &pWInfo->pTabList->a[pLoop->iTab];
    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
    if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0
     && (pLoop->wsFlags & WHERE_ONEROW)==0
    ){
      continue;
169164
169165
169166
169167
169168
169169
169170
169171



169172
169173
169174
169175
169176
169177
169178
       && ExprHasProperty(pTerm->pExpr, EP_InnerON)
       && pTerm->pExpr->w.iJoin==pItem->iCursor
      ){
        break;  /* restriction (5) */
      }
    }
    if( pTerm<pEnd ) continue;
    WHERETRACE(0xffffffff, ("-> drop loop %c not used\n", pLoop->cId));



    notReady &= ~pLoop->maskSelf;
    for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
      if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
        pTerm->wtFlags |= TERM_CODED;
      }
    }
    if( i!=pWInfo->nLevel-1 ){







|
>
>
>







169195
169196
169197
169198
169199
169200
169201
169202
169203
169204
169205
169206
169207
169208
169209
169210
169211
169212
       && ExprHasProperty(pTerm->pExpr, EP_InnerON)
       && pTerm->pExpr->w.iJoin==pItem->iCursor
      ){
        break;  /* restriction (5) */
      }
    }
    if( pTerm<pEnd ) continue;
    WHERETRACE(0xffffffff,("-> omit unused FROM-clause term %c\n",pLoop->cId));
    m1 = MASKBIT(i)-1;
    testcase( ((pWInfo->revMask>>1) & ~m1)!=0 );
    pWInfo->revMask = (m1 & pWInfo->revMask) | ((pWInfo->revMask>>1) & ~m1);
    notReady &= ~pLoop->maskSelf;
    for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
      if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
        pTerm->wtFlags |= TERM_CODED;
      }
    }
    if( i!=pWInfo->nLevel-1 ){
208865
208866
208867
208868
208869
208870
208871
208872


208873
208874
208875
208876
208877
208878
208879
  }
  if( zPath[0]=='.' ){
    int rawKey = 1;
    x = pParse->aBlob[iRoot];
    zPath++;
    if( zPath[0]=='"' ){
      zKey = zPath + 1;
      for(i=1; zPath[i] && zPath[i]!='"'; i++){}


      nKey = i-1;
      if( zPath[i] ){
        i++;
      }else{
        return JSON_LOOKUP_PATHERROR;
      }
      testcase( nKey==0 );







|
>
>







208899
208900
208901
208902
208903
208904
208905
208906
208907
208908
208909
208910
208911
208912
208913
208914
208915
  }
  if( zPath[0]=='.' ){
    int rawKey = 1;
    x = pParse->aBlob[iRoot];
    zPath++;
    if( zPath[0]=='"' ){
      zKey = zPath + 1;
      for(i=1; zPath[i] && zPath[i]!='"'; i++){
        if( zPath[i]=='\\' && zPath[i+1]!=0 ) i++;
      }
      nKey = i-1;
      if( zPath[i] ){
        i++;
      }else{
        return JSON_LOOKUP_PATHERROR;
      }
      testcase( nKey==0 );
219626
219627
219628
219629
219630
219631
219632





















219633
219634
219635
219636
219637
219638
219639
** file should be copied to page iDbPage of the database file.
*/
struct RbuFrame {
  u32 iDbPage;
  u32 iWalFrame;
};






















/*
** RBU handle.
**
** nPhaseOneStep:
**   If the RBU database contains an rbu_count table, this value is set to
**   a running estimate of the number of b-tree operations required to
**   finish populating the *-oal file. This allows the sqlite3_bp_progress()







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







219662
219663
219664
219665
219666
219667
219668
219669
219670
219671
219672
219673
219674
219675
219676
219677
219678
219679
219680
219681
219682
219683
219684
219685
219686
219687
219688
219689
219690
219691
219692
219693
219694
219695
219696
** file should be copied to page iDbPage of the database file.
*/
struct RbuFrame {
  u32 iDbPage;
  u32 iWalFrame;
};

#ifndef UNUSED_PARAMETER
/*
** The following macros are used to suppress compiler warnings and to
** make it clear to human readers when a function parameter is deliberately
** left unused within the body of a function. This usually happens when
** a function is called via a function pointer. For example the
** implementation of an SQL aggregate step callback may not use the
** parameter indicating the number of arguments passed to the aggregate,
** if it knows that this is enforced elsewhere.
**
** When a function parameter is not used at all within the body of a function,
** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
** However, these macros may also be used to suppress warnings related to
** parameters that may or may not be used depending on compilation options.
** For example those parameters only used in assert() statements. In these
** cases the parameters are named as per the usual conventions.
*/
#define UNUSED_PARAMETER(x) (void)(x)
#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
#endif

/*
** RBU handle.
**
** nPhaseOneStep:
**   If the RBU database contains an rbu_count table, this value is set to
**   a running estimate of the number of b-tree operations required to
**   finish populating the *-oal file. This allows the sqlite3_bp_progress()
219677
219678
219679
219680
219681
219682
219683
219684
219685
219686
219687
219688
219689
219690
219691
  char *zTarget;                  /* Path to target db */
  char *zRbu;                     /* Path to rbu db */
  char *zState;                   /* Path to state db (or NULL if zRbu) */
  char zStateDb[5];               /* Db name for state ("stat" or "main") */
  int rc;                         /* Value returned by last rbu_step() call */
  char *zErrmsg;                  /* Error message if rc!=SQLITE_OK */
  int nStep;                      /* Rows processed for current object */
  int nProgress;                  /* Rows processed for all objects */
  RbuObjIter objiter;             /* Iterator for skipping through tbl/idx */
  const char *zVfsName;           /* Name of automatically created rbu vfs */
  rbu_file *pTargetFd;            /* File handle open on target db */
  int nPagePerSector;             /* Pages per sector for pTargetFd */
  i64 iOalSz;
  i64 nPhaseOneStep;
  void *pRenameArg;







|







219734
219735
219736
219737
219738
219739
219740
219741
219742
219743
219744
219745
219746
219747
219748
  char *zTarget;                  /* Path to target db */
  char *zRbu;                     /* Path to rbu db */
  char *zState;                   /* Path to state db (or NULL if zRbu) */
  char zStateDb[5];               /* Db name for state ("stat" or "main") */
  int rc;                         /* Value returned by last rbu_step() call */
  char *zErrmsg;                  /* Error message if rc!=SQLITE_OK */
  int nStep;                      /* Rows processed for current object */
  sqlite3_int64 nProgress;        /* Rows processed for all objects */
  RbuObjIter objiter;             /* Iterator for skipping through tbl/idx */
  const char *zVfsName;           /* Name of automatically created rbu vfs */
  rbu_file *pTargetFd;            /* File handle open on target db */
  int nPagePerSector;             /* Pages per sector for pTargetFd */
  i64 iOalSz;
  i64 nPhaseOneStep;
  void *pRenameArg;
219794
219795
219796
219797
219798
219799
219800
219801
219802
219803
219804
219805
219806
219807
219808
  int c;
  unsigned char *z = (unsigned char*)*pz;
  unsigned char *zStart = z;
  while( (c = zValue[0x7f&*(z++)])>=0 ){
     v = (v<<6) + c;
  }
  z--;
  *pLen -= z - zStart;
  *pz = (char*)z;
  return v;
}

#if RBU_ENABLE_DELTA_CKSUM
/*
** Compute a 32-bit checksum on the N-byte buffer.  Return the result.







|







219851
219852
219853
219854
219855
219856
219857
219858
219859
219860
219861
219862
219863
219864
219865
  int c;
  unsigned char *z = (unsigned char*)*pz;
  unsigned char *zStart = z;
  while( (c = zValue[0x7f&*(z++)])>=0 ){
     v = (v<<6) + c;
  }
  z--;
  *pLen -= (int)(z - zStart);
  *pz = (char*)z;
  return v;
}

#if RBU_ENABLE_DELTA_CKSUM
/*
** Compute a 32-bit checksum on the N-byte buffer.  Return the result.
219979
219980
219981
219982
219983
219984
219985

219986
219987
219988
219989
219990
219991
219992
  int nOrig;

  int nOut;
  int nOut2;
  char *aOut;

  assert( argc==2 );


  nOrig = sqlite3_value_bytes(argv[0]);
  aOrig = (const char*)sqlite3_value_blob(argv[0]);
  nDelta = sqlite3_value_bytes(argv[1]);
  aDelta = (const char*)sqlite3_value_blob(argv[1]);

  /* Figure out the size of the output */







>







220036
220037
220038
220039
220040
220041
220042
220043
220044
220045
220046
220047
220048
220049
220050
  int nOrig;

  int nOut;
  int nOut2;
  char *aOut;

  assert( argc==2 );
  UNUSED_PARAMETER(argc);

  nOrig = sqlite3_value_bytes(argv[0]);
  aOrig = (const char*)sqlite3_value_blob(argv[0]);
  nDelta = sqlite3_value_bytes(argv[1]);
  aDelta = (const char*)sqlite3_value_blob(argv[1]);

  /* Figure out the size of the output */
221558
221559
221560
221561
221562
221563
221564
221565
221566
221567
221568
221569
221570
221571
221572
221573
221574
221575
221576
221577
221578
              pIter->aIdxCol[0].zSpan = &zSql[i+1];
            }
            nParen++;
          }
          else if( c==')' ){
            nParen--;
            if( nParen==0 ){
              int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
              pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
              i++;
              break;
            }
          }else if( c==',' && nParen==1 ){
            int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
            pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
            pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
          }else if( c=='"' || c=='\'' || c=='`' ){
            for(i++; 1; i++){
              if( zSql[i]==c ){
                if( zSql[i+1]!=c ) break;
                i++;







|





|







221616
221617
221618
221619
221620
221621
221622
221623
221624
221625
221626
221627
221628
221629
221630
221631
221632
221633
221634
221635
221636
              pIter->aIdxCol[0].zSpan = &zSql[i+1];
            }
            nParen++;
          }
          else if( c==')' ){
            nParen--;
            if( nParen==0 ){
              int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
              pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
              i++;
              break;
            }
          }else if( c==',' && nParen==1 ){
            int nSpan = (int)(&zSql[i] - pIter->aIdxCol[iIdxCol].zSpan);
            pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
            pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
          }else if( c=='"' || c=='\'' || c=='`' ){
            for(i++; 1; i++){
              if( zSql[i]==c ){
                if( zSql[i+1]!=c ) break;
                i++;
222254
222255
222256
222257
222258
222259
222260


222261
222262
222263
222264
222265
222266
222267
#endif
  {
    int i, sz;
    sz = (int)strlen(z)&0xffffff;
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4);
  }


#endif
}

/*
** Return the current wal-index header checksum for the target database
** as a 64-bit integer.
**







>
>







222312
222313
222314
222315
222316
222317
222318
222319
222320
222321
222322
222323
222324
222325
222326
222327
#endif
  {
    int i, sz;
    sz = (int)strlen(z)&0xffffff;
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && sz>i+4 ) memmove(&z[i+1], &z[sz-3], 4);
  }
#else
  UNUSED_PARAMETER2(zBase,z);
#endif
}

/*
** Return the current wal-index header checksum for the target database
** as a 64-bit integer.
**
222838
222839
222840
222841
222842
222843
222844
222845
222846
222847
222848
222849
222850
222851
222852
    rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg,
        sqlite3_mprintf(
          "INSERT OR REPLACE INTO %s.rbu_state(k, v) VALUES "
          "(%d, %d), "
          "(%d, %Q), "
          "(%d, %Q), "
          "(%d, %d), "
          "(%d, %d), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %Q)  ",
          p->zStateDb,
          RBU_STATE_STAGE, eStage,







|







222898
222899
222900
222901
222902
222903
222904
222905
222906
222907
222908
222909
222910
222911
222912
    rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg,
        sqlite3_mprintf(
          "INSERT OR REPLACE INTO %s.rbu_state(k, v) VALUES "
          "(%d, %d), "
          "(%d, %Q), "
          "(%d, %Q), "
          "(%d, %d), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %lld), "
          "(%d, %Q)  ",
          p->zStateDb,
          RBU_STATE_STAGE, eStage,
223196
223197
223198
223199
223200
223201
223202

223203
223204
223205
223206
223207
223208
223209
  sqlite3rbu *p = (sqlite3rbu*)sqlite3_user_data(pCtx);
  sqlite3_stmt *pStmt = 0;
  char *zErrmsg = 0;
  int rc;
  sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);

  assert( nVal==1 );


  rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
      sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
        "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0]))
  );
  if( rc!=SQLITE_OK ){
    sqlite3_result_error(pCtx, zErrmsg, -1);







>







223256
223257
223258
223259
223260
223261
223262
223263
223264
223265
223266
223267
223268
223269
223270
  sqlite3rbu *p = (sqlite3rbu*)sqlite3_user_data(pCtx);
  sqlite3_stmt *pStmt = 0;
  char *zErrmsg = 0;
  int rc;
  sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);

  assert( nVal==1 );
  UNUSED_PARAMETER(nVal);

  rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
      sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
        "WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0]))
  );
  if( rc!=SQLITE_OK ){
    sqlite3_result_error(pCtx, zErrmsg, -1);
223471
223472
223473
223474
223475
223476
223477
223478
223479
223480
223481
223482
223483
223484
223485
*/
SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
  const char *zTarget,
  const char *zState
){
  if( zTarget==0 ){ return rbuMisuseError(); }
  if( zState ){
    int n = strlen(zState);
    if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
      return rbuMisuseError();
    }
  }
  /* TODO: Check that both arguments are non-NULL */
  return openRbuHandle(0, zTarget, zState);
}







|







223532
223533
223534
223535
223536
223537
223538
223539
223540
223541
223542
223543
223544
223545
223546
*/
SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
  const char *zTarget,
  const char *zState
){
  if( zTarget==0 ){ return rbuMisuseError(); }
  if( zState ){
    size_t n = strlen(zState);
    if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
      return rbuMisuseError();
    }
  }
  /* TODO: Check that both arguments are non-NULL */
  return openRbuHandle(0, zTarget, zState);
}
223688
223689
223690
223691
223692
223693
223694

223695
223696
223697
223698
223699
223700
223701
}

/*
** Default xRename callback for RBU.
*/
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
  int rc = SQLITE_OK;

#if defined(_WIN32_WCE)
  {
    LPWSTR zWideOld;
    LPWSTR zWideNew;

    zWideOld = rbuWinUtf8ToUnicode(zOld);
    if( zWideOld ){







>







223749
223750
223751
223752
223753
223754
223755
223756
223757
223758
223759
223760
223761
223762
223763
}

/*
** Default xRename callback for RBU.
*/
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
  int rc = SQLITE_OK;
  UNUSED_PARAMETER(pArg);
#if defined(_WIN32_WCE)
  {
    LPWSTR zWideOld;
    LPWSTR zWideNew;

    zWideOld = rbuWinUtf8ToUnicode(zOld);
    if( zWideOld ){
224592
224593
224594
224595
224596
224597
224598



224599
224600
224601
224602
224603
224604
224605
  return pRealVfs->xCurrentTime(pRealVfs, pTimeOut);
}

/*
** No-op.
*/
static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){



  return 0;
}

/*
** Deregister and destroy an RBU vfs created by an earlier call to
** sqlite3rbu_create_vfs().
*/







>
>
>







224654
224655
224656
224657
224658
224659
224660
224661
224662
224663
224664
224665
224666
224667
224668
224669
224670
  return pRealVfs->xCurrentTime(pRealVfs, pTimeOut);
}

/*
** No-op.
*/
static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){
  UNUSED_PARAMETER(pVfs);
  UNUSED_PARAMETER(a);
  UNUSED_PARAMETER(b);
  return 0;
}

/*
** Deregister and destroy an RBU vfs created by an earlier call to
** sqlite3rbu_create_vfs().
*/
225648
225649
225650
225651
225652
225653
225654




225655


225656
225657
225658
225659
225660
225661
225662
** This is an eponymous virtual table so it does not need to be created before
** use.  The optional argument to the sqlite_dbpage() table name is the
** schema for the database file that is to be read.  The default schema is
** "main".
**
** The data field of sqlite_dbpage table can be updated.  The new
** value must be a BLOB which is the correct page size, otherwise the




** update fails.  Rows may not be deleted or inserted.


*/

/* #include "sqliteInt.h"   ** Requires access to internal data structures ** */
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
    && !defined(SQLITE_OMIT_VIRTUALTABLE)

typedef struct DbpageTable DbpageTable;







>
>
>
>
|
>
>







225713
225714
225715
225716
225717
225718
225719
225720
225721
225722
225723
225724
225725
225726
225727
225728
225729
225730
225731
225732
225733
** This is an eponymous virtual table so it does not need to be created before
** use.  The optional argument to the sqlite_dbpage() table name is the
** schema for the database file that is to be read.  The default schema is
** "main".
**
** The data field of sqlite_dbpage table can be updated.  The new
** value must be a BLOB which is the correct page size, otherwise the
** update fails.  INSERT operations also work, and operate as if they
** where REPLACE.  The size of the database can be extended by INSERT-ing
** new pages on the end.
**
** Rows may not be deleted.  However, doing an INSERT to page number N
** with NULL page data causes the N-th page and all subsequent pages to be
** deleted and the database to be truncated.
*/

/* #include "sqliteInt.h"   ** Requires access to internal data structures ** */
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
    && !defined(SQLITE_OMIT_VIRTUALTABLE)

typedef struct DbpageTable DbpageTable;
225671
225672
225673
225674
225675
225676
225677


225678
225679
225680
225681
225682
225683
225684
225685
225686
225687
225688
225689
225690
225691
  int iDb;                        /* Index of database to analyze */
  int szPage;                     /* Size of each page in bytes */
};

struct DbpageTable {
  sqlite3_vtab base;              /* Base class.  Must be first */
  sqlite3 *db;                    /* The database */


};

/* Columns */
#define DBPAGE_COLUMN_PGNO    0
#define DBPAGE_COLUMN_DATA    1
#define DBPAGE_COLUMN_SCHEMA  2



/*
** Connect to or create a dbpagevfs virtual table.
*/
static int dbpageConnect(
  sqlite3 *db,







>
>






<







225742
225743
225744
225745
225746
225747
225748
225749
225750
225751
225752
225753
225754
225755
225756

225757
225758
225759
225760
225761
225762
225763
  int iDb;                        /* Index of database to analyze */
  int szPage;                     /* Size of each page in bytes */
};

struct DbpageTable {
  sqlite3_vtab base;              /* Base class.  Must be first */
  sqlite3 *db;                    /* The database */
  int nTrunc;                     /* Entries in aTrunc[] */
  Pgno *aTrunc;                   /* Truncation size for each database */
};

/* Columns */
#define DBPAGE_COLUMN_PGNO    0
#define DBPAGE_COLUMN_DATA    1
#define DBPAGE_COLUMN_SCHEMA  2



/*
** Connect to or create a dbpagevfs virtual table.
*/
static int dbpageConnect(
  sqlite3 *db,
225720
225721
225722
225723
225724
225725
225726


225727
225728
225729
225730
225731
225732
225733
  return rc;
}

/*
** Disconnect from or destroy a dbpagevfs virtual table.
*/
static int dbpageDisconnect(sqlite3_vtab *pVtab){


  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** idxNum:
**







>
>







225792
225793
225794
225795
225796
225797
225798
225799
225800
225801
225802
225803
225804
225805
225806
225807
  return rc;
}

/*
** Disconnect from or destroy a dbpagevfs virtual table.
*/
static int dbpageDisconnect(sqlite3_vtab *pVtab){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  sqlite3_free(pTab->aTrunc);
  sqlite3_free(pVtab);
  return SQLITE_OK;
}

/*
** idxNum:
**
225941
225942
225943
225944
225945
225946
225947
225948
225949
225950
225951
225952

225953
225954
225955
225956
225957
225958
225959
225960
225961
225962




225963
225964
225965
225966
225967
225968
225969





225970
225971
225972
225973
225974
225975

225976
225977
225978
225979
225980
225981
225982
225983
225984














225985
225986

225987
225988
225989
225990
225991
225992
225993
225994
225995
225996

225997
225998
225999
226000
226001
226002
226003
  sqlite_int64 *pRowid
){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  Pgno pgno;
  DbPage *pDbPage = 0;
  int rc = SQLITE_OK;
  char *zErr = 0;
  const char *zSchema;
  int iDb;
  Btree *pBt;
  Pager *pPager;
  int szPage;


  (void)pRowid;
  if( pTab->db->flags & SQLITE_Defensive ){
    zErr = "read-only";
    goto update_fail;
  }
  if( argc==1 ){
    zErr = "cannot delete";
    goto update_fail;
  }




  pgno = sqlite3_value_int(argv[0]);
  if( sqlite3_value_type(argv[0])==SQLITE_NULL
   || (Pgno)sqlite3_value_int(argv[1])!=pgno
  ){
    zErr = "cannot insert";
    goto update_fail;
  }





  zSchema = (const char*)sqlite3_value_text(argv[4]);
  iDb = ALWAYS(zSchema) ? sqlite3FindDbName(pTab->db, zSchema) : -1;
  if( NEVER(iDb<0) ){
    zErr = "no such schema";
    goto update_fail;
  }

  pBt = pTab->db->aDb[iDb].pBt;
  if( NEVER(pgno<1) || NEVER(pBt==0) || NEVER(pgno>sqlite3BtreeLastPage(pBt)) ){
    zErr = "bad page number";
    goto update_fail;
  }
  szPage = sqlite3BtreeGetPageSize(pBt);
  if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
   || sqlite3_value_bytes(argv[3])!=szPage
  ){














    zErr = "bad page value";
    goto update_fail;

  }
  pPager = sqlite3BtreePager(pBt);
  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
  if( rc==SQLITE_OK ){
    const void *pData = sqlite3_value_blob(argv[3]);
    assert( pData!=0 || pTab->db->mallocFailed );
    if( pData
     && (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
    ){
      memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);

    }
  }
  sqlite3PagerUnref(pDbPage);
  return rc;

update_fail:
  sqlite3_free(pVtab->zErrMsg);







<




>










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

|







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





<
<
|
<
|
>







226015
226016
226017
226018
226019
226020
226021

226022
226023
226024
226025
226026
226027
226028
226029
226030
226031
226032
226033
226034
226035
226036
226037
226038
226039
226040
226041

226042

226043
226044
226045
226046
226047
226048
226049
226050
226051
226052
226053
226054
226055
226056
226057
226058
226059
226060
226061
226062
226063
226064
226065
226066
226067
226068
226069
226070
226071
226072
226073
226074
226075
226076
226077
226078
226079
226080
226081
226082
226083
226084
226085
226086
226087
226088


226089

226090
226091
226092
226093
226094
226095
226096
226097
226098
  sqlite_int64 *pRowid
){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  Pgno pgno;
  DbPage *pDbPage = 0;
  int rc = SQLITE_OK;
  char *zErr = 0;

  int iDb;
  Btree *pBt;
  Pager *pPager;
  int szPage;
  int isInsert;

  (void)pRowid;
  if( pTab->db->flags & SQLITE_Defensive ){
    zErr = "read-only";
    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 ){
    iDb = 0;
  }else{
    const char *zSchema = (const char*)sqlite3_value_text(argv[4]);
    iDb = sqlite3FindDbName(pTab->db, zSchema);
    if( iDb<0 ){
      zErr = "no such schema";
      goto update_fail;
    }
  }
  pBt = pTab->db->aDb[iDb].pBt;
  if( pgno<1 || NEVER(pBt==0) ){
    zErr = "bad page number";
    goto update_fail;
  }
  szPage = sqlite3BtreeGetPageSize(pBt);
  if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
   || sqlite3_value_bytes(argv[3])!=szPage
  ){
    if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert ){
      if( iDb>=pTab->nTrunc ){
        testcase( pTab->aTrunc!=0 );
        pTab->aTrunc = sqlite3_realloc(pTab->aTrunc, (iDb+1)*sizeof(Pgno));
        if( pTab->aTrunc ){
          int j;
          for(j=pTab->nTrunc; j<iDb; j++) pTab->aTrunc[j] = 0;
          pTab->nTrunc = iDb+1;
        }else{
          return SQLITE_NOMEM;
        }
      }
      pTab->aTrunc[iDb] = pgno;
    }else{
      zErr = "bad page value";
      goto update_fail;
    }
  }
  pPager = sqlite3BtreePager(pBt);
  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
  if( rc==SQLITE_OK ){
    const void *pData = sqlite3_value_blob(argv[3]);


    if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){

      unsigned char *aPage = sqlite3PagerGetData(pDbPage);
      memcpy(aPage, pData, szPage);
    }
  }
  sqlite3PagerUnref(pDbPage);
  return rc;

update_fail:
  sqlite3_free(pVtab->zErrMsg);
226012
226013
226014
226015
226016
226017
226018




















226019
226020
226021
226022
226023
226024
226025
static int dbpageBegin(sqlite3_vtab *pVtab){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  sqlite3 *db = pTab->db;
  int i;
  for(i=0; i<db->nDb; i++){
    Btree *pBt = db->aDb[i].pBt;
    if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);




















  }
  return SQLITE_OK;
}


/*
** Invoke this routine to register the "dbpage" virtual table module







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







226107
226108
226109
226110
226111
226112
226113
226114
226115
226116
226117
226118
226119
226120
226121
226122
226123
226124
226125
226126
226127
226128
226129
226130
226131
226132
226133
226134
226135
226136
226137
226138
226139
226140
static int dbpageBegin(sqlite3_vtab *pVtab){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  sqlite3 *db = pTab->db;
  int i;
  for(i=0; i<db->nDb; i++){
    Btree *pBt = db->aDb[i].pBt;
    if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0);
  }
  if( pTab->nTrunc>0 ){
    memset(pTab->aTrunc, 0, sizeof(pTab->aTrunc[0])*pTab->nTrunc);
  }
  return SQLITE_OK;
}

/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
*/
static int dbpageSync(sqlite3_vtab *pVtab){
  int iDb;
  DbpageTable *pTab = (DbpageTable *)pVtab;

  for(iDb=0; iDb<pTab->nTrunc; iDb++){
    if( pTab->aTrunc[iDb]>0 ){
      Btree *pBt = pTab->db->aDb[iDb].pBt;
      Pager *pPager = sqlite3BtreePager(pBt);
      sqlite3PagerTruncateImage(pPager, pTab->aTrunc[iDb]);
      pTab->aTrunc[iDb] = 0;
    }
  }
  return SQLITE_OK;
}


/*
** Invoke this routine to register the "dbpage" virtual table module
226037
226038
226039
226040
226041
226042
226043
226044
226045
226046
226047
226048
226049
226050
226051
    dbpageFilter,                 /* xFilter - configure scan constraints */
    dbpageNext,                   /* xNext - advance a cursor */
    dbpageEof,                    /* xEof - check for end of scan */
    dbpageColumn,                 /* xColumn - read data */
    dbpageRowid,                  /* xRowid - read data */
    dbpageUpdate,                 /* xUpdate */
    dbpageBegin,                  /* xBegin */
    0,                            /* xSync */
    0,                            /* xCommit */
    0,                            /* xRollback */
    0,                            /* xFindMethod */
    0,                            /* xRename */
    0,                            /* xSavepoint */
    0,                            /* xRelease */
    0,                            /* xRollbackTo */







|







226152
226153
226154
226155
226156
226157
226158
226159
226160
226161
226162
226163
226164
226165
226166
    dbpageFilter,                 /* xFilter - configure scan constraints */
    dbpageNext,                   /* xNext - advance a cursor */
    dbpageEof,                    /* xEof - check for end of scan */
    dbpageColumn,                 /* xColumn - read data */
    dbpageRowid,                  /* xRowid - read data */
    dbpageUpdate,                 /* xUpdate */
    dbpageBegin,                  /* xBegin */
    dbpageSync,                   /* xSync */
    0,                            /* xCommit */
    0,                            /* xRollback */
    0,                            /* xFindMethod */
    0,                            /* xRename */
    0,                            /* xSavepoint */
    0,                            /* xRelease */
    0,                            /* xRollbackTo */
233970
233971
233972
233973
233974
233975
233976
233977
233978
233979
233980
233981
233982
233983
233984
233985
233986
233987
233988
233989
233990
233991
233992
233993

static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);

static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);

static int sqlite3Fts5FlushToDisk(Fts5Table*);

static int sqlite3Fts5ExtractText(
  Fts5Config *pConfig,
  sqlite3_value *pVal,            /* Value to extract text from */
  int bContent,                   /* Loaded from content table */
  int *pbResetTokenizer,          /* OUT: True if ClearLocale() required */
  const char **ppText,            /* OUT: Pointer to text buffer */
  int *pnText                     /* OUT: Size of (*ppText) in bytes */
);

static void sqlite3Fts5ClearLocale(Fts5Config *pConfig);

/*
** End of interface to code in fts5.c.
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_hash.c.







|
|
|
|
|
|
<

<
<







234085
234086
234087
234088
234089
234090
234091
234092
234093
234094
234095
234096
234097

234098


234099
234100
234101
234102
234103
234104
234105

static int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);

static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);

static int sqlite3Fts5FlushToDisk(Fts5Table*);

static void sqlite3Fts5ClearLocale(Fts5Config *pConfig);
static void sqlite3Fts5SetLocale(Fts5Config *pConfig, const char *pLoc, int nLoc);

static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal);
static int sqlite3Fts5DecodeLocaleValue(sqlite3_value *pVal,
    const char **ppText, int *pnText, const char **ppLoc, int *pnLoc

);



/*
** End of interface to code in fts5.c.
**************************************************************************/

/**************************************************************************
** Interface to code in fts5_hash.c.
237542
237543
237544
237545
237546
237547
237548









237549
237550
237551
237552
237553
237554
237555
    for(i=0; i<p->nCol; i++){
      if( p->eContent==FTS5_CONTENT_EXTERNAL ){
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]);
      }else{
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i);
      }
    }









  }

  assert( p->zContentExprlist==0 );
  p->zContentExprlist = (char*)buf.p;
  return rc;
}








>
>
>
>
>
>
>
>
>







237654
237655
237656
237657
237658
237659
237660
237661
237662
237663
237664
237665
237666
237667
237668
237669
237670
237671
237672
237673
237674
237675
237676
    for(i=0; i<p->nCol; i++){
      if( p->eContent==FTS5_CONTENT_EXTERNAL ){
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]);
      }else{
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i);
      }
    }
  }
  if( p->eContent==FTS5_CONTENT_NORMAL && p->bLocale ){
    for(i=0; i<p->nCol; i++){
      if( p->abUnindexed[i]==0 ){
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.l%d", i);
      }else{
        sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
      }
    }
  }

  assert( p->zContentExprlist==0 );
  p->zContentExprlist = (char*)buf.p;
  return rc;
}

251111
251112
251113
251114
251115
251116
251117

251118








251119
251120
251121
251122
251123
251124
251125
  fts5_api api;                   /* User visible part of object (see fts5.h) */
  sqlite3 *db;                    /* Associated database connection */
  i64 iNextId;                    /* Used to allocate unique cursor ids */
  Fts5Auxiliary *pAux;            /* First in list of all aux. functions */
  Fts5TokenizerModule *pTok;      /* First in list of all tokenizer modules */
  Fts5TokenizerModule *pDfltTok;  /* Default tokenizer module */
  Fts5Cursor *pCsr;               /* First in list of all open cursors */

};









/*
** Each auxiliary function registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pAux list.
*/
struct Fts5Auxiliary {







>

>
>
>
>
>
>
>
>







251232
251233
251234
251235
251236
251237
251238
251239
251240
251241
251242
251243
251244
251245
251246
251247
251248
251249
251250
251251
251252
251253
251254
251255
  fts5_api api;                   /* User visible part of object (see fts5.h) */
  sqlite3 *db;                    /* Associated database connection */
  i64 iNextId;                    /* Used to allocate unique cursor ids */
  Fts5Auxiliary *pAux;            /* First in list of all aux. functions */
  Fts5TokenizerModule *pTok;      /* First in list of all tokenizer modules */
  Fts5TokenizerModule *pDfltTok;  /* Default tokenizer module */
  Fts5Cursor *pCsr;               /* First in list of all open cursors */
  u32 aLocaleHdr[4];
};

/*
** Size of header on fts5_locale() values. And macro to access a buffer
** containing a copy of the header from an Fts5Config pointer.
*/
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))


/*
** Each auxiliary function registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pAux list.
*/
struct Fts5Auxiliary {
251275
251276
251277
251278
251279
251280
251281
251282
251283
251284
251285
251286
251287
251288
251289
251290
251291
251292
251293
251294
#define FTS5CSR_FREE_ZRANK        0x10
#define FTS5CSR_REQUIRE_RESEEK    0x20
#define FTS5CSR_REQUIRE_POSLIST   0x40

#define BitFlagAllTest(x,y) (((x) & (y))==(y))
#define BitFlagTest(x,y)    (((x) & (y))!=0)

/*
** The subtype value and header bytes used by fts5_locale().
*/
#define FTS5_LOCALE_SUBTYPE ((unsigned int)'L')
#define FTS5_LOCALE_HEADER  "\x00\xE0\xB2\xEB"


/*
** Macros to Set(), Clear() and Test() cursor flags.
*/
#define CsrFlagSet(pCsr, flag)   ((pCsr)->csrflags |= (flag))
#define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag))
#define CsrFlagTest(pCsr, flag)  ((pCsr)->csrflags & (flag))







<
<
<
<
<
<







251405
251406
251407
251408
251409
251410
251411






251412
251413
251414
251415
251416
251417
251418
#define FTS5CSR_FREE_ZRANK        0x10
#define FTS5CSR_REQUIRE_RESEEK    0x20
#define FTS5CSR_REQUIRE_POSLIST   0x40

#define BitFlagAllTest(x,y) (((x) & (y))==(y))
#define BitFlagTest(x,y)    (((x) & (y))!=0)








/*
** Macros to Set(), Clear() and Test() cursor flags.
*/
#define CsrFlagSet(pCsr, flag)   ((pCsr)->csrflags |= (flag))
#define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag))
#define CsrFlagTest(pCsr, flag)  ((pCsr)->csrflags & (flag))
252284
252285
252286
252287
252288
252289
252290
252291
252292
252293
252294
252295
252296
252297
252298
252299
252300
252301
252302
252303
252304
252305
252306
252307
252308
252309
252310
252311
252312
252313
252314
252315
252316
252317
252318
252319
252320
252321
252322
252323
252324
252325
252326
252327
252328
252329
252330
252331
252332
252333
252334
252335
252336
252337
252338
252339
252340
252341
252342
252343
252344
252345
252346
252347
252348
252349
252350
252351
252352
252353
252354
252355
252356
252357
252358
252359
252360
252361
252362
252363
252364
252365
252366
252367
252368
252369
252370
252371
252372
252373
252374
252375
252376
252377
252378
252379
252380
252381
252382
252383
252384
252385
252386
252387
252388

252389
252390
252391
252392
252393
252394
252395
252396
252397
252398
252399
252400
252401


252402


252403
252404
252405







252406
252407
252408

252409




252410
252411


252412



252413
252414
252415
252416
252417


252418
252419
252420
252421
252422
252423
252424
252425
252426
252427
252428
252429
252430
252431
252432
252433
252434
252435
252436
252437
252438
252439
252440
252441
252442
252443
252444
252445
252446
252447
252448


252449


252450
252451
252452
252453
252454
252455
252456
252457
252458

252459
252460
252461

252462
252463
252464
252465
252466
252467
252468

/*
** Arrange for subsequent calls to sqlite3Fts5Tokenize() to use the locale
** specified by pLocale/nLocale. The buffer indicated by pLocale must remain
** valid until after the final call to sqlite3Fts5Tokenize() that will use
** the locale.
*/
static void fts5SetLocale(
  Fts5Config *pConfig,
  const char *zLocale,
  int nLocale
){
  Fts5TokenizerConfig *pT = &pConfig->t;
  pT->pLocale = zLocale;
  pT->nLocale = nLocale;
}

/*
** Clear any locale configured by an earlier call to fts5SetLocale() or
** sqlite3Fts5ExtractText().
*/
static void sqlite3Fts5ClearLocale(Fts5Config *pConfig){
  fts5SetLocale(pConfig, 0, 0);
}

/*
** This function is used to extract utf-8 text from an sqlite3_value. This
** is usually done in order to tokenize it. For example, when:
**
**     * a value is written to an fts5 table,
**     * a value is deleted from an FTS5_CONTENT_NORMAL table,
**     * a value containing a query expression is passed to xFilter()
**
** and so on.
**
** This function handles 2 cases:
**
**   1) Ordinary values. The text can be extracted from these using
**      sqlite3_value_text().
**
**   2) Combination text/locale blobs created by fts5_locale(). There
**      are several cases for these:
**
**        * Blobs tagged with FTS5_LOCALE_SUBTYPE.
**        * Blobs read from the content table of a locale=1 external-content
**          table, and
**        * Blobs read from the content table of a locale=1 regular
**          content table.
**
**      The first two cases above should have the 4 byte FTS5_LOCALE_HEADER
**      header. It is an error if a blob with the subtype or a blob read
**      from the content table of an external content table does not have
**      the required header. A blob read from the content table of a regular
**      locale=1 table does not have the header. This is to save space.
**
** If successful, SQLITE_OK is returned and output parameters (*ppText)
** and (*pnText) are set to point to a buffer containing the extracted utf-8
** text and its length in bytes, respectively. The buffer is not
** nul-terminated. It has the same lifetime as the sqlite3_value object
** from which it is extracted.
**
** Parameter bContent must be true if the value was read from an indexed
** column (i.e. not UNINDEXED) of the on disk content.
**
** If pbResetTokenizer is not NULL and if case (2) is used, then
** fts5SetLocale() is called to ensure subsequent sqlite3Fts5Tokenize() calls
** use the locale. In this case (*pbResetTokenizer) is set to true before
** returning, to indicate that the caller must call sqlite3Fts5ClearLocale()
** to clear the locale after tokenizing the text.
*/
static int sqlite3Fts5ExtractText(
  Fts5Config *pConfig,
  sqlite3_value *pVal,            /* Value to extract text from */
  int bContent,                   /* True if indexed table content */
  int *pbResetTokenizer,          /* OUT: True if xSetLocale(NULL) required */
  const char **ppText,            /* OUT: Pointer to text buffer */
  int *pnText                     /* OUT: Size of (*ppText) in bytes */
){
  const char *pText = 0;
  int nText = 0;
  int rc = SQLITE_OK;
  int bDecodeBlob = 0;

  assert( pbResetTokenizer==0 || *pbResetTokenizer==0 );
  assert( bContent==0 || pConfig->eContent!=FTS5_CONTENT_NONE );
  assert( bContent==0 || sqlite3_value_subtype(pVal)==0 );

  if( sqlite3_value_type(pVal)==SQLITE_BLOB ){
    if( sqlite3_value_subtype(pVal)==FTS5_LOCALE_SUBTYPE
     || (bContent && pConfig->bLocale)
    ){
      bDecodeBlob = 1;
    }
  }

  if( bDecodeBlob ){
    const int SZHDR = sizeof(FTS5_LOCALE_HEADER)-1;
    const u8 *pBlob = sqlite3_value_blob(pVal);
    int nBlob = sqlite3_value_bytes(pVal);

    /* Unless this blob was read from the %_content table of an
    ** FTS5_CONTENT_NORMAL table, it should have the 4 byte fts5_locale()
    ** header. Check for this. If it is not found, return an error.  */
    if( (!bContent || pConfig->eContent!=FTS5_CONTENT_NORMAL) ){
      if( nBlob<SZHDR || memcmp(FTS5_LOCALE_HEADER, pBlob, SZHDR) ){

        rc = SQLITE_ERROR;
      }else{
        pBlob += 4;
        nBlob -= 4;
      }
    }

    if( rc==SQLITE_OK ){
      int nLocale = 0;

      for(nLocale=0; nLocale<nBlob; nLocale++){
        if( pBlob[nLocale]==0x00 ) break;
      }


      if( nLocale==nBlob || nLocale==0 ){


        rc = SQLITE_ERROR;
      }else{
        pText = (const char*)&pBlob[nLocale+1];







        nText = nBlob-nLocale-1;

        if( pbResetTokenizer ){

          fts5SetLocale(pConfig, (const char*)pBlob, nLocale);




          *pbResetTokenizer = 1;
        }


      }



    }

  }else{
    pText = (const char*)sqlite3_value_text(pVal);
    nText = sqlite3_value_bytes(pVal);


  }

  *ppText = pText;
  *pnText = nText;
  return rc;
}

/*
** Argument pVal is the text of a full-text search expression. It may or
** may not have been wrapped by fts5_locale(). This function extracts
** the text of the expression, and sets output variable (*pzText) to
** point to a nul-terminated buffer containing the expression.
**
** If pVal was an fts5_locale() value, then fts5SetLocale() is called to
** set the tokenizer to use the specified locale.
**
** If output variable (*pbFreeAndReset) is set to true, then the caller
** is required to (a) call sqlite3Fts5ClearLocale() to reset the tokenizer
** locale, and (b) call sqlite3_free() to free (*pzText).
*/
static int fts5ExtractExprText(
  Fts5Config *pConfig,            /* Fts5 configuration */
  sqlite3_value *pVal,            /* Value to extract expression text from */
  char **pzText,                  /* OUT: nul-terminated buffer of text */
  int *pbFreeAndReset             /* OUT: Free (*pzText) and clear locale */
){
  const char *zText = 0;
  int nText = 0;
  int rc = SQLITE_OK;
  int bReset = 0;



  *pbFreeAndReset = 0;


  rc = sqlite3Fts5ExtractText(pConfig, pVal, 0, &bReset, &zText, &nText);
  if( rc==SQLITE_OK ){
    if( bReset ){
      *pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, zText);
      if( rc!=SQLITE_OK ){
        sqlite3Fts5ClearLocale(pConfig);
      }else{
        *pbFreeAndReset = 1;
      }

    }else{
      *pzText = (char*)zText;
    }

  }

  return rc;
}


/*







|










|
<


|



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

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

|
|
|
|
<
<
|
|
<


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

|
<
<
<
>
>
|
<
|
|
|








|
|











<
<

<

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







252408
252409
252410
252411
252412
252413
252414
252415
252416
252417
252418
252419
252420
252421
252422
252423
252424
252425
252426

252427
252428
252429
252430
252431
252432



252433










252434




























252435
252436







252437








252438
252439
252440
252441
252442


252443
252444

252445
252446
252447




252448
252449
252450



252451
252452
252453


252454


252455
252456
252457
252458
252459
252460
252461


252462
252463
252464
252465
252466
252467
252468
252469
252470
252471
252472
252473
252474
252475
252476
252477
252478
252479
252480
252481
252482
252483
252484
252485
252486
252487



252488
252489
252490

252491
252492
252493
252494
252495
252496
252497
252498
252499
252500
252501
252502
252503
252504
252505
252506
252507
252508
252509
252510
252511
252512
252513
252514


252515

252516
252517
252518
252519
252520
252521
252522


252523
252524
252525


252526
252527
252528
252529

252530
252531
252532
252533
252534
252535
252536
252537

/*
** Arrange for subsequent calls to sqlite3Fts5Tokenize() to use the locale
** specified by pLocale/nLocale. The buffer indicated by pLocale must remain
** valid until after the final call to sqlite3Fts5Tokenize() that will use
** the locale.
*/
static void sqlite3Fts5SetLocale(
  Fts5Config *pConfig,
  const char *zLocale,
  int nLocale
){
  Fts5TokenizerConfig *pT = &pConfig->t;
  pT->pLocale = zLocale;
  pT->nLocale = nLocale;
}

/*
** Clear any locale configured by an earlier call to sqlite3Fts5SetLocale().

*/
static void sqlite3Fts5ClearLocale(Fts5Config *pConfig){
  sqlite3Fts5SetLocale(pConfig, 0, 0);
}

/*



** Return true if the value passed as the only argument is an










** fts5_locale() value.




























*/
static int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal){







  int ret = 0;








  if( sqlite3_value_type(pVal)==SQLITE_BLOB ){
    /* Call sqlite3_value_bytes() after sqlite3_value_blob() in this case.
    ** If the blob was created using zeroblob(), then sqlite3_value_blob()
    ** may call malloc(). If this malloc() fails, then the values returned
    ** by both value_blob() and value_bytes() will be 0. If value_bytes() were


    ** called first, then the NULL pointer returned by value_blob() might
    ** be dereferenced.  */

    const u8 *pBlob = sqlite3_value_blob(pVal);
    int nBlob = sqlite3_value_bytes(pVal);
    if( nBlob>FTS5_LOCALE_HDR_SIZE




     && 0==memcmp(pBlob, FTS5_LOCALE_HDR(pConfig), FTS5_LOCALE_HDR_SIZE)
    ){
      ret = 1;



    }
  }
  return ret;


}



/*
** Value pVal is guaranteed to be an fts5_locale() value, according to
** sqlite3Fts5IsLocaleValue(). This function extracts the text and locale
** from the value and returns them separately.
**
** If successful, SQLITE_OK is returned and (*ppText) and (*ppLoc) set


** to point to buffers containing the text and locale, as utf-8,
** respectively. In this case output parameters (*pnText) and (*pnLoc) are
** set to the sizes in bytes of these two buffers.
**
** Or, if an error occurs, then an SQLite error code is returned. The final
** value of the four output parameters is undefined in this case.
*/
static int sqlite3Fts5DecodeLocaleValue(
  sqlite3_value *pVal,
  const char **ppText,
  int *pnText,
  const char **ppLoc,
  int *pnLoc
){
  const char *p = sqlite3_value_blob(pVal);
  int n = sqlite3_value_bytes(pVal);
  int nLoc = 0;

  assert( sqlite3_value_type(pVal)==SQLITE_BLOB );
  assert( n>FTS5_LOCALE_HDR_SIZE );

  for(nLoc=FTS5_LOCALE_HDR_SIZE; p[nLoc]; nLoc++){
    if( nLoc==(n-1) ){
      return SQLITE_MISMATCH;
    }
  }



  *ppLoc = &p[FTS5_LOCALE_HDR_SIZE];
  *pnLoc = nLoc - FTS5_LOCALE_HDR_SIZE;


  *ppText = &p[nLoc+1];
  *pnText = n - nLoc - 1;
  return SQLITE_OK;
}

/*
** Argument pVal is the text of a full-text search expression. It may or
** may not have been wrapped by fts5_locale(). This function extracts
** the text of the expression, and sets output variable (*pzText) to
** point to a nul-terminated buffer containing the expression.
**
** If pVal was an fts5_locale() value, then sqlite3Fts5SetLocale() is called
** to set the tokenizer to use the specified locale.
**
** If output variable (*pbFreeAndReset) is set to true, then the caller
** is required to (a) call sqlite3Fts5ClearLocale() to reset the tokenizer
** locale, and (b) call sqlite3_free() to free (*pzText).
*/
static int fts5ExtractExprText(
  Fts5Config *pConfig,            /* Fts5 configuration */
  sqlite3_value *pVal,            /* Value to extract expression text from */
  char **pzText,                  /* OUT: nul-terminated buffer of text */
  int *pbFreeAndReset             /* OUT: Free (*pzText) and clear locale */
){


  int rc = SQLITE_OK;


  if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
    const char *pText = 0;
    int nText = 0;
    const char *pLoc = 0;
    int nLoc = 0;
    rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);


    *pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, pText);
    if( rc==SQLITE_OK ){
      sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);


    }
    *pbFreeAndReset = 1;
  }else{
    *pzText = (char*)sqlite3_value_text(pVal);

    *pbFreeAndReset = 0;
  }

  return rc;
}


/*
252994
252995
252996
252997
252998
252999
253000
253001
253002
253003
253004
253005
253006
253007
253008
253009
253010
253011
253012
253013
253014
253015
253016
253017
253018
253019
253020
      bUpdateOrDelete = 1;
    }

    /* INSERT or UPDATE */
    else{
      int eType1 = sqlite3_value_numeric_type(apVal[1]);

      /* Ensure that no fts5_locale() values are written to locale=0 tables.
      ** And that no blobs except fts5_locale() blobs are written to indexed
      ** (i.e. not UNINDEXED) columns of locale=1 tables. */
      int ii;
      for(ii=0; ii<pConfig->nCol; ii++){
        if( sqlite3_value_type(apVal[ii+2])==SQLITE_BLOB ){
          int bSub = (sqlite3_value_subtype(apVal[ii+2])==FTS5_LOCALE_SUBTYPE);
          if( (pConfig->bLocale && !bSub && pConfig->abUnindexed[ii]==0)
           || (pConfig->bLocale==0 && bSub)
          ){
            if( pConfig->bLocale==0 ){
              fts5SetVtabError(pTab, "fts5_locale() requires locale=1");
            }
            rc = SQLITE_MISMATCH;
            goto update_out;
          }
        }
      }

      if( eType0!=SQLITE_INTEGER ){







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







253063
253064
253065
253066
253067
253068
253069
253070
253071
253072
253073
253074
253075


253076


253077

253078
253079
253080
253081
253082
253083
253084
      bUpdateOrDelete = 1;
    }

    /* INSERT or UPDATE */
    else{
      int eType1 = sqlite3_value_numeric_type(apVal[1]);

      /* It is an error to write an fts5_locale() value to a table without
      ** the locale=1 option. */
      if( pConfig->bLocale==0 ){
        int ii;
        for(ii=0; ii<pConfig->nCol; ii++){
          sqlite3_value *pVal = apVal[ii+2];


          if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){


            fts5SetVtabError(pTab, "fts5_locale() requires locale=1");

            rc = SQLITE_MISMATCH;
            goto update_out;
          }
        }
      }

      if( eType0!=SQLITE_INTEGER ){
253167
253168
253169
253170
253171
253172
253173
253174
253175
253176
253177
253178
253179
253180
253181
253182
253183
253184
253185
  void *pUserData,
  int (*xToken)(void*, int, const char*, int, int, int)
){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  int rc = SQLITE_OK;

  fts5SetLocale(pTab->pConfig, pLoc, nLoc);
  rc = sqlite3Fts5Tokenize(pTab->pConfig,
      FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
  );
  fts5SetLocale(pTab->pConfig, 0, 0);

  return rc;
}

/*
** Implementation of xTokenize() API. This is just xTokenize_v2() with NULL/0
** passed as the locale.







|



|







253231
253232
253233
253234
253235
253236
253237
253238
253239
253240
253241
253242
253243
253244
253245
253246
253247
253248
253249
  void *pUserData,
  int (*xToken)(void*, int, const char*, int, int, int)
){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
  int rc = SQLITE_OK;

  sqlite3Fts5SetLocale(pTab->pConfig, pLoc, nLoc);
  rc = sqlite3Fts5Tokenize(pTab->pConfig,
      FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken
  );
  sqlite3Fts5SetLocale(pTab->pConfig, 0, 0);

  return rc;
}

/*
** Implementation of xTokenize() API. This is just xTokenize_v2() with NULL/0
** passed as the locale.
253198
253199
253200
253201
253202
253203
253204











































253205
253206
253207
253208
253209
253210
253211
253212
253213
253214
253215
253216
253217
253218
253219
253220
253221
253222
253223
253224
253225
253226
253227
253228
253229
253230
253231
253232
253233
253234
253235
  return sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
}

static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
}












































static int fts5ApiColumnText(
  Fts5Context *pCtx,
  int iCol,
  const char **pz,
  int *pn
){
  int rc = SQLITE_OK;
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);

  assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
  if( iCol<0 || iCol>=pTab->pConfig->nCol ){
    rc = SQLITE_RANGE;
  }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) ){
    *pz = 0;
    *pn = 0;
  }else{
    rc = fts5SeekCursor(pCsr, 0);
    if( rc==SQLITE_OK ){
      Fts5Config *pConfig = pTab->pConfig;
      int bContent = (pConfig->abUnindexed[iCol]==0);
      sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
      sqlite3Fts5ExtractText(pConfig, pVal, bContent, 0, pz, pn);
    }
  }
  return rc;
}

/*
** This is called by various API functions - xInst, xPhraseFirst,







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




















|
<
<
|







253262
253263
253264
253265
253266
253267
253268
253269
253270
253271
253272
253273
253274
253275
253276
253277
253278
253279
253280
253281
253282
253283
253284
253285
253286
253287
253288
253289
253290
253291
253292
253293
253294
253295
253296
253297
253298
253299
253300
253301
253302
253303
253304
253305
253306
253307
253308
253309
253310
253311
253312
253313
253314
253315
253316
253317
253318
253319
253320
253321
253322
253323
253324
253325
253326
253327
253328
253329
253330
253331
253332


253333
253334
253335
253336
253337
253338
253339
253340
  return sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
}

static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
}

/*
** Argument pStmt is an SQL statement of the type used by Fts5Cursor. This
** function extracts the text value of column iCol of the current row.
** Additionally, if there is an associated locale, it invokes
** sqlite3Fts5SetLocale() to configure the tokenizer. In all cases the caller
** should invoke sqlite3Fts5ClearLocale() to clear the locale at some point
** after this function returns.
**
** If successful, (*ppText) is set to point to a buffer containing the text
** value as utf-8 and SQLITE_OK returned. (*pnText) is set to the size of that
** buffer in bytes. It is not guaranteed to be nul-terminated. If an error
** occurs, an SQLite error code is returned. The final values of the two
** output parameters are undefined in this case.
*/
static int fts5TextFromStmt(
  Fts5Config *pConfig,
  sqlite3_stmt *pStmt,
  int iCol,
  const char **ppText,
  int *pnText
){
  sqlite3_value *pVal = sqlite3_column_value(pStmt, iCol+1);
  const char *pLoc = 0;
  int nLoc = 0;
  int rc = SQLITE_OK;

  if( pConfig->bLocale
   && pConfig->eContent==FTS5_CONTENT_EXTERNAL
   && sqlite3Fts5IsLocaleValue(pConfig, pVal)
  ){
    rc = sqlite3Fts5DecodeLocaleValue(pVal, ppText, pnText, &pLoc, &nLoc);
  }else{
    *ppText = (const char*)sqlite3_value_text(pVal);
    *pnText = sqlite3_value_bytes(pVal);
    if( pConfig->bLocale && pConfig->eContent==FTS5_CONTENT_NORMAL ){
      pLoc = (const char*)sqlite3_column_text(pStmt, iCol+1+pConfig->nCol);
      nLoc = sqlite3_column_bytes(pStmt, iCol+1+pConfig->nCol);
    }
  }
  sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
  return rc;
}

static int fts5ApiColumnText(
  Fts5Context *pCtx,
  int iCol,
  const char **pz,
  int *pn
){
  int rc = SQLITE_OK;
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
  Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);

  assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
  if( iCol<0 || iCol>=pTab->pConfig->nCol ){
    rc = SQLITE_RANGE;
  }else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab)) ){
    *pz = 0;
    *pn = 0;
  }else{
    rc = fts5SeekCursor(pCsr, 0);
    if( rc==SQLITE_OK ){
      rc = fts5TextFromStmt(pTab->pConfig, pCsr->pStmt, iCol, pz, pn);


      sqlite3Fts5ClearLocale(pTab->pConfig);
    }
  }
  return rc;
}

/*
** This is called by various API functions - xInst, xPhraseFirst,
253263
253264
253265
253266
253267
253268
253269
253270
253271
253272
253273
253274
253275
253276
253277
253278
253279
253280
253281
253282
253283
253284
253285
253286
253287

      aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
      if( aPopulator==0 ) rc = SQLITE_NOMEM;
      if( rc==SQLITE_OK ){
        rc = fts5SeekCursor(pCsr, 0);
      }
      for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
        sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, i+1);
        const char *z = 0;
        int n = 0;
        int bReset = 0;
        rc = sqlite3Fts5ExtractText(pConfig, pVal, 1, &bReset, &z, &n);
        if( rc==SQLITE_OK ){
          rc = sqlite3Fts5ExprPopulatePoslists(
              pConfig, pCsr->pExpr, aPopulator, i, z, n
          );
        }
        if( bReset ) sqlite3Fts5ClearLocale(pConfig);
      }
      sqlite3_free(aPopulator);

      if( pCsr->pSorter ){
        sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
      }
    }







<


<
|





|







253368
253369
253370
253371
253372
253373
253374

253375
253376

253377
253378
253379
253380
253381
253382
253383
253384
253385
253386
253387
253388
253389
253390

      aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
      if( aPopulator==0 ) rc = SQLITE_NOMEM;
      if( rc==SQLITE_OK ){
        rc = fts5SeekCursor(pCsr, 0);
      }
      for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){

        const char *z = 0;
        int n = 0;

        rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
        if( rc==SQLITE_OK ){
          rc = sqlite3Fts5ExprPopulatePoslists(
              pConfig, pCsr->pExpr, aPopulator, i, z, n
          );
        }
        sqlite3Fts5ClearLocale(pConfig);
      }
      sqlite3_free(aPopulator);

      if( pCsr->pSorter ){
        sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
      }
    }
253459
253460
253461
253462
253463
253464
253465
253466
253467
253468
253469
253470
253471
253472
253473
253474
253475
253476

253477
253478
253479
253480
253481
253482
253483
    }else{
      int i;
      rc = fts5SeekCursor(pCsr, 0);
      for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
        if( pConfig->abUnindexed[i]==0 ){
          const char *z = 0;
          int n = 0;
          int bReset = 0;
          sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, i+1);

          pCsr->aColumnSize[i] = 0;
          rc = sqlite3Fts5ExtractText(pConfig, pVal, 1, &bReset, &z, &n);
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_AUX,
                z, n, (void*)&pCsr->aColumnSize[i], fts5ColumnSizeCb
            );
            if( bReset ) sqlite3Fts5ClearLocale(pConfig);
          }

        }
      }
    }
    CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
  }
  if( iCol<0 ){
    int i;







<
<
<

|




<

>







253562
253563
253564
253565
253566
253567
253568



253569
253570
253571
253572
253573
253574

253575
253576
253577
253578
253579
253580
253581
253582
253583
    }else{
      int i;
      rc = fts5SeekCursor(pCsr, 0);
      for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
        if( pConfig->abUnindexed[i]==0 ){
          const char *z = 0;
          int n = 0;



          pCsr->aColumnSize[i] = 0;
          rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
          if( rc==SQLITE_OK ){
            rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_AUX,
                z, n, (void*)&pCsr->aColumnSize[i], fts5ColumnSizeCb
            );

          }
          sqlite3Fts5ClearLocale(pConfig);
        }
      }
    }
    CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
  }
  if( iCol<0 ){
    int i;
253741
253742
253743
253744
253745
253746
253747
253748
253749
253750
253751
253752
253753
253754
253755
253756
253757
253758
253759
253760
253761
253762
253763
253764
253765
253766
253767
253768
253769
253770
253771
253772
253773
253774
253775
253776
253777
253778

253779
253780
253781
253782
253783
253784
253785
  }else if(
      pConfig->abUnindexed[iCol]==0
   && pConfig->eContent!=FTS5_CONTENT_NONE
   && pConfig->bLocale
  ){
    rc = fts5SeekCursor(pCsr, 0);
    if( rc==SQLITE_OK ){
      /* Load the value into pVal. pVal is a locale/text pair iff:
      **
      **   1) It is an SQLITE_BLOB, and
      **   2) Either the subtype is FTS5_LOCALE_SUBTYPE, or else the
      **      value was loaded from an FTS5_CONTENT_NORMAL table, and
      **   3) It does not begin with an 0x00 byte.
      */
      sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
      if( sqlite3_value_type(pVal)==SQLITE_BLOB ){
        const u8 *pBlob = (const u8*)sqlite3_value_blob(pVal);
        int nBlob = sqlite3_value_bytes(pVal);
        if( pConfig->eContent==FTS5_CONTENT_EXTERNAL ){
          const int SZHDR = sizeof(FTS5_LOCALE_HEADER)-1;
          if( nBlob<SZHDR || memcmp(FTS5_LOCALE_HEADER, pBlob, SZHDR) ){
            rc = SQLITE_ERROR;
          }
          pBlob += 4;
          nBlob -= 4;
        }
        if( rc==SQLITE_OK ){
          int nLocale = 0;
          for(nLocale=0; nLocale<nBlob && pBlob[nLocale]!=0x00; nLocale++);
          if( nLocale==nBlob || nLocale==0 ){
            rc = SQLITE_ERROR;
          }else{
            /* A locale/text pair */
            *pzLocale = (const char*)pBlob;
            *pnLocale = nLocale;
          }
        }
      }

    }
  }

  return rc;
}

static const Fts5ExtensionApi sFts5Api = {







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







253841
253842
253843
253844
253845
253846
253847









253848
253849
253850







253851
253852






253853
253854


253855
253856
253857
253858
253859
253860
253861
253862
  }else if(
      pConfig->abUnindexed[iCol]==0
   && pConfig->eContent!=FTS5_CONTENT_NONE
   && pConfig->bLocale
  ){
    rc = fts5SeekCursor(pCsr, 0);
    if( rc==SQLITE_OK ){









      const char *zDummy = 0;
      int nDummy = 0;
      rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &zDummy, &nDummy);







      if( rc==SQLITE_OK ){
        *pzLocale = pConfig->t.pLocale;






        *pnLocale = pConfig->t.nLocale;
      }


      sqlite3Fts5ClearLocale(pConfig);
    }
  }

  return rc;
}

static const Fts5ExtensionApi sFts5Api = {
253992
253993
253994
253995
253996
253997
253998
253999
254000
254001
254002
254003
254004
254005
254006
254007
254008
254009
254010
254011
254012
254013
254014
254015
254016
254017
254018
254019
254020
254021
254022
254023
254024
254025
254026
254027
254028
254029
254030
254031
254032
254033
254034
254035
254036
254037
254038
254039
254040
254041
254042
254043
254044
254045
254046
254047
254048
254049
254050
254051
254052
254053
254054
254055
254056
      break;
  }

  sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
  return rc;
}

/*
** Value pVal was read from column iCol of the FTS5 table. This function
** returns it to the owner of pCtx via a call to an sqlite3_result_xxx()
** function. This function deals with the same cases as
** sqlite3Fts5ExtractText():
**
**   1) Ordinary values. These can be returned using sqlite3_result_value().
**
**   2) Blobs from fts5_locale(). The text is extracted from these and
**      returned via sqlite3_result_text(). The locale is discarded.
*/
static void fts5ExtractValueFromColumn(
  sqlite3_context *pCtx,
  Fts5Config *pConfig,
  int iCol,
  sqlite3_value *pVal
){
  assert( pConfig->eContent!=FTS5_CONTENT_NONE );

  if( pConfig->bLocale
   && sqlite3_value_type(pVal)==SQLITE_BLOB
   && pConfig->abUnindexed[iCol]==0
  ){
    const int SZHDR = sizeof(FTS5_LOCALE_HEADER)-1;
    const u8 *pBlob = sqlite3_value_blob(pVal);
    int nBlob = sqlite3_value_bytes(pVal);
    int ii;

    if( pConfig->eContent==FTS5_CONTENT_EXTERNAL ){
      if( nBlob<SZHDR || memcmp(pBlob, FTS5_LOCALE_HEADER, SZHDR) ){
        sqlite3_result_error_code(pCtx, SQLITE_ERROR);
        return;
      }else{
        pBlob += 4;
        nBlob -= 4;
      }
    }

    for(ii=0; ii<nBlob && pBlob[ii]; ii++);
    if( ii==0 || ii==nBlob ){
      sqlite3_result_error_code(pCtx, SQLITE_ERROR);
    }else{
      const char *pText = (const char*)&pBlob[ii+1];
      sqlite3_result_text(pCtx, pText, nBlob-ii-1, SQLITE_TRANSIENT);
    }
    return;
  }

  sqlite3_result_value(pCtx, pVal);
}

/*
** This is the xColumn method, called by SQLite to request a value from
** the row that the supplied cursor currently points to.
*/
static int fts5ColumnMethod(
  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







254069
254070
254071
254072
254073
254074
254075



















































254076
254077
254078
254079
254080
254081
254082
      break;
  }

  sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
  return rc;
}




















































/*
** This is the xColumn method, called by SQLite to request a value from
** the row that the supplied cursor currently points to.
*/
static int fts5ColumnMethod(
  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
254099
254100
254101
254102
254103
254104
254105
254106








254107






254108
254109
254110
254111
254112
254113
254114
        );
      }
    }else if( bNochange==0 || pConfig->eContent!=FTS5_CONTENT_NORMAL ){
      pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
      rc = fts5SeekCursor(pCsr, 1);
      if( rc==SQLITE_OK ){
        sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
        fts5ExtractValueFromColumn(pCtx, pConfig, iCol, pVal);








      }






      pConfig->pzErrmsg = 0;
    }
  }

  return rc;
}








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







254125
254126
254127
254128
254129
254130
254131
254132
254133
254134
254135
254136
254137
254138
254139
254140
254141
254142
254143
254144
254145
254146
254147
254148
254149
254150
254151
254152
254153
254154
        );
      }
    }else if( bNochange==0 || pConfig->eContent!=FTS5_CONTENT_NORMAL ){
      pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
      rc = fts5SeekCursor(pCsr, 1);
      if( rc==SQLITE_OK ){
        sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
        if( pConfig->bLocale
         && pConfig->eContent==FTS5_CONTENT_EXTERNAL
         && sqlite3Fts5IsLocaleValue(pConfig, pVal)
        ){
          const char *z = 0;
          int n = 0;
          rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &z, &n);
          if( rc==SQLITE_OK ){
            sqlite3_result_text(pCtx, z, n, SQLITE_TRANSIENT);
          }
          sqlite3Fts5ClearLocale(pConfig);
        }else{
          sqlite3_result_value(pCtx, pVal);
        }
      }

      pConfig->pzErrmsg = 0;
    }
  }

  return rc;
}

254623
254624
254625
254626
254627
254628
254629
254630
254631
254632
254633
254634
254635
254636
254637
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: 2024-09-02 18:41:59 e6bec37ea1ca51e1d048941ce4c5211d8fc5c5e3556a1441f9c79b036843f9e3", -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







|







254663
254664
254665
254666
254667
254668
254669
254670
254671
254672
254673
254674
254675
254676
254677
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: 2024-09-17 22:57:08 a63e412b6b2939422ecfa99d91fccb7a9c61e1533bb0db20ff12f3815ef41a2c", -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
254662
254663
254664
254665
254666
254667
254668

254669
254670
254671
254672
254673
254674
254675
254676
254677
254678
254679
254680
254681
254682
254683
254684
254685
254686
254687
254688
254689
254690
254691
254692
254693
254694
254695
254696
254697
254698
254699

  zText = (const char*)sqlite3_value_text(apArg[1]);
  nText = sqlite3_value_bytes(apArg[1]);

  if( zLocale==0 || zLocale[0]=='\0' ){
    sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT);
  }else{

    u8 *pBlob = 0;
    u8 *pCsr = 0;
    int nBlob = 0;
    const int nHdr = 4;
    assert( sizeof(FTS5_LOCALE_HEADER)==nHdr+1 );

    nBlob = nHdr + nLocale + 1 + nText;
    pBlob = (u8*)sqlite3_malloc(nBlob);
    if( pBlob==0 ){
      sqlite3_result_error_nomem(pCtx);
      return;
    }

    pCsr = pBlob;
    memcpy(pCsr, FTS5_LOCALE_HEADER, nHdr);
    pCsr += nHdr;
    memcpy(pCsr, zLocale, nLocale);
    pCsr += nLocale;
    (*pCsr++) = 0x00;
    if( zText ) memcpy(pCsr, zText, nText);
    assert( &pCsr[nText]==&pBlob[nBlob] );

    sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
    sqlite3_result_subtype(pCtx, FTS5_LOCALE_SUBTYPE);
  }
}

/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/







>



<
<

|







|
|







<







254702
254703
254704
254705
254706
254707
254708
254709
254710
254711
254712


254713
254714
254715
254716
254717
254718
254719
254720
254721
254722
254723
254724
254725
254726
254727
254728
254729
254730

254731
254732
254733
254734
254735
254736
254737

  zText = (const char*)sqlite3_value_text(apArg[1]);
  nText = sqlite3_value_bytes(apArg[1]);

  if( zLocale==0 || zLocale[0]=='\0' ){
    sqlite3_result_text(pCtx, zText, nText, SQLITE_TRANSIENT);
  }else{
    Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx);
    u8 *pBlob = 0;
    u8 *pCsr = 0;
    int nBlob = 0;



    nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText;
    pBlob = (u8*)sqlite3_malloc(nBlob);
    if( pBlob==0 ){
      sqlite3_result_error_nomem(pCtx);
      return;
    }

    pCsr = pBlob;
    memcpy(pCsr, (const u8*)p->aLocaleHdr, FTS5_LOCALE_HDR_SIZE);
    pCsr += FTS5_LOCALE_HDR_SIZE;
    memcpy(pCsr, zLocale, nLocale);
    pCsr += nLocale;
    (*pCsr++) = 0x00;
    if( zText ) memcpy(pCsr, zText, nText);
    assert( &pCsr[nText]==&pBlob[nBlob] );

    sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);

  }
}

/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
254787
254788
254789
254790
254791
254792
254793










254794
254795
254796
254797
254798
254799
254800
    pGlobal->db = db;
    pGlobal->api.iVersion = 3;
    pGlobal->api.xCreateFunction = fts5CreateAux;
    pGlobal->api.xCreateTokenizer = fts5CreateTokenizer;
    pGlobal->api.xFindTokenizer = fts5FindTokenizer;
    pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2;
    pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2;










    rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
    if( rc==SQLITE_OK ){







>
>
>
>
>
>
>
>
>
>







254825
254826
254827
254828
254829
254830
254831
254832
254833
254834
254835
254836
254837
254838
254839
254840
254841
254842
254843
254844
254845
254846
254847
254848
    pGlobal->db = db;
    pGlobal->api.iVersion = 3;
    pGlobal->api.xCreateFunction = fts5CreateAux;
    pGlobal->api.xCreateTokenizer = fts5CreateTokenizer;
    pGlobal->api.xFindTokenizer = fts5FindTokenizer;
    pGlobal->api.xCreateTokenizer_v2 = fts5CreateTokenizer_v2;
    pGlobal->api.xFindTokenizer_v2 = fts5FindTokenizer_v2;

    /* Initialize pGlobal->aLocaleHdr[] to a 128-bit pseudo-random vector.
    ** The constants below were generated randomly.  */
    sqlite3_randomness(sizeof(pGlobal->aLocaleHdr), pGlobal->aLocaleHdr);
    pGlobal->aLocaleHdr[0] ^= 0xF924976D;
    pGlobal->aLocaleHdr[1] ^= 0x16596E13;
    pGlobal->aLocaleHdr[2] ^= 0x7C80BEAA;
    pGlobal->aLocaleHdr[3] ^= 0x9B03A67F;
    assert( sizeof(pGlobal->aLocaleHdr)==16 );

    rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api);
    if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
    if( rc==SQLITE_OK ){
254942
254943
254944
254945
254946
254947
254948
























254949
254950
254951
254952
254953
254954
254955
#define FTS5_STMT_REPLACE_CONTENT 5
#define FTS5_STMT_DELETE_CONTENT  6
#define FTS5_STMT_REPLACE_DOCSIZE 7
#define FTS5_STMT_DELETE_DOCSIZE  8
#define FTS5_STMT_LOOKUP_DOCSIZE  9
#define FTS5_STMT_REPLACE_CONFIG 10
#define FTS5_STMT_SCAN           11

























/*
** Prepare the two insert statements - Fts5Storage.pInsertContent and
** Fts5Storage.pInsertDocsize - if they have not already been prepared.
** Return SQLITE_OK if successful, or an SQLite error code if an error
** occurs.
*/







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







254990
254991
254992
254993
254994
254995
254996
254997
254998
254999
255000
255001
255002
255003
255004
255005
255006
255007
255008
255009
255010
255011
255012
255013
255014
255015
255016
255017
255018
255019
255020
255021
255022
255023
255024
255025
255026
255027
#define FTS5_STMT_REPLACE_CONTENT 5
#define FTS5_STMT_DELETE_CONTENT  6
#define FTS5_STMT_REPLACE_DOCSIZE 7
#define FTS5_STMT_DELETE_DOCSIZE  8
#define FTS5_STMT_LOOKUP_DOCSIZE  9
#define FTS5_STMT_REPLACE_CONFIG 10
#define FTS5_STMT_SCAN           11

/*
** Return a pointer to a buffer obtained from sqlite3_malloc() that contains
** nBind comma-separated question marks. e.g. if nBind is passed 5, this
** function returns "?,?,?,?,?".
**
** If *pRc is not SQLITE_OK when this function is called, it is a no-op and
** NULL is returned immediately. Or, if the attempt to malloc a buffer
** fails, then *pRc is set to SQLITE_NOMEM and NULL is returned. Otherwise,
** if it is SQLITE_OK when this function is called and the malloc() succeeds,
** *pRc is left unchanged.
*/
static char *fts5BindingsList(int *pRc, int nBind){
  char *zBind = sqlite3Fts5MallocZero(pRc, 1 + nBind*2);
  if( zBind ){
    int ii;
    for(ii=0; ii<nBind; ii++){
      zBind[ii*2] = '?';
      zBind[ii*2 + 1] = ',';
    }
    zBind[ii*2-1] = '\0';
  }
  return zBind;
}

/*
** Prepare the two insert statements - Fts5Storage.pInsertContent and
** Fts5Storage.pInsertDocsize - if they have not already been prepared.
** Return SQLITE_OK if successful, or an SQLite error code if an error
** occurs.
*/
255011
255012
255013
255014
255015
255016
255017
255018
255019
255020
255021
255022
255023
255024
255025
255026
255027
255028
255029

255030


255031
255032
255033
255034
255035
255036
255037
      case FTS5_STMT_LOOKUP:
      case FTS5_STMT_LOOKUP2:
        zSql = sqlite3_mprintf(azStmt[eStmt],
            pC->zContentExprlist, pC->zContent, pC->zContentRowid
        );
        break;

      case FTS5_STMT_INSERT_CONTENT:
      case FTS5_STMT_REPLACE_CONTENT: {
        int nCol = pC->nCol + 1;
        char *zBind;
        int i;

        zBind = sqlite3_malloc64(1 + nCol*2);
        if( zBind ){
          for(i=0; i<nCol; i++){
            zBind[i*2] = '?';
            zBind[i*2 + 1] = ',';
          }

          zBind[i*2-1] = '\0';


          zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
          sqlite3_free(zBind);
        }
        break;
      }

      case FTS5_STMT_REPLACE_DOCSIZE:







|
<
|



|
|
|
|
<

>
|
>
>







255083
255084
255085
255086
255087
255088
255089
255090

255091
255092
255093
255094
255095
255096
255097
255098

255099
255100
255101
255102
255103
255104
255105
255106
255107
255108
255109
255110
      case FTS5_STMT_LOOKUP:
      case FTS5_STMT_LOOKUP2:
        zSql = sqlite3_mprintf(azStmt[eStmt],
            pC->zContentExprlist, pC->zContent, pC->zContentRowid
        );
        break;

      case FTS5_STMT_INSERT_CONTENT: {

        int nCol = 0;
        char *zBind;
        int i;

        nCol = 1 + pC->nCol;
        if( pC->bLocale ){
          for(i=0; i<pC->nCol; i++){
            if( pC->abUnindexed[i]==0 ) nCol++;

          }
        }

        zBind = fts5BindingsList(&rc, nCol);
        if( zBind ){
          zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
          sqlite3_free(zBind);
        }
        break;
      }

      case FTS5_STMT_REPLACE_DOCSIZE:
255214
255215
255216
255217
255218
255219
255220
255221
255222
255223
255224
255225
255226
255227
255228
255229
255230
255231








255232
255233
255234
255235
255236
255237
255238
  p->aTotalSize = (i64*)&p[1];
  p->pConfig = pConfig;
  p->pIndex = pIndex;

  if( bCreate ){
    if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
      int nDefn = 32 + pConfig->nCol*10;
      char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
      if( zDefn==0 ){
        rc = SQLITE_NOMEM;
      }else{
        int i;
        int iOff;
        sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
        iOff = (int)strlen(zDefn);
        for(i=0; i<pConfig->nCol; i++){
          sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
          iOff += (int)strlen(&zDefn[iOff]);








        }
        rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
      }
      sqlite3_free(zDefn);
    }

    if( rc==SQLITE_OK && pConfig->bColumnsize ){







|










>
>
>
>
>
>
>
>







255287
255288
255289
255290
255291
255292
255293
255294
255295
255296
255297
255298
255299
255300
255301
255302
255303
255304
255305
255306
255307
255308
255309
255310
255311
255312
255313
255314
255315
255316
255317
255318
255319
  p->aTotalSize = (i64*)&p[1];
  p->pConfig = pConfig;
  p->pIndex = pIndex;

  if( bCreate ){
    if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
      int nDefn = 32 + pConfig->nCol*10;
      char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
      if( zDefn==0 ){
        rc = SQLITE_NOMEM;
      }else{
        int i;
        int iOff;
        sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
        iOff = (int)strlen(zDefn);
        for(i=0; i<pConfig->nCol; i++){
          sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
          iOff += (int)strlen(&zDefn[iOff]);
        }
        if( pConfig->bLocale ){
          for(i=0; i<pConfig->nCol; i++){
            if( pConfig->abUnindexed[i]==0 ){
              sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
              iOff += (int)strlen(&zDefn[iOff]);
            }
          }
        }
        rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
      }
      sqlite3_free(zDefn);
    }

    if( rc==SQLITE_OK && pConfig->bColumnsize ){
255377
255378
255379
255380
255381
255382
255383

255384
255385
255386
255387
255388
255389
255390
255391
255392
255393

255394



255395




255396
255397

255398
255399
255400
255401
255402
255403
255404
255405
255406
255407
255408
255409
255410
255411
255412
255413
  ctx.pStorage = p;
  ctx.iCol = -1;
  for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
    if( pConfig->abUnindexed[iCol-1]==0 ){
      sqlite3_value *pVal = 0;
      const char *pText = 0;
      int nText = 0;

      int bReset = 0;

      assert( pSeek==0 || apVal==0 );
      assert( pSeek!=0 || apVal!=0 );
      if( pSeek ){
        pVal = sqlite3_column_value(pSeek, iCol);
      }else{
        pVal = apVal[iCol-1];
      }


      rc = sqlite3Fts5ExtractText(



          pConfig, pVal, pSeek!=0, &bReset, &pText, &nText




      );
      if( rc==SQLITE_OK ){

        ctx.szCol = 0;
        rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
            pText, nText, (void*)&ctx, fts5StorageInsertCallback
        );
        p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
        if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
          rc = FTS5_CORRUPT;
        }
        if( bReset ) sqlite3Fts5ClearLocale(pConfig);
      }
    }
  }
  if( rc==SQLITE_OK && p->nTotalRow<1 ){
    rc = FTS5_CORRUPT;
  }else{
    p->nTotalRow--;







>
|









>
|
>
>
>
|
>
>
>
>
|

>








|







255458
255459
255460
255461
255462
255463
255464
255465
255466
255467
255468
255469
255470
255471
255472
255473
255474
255475
255476
255477
255478
255479
255480
255481
255482
255483
255484
255485
255486
255487
255488
255489
255490
255491
255492
255493
255494
255495
255496
255497
255498
255499
255500
255501
255502
255503
255504
  ctx.pStorage = p;
  ctx.iCol = -1;
  for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
    if( pConfig->abUnindexed[iCol-1]==0 ){
      sqlite3_value *pVal = 0;
      const char *pText = 0;
      int nText = 0;
      const char *pLoc = 0;
      int nLoc = 0;

      assert( pSeek==0 || apVal==0 );
      assert( pSeek!=0 || apVal!=0 );
      if( pSeek ){
        pVal = sqlite3_column_value(pSeek, iCol);
      }else{
        pVal = apVal[iCol-1];
      }

      if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
        rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
      }else{
        pText = (const char*)sqlite3_value_text(pVal);
        nText = sqlite3_value_bytes(pVal);
        if( pConfig->bLocale && pSeek ){
          pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
          nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
        }
      }

      if( rc==SQLITE_OK ){
        sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
        ctx.szCol = 0;
        rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
            pText, nText, (void*)&ctx, fts5StorageInsertCallback
        );
        p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
        if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
          rc = FTS5_CORRUPT;
        }
        sqlite3Fts5ClearLocale(pConfig);
      }
    }
  }
  if( rc==SQLITE_OK && p->nTotalRow<1 ){
    rc = FTS5_CORRUPT;
  }else{
    p->nTotalRow--;
255658
255659
255660
255661
255662
255663
255664
255665
255666
255667



255668











255669

255670
255671

255672
255673
255674
255675
255676
255677
255678
255679
255680
255681
255682
255683
255684
255685
    i64 iRowid = sqlite3_column_int64(pScan, 0);

    sqlite3Fts5BufferZero(&buf);
    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
    for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
      ctx.szCol = 0;
      if( pConfig->abUnindexed[ctx.iCol]==0 ){
        int bReset = 0;           /* True if tokenizer locale must be reset */
        int nText = 0;            /* Size of pText in bytes */
        const char *pText = 0;    /* Pointer to buffer containing text value */



        sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);













        rc = sqlite3Fts5ExtractText(pConfig, pVal, 1, &bReset, &pText, &nText);
        if( rc==SQLITE_OK ){

          rc = sqlite3Fts5Tokenize(pConfig,
              FTS5_TOKENIZE_DOCUMENT,
              pText, nText,
              (void*)&ctx,
              fts5StorageInsertCallback
          );
          if( bReset ) sqlite3Fts5ClearLocale(pConfig);
        }
      }
      sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
      p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
    }
    p->nTotalRow++;








<


>
>
>

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

>






|







255749
255750
255751
255752
255753
255754
255755

255756
255757
255758
255759
255760
255761
255762
255763
255764
255765
255766
255767
255768
255769
255770
255771
255772
255773
255774
255775
255776
255777
255778
255779
255780
255781
255782
255783
255784
255785
255786
255787
255788
255789
255790
255791
    i64 iRowid = sqlite3_column_int64(pScan, 0);

    sqlite3Fts5BufferZero(&buf);
    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
    for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
      ctx.szCol = 0;
      if( pConfig->abUnindexed[ctx.iCol]==0 ){

        int nText = 0;            /* Size of pText in bytes */
        const char *pText = 0;    /* Pointer to buffer containing text value */
        int nLoc = 0;             /* Size of pLoc in bytes */
        const char *pLoc = 0;     /* Pointer to buffer containing text value */

        sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);
        if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
         && sqlite3Fts5IsLocaleValue(pConfig, pVal)
        ){
          rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
        }else{
          pText = (const char*)sqlite3_value_text(pVal);
          nText = sqlite3_value_bytes(pVal);
          if( pConfig->bLocale ){
            int iCol = ctx.iCol + 1 + pConfig->nCol;
            pLoc = (const char*)sqlite3_column_text(pScan, iCol);
            nLoc = sqlite3_column_bytes(pScan, iCol);
          }
        }

        if( rc==SQLITE_OK ){
          sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
          rc = sqlite3Fts5Tokenize(pConfig,
              FTS5_TOKENIZE_DOCUMENT,
              pText, nText,
              (void*)&ctx,
              fts5StorageInsertCallback
          );
          sqlite3Fts5ClearLocale(pConfig);
        }
      }
      sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
      p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
    }
    p->nTotalRow++;

255754
255755
255756
255757
255758
255759
255760

255761







255762

255763


255764
255765
255766
255767
255768
255769
255770
255771
255772


255773
255774

255775


255776


255777
255778
255779
255780
255781

255782
255783


255784
255785
255786
255787
255788
255789
255790
      *piRowid = sqlite3_value_int64(apVal[1]);
    }else{
      rc = fts5StorageNewRowid(p, piRowid);
    }
  }else{
    sqlite3_stmt *pInsert = 0;    /* Statement to write %_content table */
    int i;                        /* Counter variable */

    rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);







    for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){

      sqlite3_value *pVal = apVal[i];


      if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
        /* This is an UPDATE statement, and column (i-2) was not modified.
        ** Retrieve the value from Fts5Storage.pSavedRow instead. */
        pVal = sqlite3_column_value(p->pSavedRow, i-1);
      }else if( sqlite3_value_subtype(pVal)==FTS5_LOCALE_SUBTYPE ){
        assert( pConfig->bLocale );
        assert( i>1 );
        if( pConfig->abUnindexed[i-2] ){
          /* At attempt to insert an fts5_locale() value into an UNINDEXED


          ** column. Strip the locale away and just bind the text.  */
          const char *pText = 0;

          int nText = 0;


          rc = sqlite3Fts5ExtractText(pConfig, pVal, 0, 0, &pText, &nText);


          sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
        }else{
          const u8 *pBlob = (const u8*)sqlite3_value_blob(pVal);
          int nBlob = sqlite3_value_bytes(pVal);
          assert( nBlob>4 );

          sqlite3_bind_blob(pInsert, i, pBlob+4, nBlob-4, SQLITE_TRANSIENT);
        }


        continue;
      }

      rc = sqlite3_bind_value(pInsert, i, pVal);
    }
    if( rc==SQLITE_OK ){
      sqlite3_step(pInsert);







>

>
>
>
>
>
>
>
|
>

>
>




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

<
<
<
|
>
|
|
>
>







255860
255861
255862
255863
255864
255865
255866
255867
255868
255869
255870
255871
255872
255873
255874
255875
255876
255877
255878
255879
255880
255881
255882
255883
255884

255885
255886
255887

255888
255889
255890
255891
255892
255893
255894
255895
255896
255897
255898
255899



255900
255901
255902
255903
255904
255905
255906
255907
255908
255909
255910
255911
255912
      *piRowid = sqlite3_value_int64(apVal[1]);
    }else{
      rc = fts5StorageNewRowid(p, piRowid);
    }
  }else{
    sqlite3_stmt *pInsert = 0;    /* Statement to write %_content table */
    int i;                        /* Counter variable */
    int nIndexed = 0;             /* Number indexed columns seen */
    rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
    if( pInsert ) sqlite3_clear_bindings(pInsert);

    /* Bind the rowid value */
    sqlite3_bind_value(pInsert, 1, apVal[1]);

    /* Loop through values for user-defined columns. i=2 is the leftmost
    ** user-defined column. As is column 1 of pSavedRow.  */
    for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
      int bUnindexed = pConfig->abUnindexed[i-2];
      sqlite3_value *pVal = apVal[i];

      nIndexed += !bUnindexed;
      if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
        /* This is an UPDATE statement, and column (i-2) was not modified.
        ** Retrieve the value from Fts5Storage.pSavedRow instead. */
        pVal = sqlite3_column_value(p->pSavedRow, i-1);

        if( pConfig->bLocale && bUnindexed==0 ){
          sqlite3_bind_value(pInsert, pConfig->nCol + 1 + nIndexed,
              sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1)

          );
        }
      }else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
        const char *pText = 0;
        const char *pLoc = 0;
        int nText = 0;
        int nLoc = 0;
        assert( pConfig->bLocale );

        rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
        if( rc==SQLITE_OK ){
          sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);



          if( bUnindexed==0 ){
            int iLoc = pConfig->nCol + 1 + nIndexed;
            sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
          }
        }

        continue;
      }

      rc = sqlite3_bind_value(pInsert, i, pVal);
    }
    if( rc==SQLITE_OK ){
      sqlite3_step(pInsert);
255815
255816
255817
255818
255819
255820
255821
255822
255823
255824



255825
255826
255827
255828








255829





255830
255831
255832
255833
255834
255835
255836
255837
255838
255839
255840
255841
255842
255843
255844
255845

  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
  }
  for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
    ctx.szCol = 0;
    if( pConfig->abUnindexed[ctx.iCol]==0 ){
      int bReset = 0;             /* True if tokenizer locale must be reset */
      int nText = 0;              /* Size of pText in bytes */
      const char *pText = 0;      /* Pointer to buffer containing text value */



      sqlite3_value *pVal = apVal[ctx.iCol+2];
      int bDisk = 0;
      if( p->pSavedRow && sqlite3_value_nochange(pVal) ){
        pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1);








        bDisk = 1;





      }
      rc = sqlite3Fts5ExtractText(pConfig, pVal, bDisk, &bReset, &pText,&nText);
      if( rc==SQLITE_OK ){
        assert( bReset==0 || pConfig->bLocale );
        rc = sqlite3Fts5Tokenize(pConfig,
            FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx,
            fts5StorageInsertCallback
        );
        if( bReset ) sqlite3Fts5ClearLocale(pConfig);
      }
    }
    sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
    p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
  }
  p->nTotalRow++;








<


>
>
>

<


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

|

|




|







255937
255938
255939
255940
255941
255942
255943

255944
255945
255946
255947
255948
255949

255950
255951
255952
255953
255954
255955
255956
255957
255958
255959
255960
255961
255962
255963
255964
255965
255966
255967
255968
255969
255970
255971
255972
255973
255974
255975
255976
255977
255978
255979
255980
255981

  if( rc==SQLITE_OK ){
    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
  }
  for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
    ctx.szCol = 0;
    if( pConfig->abUnindexed[ctx.iCol]==0 ){

      int nText = 0;              /* Size of pText in bytes */
      const char *pText = 0;      /* Pointer to buffer containing text value */
      int nLoc = 0;               /* Size of pText in bytes */
      const char *pLoc = 0;       /* Pointer to buffer containing text value */

      sqlite3_value *pVal = apVal[ctx.iCol+2];

      if( p->pSavedRow && sqlite3_value_nochange(pVal) ){
        pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1);
        if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
          int iCol = ctx.iCol + 1 + pConfig->nCol;
          pLoc = (const char*)sqlite3_column_text(p->pSavedRow, iCol);
          nLoc = sqlite3_column_bytes(p->pSavedRow, iCol);
        }
      }else{
        pVal = apVal[ctx.iCol+2];
      }

      if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
        rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
      }else{
        pText = (const char*)sqlite3_value_text(pVal);
        nText = sqlite3_value_bytes(pVal);
      }

      if( rc==SQLITE_OK ){
        sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
        rc = sqlite3Fts5Tokenize(pConfig,
            FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx,
            fts5StorageInsertCallback
        );
        sqlite3Fts5ClearLocale(pConfig);
      }
    }
    sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
    p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
  }
  p->nTotalRow++;

255996
255997
255998
255999
256000
256001
256002
256003






















256004
256005

256006
256007
256008
256009
256010
256011
256012
256013
256014
256015
256016
256017

256018
256019
256020
256021
256022
256023
256024
256025
256026



256027



256028
256029
256030
256031
256032
256033

256034
256035
256036
256037
256038
256039
256040
        if( pConfig->bColumnsize ){
          rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
        }
        if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
          rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
        }
        for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
          if( pConfig->abUnindexed[i] ) continue;






















          ctx.iCol = i;
          ctx.szCol = 0;

          if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
            rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
          }
          if( rc==SQLITE_OK ){
            int bReset = 0;        /* True if tokenizer locale must be reset */
            int nText = 0;         /* Size of pText in bytes */
            const char *pText = 0; /* Pointer to buffer containing text value */

            rc = sqlite3Fts5ExtractText(pConfig,
                sqlite3_column_value(pScan, i+1), 1, &bReset, &pText, &nText
            );
            if( rc==SQLITE_OK ){

              rc = sqlite3Fts5Tokenize(pConfig,
                  FTS5_TOKENIZE_DOCUMENT,
                  pText, nText,
                  (void*)&ctx,
                  fts5StorageIntegrityCallback
              );
              if( bReset ) sqlite3Fts5ClearLocale(pConfig);
            }
          }



          if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){



            rc = FTS5_CORRUPT;
          }
          aTotalSize[i] += ctx.szCol;
          if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
            sqlite3Fts5TermsetFree(ctx.pTermset);
            ctx.pTermset = 0;

          }
        }
        sqlite3Fts5TermsetFree(ctx.pTermset);
        ctx.pTermset = 0;

        if( rc!=SQLITE_OK ) break;
      }







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

<
<
<

>






|

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







256132
256133
256134
256135
256136
256137
256138
256139
256140
256141
256142
256143
256144
256145
256146
256147
256148
256149
256150
256151
256152
256153
256154
256155
256156
256157
256158
256159
256160
256161
256162
256163
256164
256165
256166
256167




256168



256169
256170
256171
256172
256173
256174
256175
256176
256177
256178
256179
256180
256181
256182
256183
256184
256185
256186
256187
256188
256189
256190
256191
256192
256193
256194
256195
256196
256197
256198
256199
256200
        if( pConfig->bColumnsize ){
          rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
        }
        if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
          rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
        }
        for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
          if( pConfig->abUnindexed[i]==0 ){
            const char *pText = 0;
            int nText = 0;
            const char *pLoc = 0;
            int nLoc = 0;
            sqlite3_value *pVal = sqlite3_column_value(pScan, i+1);

            if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
             && sqlite3Fts5IsLocaleValue(pConfig, pVal)
            ){
              rc = sqlite3Fts5DecodeLocaleValue(
                  pVal, &pText, &nText, &pLoc, &nLoc
              );
            }else{
              if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
                int iCol = i + 1 + pConfig->nCol;
                pLoc = (const char*)sqlite3_column_text(pScan, iCol);
                nLoc = sqlite3_column_bytes(pScan, iCol);
              }
              pText = (const char*)sqlite3_value_text(pVal);
              nText = sqlite3_value_bytes(pVal);
            }

            ctx.iCol = i;
            ctx.szCol = 0;

            if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
              rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
            }








            if( rc==SQLITE_OK ){
              sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
              rc = sqlite3Fts5Tokenize(pConfig,
                  FTS5_TOKENIZE_DOCUMENT,
                  pText, nText,
                  (void*)&ctx,
                  fts5StorageIntegrityCallback
              );
              sqlite3Fts5ClearLocale(pConfig);
            }

            /* If this is not a columnsize=0 database, check that the number
            ** of tokens in the value matches the aColSize[] value read from
            ** the %_docsize table.  */
            if( rc==SQLITE_OK
             && pConfig->bColumnsize
             && ctx.szCol!=aColSize[i]
            ){
              rc = FTS5_CORRUPT;
            }
            aTotalSize[i] += ctx.szCol;
            if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
              sqlite3Fts5TermsetFree(ctx.pTermset);
              ctx.pTermset = 0;
            }
          }
        }
        sqlite3Fts5TermsetFree(ctx.pTermset);
        ctx.pTermset = 0;

        if( rc!=SQLITE_OK ) break;
      }
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.47.0"
#define SQLITE_VERSION_NUMBER 3047000
#define SQLITE_SOURCE_ID      "2024-09-02 21:59:31 7891a266c4425722ae8b9231397ef9e42e2432be9e6b70632dfaf9ff15300d2c"

/*
** 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
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.47.0"
#define SQLITE_VERSION_NUMBER 3047000
#define SQLITE_SOURCE_ID      "2024-09-17 22:57:08 a63e412b6b2939422ecfa99d91fccb7a9c61e1533bb0db20ff12f3815ef41a2c"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
Changes to src/branch.c.
658
659
660
661
662
663
664
665

666
667
668
669
670
671
672
** >  fossil branch new BRANCH-NAME BASIS ?OPTIONS?
**
**        Create a new branch BRANCH-NAME off of check-in BASIS.
**
**        Options:
**          --private             Branch is private (i.e., remains local)
**          --bgcolor COLOR       Use COLOR instead of automatic background
**          --nosign              Do not sign contents on this branch

**          --nosync              Do not auto-sync prior to creating the branch
**          --date-override DATE  DATE to use instead of 'now'
**          --user-override USER  USER to use instead of the current default
**
**        DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
**        year-month-day form, it may be truncated, the "T" may be
**        replaced by a space, and it may also name a timezone offset







|
>







658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
** >  fossil branch new BRANCH-NAME BASIS ?OPTIONS?
**
**        Create a new branch BRANCH-NAME off of check-in BASIS.
**
**        Options:
**          --private             Branch is private (i.e., remains local)
**          --bgcolor COLOR       Use COLOR instead of automatic background
**          --nosign              Do not sign the manifest for the check-in
**                                that creates this branch
**          --nosync              Do not auto-sync prior to creating the branch
**          --date-override DATE  DATE to use instead of 'now'
**          --user-override USER  USER to use instead of the current default
**
**        DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
**        year-month-day form, it may be truncated, the "T" may be
**        replaced by a space, and it may also name a timezone offset
Changes to src/default.css.
932
933
934
935
936
937
938
939
940
941



942
943
944
945
946
947
948
  padding: 0.25em;
}
div.forumpost-single-controls {
  /* UI controls along the bottom of a single post
  ** in the thread view. */
}
.forum div > form {
  width: 100%;
  margin: 0.5em 0;
  display: block;



}
.forum div > form > * {
  margin-bottom: 0.35em;
}
.forum-post-collapser {
  /* Common style for the bottom-of-post and right-of-post
     expand/collapse widgets. */







<

|
>
>
>







932
933
934
935
936
937
938

939
940
941
942
943
944
945
946
947
948
949
950
  padding: 0.25em;
}
div.forumpost-single-controls {
  /* UI controls along the bottom of a single post
  ** in the thread view. */
}
.forum div > form {

  margin: 0.5em 0;
  display: inline-block;
}
body.cpage-forumedit div > form {
  width: 100%;
}
.forum div > form > * {
  margin-bottom: 0.35em;
}
.forum-post-collapser {
  /* Common style for the bottom-of-post and right-of-post
     expand/collapse widgets. */
Changes to src/finfo.c.
618
619
620
621
622
623
624

625
626
627
628
629
630
631
    int pfnid = db_column_int(&q, 11);
    int szFile = db_column_int(&q, 12);
    int fnid = db_column_int(&q, 13);
    const char *zFName = db_column_text(&q,14);
    int gidx;
    char zTime[10];
    int nParent = 0;

    GraphRowId aParent[GR_MAX_RAIL];

    db_bind_int(&qparent, ":fid", frid);
    db_bind_int(&qparent, ":mid", fmid);
    db_bind_int(&qparent, ":fnid", fnid);
    while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){
      aParent[nParent] = db_column_int64(&qparent, 0);







>







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
    int pfnid = db_column_int(&q, 11);
    int szFile = db_column_int(&q, 12);
    int fnid = db_column_int(&q, 13);
    const char *zFName = db_column_text(&q,14);
    int gidx;
    char zTime[10];
    int nParent = 0;
    int bIsModified = 0;
    GraphRowId aParent[GR_MAX_RAIL];

    db_bind_int(&qparent, ":fid", frid);
    db_bind_int(&qparent, ":mid", fmid);
    db_bind_int(&qparent, ":fnid", fnid);
    while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){
      aParent[nParent] = db_column_int64(&qparent, 0);
659
660
661
662
663
664
665



666
667
668
669
670
671
672
673



674

675
676
677
678
679
680
681
    @ %z(href("%R/file?name=%T&ci=%!S",zFName,zCkin))%s(zTime)</a></td>
    @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div>
    @ </td>
    if( zBgClr && zBgClr[0] ){
      @ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'>
    }else{
      @ <td class="timeline%s(zStyle)Cell">



    }
    if( tmFlags & TIMELINE_COMPACT ){
      @ <span class='timelineCompactComment' data-id='%d(frid)'>
    }else{
      @ <span class='timeline%s(zStyle)Comment'>
      if( pfnid ){
        char *zPrevName = db_text(0,"SELECT name FROM filename WHERE fnid=%d",
                                   pfnid);



        @ <b>Renamed</b> %h(zPrevName) &rarr; %h(zFName).

        fossil_free(zPrevName);
      }
      if( zUuid && ridTo==0 && nParent==0 ){
        @ <b>Added:</b>
      }
      if( zUuid==0 ){
        char *zNewName;







>
>
>








>
>
>
|
>







660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
    @ %z(href("%R/file?name=%T&ci=%!S",zFName,zCkin))%s(zTime)</a></td>
    @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div>
    @ </td>
    if( zBgClr && zBgClr[0] ){
      @ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'>
    }else{
      @ <td class="timeline%s(zStyle)Cell">
    }
    if( zPUuid && zUuid && fossil_strcmp(zPUuid, zUuid)!=0 ){
      bIsModified = 1;
    }
    if( tmFlags & TIMELINE_COMPACT ){
      @ <span class='timelineCompactComment' data-id='%d(frid)'>
    }else{
      @ <span class='timeline%s(zStyle)Comment'>
      if( pfnid ){
        char *zPrevName = db_text(0,"SELECT name FROM filename WHERE fnid=%d",
                                   pfnid);
        if( bIsModified ){
          @ <b>Renamed and modified</b> %h(zPrevName) &rarr; %h(zFName).
        }else{
          @ <b>Renamed</b> %h(zPrevName) &rarr; %h(zFName).
        }
        fossil_free(zPrevName);
      }
      if( zUuid && ridTo==0 && nParent==0 ){
        @ <b>Added:</b>
      }
      if( zUuid==0 ){
        char *zNewName;
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
      const char *z = zFName;
      @ <span id='links-%d(frid)'><span class='timelineExtraLinks'>
      @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
      @ [blame]</a>
      @ %z(href("%R/timeline?uf=%!S",zUuid))[check-ins&nbsp;using]</a>
      if( fpid>0 ){
        @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
      }
      if( fileedit_is_editable(zFName) ){
        @ %z(href("%R/fileedit?filename=%T&checkin=%!S",zFName,zCkin))\
        @ [edit]</a>
      }
      @ </span></span>







|







762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
      const char *z = zFName;
      @ <span id='links-%d(frid)'><span class='timelineExtraLinks'>
      @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
      @ [blame]</a>
      @ %z(href("%R/timeline?uf=%!S",zUuid))[check-ins&nbsp;using]</a>
      if( fpid>0 && bIsModified!=0 ){
        @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
      }
      if( fileedit_is_editable(zFName) ){
        @ %z(href("%R/fileedit?filename=%T&checkin=%!S",zFName,zCkin))\
        @ [edit]</a>
      }
      @ </span></span>
Changes to src/info.c.
434
435
436
437
438
439
440

441
442
443
444
445

446
447
448
449
450
451
452
    }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( pCfg ){
      append_diff(zOld, zNew, pCfg);
    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zOld,zNew))[diff]</a>

    }
  }
  @ </p>
}

/*
** Generate javascript to enhance HTML diffs.







>
|
|
|
|
|
>







434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
    }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 ){
        append_diff(zOld, zNew, pCfg);
      }else{ 
        @ &nbsp;&nbsp;
        @ %z(href("%R/fdiff?v1=%!S&v2=%!S",zOld,zNew))[diff]</a>
      }
    }
  }
  @ </p>
}

/*
** Generate javascript to enhance HTML diffs.
Changes to www/fossil-v-git.wiki.
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
</tr>
<tr>
    <td>Designed for Linux kernel development</td>
    <td>Designed for SQLite development</td>
    <td><a href="#scale">2.5.2&nbsp;&darr;</a></td>
</tr>
<tr>
    <td>Many contributors</td>
    <td>Select contributors</td>
    <td><a href="#contrib">2.5.3&nbsp;&darr;</a></td>
</tr>
<tr>
    <td>Focus on individual branches</td>
    <td>Focus on the entire tree of changes</td>
    <td><a href="#branches">2.5.4&nbsp;&darr;</a></td>
</tr>
<tr>
    <td>One check-out per repository</td>
    <td>Many check-outs per repository</td>
    <td><a href="#checkouts">2.6&nbsp;&darr;</a></td>
</tr>
<tr>







<
<
<
<
<


|







68
69
70
71
72
73
74





75
76
77
78
79
80
81
82
83
84
</tr>
<tr>
    <td>Designed for Linux kernel development</td>
    <td>Designed for SQLite development</td>
    <td><a href="#scale">2.5.2&nbsp;&darr;</a></td>
</tr>
<tr>





    <td>Focus on individual branches</td>
    <td>Focus on the entire tree of changes</td>
    <td><a href="#branches">2.5.3&nbsp;&darr;</a></td>
</tr>
<tr>
    <td>One check-out per repository</td>
    <td>Many check-outs per repository</td>
    <td><a href="#checkouts">2.6&nbsp;&darr;</a></td>
</tr>
<tr>
589
590
591
592
593
594
595



596
597
598
599
600
601
602
by every contributor to Linux: such extreme visibility does not scale
well.  Contrast Fossil, which was written for the cathedral-style SQLite project
and its handful of active committers.  Seeing all
changes on all branches all at once helps keep the whole team
up-to-date with what everybody else is doing, resulting in a more 
tightly focused and cohesive implementation.





<h3 id="checkouts">2.6 One vs. Many Check-outs per Repository</h3>

Because Git commingles the repository data with the initial checkout of
that repository, the default mode of operation in Git is to stick to that
single work/repo tree, even when that's a shortsighted way of working.








>
>
>







584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
by every contributor to Linux: such extreme visibility does not scale
well.  Contrast Fossil, which was written for the cathedral-style SQLite project
and its handful of active committers.  Seeing all
changes on all branches all at once helps keep the whole team
up-to-date with what everybody else is doing, resulting in a more 
tightly focused and cohesive implementation.

Parts of this section are [https://fossil-scm.org/forum/forumpost/5961e969fa|disputed]
by [https://github.com/olorin37|Jakub A. G.].


<h3 id="checkouts">2.6 One vs. Many Check-outs per Repository</h3>

Because Git commingles the repository data with the initial checkout of
that repository, the default mode of operation in Git is to stick to that
single work/repo tree, even when that's a shortsighted way of working.

658
659
660
661
662
663
664


665
666
667
668
669
670
671
Disk space is cheap. Having several working directories — each with its
own local state — makes switching versions cheap and fast.

Plus,
<tt>cd</tt> is faster to type than <tt>git checkout</tt> or <tt>fossil
update</tt>.




<h3 id="history">2.7 What you should have done vs. What you actually did</h3>

Git puts a lot of emphasis on maintaining
a "clean" check-in history.  Extraneous and experimental branches by
individual developers often never make it into the main repository.
Branches may be rebased before being pushed to make







>
>







656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
Disk space is cheap. Having several working directories — each with its
own local state — makes switching versions cheap and fast.

Plus,
<tt>cd</tt> is faster to type than <tt>git checkout</tt> or <tt>fossil
update</tt>.

Parts of this section are [https://fossil-scm.org/forum/forumpost/5961e969fa|disputed]
by [https://github.com/olorin37|Jakub A. G.].

<h3 id="history">2.7 What you should have done vs. What you actually did</h3>

Git puts a lot of emphasis on maintaining
a "clean" check-in history.  Extraneous and experimental branches by
individual developers often never make it into the main repository.
Branches may be rebased before being pushed to make
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
this writing in February 2020, that plan hasn't been implemented, as far
as this author is aware, but there is now
[https://lwn.net/ml/git/20200113124729.3684846-1-sandals@crustytoothpaste.net/
| a competing SHA-256 based plan] which requires complete repository
conversion from SHA-1 to SHA-256, breaking all public hashes in the
repo. One way to characterize such a massive upheaval in Git terms is a
whole-project rebase, which violates
[https://blog.axosoft.com/golden-rule-of-rebasing-in-git/ | Git's own
Golden Rule of Rebasing].

Regardless of the eventual implementation details, we fully expect Git
to move off SHA-1 eventually and for the changes to take years more to
percolate through the community.

Almost three years after Fossil solved this problem, the
[https://sha-mbles.github.io/ | SHAmbles attack] was published, further







<
|







860
861
862
863
864
865
866

867
868
869
870
871
872
873
874
this writing in February 2020, that plan hasn't been implemented, as far
as this author is aware, but there is now
[https://lwn.net/ml/git/20200113124729.3684846-1-sandals@crustytoothpaste.net/
| a competing SHA-256 based plan] which requires complete repository
conversion from SHA-1 to SHA-256, breaking all public hashes in the
repo. One way to characterize such a massive upheaval in Git terms is a
whole-project rebase, which violates

[https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing|Golden Rule of Rebasing].

Regardless of the eventual implementation details, we fully expect Git
to move off SHA-1 eventually and for the changes to take years more to
percolate through the community.

Almost three years after Fossil solved this problem, the
[https://sha-mbles.github.io/ | SHAmbles attack] was published, further