Fossil

Diff
Login

Differences From Artifact [616894956a]:

To Artifact [efb8e9cec8]:


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