better-sqlite3-multiple-ciphers 12.10.0 → 12.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/deps/sqlite3/sqlite3.c +1142 -207
- package/deps/sqlite3/sqlite3.h +19 -7
- package/deps/update-sqlite3mc.sh +2 -2
- package/package.json +1 -1
- package/src/better_sqlite3.cpp +1 -1
- package/src/util/helpers.cpp +109 -109
- package/src/util/macros.cpp +8 -1
package/deps/sqlite3/sqlite3.c
CHANGED
|
@@ -123,7 +123,7 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
|
|
123
123
|
/*** Begin of #include "sqlite3patched.c" ***/
|
|
124
124
|
/******************************************************************************
|
|
125
125
|
** This file is an amalgamation of many separate C source files from SQLite
|
|
126
|
-
** version 3.53.
|
|
126
|
+
** version 3.53.2. By combining all the individual C code files into this
|
|
127
127
|
** single large file, the entire code can be compiled as a single translation
|
|
128
128
|
** unit. This allows many compilers to do optimizations that would not be
|
|
129
129
|
** possible if the files were compiled separately. Performance improvements
|
|
@@ -141,7 +141,7 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
|
|
|
141
141
|
** separate file. This file contains only code for the core SQLite library.
|
|
142
142
|
**
|
|
143
143
|
** The content in this amalgamation comes from Fossil check-in
|
|
144
|
-
**
|
|
144
|
+
** d6e03d8c777cfa2d35e3b60d8ec3e0187f3e with changes in files:
|
|
145
145
|
**
|
|
146
146
|
**
|
|
147
147
|
*/
|
|
@@ -591,12 +591,12 @@ extern "C" {
|
|
|
591
591
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
592
592
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
593
593
|
*/
|
|
594
|
-
#define SQLITE_VERSION "3.53.
|
|
595
|
-
#define SQLITE_VERSION_NUMBER
|
|
596
|
-
#define SQLITE_SOURCE_ID "2026-
|
|
594
|
+
#define SQLITE_VERSION "3.53.2"
|
|
595
|
+
#define SQLITE_VERSION_NUMBER 3053002
|
|
596
|
+
#define SQLITE_SOURCE_ID "2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24"
|
|
597
597
|
#define SQLITE_SCM_BRANCH "branch-3.53"
|
|
598
|
-
#define SQLITE_SCM_TAGS "release version-3.53.
|
|
599
|
-
#define SQLITE_SCM_DATETIME "2026-
|
|
598
|
+
#define SQLITE_SCM_TAGS "release version-3.53.2"
|
|
599
|
+
#define SQLITE_SCM_DATETIME "2026-06-03T19:12:13.350Z"
|
|
600
600
|
|
|
601
601
|
/*
|
|
602
602
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
@@ -13298,11 +13298,23 @@ SQLITE_API int sqlite3changeset_apply_v3(
|
|
|
13298
13298
|
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
|
13299
13299
|
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
|
13300
13300
|
** or SET DEFAULT.
|
|
13301
|
+
**
|
|
13302
|
+
** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
|
|
13303
|
+
** Sometimes, a changeset contains two or more update statements such that
|
|
13304
|
+
** although after applying all updates the database will contain no
|
|
13305
|
+
** constraint violations, no single update can be applied before the others.
|
|
13306
|
+
** The simplest example of this is a pair of UPDATEs that have "swapped"
|
|
13307
|
+
** two column values with a UNIQUE constraint.
|
|
13308
|
+
** <p>
|
|
13309
|
+
** Usually, sqlite3changeset_apply() and similar functions work hard to try
|
|
13310
|
+
** to find a way to apply such a changeset. However, if this flag is set,
|
|
13311
|
+
** then all such updates are considered CONSTRAINT conflicts.
|
|
13301
13312
|
*/
|
|
13302
13313
|
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
|
13303
13314
|
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
|
13304
13315
|
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
|
13305
13316
|
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
|
13317
|
+
#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
|
|
13306
13318
|
|
|
13307
13319
|
/*
|
|
13308
13320
|
** CAPI3REF: Constants Passed To The Conflict Handler
|
|
@@ -22586,7 +22598,15 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void);
|
|
|
22586
22598
|
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
|
|
22587
22599
|
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
|
|
22588
22600
|
SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*);
|
|
22589
|
-
SQLITE_PRIVATE void sqlite3AlterAddConstraint(
|
|
22601
|
+
SQLITE_PRIVATE void sqlite3AlterAddConstraint(
|
|
22602
|
+
Parse *pParse, /* Parse context */
|
|
22603
|
+
SrcList *pSrc, /* Table to add constraint to */
|
|
22604
|
+
Token *pFirst, /* First token of new constraint */
|
|
22605
|
+
Token *pName, /* Name of new constraint. NULL if name omitted. */
|
|
22606
|
+
const char *zExpr, /* Text of CHECK expression */
|
|
22607
|
+
int nExpr, /* Size of pExpr in bytes */
|
|
22608
|
+
Expr *pExpr /* The parsed CHECK expression */
|
|
22609
|
+
);
|
|
22590
22610
|
SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
|
|
22591
22611
|
SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *);
|
|
22592
22612
|
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
|
|
@@ -33401,8 +33421,8 @@ SQLITE_API void sqlite3_str_vappendf(
|
|
|
33401
33421
|
** all control characters, and for backslash itself.
|
|
33402
33422
|
** For %#Q, do the same but only if there is at least
|
|
33403
33423
|
** one control character. */
|
|
33404
|
-
|
|
33405
|
-
|
|
33424
|
+
i64 nBack = 0;
|
|
33425
|
+
i64 nCtrl = 0;
|
|
33406
33426
|
for(k=0; k<i; k++){
|
|
33407
33427
|
if( escarg[k]=='\\' ){
|
|
33408
33428
|
nBack++;
|
|
@@ -45455,9 +45475,9 @@ static int unixShmMap(
|
|
|
45455
45475
|
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
|
|
45456
45476
|
|
|
45457
45477
|
if( pShmNode->nRegion<nReqRegion ){
|
|
45458
|
-
char **apNew;
|
|
45459
|
-
|
|
45460
|
-
struct stat sStat;
|
|
45478
|
+
char **apNew; /* New apRegion[] array */
|
|
45479
|
+
i64 nByte = nReqRegion*(i64)szRegion; /* Minimum required file size */
|
|
45480
|
+
struct stat sStat; /* Used by fstat() */
|
|
45461
45481
|
|
|
45462
45482
|
pShmNode->szRegion = szRegion;
|
|
45463
45483
|
|
|
@@ -45488,7 +45508,7 @@ static int unixShmMap(
|
|
|
45488
45508
|
*/
|
|
45489
45509
|
else{
|
|
45490
45510
|
static const int pgsz = 4096;
|
|
45491
|
-
|
|
45511
|
+
i64 iPg;
|
|
45492
45512
|
|
|
45493
45513
|
/* Write to the last byte of each newly allocated or extended page */
|
|
45494
45514
|
assert( (nByte % pgsz)==0 );
|
|
@@ -45514,8 +45534,8 @@ static int unixShmMap(
|
|
|
45514
45534
|
}
|
|
45515
45535
|
pShmNode->apRegion = apNew;
|
|
45516
45536
|
while( pShmNode->nRegion<nReqRegion ){
|
|
45517
|
-
|
|
45518
|
-
|
|
45537
|
+
i64 nMap = (i64)szRegion*(i64)nShmPerMap;
|
|
45538
|
+
i64 i;
|
|
45519
45539
|
void *pMem;
|
|
45520
45540
|
if( pShmNode->hShm>=0 ){
|
|
45521
45541
|
pMem = osMmap(0, nMap,
|
|
@@ -53489,7 +53509,7 @@ static int winShmMap(
|
|
|
53489
53509
|
if( pShmNode->nRegion<=iRegion ){
|
|
53490
53510
|
HANDLE hShared = pShmNode->hSharedShm;
|
|
53491
53511
|
struct ShmRegion *apNew; /* New aRegion[] array */
|
|
53492
|
-
|
|
53512
|
+
i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */
|
|
53493
53513
|
sqlite3_int64 sz; /* Current size of wal-index file */
|
|
53494
53514
|
|
|
53495
53515
|
pShmNode->szRegion = szRegion;
|
|
@@ -53520,7 +53540,7 @@ static int winShmMap(
|
|
|
53520
53540
|
|
|
53521
53541
|
/* Map the requested memory region into this processes address space. */
|
|
53522
53542
|
apNew = (struct ShmRegion*)sqlite3_realloc64(
|
|
53523
|
-
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
|
|
53543
|
+
pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0])
|
|
53524
53544
|
);
|
|
53525
53545
|
if( !apNew ){
|
|
53526
53546
|
rc = SQLITE_IOERR_NOMEM_BKPT;
|
|
@@ -53542,15 +53562,14 @@ static int winShmMap(
|
|
|
53542
53562
|
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
|
|
53543
53563
|
hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
|
|
53544
53564
|
#endif
|
|
53545
|
-
|
|
53546
|
-
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
|
|
53565
|
+
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n",
|
|
53547
53566
|
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
|
|
53548
53567
|
hMap ? "ok" : "failed"));
|
|
53549
53568
|
if( hMap ){
|
|
53550
|
-
|
|
53569
|
+
i64 iOffset = pShmNode->nRegion*szRegion;
|
|
53551
53570
|
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
|
|
53552
53571
|
pMap = osMapViewOfFile(hMap, flags,
|
|
53553
|
-
0, iOffset - iOffsetShift, szRegion + iOffsetShift
|
|
53572
|
+
0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift
|
|
53554
53573
|
);
|
|
53555
53574
|
OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
|
|
53556
53575
|
osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
|
|
@@ -53572,7 +53591,7 @@ static int winShmMap(
|
|
|
53572
53591
|
|
|
53573
53592
|
shmpage_out:
|
|
53574
53593
|
if( pShmNode->nRegion>iRegion ){
|
|
53575
|
-
|
|
53594
|
+
i64 iOffset = (i64)iRegion*(i64)szRegion;
|
|
53576
53595
|
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
|
|
53577
53596
|
char *p = (char *)pShmNode->aRegion[iRegion].pMap;
|
|
53578
53597
|
*pp = (void *)&p[iOffsetShift];
|
|
@@ -62301,7 +62320,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
|
|
|
62301
62320
|
if( rc!=SQLITE_OK ) goto delsuper_out;
|
|
62302
62321
|
nSuperPtr = 1 + (i64)pVfs->mxPathname;
|
|
62303
62322
|
assert( nSuperJournal>=0 && nSuperPtr>0 );
|
|
62304
|
-
zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
|
|
62323
|
+
zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
|
|
62305
62324
|
if( !zFree ){
|
|
62306
62325
|
rc = SQLITE_NOMEM_BKPT;
|
|
62307
62326
|
goto delsuper_out;
|
|
@@ -62562,10 +62581,10 @@ static int pager_playback(Pager *pPager, int isHot){
|
|
|
62562
62581
|
**
|
|
62563
62582
|
** TODO: Technically the following is an error because it assumes that
|
|
62564
62583
|
** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
|
|
62565
|
-
** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
|
|
62584
|
+
** ((pPager->pageSize+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
|
|
62566
62585
|
** mxPathname is 512, which is the same as the minimum allowable value
|
|
62567
|
-
** for pageSize.
|
|
62568
|
-
*/
|
|
62586
|
+
** for pageSize, and so this assumption holds. But it might not for some
|
|
62587
|
+
** custom VFS. */
|
|
62569
62588
|
zSuper = pPager->pTmpSpace;
|
|
62570
62589
|
rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
|
|
62571
62590
|
if( rc==SQLITE_OK && zSuper[0] ){
|
|
@@ -78455,7 +78474,9 @@ static int accessPayload(
|
|
|
78455
78474
|
** means "not yet known" (the cache is lazily populated).
|
|
78456
78475
|
*/
|
|
78457
78476
|
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
|
|
78458
|
-
|
|
78477
|
+
i64 nOvfl = pCur->info.nPayload;
|
|
78478
|
+
testcase( nOvfl - pCur->info.nLocal + ovflSize - 1 > 0xffffffffU );
|
|
78479
|
+
nOvfl = (nOvfl - pCur->info.nLocal + ovflSize-1)/ovflSize;
|
|
78459
78480
|
if( pCur->aOverflow==0
|
|
78460
78481
|
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
|
|
78461
78482
|
){
|
|
@@ -78560,6 +78581,12 @@ static int accessPayload(
|
|
|
78560
78581
|
(eOp==0 ? PAGER_GET_READONLY : 0)
|
|
78561
78582
|
);
|
|
78562
78583
|
if( rc==SQLITE_OK ){
|
|
78584
|
+
if( eOp!=0
|
|
78585
|
+
&& (sqlite3PagerPageRefcount(pDbPage)!=1
|
|
78586
|
+
|| NEVER(((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit)) ){
|
|
78587
|
+
sqlite3PagerUnref(pDbPage);
|
|
78588
|
+
return SQLITE_CORRUPT_PAGE(pPage);
|
|
78589
|
+
}
|
|
78563
78590
|
aPayload = sqlite3PagerGetData(pDbPage);
|
|
78564
78591
|
nextPage = get4byte(aPayload);
|
|
78565
78592
|
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
|
|
@@ -111254,6 +111281,7 @@ static int lookupName(
|
|
|
111254
111281
|
pExpr->op = TK_FUNCTION;
|
|
111255
111282
|
pExpr->u.zToken = "coalesce";
|
|
111256
111283
|
pExpr->x.pList = pFJMatch;
|
|
111284
|
+
pExpr->affExpr = SQLITE_AFF_DEFER;
|
|
111257
111285
|
cnt = 1;
|
|
111258
111286
|
goto lookupname_end;
|
|
111259
111287
|
}else{
|
|
@@ -111422,6 +111450,26 @@ static int exprProbability(Expr *p){
|
|
|
111422
111450
|
return (int)(r*134217728.0);
|
|
111423
111451
|
}
|
|
111424
111452
|
|
|
111453
|
+
/*
|
|
111454
|
+
** Set the EP_SubtArg property on every expression inside of
|
|
111455
|
+
** pList. If any subexpression is actually a subquery, then
|
|
111456
|
+
** also set the EP_SubtArg property on the first result-set
|
|
111457
|
+
** column of that subquery.
|
|
111458
|
+
*/
|
|
111459
|
+
static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
|
|
111460
|
+
int nn, ii;
|
|
111461
|
+
nn = pList ? pList->nExpr : 0;
|
|
111462
|
+
for(ii=0; ii<nn; ii++){
|
|
111463
|
+
Expr *pExpr = pList->a[ii].pExpr;
|
|
111464
|
+
ExprSetProperty(pExpr, EP_SubtArg);
|
|
111465
|
+
if( pExpr->op==TK_SELECT ){
|
|
111466
|
+
assert( ExprUseXSelect(pExpr) );
|
|
111467
|
+
assert( pExpr->x.pSelect!=0 );
|
|
111468
|
+
resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
|
|
111469
|
+
}
|
|
111470
|
+
}
|
|
111471
|
+
}
|
|
111472
|
+
|
|
111425
111473
|
/*
|
|
111426
111474
|
** This routine is callback for sqlite3WalkExpr().
|
|
111427
111475
|
**
|
|
@@ -111666,10 +111714,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|
|
111666
111714
|
if( (pDef->funcFlags & SQLITE_SUBTYPE)
|
|
111667
111715
|
|| ExprHasProperty(pExpr, EP_SubtArg)
|
|
111668
111716
|
){
|
|
111669
|
-
|
|
111670
|
-
for(ii=0; ii<n; ii++){
|
|
111671
|
-
ExprSetProperty(pList->a[ii].pExpr, EP_SubtArg);
|
|
111672
|
-
}
|
|
111717
|
+
resolveSetExprSubtypeArg(pList);
|
|
111673
111718
|
}
|
|
111674
111719
|
|
|
111675
111720
|
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
|
|
@@ -117064,7 +117109,16 @@ static void sqlite3ExprCodeIN(
|
|
|
117064
117109
|
CollSeq *pColl;
|
|
117065
117110
|
int r3 = sqlite3GetTempReg(pParse);
|
|
117066
117111
|
p = sqlite3VectorFieldSubexpr(pLeft, i);
|
|
117067
|
-
|
|
117112
|
+
if( ExprUseXSelect(pExpr) ){
|
|
117113
|
+
Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr;
|
|
117114
|
+
pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs);
|
|
117115
|
+
}else{
|
|
117116
|
+
/* If the RHS of the IN(...) expression are scalar expressions, do
|
|
117117
|
+
** not consider their collation sequences. The documentation says
|
|
117118
|
+
** "The collating sequence used for expressions of the form "x IN (y, z,
|
|
117119
|
+
** ...)" is the collating sequence of x.". */
|
|
117120
|
+
pColl = sqlite3ExprCollSeq(pParse, p);
|
|
117121
|
+
}
|
|
117068
117122
|
sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
|
|
117069
117123
|
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
|
|
117070
117124
|
(void*)pColl, P4_COLLSEQ);
|
|
@@ -117487,26 +117541,37 @@ static int exprCodeInlineFunction(
|
|
|
117487
117541
|
}
|
|
117488
117542
|
|
|
117489
117543
|
/*
|
|
117490
|
-
** Expression Node callback for sqlite3ExprCanReturnSubtype().
|
|
117544
|
+
** Expression Node callback for sqlite3ExprCanReturnSubtype(). If
|
|
117545
|
+
** pExpr is able to return a subtype, set pWalker->eCode and abort
|
|
117546
|
+
** the search. If pExpr can never return a subtype, prune search.
|
|
117547
|
+
**
|
|
117548
|
+
** The only expressions that can return a subtype are:
|
|
117491
117549
|
**
|
|
117492
|
-
**
|
|
117493
|
-
**
|
|
117550
|
+
** 1. A function
|
|
117551
|
+
** 2. The no-op "+" operator
|
|
117552
|
+
** 3. A CASE...END expression
|
|
117553
|
+
** 4. A CAST() expression
|
|
117554
|
+
** 5. A "expr COLLATE colseq" expression.
|
|
117494
117555
|
**
|
|
117495
|
-
**
|
|
117496
|
-
** SQLITE_RESULT_SUBTYPE property.
|
|
117556
|
+
** For any other kind of expression, prune the search.
|
|
117497
117557
|
**
|
|
117498
|
-
**
|
|
117499
|
-
**
|
|
117500
|
-
**
|
|
117501
|
-
**
|
|
117502
|
-
**
|
|
117503
|
-
**
|
|
117504
|
-
**
|
|
117558
|
+
** For case 1, the expression can yield a subtype if the function has
|
|
117559
|
+
** the SQLITE_RESULT_SUBTYPE property. Functions can also return
|
|
117560
|
+
** a subtype (via sqlite3_result_value()) if any of the arguments can
|
|
117561
|
+
** return a subtype.
|
|
117562
|
+
**
|
|
117563
|
+
** In all cases 1 through 5, the expression might also return a subtype
|
|
117564
|
+
** if any operand can return a subtype.
|
|
117505
117565
|
*/
|
|
117506
117566
|
static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
|
|
117507
117567
|
int n;
|
|
117508
117568
|
FuncDef *pDef;
|
|
117509
117569
|
sqlite3 *db;
|
|
117570
|
+
if( pExpr->op==TK_CASE || pExpr->op==TK_UPLUS
|
|
117571
|
+
|| pExpr->op==TK_COLLATE || pExpr->op==TK_CAST
|
|
117572
|
+
){
|
|
117573
|
+
return WRC_Continue;
|
|
117574
|
+
}
|
|
117510
117575
|
if( pExpr->op!=TK_FUNCTION ){
|
|
117511
117576
|
return WRC_Prune;
|
|
117512
117577
|
}
|
|
@@ -117516,7 +117581,7 @@ static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
|
|
|
117516
117581
|
pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
|
|
117517
117582
|
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
|
|
117518
117583
|
pWalker->eCode = 1;
|
|
117519
|
-
return
|
|
117584
|
+
return WRC_Abort;
|
|
117520
117585
|
}
|
|
117521
117586
|
return WRC_Continue;
|
|
117522
117587
|
}
|
|
@@ -123494,19 +123559,31 @@ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
|
|
|
123494
123559
|
SrcList *pSrc, /* Table to add constraint to */
|
|
123495
123560
|
Token *pFirst, /* First token of new constraint */
|
|
123496
123561
|
Token *pName, /* Name of new constraint. NULL if name omitted. */
|
|
123497
|
-
const char *
|
|
123498
|
-
int nExpr
|
|
123562
|
+
const char *zExpr, /* Text of CHECK expression */
|
|
123563
|
+
int nExpr, /* Size of pExpr in bytes */
|
|
123564
|
+
Expr *pExpr /* The parsed CHECK expression */
|
|
123499
123565
|
){
|
|
123500
123566
|
Table *pTab = 0; /* Table identified by pSrc */
|
|
123501
123567
|
int iDb = 0; /* Which schema does pTab live in */
|
|
123502
123568
|
const char *zDb = 0; /* Name of the schema in which pTab lives */
|
|
123503
123569
|
const char *pCons = 0; /* Text of the constraint */
|
|
123504
123570
|
int nCons; /* Bytes of text to use from pCons[] */
|
|
123571
|
+
int rc; /* Result from error checking pExpr */
|
|
123505
123572
|
|
|
123506
123573
|
/* Look up the table being altered. */
|
|
123507
123574
|
assert( pSrc->nSrc==1 );
|
|
123508
123575
|
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
|
|
123509
|
-
if( !pTab )
|
|
123576
|
+
if( !pTab ){
|
|
123577
|
+
sqlite3ExprDelete(pParse->db, pExpr);
|
|
123578
|
+
return;
|
|
123579
|
+
}
|
|
123580
|
+
|
|
123581
|
+
/* Verify that the new CHECK constraint does not contain any
|
|
123582
|
+
** internal-use-only function. Forum post 2026-05-10T01:11:28Z
|
|
123583
|
+
*/
|
|
123584
|
+
rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0);
|
|
123585
|
+
sqlite3ExprDelete(pParse->db, pExpr);
|
|
123586
|
+
if( rc ) return;
|
|
123510
123587
|
|
|
123511
123588
|
/* If this new constraint has a name, check that it is not a duplicate of
|
|
123512
123589
|
** an existing constraint. It is an error if it is. */
|
|
@@ -123527,7 +123604,7 @@ SQLITE_PRIVATE void sqlite3AlterAddConstraint(
|
|
|
123527
123604
|
sqlite3NestedParse(pParse,
|
|
123528
123605
|
"SELECT sqlite_fail('constraint failed', %d) "
|
|
123529
123606
|
"FROM %Q.%Q WHERE (%.*s) IS NOT TRUE",
|
|
123530
|
-
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr,
|
|
123607
|
+
SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr
|
|
123531
123608
|
);
|
|
123532
123609
|
|
|
123533
123610
|
/* Edit the SQL for the named table. */
|
|
@@ -134209,9 +134286,18 @@ static void printfFunc(
|
|
|
134209
134286
|
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
|
134210
134287
|
str.printfFlags = SQLITE_PRINTF_SQLFUNC;
|
|
134211
134288
|
sqlite3_str_appendf(&str, zFormat, &x);
|
|
134212
|
-
|
|
134213
|
-
|
|
134214
|
-
|
|
134289
|
+
if( str.accError==SQLITE_OK ){
|
|
134290
|
+
n = str.nChar;
|
|
134291
|
+
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
|
|
134292
|
+
SQLITE_DYNAMIC);
|
|
134293
|
+
}else{
|
|
134294
|
+
if( str.accError==SQLITE_NOMEM ){
|
|
134295
|
+
sqlite3_result_error_nomem(context);
|
|
134296
|
+
}else{
|
|
134297
|
+
sqlite3_result_error_toobig(context);
|
|
134298
|
+
}
|
|
134299
|
+
sqlite3_str_reset(&str);
|
|
134300
|
+
}
|
|
134215
134301
|
}
|
|
134216
134302
|
}
|
|
134217
134303
|
|
|
@@ -135849,11 +135935,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
|
|
|
135849
135935
|
assert( p->cnt>0 );
|
|
135850
135936
|
p->cnt--;
|
|
135851
135937
|
if( !p->approx ){
|
|
135852
|
-
|
|
135853
|
-
|
|
135854
|
-
p->
|
|
135938
|
+
i64 x = p->iSum;
|
|
135939
|
+
if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){
|
|
135940
|
+
p->iSum = x;
|
|
135941
|
+
return;
|
|
135855
135942
|
}
|
|
135856
|
-
|
|
135943
|
+
p->ovrfl = 1;
|
|
135944
|
+
p->approx = 1;
|
|
135945
|
+
kahanBabuskaNeumaierInit(p, p->iSum);
|
|
135946
|
+
}
|
|
135947
|
+
if( type==SQLITE_INTEGER ){
|
|
135857
135948
|
i64 iVal = sqlite3_value_int64(argv[0]);
|
|
135858
135949
|
if( iVal!=SMALLEST_INT64 ){
|
|
135859
135950
|
kahanBabuskaNeumaierStepInt64(p, -iVal);
|
|
@@ -136826,47 +136917,46 @@ static void percentSort(double *a, unsigned int n){
|
|
|
136826
136917
|
int i; /* Loop counter */
|
|
136827
136918
|
double rPivot; /* The pivot value */
|
|
136828
136919
|
|
|
136829
|
-
|
|
136830
|
-
|
|
136831
|
-
|
|
136832
|
-
|
|
136833
|
-
|
|
136834
|
-
|
|
136835
|
-
|
|
136836
|
-
|
|
136837
|
-
|
|
136838
|
-
|
|
136839
|
-
SWAP_DOUBLE(a[i],a[iGt])
|
|
136840
|
-
}
|
|
136841
|
-
if( n==3 ) return;
|
|
136842
|
-
rPivot = a[i];
|
|
136843
|
-
iLt = i = 1;
|
|
136844
|
-
do{
|
|
136845
|
-
if( a[i]<rPivot ){
|
|
136846
|
-
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
|
136847
|
-
iLt++;
|
|
136848
|
-
i++;
|
|
136849
|
-
}else if( a[i]>rPivot ){
|
|
136850
|
-
do{
|
|
136851
|
-
iGt--;
|
|
136852
|
-
}while( iGt>i && a[iGt]>rPivot );
|
|
136920
|
+
while( n>=2 ){
|
|
136921
|
+
if( a[0]>a[n-1] ){
|
|
136922
|
+
SWAP_DOUBLE(a[0],a[n-1])
|
|
136923
|
+
}
|
|
136924
|
+
if( n==2 ) return;
|
|
136925
|
+
iGt = n-1;
|
|
136926
|
+
i = n/2;
|
|
136927
|
+
if( a[0]>a[i] ){
|
|
136928
|
+
SWAP_DOUBLE(a[0],a[i])
|
|
136929
|
+
}else if( a[i]>a[iGt] ){
|
|
136853
136930
|
SWAP_DOUBLE(a[i],a[iGt])
|
|
136931
|
+
}
|
|
136932
|
+
if( n==3 ) return;
|
|
136933
|
+
rPivot = a[i];
|
|
136934
|
+
iLt = i = 1;
|
|
136935
|
+
do{
|
|
136936
|
+
if( a[i]<rPivot ){
|
|
136937
|
+
if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt])
|
|
136938
|
+
iLt++;
|
|
136939
|
+
i++;
|
|
136940
|
+
}else if( a[i]>rPivot ){
|
|
136941
|
+
do{
|
|
136942
|
+
iGt--;
|
|
136943
|
+
}while( iGt>i && a[iGt]>rPivot );
|
|
136944
|
+
SWAP_DOUBLE(a[i],a[iGt])
|
|
136945
|
+
}else{
|
|
136946
|
+
i++;
|
|
136947
|
+
}
|
|
136948
|
+
}while( i<iGt );
|
|
136949
|
+
if( iLt>n/2 ){
|
|
136950
|
+
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
|
136951
|
+
n = iLt;
|
|
136854
136952
|
}else{
|
|
136855
|
-
|
|
136953
|
+
if( iLt>=2 ) percentSort(a, iLt);
|
|
136954
|
+
a += iGt;
|
|
136955
|
+
n -= iGt;
|
|
136856
136956
|
}
|
|
136857
|
-
}while( i<iGt );
|
|
136858
|
-
if( iLt>=2 ) percentSort(a, iLt);
|
|
136859
|
-
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
|
|
136860
|
-
|
|
136861
|
-
/* Uncomment for testing */
|
|
136862
|
-
#if 0
|
|
136863
|
-
for(i=0; i<n-1; i++){
|
|
136864
|
-
assert( a[i]<=a[i+1] );
|
|
136865
136957
|
}
|
|
136866
|
-
#endif
|
|
136867
136958
|
}
|
|
136868
136959
|
|
|
136869
|
-
|
|
136870
136960
|
/*
|
|
136871
136961
|
** The "inverse" function for percentile(Y,P) is called to remove a
|
|
136872
136962
|
** row that was previously inserted by "step".
|
|
@@ -156364,8 +156454,11 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
|
|
|
156364
156454
|
** does not refer to a table to the right of CheckOnCtx.iJoin. */
|
|
156365
156455
|
do {
|
|
156366
156456
|
SrcList *pSrc = pCtx->pSrc;
|
|
156457
|
+
int nSrc = pSrc->nSrc;
|
|
156367
156458
|
int iTab = pExpr->iTable;
|
|
156368
|
-
|
|
156459
|
+
int ii;
|
|
156460
|
+
for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){}
|
|
156461
|
+
if( ii<nSrc ){
|
|
156369
156462
|
if( pCtx->iJoin && iTab>pCtx->iJoin ){
|
|
156370
156463
|
sqlite3ErrorMsg(pWalker->pParse,
|
|
156371
156464
|
"%s references tables to its right",
|
|
@@ -166574,6 +166667,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
|
|
166574
166667
|
WO_EQ|WO_IN|WO_IS, 0);
|
|
166575
166668
|
if( pAlt==0 ) continue;
|
|
166576
166669
|
if( pAlt->wtFlags & (TERM_CODED) ) continue;
|
|
166670
|
+
if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue;
|
|
166577
166671
|
if( (pAlt->eOperator & WO_IN)
|
|
166578
166672
|
&& ExprUseXSelect(pAlt->pExpr)
|
|
166579
166673
|
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
|
|
@@ -167766,8 +167860,8 @@ static void exprAnalyzeOrTerm(
|
|
|
167766
167860
|
** 3. Not originating in the ON clause of an OUTER JOIN
|
|
167767
167861
|
** 4. The operator is not IS or else the query does not contain RIGHT JOIN
|
|
167768
167862
|
** 5. The affinities of A and B must be compatible
|
|
167769
|
-
**
|
|
167770
|
-
**
|
|
167863
|
+
** 6. Both operands use the same collating sequence, and they must not
|
|
167864
|
+
** use explicit COLLATE clauses.
|
|
167771
167865
|
** If this routine returns TRUE, that means that the RHS can be substituted
|
|
167772
167866
|
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
|
|
167773
167867
|
** This is an optimization. No harm comes from returning 0. But if 1 is
|
|
@@ -167775,10 +167869,9 @@ static void exprAnalyzeOrTerm(
|
|
|
167775
167869
|
*/
|
|
167776
167870
|
static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
|
167777
167871
|
char aff1, aff2;
|
|
167778
|
-
CollSeq *pColl;
|
|
167779
167872
|
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
|
|
167780
167873
|
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
|
|
167781
|
-
if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
|
|
167874
|
+
if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */
|
|
167782
167875
|
assert( pSrc!=0 );
|
|
167783
167876
|
if( pExpr->op==TK_IS
|
|
167784
167877
|
&& pSrc->nSrc>=2
|
|
@@ -167793,10 +167886,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
|
|
|
167793
167886
|
){
|
|
167794
167887
|
return 0; /* (5) */
|
|
167795
167888
|
}
|
|
167796
|
-
|
|
167797
|
-
if( !sqlite3IsBinary(pColl)
|
|
167798
|
-
&& !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
|
|
167799
|
-
){
|
|
167889
|
+
if( !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight) ){
|
|
167800
167890
|
return 0; /* (6) */
|
|
167801
167891
|
}
|
|
167802
167892
|
return 1;
|
|
@@ -168128,7 +168218,7 @@ static void exprAnalyze(
|
|
|
168128
168218
|
/* Analyze a term that is composed of two or more subterms connected by
|
|
168129
168219
|
** an OR operator.
|
|
168130
168220
|
*/
|
|
168131
|
-
else if( pExpr->op==TK_OR ){
|
|
168221
|
+
else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){
|
|
168132
168222
|
assert( pWC->op==TK_AND );
|
|
168133
168223
|
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
|
|
168134
168224
|
pTerm = &pWC->a[idxTerm];
|
|
@@ -171946,7 +172036,8 @@ static int whereRangeVectorLen(
|
|
|
171946
172036
|
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
|
|
171947
172037
|
if( aff!=idxaff ) break;
|
|
171948
172038
|
|
|
171949
|
-
|
|
172039
|
+
if( ExprHasProperty(pTerm->pExpr, EP_Commuted) ) SWAP(Expr*, pRhs, pLhs);
|
|
172040
|
+
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
|
|
171950
172041
|
if( pColl==0 ) break;
|
|
171951
172042
|
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
|
|
171952
172043
|
}
|
|
@@ -184438,9 +184529,11 @@ static YYACTIONTYPE yy_reduce(
|
|
|
184438
184529
|
ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454);
|
|
184439
184530
|
yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
|
184440
184531
|
if( yymsp[-4].minor.yy454 ){
|
|
184532
|
+
int i;
|
|
184441
184533
|
yymsp[-4].minor.yy454->x.pList = pList;
|
|
184442
|
-
|
|
184443
|
-
|
|
184534
|
+
for(i=0; i<pList->nExpr; i++){
|
|
184535
|
+
assert( pList->a[i].pExpr!=0 );
|
|
184536
|
+
yymsp[-4].minor.yy454->flags |= pList->a[i].pExpr->flags & EP_Propagate;
|
|
184444
184537
|
}
|
|
184445
184538
|
}else{
|
|
184446
184539
|
sqlite3ExprListDelete(pParse->db, pList);
|
|
@@ -184908,15 +185001,13 @@ static YYACTIONTYPE yy_reduce(
|
|
|
184908
185001
|
break;
|
|
184909
185002
|
case 300: /* cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */
|
|
184910
185003
|
{
|
|
184911
|
-
sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1));
|
|
185004
|
+
sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
|
|
184912
185005
|
}
|
|
184913
|
-
yy_destructor(yypParser,219,&yymsp[-2].minor);
|
|
184914
185006
|
break;
|
|
184915
185007
|
case 301: /* cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */
|
|
184916
185008
|
{
|
|
184917
|
-
sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1));
|
|
185009
|
+
sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1), yymsp[-2].minor.yy454);
|
|
184918
185010
|
}
|
|
184919
|
-
yy_destructor(yypParser,219,&yymsp[-2].minor);
|
|
184920
185011
|
break;
|
|
184921
185012
|
case 302: /* cmd ::= create_vtab */
|
|
184922
185013
|
{sqlite3VtabFinishParse(pParse,0);}
|
|
@@ -194133,6 +194224,12 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
|
|
|
194133
194224
|
SQLITE_EXTENSION_INIT1
|
|
194134
194225
|
#endif
|
|
194135
194226
|
|
|
194227
|
+
|
|
194228
|
+
/*
|
|
194229
|
+
** Assume any b-tree layer with more levels than this is corrupt.
|
|
194230
|
+
*/
|
|
194231
|
+
#define FTS3_MAX_BTREE_HEIGHT 48
|
|
194232
|
+
|
|
194136
194233
|
typedef struct Fts3HashWrapper Fts3HashWrapper;
|
|
194137
194234
|
struct Fts3HashWrapper {
|
|
194138
194235
|
Fts3Hash hash; /* Hash table */
|
|
@@ -195849,7 +195946,11 @@ static int fts3SelectLeaf(
|
|
|
195849
195946
|
assert( piLeaf || piLeaf2 );
|
|
195850
195947
|
|
|
195851
195948
|
fts3GetVarint32(zNode, &iHeight);
|
|
195852
|
-
|
|
195949
|
+
if( iHeight>FTS3_MAX_BTREE_HEIGHT ){
|
|
195950
|
+
rc = FTS_CORRUPT_VTAB;
|
|
195951
|
+
}else{
|
|
195952
|
+
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
|
|
195953
|
+
}
|
|
195853
195954
|
assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
|
|
195854
195955
|
|
|
195855
195956
|
if( rc==SQLITE_OK && iHeight>1 ){
|
|
@@ -200378,7 +200479,7 @@ static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
|
|
|
200378
200479
|
/* State 3. The integer just read is a column number. */
|
|
200379
200480
|
default: assert( eState==3 );
|
|
200380
200481
|
iCol = (int)v;
|
|
200381
|
-
if( iCol<1 ){
|
|
200482
|
+
if( iCol<1 || iCol>(pFts3->nColumn+1) ){
|
|
200382
200483
|
rc = SQLITE_CORRUPT_VTAB;
|
|
200383
200484
|
break;
|
|
200384
200485
|
}
|
|
@@ -201068,6 +201169,7 @@ static int getNextNode(
|
|
|
201068
201169
|
assert( nKey==4 );
|
|
201069
201170
|
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
|
|
201070
201171
|
nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
|
|
201172
|
+
if( nNear>=1000000000 ) nNear = 1000000000;
|
|
201071
201173
|
}
|
|
201072
201174
|
}
|
|
201073
201175
|
|
|
@@ -210931,7 +211033,7 @@ static int fts3ExprLHits(
|
|
|
210931
211033
|
if( p->flag==FTS3_MATCHINFO_LHITS ){
|
|
210932
211034
|
p->aMatchinfo[iStart + iCol] = (u32)nHit;
|
|
210933
211035
|
}else if( nHit ){
|
|
210934
|
-
p->aMatchinfo[iStart +
|
|
211036
|
+
p->aMatchinfo[iStart + iCol/32] |= (1U << (iCol&0x1F));
|
|
210935
211037
|
}
|
|
210936
211038
|
}
|
|
210937
211039
|
assert( *pIter==0x00 || *pIter==0x01 );
|
|
@@ -213421,7 +213523,7 @@ static void jsonAppendSqlValue(
|
|
|
213421
213523
|
break;
|
|
213422
213524
|
}
|
|
213423
213525
|
case SQLITE_FLOAT: {
|
|
213424
|
-
jsonPrintf(100, p, "%!0.
|
|
213526
|
+
jsonPrintf(100, p, "%!0.17g", sqlite3_value_double(pValue));
|
|
213425
213527
|
break;
|
|
213426
213528
|
}
|
|
213427
213529
|
case SQLITE_INTEGER: {
|
|
@@ -214735,9 +214837,10 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
|
|
|
214735
214837
|
u8 x;
|
|
214736
214838
|
u32 sz;
|
|
214737
214839
|
u32 n;
|
|
214738
|
-
|
|
214739
|
-
|
|
214740
|
-
|
|
214840
|
+
if( i>=pParse->nBlob ){
|
|
214841
|
+
*pSz = 0;
|
|
214842
|
+
return 0;
|
|
214843
|
+
}else if( (x = pParse->aBlob[i]>>4)<=11 ){
|
|
214741
214844
|
sz = x;
|
|
214742
214845
|
n = 1;
|
|
214743
214846
|
}else if( x==12 ){
|
|
@@ -217520,11 +217623,9 @@ static void jsonGroupInverse(
|
|
|
217520
217623
|
UNUSED_PARAMETER(argc);
|
|
217521
217624
|
UNUSED_PARAMETER(argv);
|
|
217522
217625
|
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
|
217523
|
-
#ifdef NEVER
|
|
217524
217626
|
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
|
|
217525
217627
|
** always have been called to initialize it */
|
|
217526
217628
|
if( NEVER(!pStr) ) return;
|
|
217527
|
-
#endif
|
|
217528
217629
|
z = pStr->zBuf;
|
|
217529
217630
|
for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
|
|
217530
217631
|
if( c=='"' ){
|
|
@@ -217553,6 +217654,13 @@ static void jsonGroupInverse(
|
|
|
217553
217654
|
** json_group_obj(NAME,VALUE)
|
|
217554
217655
|
**
|
|
217555
217656
|
** Return a JSON object composed of all names and values in the aggregate.
|
|
217657
|
+
**
|
|
217658
|
+
** Rows for which NAME is NULL do not result in a new entry. However, we
|
|
217659
|
+
** do initially insert a "@" entry into the growing string for each null entry
|
|
217660
|
+
** and change the first character of the string to "@" to signal that the
|
|
217661
|
+
** string contains null entries. The "@" markers are needed in order to
|
|
217662
|
+
** correctly process xInverse() requests. The initial "@" is converted
|
|
217663
|
+
** back into "{" and the "@" null values are removed by jsonObjectCompute().
|
|
217556
217664
|
*/
|
|
217557
217665
|
static void jsonObjectStep(
|
|
217558
217666
|
sqlite3_context *ctx,
|
|
@@ -217570,7 +217678,7 @@ static void jsonObjectStep(
|
|
|
217570
217678
|
if( pStr->zBuf==0 ){
|
|
217571
217679
|
jsonStringInit(pStr, ctx);
|
|
217572
217680
|
jsonAppendChar(pStr, '{');
|
|
217573
|
-
}else if( pStr->nUsed>1
|
|
217681
|
+
}else if( pStr->nUsed>1 ){
|
|
217574
217682
|
jsonAppendChar(pStr, ',');
|
|
217575
217683
|
}
|
|
217576
217684
|
pStr->pCtx = ctx;
|
|
@@ -217578,6 +217686,9 @@ static void jsonObjectStep(
|
|
|
217578
217686
|
jsonAppendString(pStr, z, n);
|
|
217579
217687
|
jsonAppendChar(pStr, ':');
|
|
217580
217688
|
jsonAppendSqlValue(pStr, argv[1]);
|
|
217689
|
+
}else{
|
|
217690
|
+
pStr->zBuf[0] = '@';
|
|
217691
|
+
jsonAppendRawNZ(pStr, "@", 1);
|
|
217581
217692
|
}
|
|
217582
217693
|
}
|
|
217583
217694
|
}
|
|
@@ -217586,20 +217697,64 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
|
|
217586
217697
|
int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
|
|
217587
217698
|
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
|
217588
217699
|
if( pStr ){
|
|
217589
|
-
|
|
217590
|
-
|
|
217700
|
+
JsonString *pOgStr = pStr;
|
|
217701
|
+
JsonString tmpStr;
|
|
217702
|
+
jsonAppendRawNZ(pOgStr, "}", 2); /* Ensure it is zero-terminated */
|
|
217703
|
+
jsonStringTrimOneChar(pOgStr); /* Remove the zero terminator */
|
|
217591
217704
|
pStr->pCtx = ctx;
|
|
217592
217705
|
if( pStr->eErr ){
|
|
217593
217706
|
jsonReturnString(pStr, 0, 0);
|
|
217594
217707
|
return;
|
|
217595
|
-
}
|
|
217708
|
+
}
|
|
217709
|
+
if( pStr->zBuf[0]!='{' ){
|
|
217710
|
+
/* The string contains null entries that need to be removed */
|
|
217711
|
+
u64 i, j;
|
|
217712
|
+
int inStr = 0;
|
|
217713
|
+
if( !isFinal ){
|
|
217714
|
+
/* Work with a temporary copy of the string if this is not the
|
|
217715
|
+
** final result */
|
|
217716
|
+
jsonStringInit(&tmpStr, ctx);
|
|
217717
|
+
jsonAppendRawNZ(&tmpStr, pStr->zBuf, pStr->nUsed+1);
|
|
217718
|
+
pStr = &tmpStr;
|
|
217719
|
+
if( pStr->eErr ){
|
|
217720
|
+
jsonReturnString(pStr, 0, 0);
|
|
217721
|
+
return;
|
|
217722
|
+
}
|
|
217723
|
+
jsonStringTrimOneChar(pStr); /* Remove zero terminator */
|
|
217724
|
+
}
|
|
217725
|
+
/* Fix up the string by changing the initial "@" flag back to
|
|
217726
|
+
** to "{" and removing all subsequence "@" entries, with their
|
|
217727
|
+
** associated comma delimeters. */
|
|
217728
|
+
pStr->zBuf[0] = '{';
|
|
217729
|
+
for(i=j=1; i<pStr->nUsed; i++){
|
|
217730
|
+
char c = pStr->zBuf[i];
|
|
217731
|
+
if( c=='"' ){
|
|
217732
|
+
inStr = !inStr;
|
|
217733
|
+
pStr->zBuf[j++] = '"';
|
|
217734
|
+
}else if( c=='\\' ){
|
|
217735
|
+
pStr->zBuf[j++] = '\\';
|
|
217736
|
+
pStr->zBuf[j++] = pStr->zBuf[++i];
|
|
217737
|
+
}else if( c=='@' && !inStr ){
|
|
217738
|
+
assert( i+1<pStr->nUsed );
|
|
217739
|
+
if( pStr->zBuf[i+1]==',' ){
|
|
217740
|
+
i++;
|
|
217741
|
+
}else if( pStr->zBuf[j-1]==',' ){
|
|
217742
|
+
j--;
|
|
217743
|
+
}
|
|
217744
|
+
}else{
|
|
217745
|
+
pStr->zBuf[j++] = c;
|
|
217746
|
+
}
|
|
217747
|
+
}
|
|
217748
|
+
pStr->zBuf[j] = 0; /* Restore zero terminator */
|
|
217749
|
+
pStr->nUsed = j; /* Truncate the string */
|
|
217750
|
+
}
|
|
217751
|
+
if( flags & JSON_BLOB ){
|
|
217596
217752
|
jsonReturnStringAsBlob(pStr);
|
|
217597
217753
|
if( isFinal ){
|
|
217598
217754
|
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
|
|
217599
217755
|
}else{
|
|
217600
|
-
jsonStringTrimOneChar(
|
|
217756
|
+
jsonStringTrimOneChar(pOgStr);
|
|
217601
217757
|
}
|
|
217602
|
-
return;
|
|
217603
217758
|
}else if( isFinal ){
|
|
217604
217759
|
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
|
|
217605
217760
|
pStr->bStatic ? SQLITE_TRANSIENT :
|
|
@@ -217607,8 +217762,9 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
|
|
217607
217762
|
pStr->bStatic = 1;
|
|
217608
217763
|
}else{
|
|
217609
217764
|
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
|
|
217610
|
-
jsonStringTrimOneChar(
|
|
217765
|
+
jsonStringTrimOneChar(pOgStr);
|
|
217611
217766
|
}
|
|
217767
|
+
if( pStr!=pOgStr ) jsonStringReset(pStr);
|
|
217612
217768
|
}else if( flags & JSON_BLOB ){
|
|
217613
217769
|
static const unsigned char emptyObject = 0x0c;
|
|
217614
217770
|
sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC);
|
|
@@ -218460,7 +218616,7 @@ struct Rtree {
|
|
|
218460
218616
|
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
|
|
218461
218617
|
u8 nBytesPerCell; /* Bytes consumed per cell */
|
|
218462
218618
|
u8 inWrTrans; /* True if inside write transaction */
|
|
218463
|
-
|
|
218619
|
+
u16 nAux; /* # of auxiliary columns in %_rowid */
|
|
218464
218620
|
#ifdef SQLITE_ENABLE_GEOPOLY
|
|
218465
218621
|
u8 nAuxNotNull; /* Number of initial not-null aux columns */
|
|
218466
218622
|
#endif
|
|
@@ -219696,7 +219852,7 @@ static int nodeRowidIndex(
|
|
|
219696
219852
|
){
|
|
219697
219853
|
int ii;
|
|
219698
219854
|
int nCell = NCELL(pNode);
|
|
219699
|
-
assert( nCell<
|
|
219855
|
+
assert( nCell<65536 && nCell>=0 );
|
|
219700
219856
|
for(ii=0; ii<nCell; ii++){
|
|
219701
219857
|
if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
|
|
219702
219858
|
*piIndex = ii;
|
|
@@ -219958,7 +220114,10 @@ static int rtreeStepToLeaf(RtreeCursor *pCur){
|
|
|
219958
220114
|
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
|
|
219959
220115
|
if( rc ) return rc;
|
|
219960
220116
|
nCell = NCELL(pNode);
|
|
219961
|
-
|
|
220117
|
+
if( nCell>RTREE_MAXCELLS ){
|
|
220118
|
+
RTREE_IS_CORRUPT(pRtree);
|
|
220119
|
+
return SQLITE_CORRUPT_VTAB;
|
|
220120
|
+
}
|
|
219962
220121
|
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
|
|
219963
220122
|
while( p->iCell<nCell ){
|
|
219964
220123
|
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
|
|
@@ -221935,7 +222094,7 @@ static int rtreeInit(
|
|
|
221935
222094
|
"Auxiliary rtree columns must be last" /* 4 */
|
|
221936
222095
|
};
|
|
221937
222096
|
|
|
221938
|
-
assert( RTREE_MAX_AUX_COLUMN<256 );
|
|
222097
|
+
assert( RTREE_MAX_AUX_COLUMN<256 );
|
|
221939
222098
|
if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
|
|
221940
222099
|
*pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
|
|
221941
222100
|
return SQLITE_ERROR;
|
|
@@ -223854,6 +224013,11 @@ static int geopolyInit(
|
|
|
223854
224013
|
int ii;
|
|
223855
224014
|
(void)pAux;
|
|
223856
224015
|
|
|
224016
|
+
if( argc>=RTREE_MAX_AUX_COLUMN+4 ){
|
|
224017
|
+
*pzErr = sqlite3_mprintf("Too many columns for a geopoly table");
|
|
224018
|
+
return SQLITE_ERROR;
|
|
224019
|
+
}
|
|
224020
|
+
|
|
223857
224021
|
sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
|
|
223858
224022
|
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
|
223859
224023
|
|
|
@@ -224988,7 +225152,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
|
|
224988
225152
|
const UChar *zInput; /* Pointer to input string */
|
|
224989
225153
|
UChar *zOutput = 0; /* Pointer to output buffer */
|
|
224990
225154
|
int nInput; /* Size of utf-16 input string in bytes */
|
|
224991
|
-
|
|
225155
|
+
sqlite3_int64 nOut; /* Size of output buffer in bytes */
|
|
224992
225156
|
int cnt;
|
|
224993
225157
|
int bToUpper; /* True for toupper(), false for tolower() */
|
|
224994
225158
|
UErrorCode status;
|
|
@@ -225011,7 +225175,7 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
|
|
225011
225175
|
}
|
|
225012
225176
|
|
|
225013
225177
|
for(cnt=0; cnt<2; cnt++){
|
|
225014
|
-
UChar *zNew =
|
|
225178
|
+
UChar *zNew = sqlite3_realloc64(zOutput, nOut);
|
|
225015
225179
|
if( zNew==0 ){
|
|
225016
225180
|
sqlite3_free(zOutput);
|
|
225017
225181
|
sqlite3_result_error_nomem(p);
|
|
@@ -225020,9 +225184,9 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
|
|
225020
225184
|
zOutput = zNew;
|
|
225021
225185
|
status = U_ZERO_ERROR;
|
|
225022
225186
|
if( bToUpper ){
|
|
225023
|
-
nOut =
|
|
225187
|
+
nOut = 2LL*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
|
225024
225188
|
}else{
|
|
225025
|
-
nOut =
|
|
225189
|
+
nOut = 2LL*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
|
225026
225190
|
}
|
|
225027
225191
|
|
|
225028
225192
|
if( U_SUCCESS(status) ){
|
|
@@ -232737,12 +232901,13 @@ static int dbpageFilter(
|
|
|
232737
232901
|
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
|
|
232738
232902
|
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
|
|
232739
232903
|
if( idxNum & 1 ){
|
|
232904
|
+
i64 iPg = sqlite3_value_int64(argv[idxNum>>1]);
|
|
232740
232905
|
assert( argc>(idxNum>>1) );
|
|
232741
|
-
pCsr->
|
|
232742
|
-
if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
|
|
232906
|
+
if( iPg<1 || iPg>pCsr->mxPgno ){
|
|
232743
232907
|
pCsr->pgno = 1;
|
|
232744
232908
|
pCsr->mxPgno = 0;
|
|
232745
232909
|
}else{
|
|
232910
|
+
pCsr->pgno = (Pgno)iPg;
|
|
232746
232911
|
pCsr->mxPgno = pCsr->pgno;
|
|
232747
232912
|
}
|
|
232748
232913
|
}else{
|
|
@@ -235089,6 +235254,16 @@ static int sessionPrepareDfltStmt(
|
|
|
235089
235254
|
return rc;
|
|
235090
235255
|
}
|
|
235091
235256
|
|
|
235257
|
+
/*
|
|
235258
|
+
** Finalize statement pStmt. If (*pRc) is SQLITE_OK when this function is
|
|
235259
|
+
** called, set it to the results of the sqlite3_finalize() call. Or, if
|
|
235260
|
+
** it is already set to an error code, leave it as is.
|
|
235261
|
+
*/
|
|
235262
|
+
static void sessionFinalizeStmt(sqlite3_stmt *pStmt, int *pRc){
|
|
235263
|
+
int rc = sqlite3_finalize(pStmt);
|
|
235264
|
+
if( *pRc==SQLITE_OK ) *pRc = rc;
|
|
235265
|
+
}
|
|
235266
|
+
|
|
235092
235267
|
/*
|
|
235093
235268
|
** Table pTab has one or more existing change-records with old.* records
|
|
235094
235269
|
** with fewer than pTab->nCol columns. This function updates all such
|
|
@@ -235111,9 +235286,8 @@ static int sessionUpdateChanges(sqlite3_session *pSession, SessionTable *pTab){
|
|
|
235111
235286
|
}
|
|
235112
235287
|
}
|
|
235113
235288
|
|
|
235289
|
+
sessionFinalizeStmt(pStmt, &rc);
|
|
235114
235290
|
pSession->rc = rc;
|
|
235115
|
-
rc = sqlite3_finalize(pStmt);
|
|
235116
|
-
if( pSession->rc==SQLITE_OK ) pSession->rc = rc;
|
|
235117
235291
|
return pSession->rc;
|
|
235118
235292
|
}
|
|
235119
235293
|
|
|
@@ -235681,7 +235855,7 @@ static int sessionDiffFindNew(
|
|
|
235681
235855
|
rc = SQLITE_NOMEM;
|
|
235682
235856
|
}else{
|
|
235683
235857
|
sqlite3_stmt *pStmt;
|
|
235684
|
-
rc =
|
|
235858
|
+
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
|
|
235685
235859
|
if( rc==SQLITE_OK ){
|
|
235686
235860
|
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
|
|
235687
235861
|
pDiffCtx->pStmt = pStmt;
|
|
@@ -235744,7 +235918,7 @@ static int sessionDiffFindModified(
|
|
|
235744
235918
|
rc = SQLITE_NOMEM;
|
|
235745
235919
|
}else{
|
|
235746
235920
|
sqlite3_stmt *pStmt;
|
|
235747
|
-
rc =
|
|
235921
|
+
rc = sqlite3_prepare_v2(pSession->db, zStmt, -1, &pStmt, 0);
|
|
235748
235922
|
|
|
235749
235923
|
if( rc==SQLITE_OK ){
|
|
235750
235924
|
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
|
|
@@ -236439,11 +236613,11 @@ static int sessionSelectStmt(
|
|
|
236439
236613
|
);
|
|
236440
236614
|
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
|
|
236441
236615
|
}else{
|
|
236442
|
-
|
|
236616
|
+
#if 0
|
|
236443
236617
|
if( bRowid ){
|
|
236444
236618
|
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
|
236445
236619
|
}
|
|
236446
|
-
|
|
236620
|
+
#endif
|
|
236447
236621
|
for(i=0; i<nCol; i++){
|
|
236448
236622
|
if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
|
|
236449
236623
|
sessionAppendIdent(&cols, azCol[i], &rc);
|
|
@@ -237697,7 +237871,13 @@ static int sessionChangesetInvert(
|
|
|
237697
237871
|
|
|
237698
237872
|
/* Test for EOF. */
|
|
237699
237873
|
if( (rc = sessionInputBuffer(pInput, 2)) ) goto finished_invert;
|
|
237700
|
-
if( pInput->iNext>=pInput->nData )
|
|
237874
|
+
if( pInput->iNext+1>=pInput->nData ){
|
|
237875
|
+
if( pInput->iNext!=pInput->nData ){
|
|
237876
|
+
rc = SQLITE_CORRUPT_BKPT;
|
|
237877
|
+
goto finished_invert;
|
|
237878
|
+
}
|
|
237879
|
+
break;
|
|
237880
|
+
}
|
|
237701
237881
|
eType = pInput->aData[pInput->iNext];
|
|
237702
237882
|
|
|
237703
237883
|
switch( eType ){
|
|
@@ -237893,6 +238073,7 @@ struct SessionApplyCtx {
|
|
|
237893
238073
|
u8 bRebaseStarted; /* If table header is already in rebase */
|
|
237894
238074
|
u8 bRebase; /* True to collect rebase information */
|
|
237895
238075
|
u8 bIgnoreNoop; /* True to ignore no-op conflicts */
|
|
238076
|
+
u8 bNoUpdateLoop; /* No update-loop processing */
|
|
237896
238077
|
int bRowid;
|
|
237897
238078
|
char *zErr; /* Error message, if any */
|
|
237898
238079
|
};
|
|
@@ -238466,7 +238647,7 @@ static int sessionConflictHandler(
|
|
|
238466
238647
|
u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent];
|
|
238467
238648
|
int nBlob = pIter->in.iNext - pIter->in.iCurrent;
|
|
238468
238649
|
sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc);
|
|
238469
|
-
return
|
|
238650
|
+
return rc;
|
|
238470
238651
|
}else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE
|
|
238471
238652
|
|| eType==SQLITE_CHANGESET_CONFLICT
|
|
238472
238653
|
){
|
|
@@ -238588,7 +238769,7 @@ static int sessionApplyOneOp(
|
|
|
238588
238769
|
for(i=0; rc==SQLITE_OK && i<nCol; i++){
|
|
238589
238770
|
sqlite3_value *pOld = sessionChangesetOld(pIter, i);
|
|
238590
238771
|
sqlite3_value *pNew = sessionChangesetNew(pIter, i);
|
|
238591
|
-
if( p->abPK[i] ||
|
|
238772
|
+
if( pOld && (p->abPK[i] || bPatchset==0) ){
|
|
238592
238773
|
rc = sessionBindValue(pUp, i*2+2, pOld);
|
|
238593
238774
|
}
|
|
238594
238775
|
if( rc==SQLITE_OK && pNew ){
|
|
@@ -238714,7 +238895,264 @@ static int sessionApplyOneWithRetry(
|
|
|
238714
238895
|
}
|
|
238715
238896
|
|
|
238716
238897
|
/*
|
|
238717
|
-
**
|
|
238898
|
+
** Create an iterator to iterate through the retry buffer pRetry.
|
|
238899
|
+
*/
|
|
238900
|
+
static int sessionRetryIterInit(
|
|
238901
|
+
SessionBuffer *pRetry, /* Buffer to iterate through */
|
|
238902
|
+
int bPatchset, /* True for patchset, false for changeset */
|
|
238903
|
+
const char *zTab, /* Table name */
|
|
238904
|
+
SessionApplyCtx *pApply, /* Session apply context */
|
|
238905
|
+
sqlite3_changeset_iter **ppIter /* OUT: New iterator */
|
|
238906
|
+
){
|
|
238907
|
+
sqlite3_changeset_iter *pRet = 0;
|
|
238908
|
+
int rc = SQLITE_OK;
|
|
238909
|
+
|
|
238910
|
+
rc = sessionChangesetStart(
|
|
238911
|
+
&pRet, 0, 0, pRetry->nBuf, pRetry->aBuf, pApply->bInvertConstraints, 1
|
|
238912
|
+
);
|
|
238913
|
+
if( rc==SQLITE_OK ){
|
|
238914
|
+
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
|
|
238915
|
+
pRet->bPatchset = bPatchset;
|
|
238916
|
+
pRet->zTab = (char*)zTab;
|
|
238917
|
+
pRet->nCol = pApply->nCol;
|
|
238918
|
+
pRet->abPK = pApply->abPK;
|
|
238919
|
+
sessionBufferGrow(&pRet->tblhdr, nByte, &rc);
|
|
238920
|
+
pRet->apValue = (sqlite3_value**)pRet->tblhdr.aBuf;
|
|
238921
|
+
if( rc==SQLITE_OK ){
|
|
238922
|
+
memset(pRet->apValue, 0, nByte);
|
|
238923
|
+
}else{
|
|
238924
|
+
sqlite3changeset_finalize(pRet);
|
|
238925
|
+
pRet = 0;
|
|
238926
|
+
}
|
|
238927
|
+
}
|
|
238928
|
+
|
|
238929
|
+
*ppIter = pRet;
|
|
238930
|
+
return rc;
|
|
238931
|
+
}
|
|
238932
|
+
|
|
238933
|
+
/*
|
|
238934
|
+
** Attempt to apply all the changes in retry buffer pRetry to the database.
|
|
238935
|
+
** Except, if parameter iSkip is greater than or equal to 0, skip change
|
|
238936
|
+
** iSkip.
|
|
238937
|
+
*/
|
|
238938
|
+
static int sessionApplyRetryBuffer(
|
|
238939
|
+
SessionBuffer *pRetry, /* Buffer to apply changes from */
|
|
238940
|
+
int iSkip, /* If >=0, index of change to omit */
|
|
238941
|
+
sqlite3 *db, /* Database handle */
|
|
238942
|
+
int bPatchset, /* True for patchset, false for changeset */
|
|
238943
|
+
const char *zTab, /* Name of table to write to */
|
|
238944
|
+
SessionApplyCtx *pApply, /* Apply context */
|
|
238945
|
+
int(*xConflict)(void*, int, sqlite3_changeset_iter*),
|
|
238946
|
+
void *pCtx /* First argument passed to xConflict */
|
|
238947
|
+
){
|
|
238948
|
+
int rc = SQLITE_OK;
|
|
238949
|
+
int rc2 = SQLITE_OK;
|
|
238950
|
+
int ii = 0;
|
|
238951
|
+
sqlite3_changeset_iter *pIter = 0;
|
|
238952
|
+
|
|
238953
|
+
assert( pApply->constraints.nBuf==0 );
|
|
238954
|
+
|
|
238955
|
+
rc = sessionRetryIterInit(pRetry, bPatchset, zTab, pApply, &pIter);
|
|
238956
|
+
|
|
238957
|
+
for(ii=0; rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter); ii++){
|
|
238958
|
+
if( ii!=iSkip ){
|
|
238959
|
+
rc = sessionApplyOneWithRetry(db, pIter, pApply, xConflict, pCtx);
|
|
238960
|
+
}
|
|
238961
|
+
}
|
|
238962
|
+
|
|
238963
|
+
rc2 = sqlite3changeset_finalize(pIter);
|
|
238964
|
+
if( rc==SQLITE_OK ) rc = rc2;
|
|
238965
|
+
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
|
|
238966
|
+
|
|
238967
|
+
return rc;
|
|
238968
|
+
}
|
|
238969
|
+
|
|
238970
|
+
/*
|
|
238971
|
+
** Check if table zTab in the "main" database of db is a WITHOUT ROWID
|
|
238972
|
+
** table.
|
|
238973
|
+
**
|
|
238974
|
+
** If no error occurs, return SQLITE_OK and set output variable (*pbWR) to
|
|
238975
|
+
** true if zTab is a WITHOUT ROWID table, or false otherwise. Or, if an
|
|
238976
|
+
** error does occur, return an SQLite error code. The final value of (*pbWR)
|
|
238977
|
+
** is undefined in this case.
|
|
238978
|
+
*/
|
|
238979
|
+
static int sessionTableIsWithoutRowid(sqlite3 *db, const char *zTab, int *pbWR){
|
|
238980
|
+
sqlite3_stmt *pList = 0;
|
|
238981
|
+
char *zSql = 0;
|
|
238982
|
+
int rc = SQLITE_OK;
|
|
238983
|
+
|
|
238984
|
+
zSql = sqlite3_mprintf("PRAGMA table_list = %Q", zTab);
|
|
238985
|
+
if( zSql==0 ){
|
|
238986
|
+
rc = SQLITE_NOMEM;
|
|
238987
|
+
}else{
|
|
238988
|
+
rc = sqlite3_prepare_v2(db, zSql, -1, &pList, 0);
|
|
238989
|
+
sqlite3_free(zSql);
|
|
238990
|
+
}
|
|
238991
|
+
|
|
238992
|
+
if( rc==SQLITE_OK ){
|
|
238993
|
+
sqlite3_step(pList);
|
|
238994
|
+
*pbWR = sqlite3_column_int(pList, 4);
|
|
238995
|
+
rc = sqlite3_finalize(pList);
|
|
238996
|
+
}
|
|
238997
|
+
|
|
238998
|
+
return rc;
|
|
238999
|
+
}
|
|
239000
|
+
|
|
239001
|
+
/*
|
|
239002
|
+
** Iterator pUp points to an UPDATE change. This function deletes the
|
|
239003
|
+
** affected row from the database and creates an INSERT statement that
|
|
239004
|
+
** may be used to reinsert the row as it is after the UPDATE change
|
|
239005
|
+
** has been applied.
|
|
239006
|
+
**
|
|
239007
|
+
** If successful, SQLITE_OK is returned and output variable (*ppInsert)
|
|
239008
|
+
** is left pointing to a prepared INSERT statement. It is the responsibility
|
|
239009
|
+
** of the caller to eventually free this statement using sqlite3_finalize().
|
|
239010
|
+
** Or, if an error occurs, an SQLite error code is returned and (*ppInsert)
|
|
239011
|
+
** set to NULL. pApply->zErr may be set to an error message in this case.
|
|
239012
|
+
*/
|
|
239013
|
+
static int sessionUpdateToDeleteInsert(
|
|
239014
|
+
sqlite3 *db, /* Database to write to */
|
|
239015
|
+
const char *zTab, /* Table name */
|
|
239016
|
+
SessionApplyCtx *pApply, /* Apply context */
|
|
239017
|
+
sqlite3_changeset_iter *pUp, /* Iterator pointing to UPDATE change */
|
|
239018
|
+
sqlite3_stmt **ppInsert /* OUT: INSERT statement */
|
|
239019
|
+
){
|
|
239020
|
+
sqlite3_stmt *pRet = 0; /* The INSERT statement */
|
|
239021
|
+
sqlite3_stmt *pSelect = 0; /* SELECT to read current values of row */
|
|
239022
|
+
int rc = SQLITE_OK;
|
|
239023
|
+
int bWR = 0;
|
|
239024
|
+
|
|
239025
|
+
rc = sessionTableIsWithoutRowid(db, zTab, &bWR);
|
|
239026
|
+
if( rc==SQLITE_OK ){
|
|
239027
|
+
char *zSelect = 0;
|
|
239028
|
+
char *zInsert = 0;
|
|
239029
|
+
SessionBuffer cols = {0, 0, 0};
|
|
239030
|
+
SessionBuffer insbind = {0, 0, 0};
|
|
239031
|
+
SessionBuffer pkcols = {0, 0, 0};
|
|
239032
|
+
SessionBuffer selbind = {0, 0, 0};
|
|
239033
|
+
|
|
239034
|
+
const char *zComma = "";
|
|
239035
|
+
const char *zComma2 = "";
|
|
239036
|
+
int ii;
|
|
239037
|
+
for(ii=0; ii<pApply->nCol; ii++){
|
|
239038
|
+
sessionAppendStr(&cols, zComma, &rc);
|
|
239039
|
+
sessionAppendIdent(&cols, pApply->azCol[ii], &rc);
|
|
239040
|
+
sessionAppendStr(&insbind, zComma, &rc);
|
|
239041
|
+
sessionAppendStr(&insbind, "?", &rc);
|
|
239042
|
+
zComma = ", ";
|
|
239043
|
+
|
|
239044
|
+
if( pApply->abPK[ii] ){
|
|
239045
|
+
sessionAppendStr(&pkcols, zComma2, &rc);
|
|
239046
|
+
sessionAppendIdent(&pkcols, pApply->azCol[ii], &rc);
|
|
239047
|
+
sessionAppendStr(&selbind, zComma2, &rc);
|
|
239048
|
+
sessionAppendPrintf(&selbind, &rc, "?%d", ii+1);
|
|
239049
|
+
zComma2 = ", ";
|
|
239050
|
+
}
|
|
239051
|
+
}
|
|
239052
|
+
if( bWR==0 ){
|
|
239053
|
+
sessionAppendStr(&cols, zComma, &rc);
|
|
239054
|
+
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
|
239055
|
+
sessionAppendStr(&insbind, zComma, &rc);
|
|
239056
|
+
sessionAppendStr(&insbind, "?", &rc);
|
|
239057
|
+
}
|
|
239058
|
+
|
|
239059
|
+
if( rc==SQLITE_OK ){
|
|
239060
|
+
zSelect = sqlite3_mprintf("SELECT %s FROM %Q WHERE (%s) IS (%s)",
|
|
239061
|
+
cols.aBuf, zTab, pkcols.aBuf, selbind.aBuf
|
|
239062
|
+
);
|
|
239063
|
+
if( zSelect==0 ) rc = SQLITE_NOMEM;
|
|
239064
|
+
}
|
|
239065
|
+
if( rc==SQLITE_OK ){
|
|
239066
|
+
zInsert = sqlite3_mprintf("INSERT INTO %Q(%s) VALUES(%s)",
|
|
239067
|
+
zTab, cols.aBuf, insbind.aBuf
|
|
239068
|
+
);
|
|
239069
|
+
if( zInsert==0 ) rc = SQLITE_NOMEM;
|
|
239070
|
+
}
|
|
239071
|
+
|
|
239072
|
+
if( rc==SQLITE_OK ){
|
|
239073
|
+
rc = sessionPrepare(db, &pSelect, &pApply->zErr, zSelect);
|
|
239074
|
+
}
|
|
239075
|
+
if( rc==SQLITE_OK ){
|
|
239076
|
+
rc = sessionPrepare(db, &pRet, &pApply->zErr, zInsert);
|
|
239077
|
+
}
|
|
239078
|
+
|
|
239079
|
+
sqlite3_free(zSelect);
|
|
239080
|
+
sqlite3_free(zInsert);
|
|
239081
|
+
sqlite3_free(cols.aBuf);
|
|
239082
|
+
sqlite3_free(insbind.aBuf);
|
|
239083
|
+
sqlite3_free(pkcols.aBuf);
|
|
239084
|
+
sqlite3_free(selbind.aBuf);
|
|
239085
|
+
}
|
|
239086
|
+
|
|
239087
|
+
if( rc==SQLITE_OK ){
|
|
239088
|
+
rc = sessionBindRow(
|
|
239089
|
+
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pSelect
|
|
239090
|
+
);
|
|
239091
|
+
}
|
|
239092
|
+
|
|
239093
|
+
if( rc==SQLITE_OK && sqlite3_step(pSelect)==SQLITE_ROW ){
|
|
239094
|
+
int iCol;
|
|
239095
|
+
for(iCol=0; iCol<pApply->nCol; iCol++){
|
|
239096
|
+
sqlite3_value *pVal = pUp->apValue[iCol+pApply->nCol];
|
|
239097
|
+
if( pVal==0 ){
|
|
239098
|
+
pVal = sqlite3_column_value(pSelect, iCol);
|
|
239099
|
+
}
|
|
239100
|
+
rc = sqlite3_bind_value(pRet, iCol+1, pVal);
|
|
239101
|
+
}
|
|
239102
|
+
if( bWR==0 ){
|
|
239103
|
+
sqlite3_bind_int64(pRet, iCol+1, sqlite3_column_int64(pSelect, iCol));
|
|
239104
|
+
}
|
|
239105
|
+
}
|
|
239106
|
+
sessionFinalizeStmt(pSelect, &rc);
|
|
239107
|
+
|
|
239108
|
+
/* Delete the row from the database. */
|
|
239109
|
+
if( rc==SQLITE_OK ){
|
|
239110
|
+
rc = sessionBindRow(
|
|
239111
|
+
pUp, sqlite3changeset_old, pApply->nCol, pApply->abPK, pApply->pDelete
|
|
239112
|
+
);
|
|
239113
|
+
sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1);
|
|
239114
|
+
}
|
|
239115
|
+
if( rc==SQLITE_OK ){
|
|
239116
|
+
sqlite3_step(pApply->pDelete);
|
|
239117
|
+
rc = sqlite3_reset(pApply->pDelete);
|
|
239118
|
+
}
|
|
239119
|
+
|
|
239120
|
+
if( rc!=SQLITE_OK ){
|
|
239121
|
+
sqlite3_finalize(pRet);
|
|
239122
|
+
pRet = 0;
|
|
239123
|
+
}
|
|
239124
|
+
|
|
239125
|
+
*ppInsert = pRet;
|
|
239126
|
+
return rc;
|
|
239127
|
+
}
|
|
239128
|
+
|
|
239129
|
+
/*
|
|
239130
|
+
** Retry the changes accumulated in the pApply->constraints buffer. The
|
|
239131
|
+
** pApply->constraints buffer contains all changes to table zTab that
|
|
239132
|
+
** could not be applied due to SQLITE_CONSTRAINT errors. This function
|
|
239133
|
+
** attempts to apply them as follows:
|
|
239134
|
+
**
|
|
239135
|
+
** 1) It runs through the buffer and attempts to retry each change,
|
|
239136
|
+
** removing any that are successfully applied from the buffer. This
|
|
239137
|
+
** is repeated until no further progress can be made.
|
|
239138
|
+
**
|
|
239139
|
+
** 2) For each UPDATE change in the buffer, try the following in a
|
|
239140
|
+
** savepoint transaction:
|
|
239141
|
+
**
|
|
239142
|
+
** a) DELETE the affected row,
|
|
239143
|
+
** b) Attempt step (1) with remaining changes,
|
|
239144
|
+
** c) Attempt to INSERT a row equivalent to the one that would be
|
|
239145
|
+
** created by applying this UPDATE change.
|
|
239146
|
+
**
|
|
239147
|
+
** If the INSERT in (c) succeeds, the savepoint is committed and all
|
|
239148
|
+
** successfully applied changes are removed from the buffer. Step (2)
|
|
239149
|
+
** is then repeated.
|
|
239150
|
+
**
|
|
239151
|
+
** 3) Once step (2) has been attempted for each UPDATE in the change,
|
|
239152
|
+
** a final attempt is made to apply each remaining change. This time,
|
|
239153
|
+
** if an SQLITE_CONSTRAINT error is encountered, the conflict handler
|
|
239154
|
+
** is invoked and the user has to decide whether to omit the change
|
|
239155
|
+
** or rollback the entire _apply() operation.
|
|
238718
239156
|
*/
|
|
238719
239157
|
static int sessionRetryConstraints(
|
|
238720
239158
|
sqlite3 *db,
|
|
@@ -238725,41 +239163,101 @@ static int sessionRetryConstraints(
|
|
|
238725
239163
|
void *pCtx /* First argument passed to xConflict */
|
|
238726
239164
|
){
|
|
238727
239165
|
int rc = SQLITE_OK;
|
|
239166
|
+
int iUpdate = 0;
|
|
238728
239167
|
|
|
239168
|
+
/* Step (1) */
|
|
238729
239169
|
while( pApply->constraints.nBuf ){
|
|
238730
|
-
sqlite3_changeset_iter *pIter2 = 0;
|
|
238731
239170
|
SessionBuffer cons = pApply->constraints;
|
|
238732
239171
|
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
|
238733
239172
|
|
|
238734
|
-
rc =
|
|
238735
|
-
&
|
|
239173
|
+
rc = sessionApplyRetryBuffer(
|
|
239174
|
+
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
|
|
239175
|
+
);
|
|
239176
|
+
|
|
239177
|
+
sqlite3_free(cons.aBuf);
|
|
239178
|
+
if( rc!=SQLITE_OK ) break;
|
|
239179
|
+
|
|
239180
|
+
/* If no progress has been made this round, break out of the loop. */
|
|
239181
|
+
if( pApply->constraints.nBuf>=cons.nBuf ) break;
|
|
239182
|
+
}
|
|
239183
|
+
|
|
239184
|
+
/* Step (2) */
|
|
239185
|
+
while( rc==SQLITE_OK && pApply->constraints.nBuf && !pApply->bNoUpdateLoop ){
|
|
239186
|
+
SessionBuffer cons = {0, 0, 0};
|
|
239187
|
+
sqlite3_changeset_iter *pUp = 0;
|
|
239188
|
+
sqlite3_stmt *pInsert = 0;
|
|
239189
|
+
int iSkip = 0;
|
|
239190
|
+
|
|
239191
|
+
rc = sessionRetryIterInit(
|
|
239192
|
+
&pApply->constraints, bPatchset, zTab, pApply, &pUp
|
|
238736
239193
|
);
|
|
238737
239194
|
if( rc==SQLITE_OK ){
|
|
238738
|
-
|
|
238739
|
-
|
|
238740
|
-
|
|
238741
|
-
|
|
238742
|
-
|
|
238743
|
-
|
|
238744
|
-
|
|
238745
|
-
|
|
238746
|
-
|
|
239195
|
+
int iThis = -1;
|
|
239196
|
+
while( SQLITE_ROW==sqlite3changeset_next(pUp) ){
|
|
239197
|
+
if( pUp->op==SQLITE_UPDATE ) iThis++;
|
|
239198
|
+
if( iThis==iUpdate ) break;
|
|
239199
|
+
iSkip++;
|
|
239200
|
+
}
|
|
239201
|
+
if( iThis==iUpdate ){
|
|
239202
|
+
rc = sqlite3_exec(db, "SAVEPOINT update_op", 0, 0, 0);
|
|
239203
|
+
if( rc==SQLITE_OK ){
|
|
239204
|
+
rc = sessionUpdateToDeleteInsert(db, zTab, pApply, pUp, &pInsert);
|
|
239205
|
+
}
|
|
239206
|
+
}
|
|
239207
|
+
sqlite3changeset_finalize(pUp);
|
|
239208
|
+
if( iThis!=iUpdate ) break;
|
|
239209
|
+
}
|
|
239210
|
+
|
|
239211
|
+
if( rc==SQLITE_OK ){
|
|
239212
|
+
cons = pApply->constraints;
|
|
238747
239213
|
|
|
238748
|
-
while( rc==SQLITE_OK &&
|
|
238749
|
-
|
|
239214
|
+
while( rc==SQLITE_OK && pApply->constraints.nBuf>0 ){
|
|
239215
|
+
SessionBuffer app = pApply->constraints;
|
|
239216
|
+
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
|
239217
|
+
rc = sessionApplyRetryBuffer(
|
|
239218
|
+
&app, iSkip, db, bPatchset, zTab, pApply, xConflict, pCtx
|
|
239219
|
+
);
|
|
239220
|
+
if( app.aBuf!=cons.aBuf ){
|
|
239221
|
+
sqlite3_free(app.aBuf);
|
|
239222
|
+
}
|
|
239223
|
+
if( pApply->constraints.nBuf>=app.nBuf ){
|
|
239224
|
+
break;
|
|
239225
|
+
}
|
|
239226
|
+
iSkip = -1;
|
|
238750
239227
|
}
|
|
239228
|
+
}
|
|
238751
239229
|
|
|
238752
|
-
|
|
238753
|
-
|
|
239230
|
+
iUpdate++;
|
|
239231
|
+
if( rc==SQLITE_OK ){
|
|
239232
|
+
sqlite3_step(pInsert);
|
|
239233
|
+
rc = sqlite3_finalize(pInsert);
|
|
239234
|
+
if( rc==SQLITE_CONSTRAINT ){
|
|
239235
|
+
rc = sqlite3_exec(db, "ROLLBACK TO update_op", 0, 0, 0);
|
|
239236
|
+
sqlite3_free(pApply->constraints.aBuf);
|
|
239237
|
+
pApply->constraints = cons;
|
|
239238
|
+
memset(&cons, 0, sizeof(cons));
|
|
239239
|
+
}else if( rc==SQLITE_OK ){
|
|
239240
|
+
iUpdate = 0;
|
|
239241
|
+
}
|
|
239242
|
+
if( rc==SQLITE_OK ){
|
|
239243
|
+
rc = sqlite3_exec(db, "RELEASE update_op", 0, 0, 0);
|
|
239244
|
+
}
|
|
239245
|
+
}else{
|
|
239246
|
+
sqlite3_finalize(pInsert);
|
|
238754
239247
|
}
|
|
238755
|
-
assert( pApply->bDeferConstraints || pApply->constraints.nBuf==0 );
|
|
238756
239248
|
|
|
238757
239249
|
sqlite3_free(cons.aBuf);
|
|
238758
|
-
|
|
238759
|
-
|
|
238760
|
-
|
|
238761
|
-
|
|
238762
|
-
|
|
239250
|
+
}
|
|
239251
|
+
|
|
239252
|
+
/* Step (3) */
|
|
239253
|
+
if( rc==SQLITE_OK && pApply->constraints.nBuf ){
|
|
239254
|
+
SessionBuffer cons = pApply->constraints;
|
|
239255
|
+
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
|
|
239256
|
+
pApply->bDeferConstraints = 0;
|
|
239257
|
+
rc = sessionApplyRetryBuffer(
|
|
239258
|
+
&cons, -1, db, bPatchset, zTab, pApply, xConflict, pCtx
|
|
239259
|
+
);
|
|
239260
|
+
sqlite3_free(cons.aBuf);
|
|
238763
239261
|
}
|
|
238764
239262
|
|
|
238765
239263
|
return rc;
|
|
@@ -238813,6 +239311,7 @@ static int sessionChangesetApply(
|
|
|
238813
239311
|
sApply.bRebase = (ppRebase && pnRebase);
|
|
238814
239312
|
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
|
|
238815
239313
|
sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
|
|
239314
|
+
sApply.bNoUpdateLoop = !!(flags & SQLITE_CHANGESETAPPLY_NOUPDATELOOP);
|
|
238816
239315
|
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
|
|
238817
239316
|
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
|
|
238818
239317
|
}
|
|
@@ -240624,7 +241123,7 @@ SQLITE_API int sqlite3changegroup_change_blob(
|
|
|
240624
241123
|
const void *pVal,
|
|
240625
241124
|
int nVal
|
|
240626
241125
|
){
|
|
240627
|
-
sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + nVal;
|
|
241126
|
+
sqlite3_int64 nByte = 1 + sessionVarintLen(nVal) + (i64)nVal;
|
|
240628
241127
|
int rc = SQLITE_OK;
|
|
240629
241128
|
SessionBuffer *pBuf = 0;
|
|
240630
241129
|
|
|
@@ -251208,7 +251707,7 @@ static void fts5DataRelease(Fts5Data *pData){
|
|
|
251208
251707
|
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
|
|
251209
251708
|
Fts5Data *pRet = fts5DataRead(p, iRowid);
|
|
251210
251709
|
if( pRet ){
|
|
251211
|
-
if( pRet->
|
|
251710
|
+
if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
|
|
251212
251711
|
FTS5_CORRUPT_ROWID(p, iRowid);
|
|
251213
251712
|
fts5DataRelease(pRet);
|
|
251214
251713
|
pRet = 0;
|
|
@@ -252862,6 +253361,10 @@ static void fts5LeafSeek(
|
|
|
252862
253361
|
if( nKeep<nMatch ){
|
|
252863
253362
|
goto search_failed;
|
|
252864
253363
|
}
|
|
253364
|
+
if( (iOff+nNew)>n ){
|
|
253365
|
+
FTS5_CORRUPT_ITER(p, pIter);
|
|
253366
|
+
return;
|
|
253367
|
+
}
|
|
252865
253368
|
|
|
252866
253369
|
assert( nKeep>=nMatch );
|
|
252867
253370
|
if( nKeep==nMatch ){
|
|
@@ -253838,8 +254341,7 @@ static void fts5PoslistFilterCallback(
|
|
|
253838
254341
|
|
|
253839
254342
|
do {
|
|
253840
254343
|
while( i<nChunk && pChunk[i]!=0x01 ){
|
|
253841
|
-
|
|
253842
|
-
i++;
|
|
254344
|
+
fts5IndexSkipVarint(pChunk, i);
|
|
253843
254345
|
}
|
|
253844
254346
|
if( pCtx->eState ){
|
|
253845
254347
|
fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
|
|
@@ -253988,7 +254490,7 @@ static void fts5IndexExtractColset(
|
|
|
253988
254490
|
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
|
|
253989
254491
|
** not part of a varint */
|
|
253990
254492
|
while( p<pEnd && *p!=0x01 ){
|
|
253991
|
-
while( *p++ & 0x80 );
|
|
254493
|
+
while( p<pEnd && (*p++ & 0x80) );
|
|
253992
254494
|
}
|
|
253993
254495
|
|
|
253994
254496
|
if( pColset->aiCol[i]==iCurrent ){
|
|
@@ -254085,8 +254587,11 @@ static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
|
|
|
254085
254587
|
|
|
254086
254588
|
assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
|
|
254087
254589
|
assert( pIter->pColset );
|
|
254590
|
+
assert( pIter->poslist.nSpace>=pIter->pIndex->pConfig->nCol );
|
|
254088
254591
|
|
|
254089
|
-
if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf
|
|
254592
|
+
if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf
|
|
254593
|
+
|| pSeg->nPos>pIter->pIndex->pConfig->nCol
|
|
254594
|
+
){
|
|
254090
254595
|
fts5IterSetOutputs_Col(pIter, pSeg);
|
|
254091
254596
|
}else{
|
|
254092
254597
|
u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
|
|
@@ -255580,6 +256085,11 @@ static void fts5DoSecureDelete(
|
|
|
255580
256085
|
}else{
|
|
255581
256086
|
iStart = fts5GetU16(&aPg[0]);
|
|
255582
256087
|
}
|
|
256088
|
+
if( iStart>nPg ){
|
|
256089
|
+
FTS5_CORRUPT_IDX(p);
|
|
256090
|
+
sqlite3_free(aIdx);
|
|
256091
|
+
return;
|
|
256092
|
+
}
|
|
255583
256093
|
|
|
255584
256094
|
iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
|
|
255585
256095
|
assert_nc( iSOP<=pSeg->iLeafOffset );
|
|
@@ -263456,7 +263966,7 @@ static void fts5SourceIdFunc(
|
|
|
263456
263966
|
){
|
|
263457
263967
|
assert( nArg==0 );
|
|
263458
263968
|
UNUSED_PARAM2(nArg, apUnused);
|
|
263459
|
-
sqlite3_result_text(pCtx, "fts5: 2026-
|
|
263969
|
+
sqlite3_result_text(pCtx, "fts5: 2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24", -1, SQLITE_TRANSIENT);
|
|
263460
263970
|
}
|
|
263461
263971
|
|
|
263462
263972
|
/*
|
|
@@ -265850,8 +266360,14 @@ static int fts5PorterCreate(
|
|
|
265850
266360
|
const char *zBase = "unicode61";
|
|
265851
266361
|
fts5_tokenizer_v2 *pV2 = 0;
|
|
265852
266362
|
|
|
265853
|
-
|
|
265854
|
-
|
|
266363
|
+
while( nArg>0 ){
|
|
266364
|
+
if( sqlite3_stricmp(azArg[0],"porter")==0 ){
|
|
266365
|
+
nArg--;
|
|
266366
|
+
azArg++;
|
|
266367
|
+
}else{
|
|
266368
|
+
zBase = azArg[0];
|
|
266369
|
+
break;
|
|
266370
|
+
}
|
|
265855
266371
|
}
|
|
265856
266372
|
|
|
265857
266373
|
pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer));
|
|
@@ -269307,9 +269823,9 @@ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
|
|
|
269307
269823
|
|
|
269308
269824
|
#define SQLITE3MC_VERSION_MAJOR 2
|
|
269309
269825
|
#define SQLITE3MC_VERSION_MINOR 3
|
|
269310
|
-
#define SQLITE3MC_VERSION_RELEASE
|
|
269826
|
+
#define SQLITE3MC_VERSION_RELEASE 5
|
|
269311
269827
|
#define SQLITE3MC_VERSION_SUBRELEASE 0
|
|
269312
|
-
#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 2.3.
|
|
269828
|
+
#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 2.3.5"
|
|
269313
269829
|
|
|
269314
269830
|
#endif /* SQLITE3MC_VERSION_H_ */
|
|
269315
269831
|
/*** End of #include "sqlite3mc_version.h" ***/
|
|
@@ -269468,12 +269984,12 @@ extern "C" {
|
|
|
269468
269984
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
269469
269985
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
269470
269986
|
*/
|
|
269471
|
-
#define SQLITE_VERSION "3.53.
|
|
269472
|
-
#define SQLITE_VERSION_NUMBER
|
|
269473
|
-
#define SQLITE_SOURCE_ID "2026-
|
|
269987
|
+
#define SQLITE_VERSION "3.53.2"
|
|
269988
|
+
#define SQLITE_VERSION_NUMBER 3053002
|
|
269989
|
+
#define SQLITE_SOURCE_ID "2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24"
|
|
269474
269990
|
#define SQLITE_SCM_BRANCH "branch-3.53"
|
|
269475
|
-
#define SQLITE_SCM_TAGS "release version-3.53.
|
|
269476
|
-
#define SQLITE_SCM_DATETIME "2026-
|
|
269991
|
+
#define SQLITE_SCM_TAGS "release version-3.53.2"
|
|
269992
|
+
#define SQLITE_SCM_DATETIME "2026-06-03T19:12:13.350Z"
|
|
269477
269993
|
|
|
269478
269994
|
/*
|
|
269479
269995
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
@@ -282175,11 +282691,23 @@ SQLITE_API int sqlite3changeset_apply_v3(
|
|
|
282175
282691
|
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
|
282176
282692
|
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
|
282177
282693
|
** or SET DEFAULT.
|
|
282694
|
+
**
|
|
282695
|
+
** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
|
|
282696
|
+
** Sometimes, a changeset contains two or more update statements such that
|
|
282697
|
+
** although after applying all updates the database will contain no
|
|
282698
|
+
** constraint violations, no single update can be applied before the others.
|
|
282699
|
+
** The simplest example of this is a pair of UPDATEs that have "swapped"
|
|
282700
|
+
** two column values with a UNIQUE constraint.
|
|
282701
|
+
** <p>
|
|
282702
|
+
** Usually, sqlite3changeset_apply() and similar functions work hard to try
|
|
282703
|
+
** to find a way to apply such a changeset. However, if this flag is set,
|
|
282704
|
+
** then all such updates are considered CONSTRAINT conflicts.
|
|
282178
282705
|
*/
|
|
282179
282706
|
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
|
282180
282707
|
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
|
282181
282708
|
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
|
282182
282709
|
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
|
282710
|
+
#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010
|
|
282183
282711
|
|
|
282184
282712
|
/*
|
|
282185
282713
|
** CAPI3REF: Constants Passed To The Conflict Handler
|
|
@@ -338118,7 +338646,7 @@ sqlite3mcBtreeSetPageSize(Btree* p, int pageSize, int nReserve, int iFix)
|
|
|
338118
338646
|
** Change 4: Call sqlite3mcBtreeSetPageSize instead of sqlite3BtreeSetPageSize for main database
|
|
338119
338647
|
** (sqlite3mcBtreeSetPageSize allows to reduce the number of reserved bytes)
|
|
338120
338648
|
**
|
|
338121
|
-
** This code is generated by the script rekeyvacuum.sh from SQLite version 3.53.
|
|
338649
|
+
** This code is generated by the script rekeyvacuum.sh from SQLite version 3.53.2 amalgamation.
|
|
338122
338650
|
*/
|
|
338123
338651
|
SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey(
|
|
338124
338652
|
char **pzErrMsg, /* Write error message here */
|
|
@@ -347868,7 +348396,7 @@ static int seriesFilter(
|
|
|
347868
348396
|
if( r<(double)SMALLEST_INT64 ){
|
|
347869
348397
|
iMin = SMALLEST_INT64;
|
|
347870
348398
|
}else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){
|
|
347871
|
-
iMin = (sqlite3_int64)seriesCeil(r+1
|
|
348399
|
+
iMin = (sqlite3_int64)seriesCeil(r)+1;
|
|
347872
348400
|
}else{
|
|
347873
348401
|
iMin = (sqlite3_int64)seriesCeil(r);
|
|
347874
348402
|
}
|
|
@@ -347889,7 +348417,7 @@ static int seriesFilter(
|
|
|
347889
348417
|
if( r>(double)LARGEST_INT64 ){
|
|
347890
348418
|
iMax = LARGEST_INT64;
|
|
347891
348419
|
}else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){
|
|
347892
|
-
iMax = (sqlite3_int64)
|
|
348420
|
+
iMax = ((sqlite3_int64)r)-1;
|
|
347893
348421
|
}else{
|
|
347894
348422
|
iMax = (sqlite3_int64)seriesFloor(r);
|
|
347895
348423
|
}
|
|
@@ -358655,6 +359183,10 @@ static void compressFunc(
|
|
|
358655
359183
|
nIn = sqlite3_value_bytes(argv[0]);
|
|
358656
359184
|
nOut = 13 + nIn + (nIn+999)/1000;
|
|
358657
359185
|
pOut = sqlite3_malloc64( nOut+5 );
|
|
359186
|
+
if( pOut==0 ){
|
|
359187
|
+
sqlite3_result_error_nomem(context);
|
|
359188
|
+
return;
|
|
359189
|
+
}
|
|
358658
359190
|
for(i=4; i>=0; i--){
|
|
358659
359191
|
x[i] = (nIn >> (7*(4-i)))&0x7f;
|
|
358660
359192
|
}
|
|
@@ -358694,6 +359226,10 @@ static void uncompressFunc(
|
|
|
358694
359226
|
if( (pIn[i]&0x80)!=0 ){ i++; break; }
|
|
358695
359227
|
}
|
|
358696
359228
|
pOut = sqlite3_malloc64( nOut+1 );
|
|
359229
|
+
if( pOut==0 ){
|
|
359230
|
+
sqlite3_result_error_nomem(context);
|
|
359231
|
+
return;
|
|
359232
|
+
}
|
|
358697
359233
|
rc = uncompress(pOut, &nOut, &pIn[i], nIn-i);
|
|
358698
359234
|
if( rc==Z_OK ){
|
|
358699
359235
|
sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
|
|
@@ -359369,6 +359905,7 @@ static void zipfileResetCursor(ZipfileCsr *pCsr){
|
|
|
359369
359905
|
pNext = p->pNext;
|
|
359370
359906
|
zipfileEntryFree(p);
|
|
359371
359907
|
}
|
|
359908
|
+
pCsr->pFreeEntry = 0;
|
|
359372
359909
|
}
|
|
359373
359910
|
|
|
359374
359911
|
/*
|
|
@@ -359771,7 +360308,13 @@ static int zipfileGetEntry(
|
|
|
359771
360308
|
|
|
359772
360309
|
if( rc==SQLITE_OK ){
|
|
359773
360310
|
u32 *pt = &pNew->mUnixTime;
|
|
359774
|
-
|
|
360311
|
+
/* aRead[0..nFile-1] might contain embedded \000 characters
|
|
360312
|
+
** See Bug 2026-05-31T11:43:05Z */
|
|
360313
|
+
pNew->cds.zFile = sqlite3_malloc64(nFile+1);
|
|
360314
|
+
if( pNew->cds.zFile!=0 ){
|
|
360315
|
+
memcpy(pNew->cds.zFile, aRead, nFile);
|
|
360316
|
+
pNew->cds.zFile[nFile] = 0;
|
|
360317
|
+
}
|
|
359775
360318
|
pNew->aExtra = (u8*)&pNew[1];
|
|
359776
360319
|
memcpy(pNew->aExtra, &aRead[nFile], nExtra);
|
|
359777
360320
|
if( pNew->cds.zFile==0 ){
|
|
@@ -360875,10 +361418,10 @@ struct ZipfileCtx {
|
|
|
360875
361418
|
};
|
|
360876
361419
|
|
|
360877
361420
|
static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){
|
|
360878
|
-
if( pBuf->n
|
|
361421
|
+
if( (pBuf->nAlloc-pBuf->n)<nByte ){
|
|
360879
361422
|
u8 *aNew;
|
|
360880
|
-
|
|
360881
|
-
|
|
361423
|
+
i64 nNew = pBuf->n ? (i64)pBuf->n*2 : 512;
|
|
361424
|
+
i64 nReq = pBuf->n + nByte;
|
|
360882
361425
|
|
|
360883
361426
|
while( nNew<nReq ) nNew = nNew*2;
|
|
360884
361427
|
aNew = sqlite3_realloc64(pBuf->a, nNew);
|
|
@@ -363297,6 +363840,15 @@ sqlite3mc_shutdown(void)
|
|
|
363297
363840
|
/* Forward declaration */
|
|
363298
363841
|
typedef struct SqliteDb SqliteDb;
|
|
363299
363842
|
|
|
363843
|
+
/* Add -DSQLITE_ENABLE_QRF_IN_TCL to add the Query Result Formatter (QRF)
|
|
363844
|
+
** into the build of the TCL extension, when building using separate
|
|
363845
|
+
** source files. The QRF is included automatically when building from
|
|
363846
|
+
** the tclsqlite3.c amalgamation.
|
|
363847
|
+
*/
|
|
363848
|
+
#if defined(SQLITE_ENABLE_QRF_IN_TCL)
|
|
363849
|
+
#include "qrf.h"
|
|
363850
|
+
#endif
|
|
363851
|
+
|
|
363300
363852
|
/*
|
|
363301
363853
|
** New SQL functions can be created as TCL scripts. Each such function
|
|
363302
363854
|
** is described by an instance of the following structure.
|
|
@@ -365208,6 +365760,376 @@ static void DbHookCmd(
|
|
|
365208
365760
|
sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb);
|
|
365209
365761
|
}
|
|
365210
365762
|
|
|
365763
|
+
/*
|
|
365764
|
+
** Implementation of the "db format" command.
|
|
365765
|
+
**
|
|
365766
|
+
** Based on provided options, format the results of the SQL statement(s)
|
|
365767
|
+
** provided into human-readable form using the Query Result Formatter (QRF)
|
|
365768
|
+
** and return the resuling text.
|
|
365769
|
+
**
|
|
365770
|
+
** Syntax: db format OPTIONS SQL
|
|
365771
|
+
**
|
|
365772
|
+
** OPTIONS may be:
|
|
365773
|
+
**
|
|
365774
|
+
** -style ("auto"|"box"|"column"|...) Output style
|
|
365775
|
+
** -esc ("auto"|"off"|"ascii"|"symbol") How to deal with ctrl chars
|
|
365776
|
+
** -text ("auto"|"off"|"sql"|"csv"|...) How to escape TEXT values
|
|
365777
|
+
** -title ("auto"|"off"|"sql"|...|"off") How to escape column names
|
|
365778
|
+
** -blob ("auto"|"text"|"sql"|...) How to escape BLOB values
|
|
365779
|
+
** -wordwrap ("auto"|"off"|"on") Try to wrap at word boundry?
|
|
365780
|
+
** -textjsonb ("auto"|"off"|"on") Auto-convert JSONB to text?
|
|
365781
|
+
** -splitcolumn ("auto"|"off"|"on") Enable split-column mode
|
|
365782
|
+
** -defaultalign ("auto"|"left"|...) Default alignment
|
|
365783
|
+
** -titalalign ("auto"|"left"|"right"|...) Default column name alignment
|
|
365784
|
+
** -border ("auto"|"off"|"on") Border for box and table styles
|
|
365785
|
+
** -wrap NUMBER Max width of any single column
|
|
365786
|
+
** -screenwidth NUMBER Width of the display TTY
|
|
365787
|
+
** -linelimit NUMBER Max lines for any cell
|
|
365788
|
+
** -charlimit NUMBER Content truncated to this size
|
|
365789
|
+
** -titlelimit NUMBER Max width of column titles
|
|
365790
|
+
** -multiinsert NUMBER Multi-row INSERT byte size
|
|
365791
|
+
** -align LIST-OF-ALIGNMENT Alignment of columns
|
|
365792
|
+
** -widths LIST-OF-NUMBERS Widths for individual columns
|
|
365793
|
+
** -columnsep TEXT Column separator text
|
|
365794
|
+
** -rowsep TEXT Row separator text
|
|
365795
|
+
** -tablename TEXT Table name for style "insert"
|
|
365796
|
+
** -null TEXT Text for NULL values
|
|
365797
|
+
**
|
|
365798
|
+
** A mapping from TCL "format" command options to sqlite3_qrf_spec fields
|
|
365799
|
+
** is below. Use this to reference the QRF documentation:
|
|
365800
|
+
**
|
|
365801
|
+
** TCL Option spec field
|
|
365802
|
+
** ---------- ----------
|
|
365803
|
+
** -style eStyle
|
|
365804
|
+
** -esc eEsc
|
|
365805
|
+
** -text eText
|
|
365806
|
+
** -title eTitle, bTitle
|
|
365807
|
+
** -blob eBlob
|
|
365808
|
+
** -wordwrap bWordWrap
|
|
365809
|
+
** -textjsonb bTextJsonb
|
|
365810
|
+
** -splitcolumn bSplitColumn
|
|
365811
|
+
** -defaultalign eDfltAlign
|
|
365812
|
+
** -titlealign eTitleAlign
|
|
365813
|
+
** -border bBorder
|
|
365814
|
+
** -wrap nWrap
|
|
365815
|
+
** -screenwidth nScreenWidth
|
|
365816
|
+
** -linelimit nLineLimit
|
|
365817
|
+
** -charlimit nCharLimit
|
|
365818
|
+
** -titlelimit nTitleLimit
|
|
365819
|
+
** -multiinsert nMultiInsert
|
|
365820
|
+
** -align nAlign, aAlign
|
|
365821
|
+
** -widths nWidth, aWidth
|
|
365822
|
+
** -columnsep zColumnSep
|
|
365823
|
+
** -rowsep zRowSep
|
|
365824
|
+
** -tablename zTableName
|
|
365825
|
+
** -null zNull
|
|
365826
|
+
*/
|
|
365827
|
+
static int dbQrf(SqliteDb *pDb, int objc, Tcl_Obj *const*objv){
|
|
365828
|
+
#ifndef SQLITE_QRF_H
|
|
365829
|
+
Tcl_SetResult(pDb->interp, "QRF not available in this build", TCL_VOLATILE);
|
|
365830
|
+
return TCL_ERROR;
|
|
365831
|
+
#else
|
|
365832
|
+
char *zResult = 0; /* Result to be returned */
|
|
365833
|
+
const char *zSql = 0; /* SQL to run */
|
|
365834
|
+
int i; /* Loop counter */
|
|
365835
|
+
int rc; /* Result code */
|
|
365836
|
+
sqlite3_qrf_spec qrf; /* Formatting spec */
|
|
365837
|
+
static const char *azAlign[] = {
|
|
365838
|
+
"auto", "bottom", "c",
|
|
365839
|
+
"center", "e", "left",
|
|
365840
|
+
"middle", "n", "ne",
|
|
365841
|
+
"nw", "right", "s",
|
|
365842
|
+
"se", "sw", "top",
|
|
365843
|
+
"w", 0
|
|
365844
|
+
};
|
|
365845
|
+
static const unsigned char aAlignMap[] = {
|
|
365846
|
+
QRF_ALIGN_Auto, QRF_ALIGN_Bottom, QRF_ALIGN_C,
|
|
365847
|
+
QRF_ALIGN_Center, QRF_ALIGN_E, QRF_ALIGN_Left,
|
|
365848
|
+
QRF_ALIGN_Middle, QRF_ALIGN_N, QRF_ALIGN_NE,
|
|
365849
|
+
QRF_ALIGN_NW, QRF_ALIGN_Right, QRF_ALIGN_S,
|
|
365850
|
+
QRF_ALIGN_SE, QRF_ALIGN_SW, QRF_ALIGN_Top,
|
|
365851
|
+
QRF_ALIGN_W
|
|
365852
|
+
};
|
|
365853
|
+
|
|
365854
|
+
memset(&qrf, 0, sizeof(qrf));
|
|
365855
|
+
qrf.iVersion = 1;
|
|
365856
|
+
qrf.pzOutput = &zResult;
|
|
365857
|
+
for(i=2; i<objc; i++){
|
|
365858
|
+
const char *zArg = Tcl_GetString(objv[i]);
|
|
365859
|
+
const char *azBool[] = { "auto", "yes", "no", "on", "off", 0 };
|
|
365860
|
+
const unsigned char aBoolMap[] = { 0, 2, 1, 2, 1 };
|
|
365861
|
+
if( zArg[0]!='-' ){
|
|
365862
|
+
if( zSql ){
|
|
365863
|
+
Tcl_AppendResult(pDb->interp, "unknown argument: ", zArg, (char*)0);
|
|
365864
|
+
rc = TCL_ERROR;
|
|
365865
|
+
goto format_failed;
|
|
365866
|
+
}
|
|
365867
|
+
zSql = zArg;
|
|
365868
|
+
}else if( i==objc-1 ){
|
|
365869
|
+
Tcl_AppendResult(pDb->interp, "option has no argument: ", zArg, (char*)0);
|
|
365870
|
+
rc = TCL_ERROR;
|
|
365871
|
+
goto format_failed;
|
|
365872
|
+
}else if( strcmp(zArg,"-style")==0 ){
|
|
365873
|
+
static const char *azStyles[] = {
|
|
365874
|
+
"auto", "box", "column",
|
|
365875
|
+
"count", "csv", "eqp",
|
|
365876
|
+
"explain", "html", "insert",
|
|
365877
|
+
"jobject", "json", "line",
|
|
365878
|
+
"list", "markdown", "quote",
|
|
365879
|
+
"stats", "stats-est", "stats-vm",
|
|
365880
|
+
"table", 0
|
|
365881
|
+
};
|
|
365882
|
+
static unsigned char aStyleMap[] = {
|
|
365883
|
+
QRF_STYLE_Auto, QRF_STYLE_Box, QRF_STYLE_Column,
|
|
365884
|
+
QRF_STYLE_Count, QRF_STYLE_Csv, QRF_STYLE_Eqp,
|
|
365885
|
+
QRF_STYLE_Explain, QRF_STYLE_Html, QRF_STYLE_Insert,
|
|
365886
|
+
QRF_STYLE_JObject, QRF_STYLE_Json, QRF_STYLE_Line,
|
|
365887
|
+
QRF_STYLE_List, QRF_STYLE_Markdown, QRF_STYLE_Quote,
|
|
365888
|
+
QRF_STYLE_Stats, QRF_STYLE_StatsEst, QRF_STYLE_StatsVm,
|
|
365889
|
+
QRF_STYLE_Table
|
|
365890
|
+
};
|
|
365891
|
+
int style;
|
|
365892
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azStyles,
|
|
365893
|
+
"format style (-style)", 0, &style);
|
|
365894
|
+
if( rc ) goto format_failed;
|
|
365895
|
+
qrf.eStyle = aStyleMap[style];
|
|
365896
|
+
i++;
|
|
365897
|
+
}else if( strcmp(zArg,"-esc")==0 ){
|
|
365898
|
+
static const char *azEsc[] = {
|
|
365899
|
+
"ascii", "auto", "off", "symbol", 0
|
|
365900
|
+
};
|
|
365901
|
+
static unsigned char aEscMap[] = {
|
|
365902
|
+
QRF_ESC_Ascii, QRF_ESC_Auto, QRF_ESC_Off, QRF_ESC_Symbol
|
|
365903
|
+
};
|
|
365904
|
+
int esc;
|
|
365905
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azEsc,
|
|
365906
|
+
"control character escape (-esc)", 0, &esc);
|
|
365907
|
+
if( rc ) goto format_failed;
|
|
365908
|
+
qrf.eEsc = aEscMap[esc];
|
|
365909
|
+
i++;
|
|
365910
|
+
}else if( strcmp(zArg,"-text")==0 || strcmp(zArg, "-title")==0 ){
|
|
365911
|
+
/* NB: --title can be "off" or "on but --text may not be. Thus we put
|
|
365912
|
+
** the "off" and "on" choices first and start the search on the
|
|
365913
|
+
** thrid element of the array when processing --text */
|
|
365914
|
+
static const char *azText[] = { "off", "on",
|
|
365915
|
+
"auto", "csv", "html",
|
|
365916
|
+
"json", "plain", "relaxed",
|
|
365917
|
+
"sql", "tcl", 0
|
|
365918
|
+
};
|
|
365919
|
+
static unsigned char aTextMap[] = {
|
|
365920
|
+
QRF_TEXT_Auto, QRF_TEXT_Csv, QRF_TEXT_Html,
|
|
365921
|
+
QRF_TEXT_Json, QRF_TEXT_Plain, QRF_TEXT_Relaxed,
|
|
365922
|
+
QRF_TEXT_Sql, QRF_TEXT_Tcl
|
|
365923
|
+
};
|
|
365924
|
+
int txt;
|
|
365925
|
+
int k = zArg[2]=='e';
|
|
365926
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], &azText[k*2], zArg,
|
|
365927
|
+
0, &txt);
|
|
365928
|
+
if( rc ) goto format_failed;
|
|
365929
|
+
if( k ){
|
|
365930
|
+
qrf.eText = aTextMap[txt];
|
|
365931
|
+
}else if( txt<=1 ){
|
|
365932
|
+
qrf.bTitles = txt ? QRF_Yes : QRF_No;
|
|
365933
|
+
qrf.eTitle = QRF_TEXT_Auto;
|
|
365934
|
+
}else{
|
|
365935
|
+
qrf.bTitles = QRF_Yes;
|
|
365936
|
+
qrf.eTitle = aTextMap[txt-2];
|
|
365937
|
+
}
|
|
365938
|
+
i++;
|
|
365939
|
+
}else if( strcmp(zArg,"-blob")==0 ){
|
|
365940
|
+
static const char *azBlob[] = {
|
|
365941
|
+
"auto", "hex", "json",
|
|
365942
|
+
"tcl", "text", "sql",
|
|
365943
|
+
"size", 0
|
|
365944
|
+
};
|
|
365945
|
+
static unsigned char aBlobMap[] = {
|
|
365946
|
+
QRF_BLOB_Auto, QRF_BLOB_Hex, QRF_BLOB_Json,
|
|
365947
|
+
QRF_BLOB_Tcl, QRF_BLOB_Text, QRF_BLOB_Sql,
|
|
365948
|
+
QRF_BLOB_Size
|
|
365949
|
+
};
|
|
365950
|
+
int blob;
|
|
365951
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBlob,
|
|
365952
|
+
"BLOB encoding (-blob)", 0, &blob);
|
|
365953
|
+
if( rc ) goto format_failed;
|
|
365954
|
+
qrf.eBlob = aBlobMap[blob];
|
|
365955
|
+
i++;
|
|
365956
|
+
}else if( strcmp(zArg,"-wordwrap")==0 ){
|
|
365957
|
+
int v = 0;
|
|
365958
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
|
|
365959
|
+
"-wordwrap", 0, &v);
|
|
365960
|
+
if( rc ) goto format_failed;
|
|
365961
|
+
qrf.bWordWrap = aBoolMap[v];
|
|
365962
|
+
i++;
|
|
365963
|
+
}else if( strcmp(zArg,"-textjsonb")==0
|
|
365964
|
+
|| strcmp(zArg,"-splitcolumn")==0
|
|
365965
|
+
|| strcmp(zArg,"-border")==0
|
|
365966
|
+
){
|
|
365967
|
+
int v = 0;
|
|
365968
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azBool,
|
|
365969
|
+
zArg, 0, &v);
|
|
365970
|
+
if( rc ) goto format_failed;
|
|
365971
|
+
if( zArg[1]=='t' ){
|
|
365972
|
+
qrf.bTextJsonb = aBoolMap[v];
|
|
365973
|
+
}else if( zArg[1]=='b' ){
|
|
365974
|
+
qrf.bBorder = aBoolMap[v];
|
|
365975
|
+
}else{
|
|
365976
|
+
qrf.bSplitColumn = aBoolMap[v];
|
|
365977
|
+
}
|
|
365978
|
+
i++;
|
|
365979
|
+
}else if( strcmp(zArg,"-defaultalign")==0 || strcmp(zArg,"-titlealign")==0){
|
|
365980
|
+
int ax = 0;
|
|
365981
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, objv[i+1], azAlign,
|
|
365982
|
+
zArg[1]=='d' ? "default alignment (-defaultalign)" :
|
|
365983
|
+
"title alignment (-titlealign)",
|
|
365984
|
+
0, &ax);
|
|
365985
|
+
if( rc ) goto format_failed;
|
|
365986
|
+
if( zArg[1]=='d' ){
|
|
365987
|
+
qrf.eDfltAlign = aAlignMap[ax];
|
|
365988
|
+
}else{
|
|
365989
|
+
qrf.eTitleAlign = aAlignMap[ax];
|
|
365990
|
+
}
|
|
365991
|
+
i++;
|
|
365992
|
+
}else if( strcmp(zArg,"-wrap")==0
|
|
365993
|
+
|| strcmp(zArg,"-screenwidth")==0
|
|
365994
|
+
|| strcmp(zArg,"-linelimit")==0
|
|
365995
|
+
|| strcmp(zArg,"-titlelimit")==0
|
|
365996
|
+
){
|
|
365997
|
+
int v = 0;
|
|
365998
|
+
rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
|
|
365999
|
+
if( rc ) goto format_failed;
|
|
366000
|
+
if( v<QRF_MIN_WIDTH ){
|
|
366001
|
+
v = QRF_MIN_WIDTH;
|
|
366002
|
+
}else if( v>QRF_MAX_WIDTH ){
|
|
366003
|
+
v = QRF_MAX_WIDTH;
|
|
366004
|
+
}
|
|
366005
|
+
if( zArg[1]=='w' ){
|
|
366006
|
+
qrf.nWrap = v;
|
|
366007
|
+
}else if( zArg[1]=='s' ){
|
|
366008
|
+
qrf.nScreenWidth = v;
|
|
366009
|
+
}else if( zArg[1]=='t' ){
|
|
366010
|
+
qrf.nTitleLimit = v;
|
|
366011
|
+
}else{
|
|
366012
|
+
qrf.nLineLimit = v;
|
|
366013
|
+
}
|
|
366014
|
+
i++;
|
|
366015
|
+
}else if( strcmp(zArg,"-charlimit")==0 ){
|
|
366016
|
+
int v = 0;
|
|
366017
|
+
rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
|
|
366018
|
+
if( rc ) goto format_failed;
|
|
366019
|
+
if( v<0 ) v = 0;
|
|
366020
|
+
qrf.nCharLimit = v;
|
|
366021
|
+
i++;
|
|
366022
|
+
}else if( strcmp(zArg,"-multiinsert")==0 ){
|
|
366023
|
+
int v = 0;
|
|
366024
|
+
rc = Tcl_GetIntFromObj(pDb->interp, objv[i+1], &v);
|
|
366025
|
+
if( rc ) goto format_failed;
|
|
366026
|
+
if( v<0 ) v = 0;
|
|
366027
|
+
qrf.nMultiInsert = v;
|
|
366028
|
+
i++;
|
|
366029
|
+
}else if( strcmp(zArg,"-align")==0 ){
|
|
366030
|
+
Tcl_Size n = 0;
|
|
366031
|
+
int jj;
|
|
366032
|
+
rc = Tcl_ListObjLength(pDb->interp, objv[i+1], &n);
|
|
366033
|
+
if( rc ) goto format_failed;
|
|
366034
|
+
sqlite3_free(qrf.aAlign);
|
|
366035
|
+
qrf.aAlign = sqlite3_malloc64( (n+1)*sizeof(qrf.aAlign[0]) );
|
|
366036
|
+
if( qrf.aAlign==0 ){
|
|
366037
|
+
Tcl_AppendResult(pDb->interp, "out of memory", (char*)0);
|
|
366038
|
+
rc = TCL_ERROR;
|
|
366039
|
+
goto format_failed;
|
|
366040
|
+
}
|
|
366041
|
+
memset(qrf.aAlign, 0, (n+1)*sizeof(qrf.aAlign[0]));
|
|
366042
|
+
qrf.nAlign = n;
|
|
366043
|
+
for(jj=0; jj<n; jj++){
|
|
366044
|
+
int x;
|
|
366045
|
+
Tcl_Obj *pTerm;
|
|
366046
|
+
rc = Tcl_ListObjIndex(pDb->interp, objv[i+1], jj, &pTerm);
|
|
366047
|
+
if( rc ) goto format_failed;
|
|
366048
|
+
rc = Tcl_GetIndexFromObj(pDb->interp, pTerm, azAlign,
|
|
366049
|
+
"column alignment (-align)", 0, &x);
|
|
366050
|
+
if( rc ) goto format_failed;
|
|
366051
|
+
qrf.aAlign[jj] = aAlignMap[x];
|
|
366052
|
+
}
|
|
366053
|
+
i++;
|
|
366054
|
+
}else if( strcmp(zArg,"-widths")==0 ){
|
|
366055
|
+
Tcl_Size n = 0;
|
|
366056
|
+
int jj;
|
|
366057
|
+
rc = Tcl_ListObjLength(pDb->interp, objv[i+1], &n);
|
|
366058
|
+
if( rc ) goto format_failed;
|
|
366059
|
+
sqlite3_free(qrf.aWidth);
|
|
366060
|
+
qrf.aWidth = sqlite3_malloc64( (n+1)*sizeof(qrf.aWidth[0]) );
|
|
366061
|
+
if( qrf.aWidth==0 ){
|
|
366062
|
+
Tcl_AppendResult(pDb->interp, "out of memory", (char*)0);
|
|
366063
|
+
rc = TCL_ERROR;
|
|
366064
|
+
goto format_failed;
|
|
366065
|
+
}
|
|
366066
|
+
memset(qrf.aWidth, 0, (n+1)*sizeof(qrf.aWidth[0]));
|
|
366067
|
+
qrf.nWidth = n;
|
|
366068
|
+
for(jj=0; jj<n; jj++){
|
|
366069
|
+
Tcl_Obj *pTerm;
|
|
366070
|
+
int v;
|
|
366071
|
+
rc = Tcl_ListObjIndex(pDb->interp, objv[i+1], jj, &pTerm);
|
|
366072
|
+
if( rc ) goto format_failed;
|
|
366073
|
+
rc = Tcl_GetIntFromObj(pDb->interp, pTerm, &v);
|
|
366074
|
+
if( v<(-QRF_MAX_WIDTH) ){
|
|
366075
|
+
v = -QRF_MAX_WIDTH;
|
|
366076
|
+
}else if( v>QRF_MAX_WIDTH ){
|
|
366077
|
+
v = QRF_MAX_WIDTH;
|
|
366078
|
+
}
|
|
366079
|
+
qrf.aWidth[jj] = (short int)v;
|
|
366080
|
+
}
|
|
366081
|
+
i++;
|
|
366082
|
+
}else if( strcmp(zArg,"-columnsep")==0 ){
|
|
366083
|
+
qrf.zColumnSep = Tcl_GetString(objv[i+1]);
|
|
366084
|
+
i++;
|
|
366085
|
+
}else if( strcmp(zArg,"-rowsep")==0 ){
|
|
366086
|
+
qrf.zRowSep = Tcl_GetString(objv[i+1]);
|
|
366087
|
+
i++;
|
|
366088
|
+
}else if( strcmp(zArg,"-tablename")==0 ){
|
|
366089
|
+
qrf.zTableName = Tcl_GetString(objv[i+1]);
|
|
366090
|
+
i++;
|
|
366091
|
+
}else if( strcmp(zArg,"-null")==0 ){
|
|
366092
|
+
qrf.zNull = Tcl_GetString(objv[i+1]);
|
|
366093
|
+
i++;
|
|
366094
|
+
}else if( strcmp(zArg,"-version")==0 ){
|
|
366095
|
+
/* Undocumented. Testing use only */
|
|
366096
|
+
qrf.iVersion = atoi(Tcl_GetString(objv[i+1]));
|
|
366097
|
+
i++;
|
|
366098
|
+
}else{
|
|
366099
|
+
Tcl_AppendResult(pDb->interp, "unknown option: ", zArg, (char*)0);
|
|
366100
|
+
rc = TCL_ERROR;
|
|
366101
|
+
goto format_failed;
|
|
366102
|
+
}
|
|
366103
|
+
}
|
|
366104
|
+
while( zSql && zSql[0] ){
|
|
366105
|
+
SqlPreparedStmt *pStmt = 0; /* Next statement to run */
|
|
366106
|
+
char *zErr = 0; /* Error message from QRF */
|
|
366107
|
+
|
|
366108
|
+
rc = dbPrepareAndBind(pDb, zSql, &zSql, &pStmt);
|
|
366109
|
+
if( rc ) goto format_failed;
|
|
366110
|
+
if( pStmt==0 ) continue;
|
|
366111
|
+
rc = sqlite3_format_query_result(pStmt->pStmt, &qrf, &zErr);
|
|
366112
|
+
dbReleaseStmt(pDb, pStmt, 0);
|
|
366113
|
+
if( rc ){
|
|
366114
|
+
Tcl_SetResult(pDb->interp, zErr, TCL_VOLATILE);
|
|
366115
|
+
sqlite3_free(zErr);
|
|
366116
|
+
rc = TCL_ERROR;
|
|
366117
|
+
goto format_failed;
|
|
366118
|
+
}
|
|
366119
|
+
}
|
|
366120
|
+
Tcl_SetResult(pDb->interp, zResult, TCL_VOLATILE);
|
|
366121
|
+
rc = TCL_OK;
|
|
366122
|
+
/* Fall through...*/
|
|
366123
|
+
|
|
366124
|
+
format_failed:
|
|
366125
|
+
sqlite3_free(qrf.aWidth);
|
|
366126
|
+
sqlite3_free(qrf.aAlign);
|
|
366127
|
+
sqlite3_free(zResult);
|
|
366128
|
+
return rc;
|
|
366129
|
+
|
|
366130
|
+
#endif
|
|
366131
|
+
}
|
|
366132
|
+
|
|
365211
366133
|
/*
|
|
365212
366134
|
** The "sqlite" command below creates a new Tcl command for each
|
|
365213
366135
|
** connection it opens to an SQLite database. This routine is invoked
|
|
@@ -365237,15 +366159,15 @@ static int SQLITE_TCLAPI DbObjCmd(
|
|
|
365237
366159
|
"commit_hook", "complete", "config",
|
|
365238
366160
|
"copy", "deserialize", "enable_load_extension",
|
|
365239
366161
|
"errorcode", "erroroffset", "eval",
|
|
365240
|
-
"exists", "
|
|
365241
|
-
"
|
|
365242
|
-
"
|
|
365243
|
-
"
|
|
365244
|
-
"
|
|
365245
|
-
"
|
|
365246
|
-
"
|
|
365247
|
-
"
|
|
365248
|
-
0
|
|
366162
|
+
"exists", "format", "function",
|
|
366163
|
+
"incrblob", "interrupt", "last_insert_rowid",
|
|
366164
|
+
"nullvalue", "onecolumn", "preupdate",
|
|
366165
|
+
"profile", "progress", "rekey",
|
|
366166
|
+
"restore", "rollback_hook", "serialize",
|
|
366167
|
+
"status", "timeout", "total_changes",
|
|
366168
|
+
"trace", "trace_v2", "transaction",
|
|
366169
|
+
"unlock_notify", "update_hook", "version",
|
|
366170
|
+
"wal_hook", 0
|
|
365249
366171
|
};
|
|
365250
366172
|
enum DB_enum {
|
|
365251
366173
|
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
|
|
@@ -365254,14 +366176,15 @@ static int SQLITE_TCLAPI DbObjCmd(
|
|
|
365254
366176
|
DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG,
|
|
365255
366177
|
DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,
|
|
365256
366178
|
DB_ERRORCODE, DB_ERROROFFSET, DB_EVAL,
|
|
365257
|
-
DB_EXISTS, DB_FUNCTION,
|
|
365258
|
-
DB_INTERRUPT,
|
|
365259
|
-
|
|
365260
|
-
DB_PROGRESS,
|
|
365261
|
-
DB_ROLLBACK_HOOK,
|
|
365262
|
-
DB_TIMEOUT,
|
|
365263
|
-
DB_TRACE_V2,
|
|
365264
|
-
DB_UPDATE_HOOK,
|
|
366179
|
+
DB_EXISTS, DB_FORMAT, DB_FUNCTION,
|
|
366180
|
+
DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID,
|
|
366181
|
+
DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE,
|
|
366182
|
+
DB_PROFILE, DB_PROGRESS, DB_REKEY,
|
|
366183
|
+
DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE,
|
|
366184
|
+
DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES,
|
|
366185
|
+
DB_TRACE, DB_TRACE_V2, DB_TRANSACTION,
|
|
366186
|
+
DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION,
|
|
366187
|
+
DB_WAL_HOOK
|
|
365265
366188
|
};
|
|
365266
366189
|
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
|
|
365267
366190
|
|
|
@@ -366151,6 +367074,18 @@ deserialize_error:
|
|
|
366151
367074
|
break;
|
|
366152
367075
|
}
|
|
366153
367076
|
|
|
367077
|
+
/*
|
|
367078
|
+
** $db format [OPTIONS] SQL
|
|
367079
|
+
**
|
|
367080
|
+
** Run the SQL statement(s) given as the final argument. Use the
|
|
367081
|
+
** Query Result Formatter extension of SQLite to format the output as
|
|
367082
|
+
** text and return that text.
|
|
367083
|
+
*/
|
|
367084
|
+
case DB_FORMAT: {
|
|
367085
|
+
rc = dbQrf(pDb, objc, objv);
|
|
367086
|
+
break;
|
|
367087
|
+
}
|
|
367088
|
+
|
|
366154
367089
|
/*
|
|
366155
367090
|
** $db function NAME [OPTIONS] SCRIPT
|
|
366156
367091
|
**
|