extralite-bundle 2.7.1 → 2.8.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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/CHANGELOG.md +17 -4
- data/README.md +79 -42
- data/examples/kv_store.rb +1 -1
- data/examples/pubsub_store_polyphony.rb +7 -7
- data/examples/pubsub_store_threads.rb +3 -3
- data/ext/extralite/changeset.c +1 -1
- data/ext/extralite/common.c +27 -27
- data/ext/extralite/database.c +134 -61
- data/ext/extralite/extralite.h +10 -17
- data/ext/extralite/query.c +17 -17
- data/ext/sqlite3/sqlite3.c +494 -198
- data/ext/sqlite3/sqlite3.h +22 -3
- data/gemspec.rb +1 -1
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +158 -3
- data/test/{perf_ary.rb → perf_array.rb} +1 -1
- data/test/perf_splat.rb +63 -0
- data/test/{perf_argv_transform.rb → perf_splat_transform.rb} +7 -7
- data/test/test_database.rb +193 -120
- data/test/test_iterator.rb +12 -12
- data/test/test_query.rb +92 -92
- metadata +7 -7
- data/lib/extralite/sqlite3_constants.rb +0 -157
data/ext/sqlite3/sqlite3.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/******************************************************************************
|
2
2
|
** This file is an amalgamation of many separate C source files from SQLite
|
3
|
-
** version 3.45.
|
3
|
+
** version 3.45.3. By combining all the individual C code files into this
|
4
4
|
** single large file, the entire code can be compiled as a single translation
|
5
5
|
** unit. This allows many compilers to do optimizations that would not be
|
6
6
|
** possible if the files were compiled separately. Performance improvements
|
@@ -18,7 +18,7 @@
|
|
18
18
|
** separate file. This file contains only code for the core SQLite library.
|
19
19
|
**
|
20
20
|
** The content in this amalgamation comes from Fossil check-in
|
21
|
-
**
|
21
|
+
** 8653b758870e6ef0c98d46b3ace27849054a.
|
22
22
|
*/
|
23
23
|
#define SQLITE_CORE 1
|
24
24
|
#define SQLITE_AMALGAMATION 1
|
@@ -459,9 +459,9 @@ extern "C" {
|
|
459
459
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
460
460
|
** [sqlite_version()] and [sqlite_source_id()].
|
461
461
|
*/
|
462
|
-
#define SQLITE_VERSION "3.45.
|
463
|
-
#define SQLITE_VERSION_NUMBER
|
464
|
-
#define SQLITE_SOURCE_ID "2024-
|
462
|
+
#define SQLITE_VERSION "3.45.3"
|
463
|
+
#define SQLITE_VERSION_NUMBER 3045003
|
464
|
+
#define SQLITE_SOURCE_ID "2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1e8355"
|
465
465
|
|
466
466
|
/*
|
467
467
|
** CAPI3REF: Run-Time Library Version Numbers
|
@@ -733,6 +733,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
|
|
733
733
|
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
|
734
734
|
** <li> The application must not modify the SQL statement text passed into
|
735
735
|
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
|
736
|
+
** <li> The application must not dereference the arrays or string pointers
|
737
|
+
** passed as the 3rd and 4th callback parameters after it returns.
|
736
738
|
** </ul>
|
737
739
|
*/
|
738
740
|
SQLITE_API int sqlite3_exec(
|
@@ -2454,6 +2456,22 @@ struct sqlite3_mem_methods {
|
|
2454
2456
|
** configuration setting is never used, then the default maximum is determined
|
2455
2457
|
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
|
2456
2458
|
** compile-time option is not set, then the default maximum is 1073741824.
|
2459
|
+
**
|
2460
|
+
** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
|
2461
|
+
** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
|
2462
|
+
** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
|
2463
|
+
** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
|
2464
|
+
** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
|
2465
|
+
** defaults to on. This configuration option queries the current setting or
|
2466
|
+
** changes the setting to off or on. The argument is a pointer to an integer.
|
2467
|
+
** If that integer initially holds a value of 1, then the ability for VIEWs to
|
2468
|
+
** have ROWIDs is activated. If the integer initially holds zero, then the
|
2469
|
+
** ability is deactivated. Any other initial value for the integer leaves the
|
2470
|
+
** setting unchanged. After changes, if any, the integer is written with
|
2471
|
+
** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
|
2472
|
+
** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
|
2473
|
+
** recommended case) then the integer is always filled with zero, regardless
|
2474
|
+
** if its initial value.
|
2457
2475
|
** </dl>
|
2458
2476
|
*/
|
2459
2477
|
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
@@ -2485,6 +2503,7 @@ struct sqlite3_mem_methods {
|
|
2485
2503
|
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
|
2486
2504
|
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
|
2487
2505
|
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
|
2506
|
+
#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
|
2488
2507
|
|
2489
2508
|
/*
|
2490
2509
|
** CAPI3REF: Database Connection Configuration Options
|
@@ -15097,6 +15116,7 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace;
|
|
15097
15116
|
** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing
|
15098
15117
|
** 0x00020000 Transform DISTINCT into GROUP BY
|
15099
15118
|
** 0x00040000 SELECT tree dump after all code has been generated
|
15119
|
+
** 0x00080000 NOT NULL strength reduction
|
15100
15120
|
*/
|
15101
15121
|
|
15102
15122
|
/*
|
@@ -18427,6 +18447,15 @@ struct Table {
|
|
18427
18447
|
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
|
18428
18448
|
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
|
18429
18449
|
|
18450
|
+
/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is
|
18451
|
+
** available. By default, this macro is false
|
18452
|
+
*/
|
18453
|
+
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
18454
|
+
# define ViewCanHaveRowid 0
|
18455
|
+
#else
|
18456
|
+
# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0)
|
18457
|
+
#endif
|
18458
|
+
|
18430
18459
|
/*
|
18431
18460
|
** Each foreign key constraint is an instance of the following structure.
|
18432
18461
|
**
|
@@ -19346,6 +19375,7 @@ struct NameContext {
|
|
19346
19375
|
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
|
19347
19376
|
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
|
19348
19377
|
#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
|
19378
|
+
#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
|
19349
19379
|
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
|
19350
19380
|
|
19351
19381
|
/*
|
@@ -19369,6 +19399,7 @@ struct Upsert {
|
|
19369
19399
|
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
|
19370
19400
|
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
|
19371
19401
|
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
|
19402
|
+
u8 isDup; /* True if 2nd or later with same pUpsertIdx */
|
19372
19403
|
/* Above this point is the parse tree for the ON CONFLICT clauses.
|
19373
19404
|
** The next group of fields stores intermediate data. */
|
19374
19405
|
void *pToFree; /* Free memory when deleting the Upsert object */
|
@@ -20139,6 +20170,11 @@ struct Sqlite3Config {
|
|
20139
20170
|
#endif
|
20140
20171
|
#ifndef SQLITE_UNTESTABLE
|
20141
20172
|
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
20173
|
+
#endif
|
20174
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
20175
|
+
u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
|
20176
|
+
** feature is disabled. 0 if rowids can
|
20177
|
+
** occur in views. */
|
20142
20178
|
#endif
|
20143
20179
|
int bLocaltimeFault; /* True to fail localtime() calls */
|
20144
20180
|
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
|
@@ -20595,10 +20631,13 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
|
|
20595
20631
|
# define EXP754 (((u64)0x7ff)<<52)
|
20596
20632
|
# define MAN754 ((((u64)1)<<52)-1)
|
20597
20633
|
# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
|
20634
|
+
# define IsOvfl(X) (((X)&EXP754)==EXP754)
|
20598
20635
|
SQLITE_PRIVATE int sqlite3IsNaN(double);
|
20636
|
+
SQLITE_PRIVATE int sqlite3IsOverflow(double);
|
20599
20637
|
#else
|
20600
|
-
# define IsNaN(X)
|
20601
|
-
# define sqlite3IsNaN(X)
|
20638
|
+
# define IsNaN(X) 0
|
20639
|
+
# define sqlite3IsNaN(X) 0
|
20640
|
+
# define sqlite3IsOVerflow(X) 0
|
20602
20641
|
#endif
|
20603
20642
|
|
20604
20643
|
/*
|
@@ -21444,7 +21483,7 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8);
|
|
21444
21483
|
SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
|
21445
21484
|
SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*);
|
21446
21485
|
SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
|
21447
|
-
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
|
21486
|
+
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*);
|
21448
21487
|
SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
|
21449
21488
|
SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
|
21450
21489
|
SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*);
|
@@ -21834,6 +21873,9 @@ static const char * const sqlite3azCompileOpt[] = {
|
|
21834
21873
|
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
|
21835
21874
|
# endif
|
21836
21875
|
#endif
|
21876
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
21877
|
+
"ALLOW_ROWID_IN_VIEW",
|
21878
|
+
#endif
|
21837
21879
|
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
21838
21880
|
"ALLOW_URI_AUTHORITY",
|
21839
21881
|
#endif
|
@@ -22853,6 +22895,9 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
|
22853
22895
|
#endif
|
22854
22896
|
#ifndef SQLITE_UNTESTABLE
|
22855
22897
|
0, /* xTestCallback */
|
22898
|
+
#endif
|
22899
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
22900
|
+
0, /* mNoVisibleRowid. 0 == allow rowid-in-view */
|
22856
22901
|
#endif
|
22857
22902
|
0, /* bLocaltimeFault */
|
22858
22903
|
0, /* xAltLocaltime */
|
@@ -31309,6 +31354,7 @@ SQLITE_API void sqlite3_str_vappendf(
|
|
31309
31354
|
if( xtype==etFLOAT ){
|
31310
31355
|
iRound = -precision;
|
31311
31356
|
}else if( xtype==etGENERIC ){
|
31357
|
+
if( precision==0 ) precision = 1;
|
31312
31358
|
iRound = precision;
|
31313
31359
|
}else{
|
31314
31360
|
iRound = precision+1;
|
@@ -34640,6 +34686,19 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
|
|
34640
34686
|
}
|
34641
34687
|
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
34642
34688
|
|
34689
|
+
#ifndef SQLITE_OMIT_FLOATING_POINT
|
34690
|
+
/*
|
34691
|
+
** Return true if the floating point value is NaN or +Inf or -Inf.
|
34692
|
+
*/
|
34693
|
+
SQLITE_PRIVATE int sqlite3IsOverflow(double x){
|
34694
|
+
int rc; /* The value return */
|
34695
|
+
u64 y;
|
34696
|
+
memcpy(&y,&x,sizeof(y));
|
34697
|
+
rc = IsOvfl(y);
|
34698
|
+
return rc;
|
34699
|
+
}
|
34700
|
+
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
34701
|
+
|
34643
34702
|
/*
|
34644
34703
|
** Compute a string length that is limited to what can be stored in
|
34645
34704
|
** lower 30 bits of a 32-bit signed integer.
|
@@ -35199,6 +35258,9 @@ do_atof_calc:
|
|
35199
35258
|
u64 s2;
|
35200
35259
|
rr[0] = (double)s;
|
35201
35260
|
s2 = (u64)rr[0];
|
35261
|
+
#if defined(_MSC_VER) && _MSC_VER<1700
|
35262
|
+
if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
|
35263
|
+
#endif
|
35202
35264
|
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
|
35203
35265
|
if( e>0 ){
|
35204
35266
|
while( e>=100 ){
|
@@ -35641,7 +35703,7 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
|
|
35641
35703
|
assert( p->n>0 );
|
35642
35704
|
assert( p->n<sizeof(p->zBuf) );
|
35643
35705
|
p->iDP = p->n + exp;
|
35644
|
-
if( iRound
|
35706
|
+
if( iRound<=0 ){
|
35645
35707
|
iRound = p->iDP - iRound;
|
35646
35708
|
if( iRound==0 && p->zBuf[i+1]>='5' ){
|
35647
35709
|
iRound = 1;
|
@@ -43408,11 +43470,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
|
43408
43470
|
|
43409
43471
|
#if SQLITE_MAX_MMAP_SIZE>0
|
43410
43472
|
if( pFd->mmapSizeMax>0 ){
|
43473
|
+
/* Ensure that there is always at least a 256 byte buffer of addressable
|
43474
|
+
** memory following the returned page. If the database is corrupt,
|
43475
|
+
** SQLite may overread the page slightly (in practice only a few bytes,
|
43476
|
+
** but 256 is safe, round, number). */
|
43477
|
+
const int nEofBuffer = 256;
|
43411
43478
|
if( pFd->pMapRegion==0 ){
|
43412
43479
|
int rc = unixMapfile(pFd, -1);
|
43413
43480
|
if( rc!=SQLITE_OK ) return rc;
|
43414
43481
|
}
|
43415
|
-
if( pFd->mmapSize >= iOff+nAmt ){
|
43482
|
+
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
|
43416
43483
|
*pp = &((u8 *)pFd->pMapRegion)[iOff];
|
43417
43484
|
pFd->nFetchOut++;
|
43418
43485
|
}
|
@@ -50765,6 +50832,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
|
50765
50832
|
|
50766
50833
|
#if SQLITE_MAX_MMAP_SIZE>0
|
50767
50834
|
if( pFd->mmapSizeMax>0 ){
|
50835
|
+
/* Ensure that there is always at least a 256 byte buffer of addressable
|
50836
|
+
** memory following the returned page. If the database is corrupt,
|
50837
|
+
** SQLite may overread the page slightly (in practice only a few bytes,
|
50838
|
+
** but 256 is safe, round, number). */
|
50839
|
+
const int nEofBuffer = 256;
|
50768
50840
|
if( pFd->pMapRegion==0 ){
|
50769
50841
|
int rc = winMapfile(pFd, -1);
|
50770
50842
|
if( rc!=SQLITE_OK ){
|
@@ -50773,7 +50845,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
|
50773
50845
|
return rc;
|
50774
50846
|
}
|
50775
50847
|
}
|
50776
|
-
if( pFd->mmapSize >= iOff+nAmt ){
|
50848
|
+
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
|
50777
50849
|
assert( pFd->pMapRegion!=0 );
|
50778
50850
|
*pp = &((u8 *)pFd->pMapRegion)[iOff];
|
50779
50851
|
pFd->nFetchOut++;
|
@@ -53252,6 +53324,14 @@ SQLITE_API unsigned char *sqlite3_serialize(
|
|
53252
53324
|
pOut = 0;
|
53253
53325
|
}else{
|
53254
53326
|
sz = sqlite3_column_int64(pStmt, 0)*szPage;
|
53327
|
+
if( sz==0 ){
|
53328
|
+
sqlite3_reset(pStmt);
|
53329
|
+
sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0);
|
53330
|
+
rc = sqlite3_step(pStmt);
|
53331
|
+
if( rc==SQLITE_ROW ){
|
53332
|
+
sz = sqlite3_column_int64(pStmt, 0)*szPage;
|
53333
|
+
}
|
53334
|
+
}
|
53255
53335
|
if( piSize ) *piSize = sz;
|
53256
53336
|
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
|
53257
53337
|
pOut = 0;
|
@@ -63775,7 +63855,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
|
|
63775
63855
|
** This will be either the rollback journal or the WAL file.
|
63776
63856
|
*/
|
63777
63857
|
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
|
63778
|
-
#
|
63858
|
+
#ifdef SQLITE_OMIT_WAL
|
63779
63859
|
return pPager->jfd;
|
63780
63860
|
#else
|
63781
63861
|
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
|
@@ -76402,7 +76482,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
|
|
76402
76482
|
}
|
76403
76483
|
|
76404
76484
|
pPage = pCur->pPage;
|
76405
|
-
|
76485
|
+
if( sqlite3FaultSim(412) ) pPage->isInit = 0;
|
76486
|
+
if( !pPage->isInit ){
|
76487
|
+
return SQLITE_CORRUPT_BKPT;
|
76488
|
+
}
|
76406
76489
|
if( !pPage->leaf ){
|
76407
76490
|
int idx = pCur->ix;
|
76408
76491
|
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
|
@@ -77075,7 +77158,10 @@ static int fillInCell(
|
|
77075
77158
|
n = nHeader + nPayload;
|
77076
77159
|
testcase( n==3 );
|
77077
77160
|
testcase( n==4 );
|
77078
|
-
if( n<4 )
|
77161
|
+
if( n<4 ){
|
77162
|
+
n = 4;
|
77163
|
+
pPayload[nPayload] = 0;
|
77164
|
+
}
|
77079
77165
|
*pnSize = n;
|
77080
77166
|
assert( nSrc<=nPayload );
|
77081
77167
|
testcase( nSrc<nPayload );
|
@@ -79521,7 +79607,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
|
|
79521
79607
|
if( flags & BTREE_PREFORMAT ){
|
79522
79608
|
rc = SQLITE_OK;
|
79523
79609
|
szNew = p->pBt->nPreformatSize;
|
79524
|
-
if( szNew<4 )
|
79610
|
+
if( szNew<4 ){
|
79611
|
+
szNew = 4;
|
79612
|
+
newCell[3] = 0;
|
79613
|
+
}
|
79525
79614
|
if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){
|
79526
79615
|
CellInfo info;
|
79527
79616
|
pPage->xParseCell(pPage, newCell, &info);
|
@@ -79583,7 +79672,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
|
|
79583
79672
|
}else if( loc<0 && pPage->nCell>0 ){
|
79584
79673
|
assert( pPage->leaf );
|
79585
79674
|
idx = ++pCur->ix;
|
79586
|
-
pCur->curFlags &= ~BTCF_ValidNKey;
|
79675
|
+
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
79587
79676
|
}else{
|
79588
79677
|
assert( pPage->leaf );
|
79589
79678
|
}
|
@@ -79613,7 +79702,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
|
|
79613
79702
|
*/
|
79614
79703
|
if( pPage->nOverflow ){
|
79615
79704
|
assert( rc==SQLITE_OK );
|
79616
|
-
pCur->curFlags &= ~(BTCF_ValidNKey);
|
79705
|
+
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
79617
79706
|
rc = balance(pCur);
|
79618
79707
|
|
79619
79708
|
/* Must make sure nOverflow is reset to zero even if the balance()
|
@@ -88366,6 +88455,23 @@ static void serialGet(
|
|
88366
88455
|
pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
|
88367
88456
|
}
|
88368
88457
|
}
|
88458
|
+
static int serialGet7(
|
88459
|
+
const unsigned char *buf, /* Buffer to deserialize from */
|
88460
|
+
Mem *pMem /* Memory cell to write value into */
|
88461
|
+
){
|
88462
|
+
u64 x = FOUR_BYTE_UINT(buf);
|
88463
|
+
u32 y = FOUR_BYTE_UINT(buf+4);
|
88464
|
+
x = (x<<32) + y;
|
88465
|
+
assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
|
88466
|
+
swapMixedEndianFloat(x);
|
88467
|
+
memcpy(&pMem->u.r, &x, sizeof(x));
|
88468
|
+
if( IsNaN(x) ){
|
88469
|
+
pMem->flags = MEM_Null;
|
88470
|
+
return 1;
|
88471
|
+
}
|
88472
|
+
pMem->flags = MEM_Real;
|
88473
|
+
return 0;
|
88474
|
+
}
|
88369
88475
|
SQLITE_PRIVATE void sqlite3VdbeSerialGet(
|
88370
88476
|
const unsigned char *buf, /* Buffer to deserialize from */
|
88371
88477
|
u32 serial_type, /* Serial type to deserialize */
|
@@ -89045,7 +89151,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
|
|
89045
89151
|
}else if( serial_type==0 ){
|
89046
89152
|
rc = -1;
|
89047
89153
|
}else if( serial_type==7 ){
|
89048
|
-
|
89154
|
+
serialGet7(&aKey1[d1], &mem1);
|
89049
89155
|
rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
|
89050
89156
|
}else{
|
89051
89157
|
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
|
@@ -89070,14 +89176,18 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
|
|
89070
89176
|
}else if( serial_type==0 ){
|
89071
89177
|
rc = -1;
|
89072
89178
|
}else{
|
89073
|
-
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
|
89074
89179
|
if( serial_type==7 ){
|
89075
|
-
if( mem1
|
89180
|
+
if( serialGet7(&aKey1[d1], &mem1) ){
|
89181
|
+
rc = -1; /* mem1 is a NaN */
|
89182
|
+
}else if( mem1.u.r<pRhs->u.r ){
|
89076
89183
|
rc = -1;
|
89077
89184
|
}else if( mem1.u.r>pRhs->u.r ){
|
89078
89185
|
rc = +1;
|
89186
|
+
}else{
|
89187
|
+
assert( rc==0 );
|
89079
89188
|
}
|
89080
89189
|
}else{
|
89190
|
+
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
|
89081
89191
|
rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
|
89082
89192
|
}
|
89083
89193
|
}
|
@@ -89147,7 +89257,14 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
|
|
89147
89257
|
/* RHS is null */
|
89148
89258
|
else{
|
89149
89259
|
serial_type = aKey1[idx1];
|
89150
|
-
|
89260
|
+
if( serial_type==0
|
89261
|
+
|| serial_type==10
|
89262
|
+
|| (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0)
|
89263
|
+
){
|
89264
|
+
assert( rc==0 );
|
89265
|
+
}else{
|
89266
|
+
rc = 1;
|
89267
|
+
}
|
89151
89268
|
}
|
89152
89269
|
|
89153
89270
|
if( rc!=0 ){
|
@@ -94845,7 +94962,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
|
94845
94962
|
}
|
94846
94963
|
}
|
94847
94964
|
}else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){
|
94848
|
-
if( (flags1 & MEM_Str)
|
94965
|
+
if( (flags1 & MEM_Str)!=0 ){
|
94966
|
+
pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
|
94967
|
+
}else if( (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
|
94849
94968
|
testcase( pIn1->flags & MEM_Int );
|
94850
94969
|
testcase( pIn1->flags & MEM_Real );
|
94851
94970
|
testcase( pIn1->flags & MEM_IntReal );
|
@@ -94854,7 +94973,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
|
94854
94973
|
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
|
94855
94974
|
if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
|
94856
94975
|
}
|
94857
|
-
if( (flags3 & MEM_Str)
|
94976
|
+
if( (flags3 & MEM_Str)!=0 ){
|
94977
|
+
pIn3->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
|
94978
|
+
}else if( (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
|
94858
94979
|
testcase( pIn3->flags & MEM_Int );
|
94859
94980
|
testcase( pIn3->flags & MEM_Real );
|
94860
94981
|
testcase( pIn3->flags & MEM_IntReal );
|
@@ -106199,6 +106320,8 @@ static void resolveAlias(
|
|
106199
106320
|
assert( iCol>=0 && iCol<pEList->nExpr );
|
106200
106321
|
pOrig = pEList->a[iCol].pExpr;
|
106201
106322
|
assert( pOrig!=0 );
|
106323
|
+
assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
|
106324
|
+
if( pExpr->pAggInfo ) return;
|
106202
106325
|
db = pParse->db;
|
106203
106326
|
pDup = sqlite3ExprDup(db, pOrig, 0);
|
106204
106327
|
if( db->mallocFailed ){
|
@@ -106586,8 +106709,37 @@ static int lookupName(
|
|
106586
106709
|
}
|
106587
106710
|
}
|
106588
106711
|
if( 0==cnt && VisibleRowid(pTab) ){
|
106712
|
+
/* pTab is a potential ROWID match. Keep track of it and match
|
106713
|
+
** the ROWID later if that seems appropriate. (Search for "cntTab"
|
106714
|
+
** to find related code.) Only allow a ROWID match if there is
|
106715
|
+
** a single ROWID match candidate.
|
106716
|
+
*/
|
106717
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
106718
|
+
/* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match
|
106719
|
+
** if there is a single VIEW candidate or if there is a single
|
106720
|
+
** non-VIEW candidate plus multiple VIEW candidates. In other
|
106721
|
+
** words non-VIEW candidate terms take precedence over VIEWs.
|
106722
|
+
*/
|
106723
|
+
if( cntTab==0
|
106724
|
+
|| (cntTab==1
|
106725
|
+
&& ALWAYS(pMatch!=0)
|
106726
|
+
&& ALWAYS(pMatch->pTab!=0)
|
106727
|
+
&& (pMatch->pTab->tabFlags & TF_Ephemeral)!=0
|
106728
|
+
&& (pTab->tabFlags & TF_Ephemeral)==0)
|
106729
|
+
){
|
106730
|
+
cntTab = 1;
|
106731
|
+
pMatch = pItem;
|
106732
|
+
}else{
|
106733
|
+
cntTab++;
|
106734
|
+
}
|
106735
|
+
#else
|
106736
|
+
/* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is
|
106737
|
+
** simpler since we require exactly one candidate, which will
|
106738
|
+
** always be a non-VIEW
|
106739
|
+
*/
|
106589
106740
|
cntTab++;
|
106590
106741
|
pMatch = pItem;
|
106742
|
+
#endif
|
106591
106743
|
}
|
106592
106744
|
}
|
106593
106745
|
if( pMatch ){
|
@@ -106713,13 +106865,13 @@ static int lookupName(
|
|
106713
106865
|
** Perhaps the name is a reference to the ROWID
|
106714
106866
|
*/
|
106715
106867
|
if( cnt==0
|
106716
|
-
&& cntTab
|
106868
|
+
&& cntTab>=1
|
106717
106869
|
&& pMatch
|
106718
106870
|
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
|
106719
106871
|
&& sqlite3IsRowid(zCol)
|
106720
106872
|
&& ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
|
106721
106873
|
){
|
106722
|
-
cnt =
|
106874
|
+
cnt = cntTab;
|
106723
106875
|
if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
|
106724
106876
|
pExpr->affExpr = SQLITE_AFF_INTEGER;
|
106725
106877
|
}
|
@@ -107084,6 +107236,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|
107084
107236
|
** resolved. This prevents "column" from being counted as having been
|
107085
107237
|
** referenced, which might prevent a SELECT from being erroneously
|
107086
107238
|
** marked as correlated.
|
107239
|
+
**
|
107240
|
+
** 2024-03-28: Beware of aggregates. A bare column of aggregated table
|
107241
|
+
** can still evaluate to NULL even though it is marked as NOT NULL.
|
107242
|
+
** Example:
|
107243
|
+
**
|
107244
|
+
** CREATE TABLE t1(a INT NOT NULL);
|
107245
|
+
** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1;
|
107246
|
+
**
|
107247
|
+
** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized
|
107248
|
+
** here because at the time this case is hit, we do not yet know whether
|
107249
|
+
** or not t1 is being aggregated. We have to assume the worst and omit
|
107250
|
+
** the optimization. The only time it is safe to apply this optimization
|
107251
|
+
** is within the WHERE clause.
|
107087
107252
|
*/
|
107088
107253
|
case TK_NOTNULL:
|
107089
107254
|
case TK_ISNULL: {
|
@@ -107094,19 +107259,36 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|
107094
107259
|
anRef[i] = p->nRef;
|
107095
107260
|
}
|
107096
107261
|
sqlite3WalkExpr(pWalker, pExpr->pLeft);
|
107097
|
-
if(
|
107098
|
-
|
107099
|
-
|
107100
|
-
|
107101
|
-
|
107102
|
-
pExpr->op = TK_INTEGER;
|
107262
|
+
if( IN_RENAME_OBJECT ) return WRC_Prune;
|
107263
|
+
if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
|
107264
|
+
/* The expression can be NULL. So the optimization does not apply */
|
107265
|
+
return WRC_Prune;
|
107266
|
+
}
|
107103
107267
|
|
107104
|
-
|
107105
|
-
|
107268
|
+
for(i=0, p=pNC; p; p=p->pNext, i++){
|
107269
|
+
if( (p->ncFlags & NC_Where)==0 ){
|
107270
|
+
return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */
|
107106
107271
|
}
|
107107
|
-
sqlite3ExprDelete(pParse->db, pExpr->pLeft);
|
107108
|
-
pExpr->pLeft = 0;
|
107109
107272
|
}
|
107273
|
+
testcase( ExprHasProperty(pExpr, EP_OuterON) );
|
107274
|
+
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
107275
|
+
#if TREETRACE_ENABLED
|
107276
|
+
if( sqlite3TreeTrace & 0x80000 ){
|
107277
|
+
sqlite3DebugPrintf(
|
107278
|
+
"NOT NULL strength reduction converts the following to %d:\n",
|
107279
|
+
pExpr->op==TK_NOTNULL
|
107280
|
+
);
|
107281
|
+
sqlite3ShowExpr(pExpr);
|
107282
|
+
}
|
107283
|
+
#endif /* TREETRACE_ENABLED */
|
107284
|
+
pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
|
107285
|
+
pExpr->flags |= EP_IntValue;
|
107286
|
+
pExpr->op = TK_INTEGER;
|
107287
|
+
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
|
107288
|
+
p->nRef = anRef[i];
|
107289
|
+
}
|
107290
|
+
sqlite3ExprDelete(pParse->db, pExpr->pLeft);
|
107291
|
+
pExpr->pLeft = 0;
|
107110
107292
|
return WRC_Prune;
|
107111
107293
|
}
|
107112
107294
|
|
@@ -108006,7 +108188,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
|
108006
108188
|
}
|
108007
108189
|
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
|
108008
108190
|
}
|
108191
|
+
sNC.ncFlags |= NC_Where;
|
108009
108192
|
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
|
108193
|
+
sNC.ncFlags &= ~NC_Where;
|
108010
108194
|
|
108011
108195
|
/* Resolve names in table-valued-function arguments */
|
108012
108196
|
for(i=0; i<p->pSrc->nSrc; i++){
|
@@ -108545,9 +108729,10 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
|
|
108545
108729
|
assert( pExpr->x.pList->nExpr>0 );
|
108546
108730
|
assert( pExpr->op==TK_FUNCTION );
|
108547
108731
|
pExpr = pExpr->x.pList->a[0].pExpr;
|
108548
|
-
}else{
|
108549
|
-
assert( pExpr->op==TK_COLLATE );
|
108732
|
+
}else if( pExpr->op==TK_COLLATE ){
|
108550
108733
|
pExpr = pExpr->pLeft;
|
108734
|
+
}else{
|
108735
|
+
break;
|
108551
108736
|
}
|
108552
108737
|
}
|
108553
108738
|
return pExpr;
|
@@ -111066,9 +111251,12 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
|
|
111066
111251
|
return 0;
|
111067
111252
|
case TK_COLUMN:
|
111068
111253
|
assert( ExprUseYTab(p) );
|
111069
|
-
return ExprHasProperty(p, EP_CanBeNull)
|
111070
|
-
|
111071
|
-
|
111254
|
+
return ExprHasProperty(p, EP_CanBeNull)
|
111255
|
+
|| NEVER(p->y.pTab==0) /* Reference to column of index on expr */
|
111256
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
111257
|
+
|| (p->iColumn==XN_ROWID && IsView(p->y.pTab))
|
111258
|
+
#endif
|
111259
|
+
|| (p->iColumn>=0
|
111072
111260
|
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
|
111073
111261
|
&& ALWAYS(p->iColumn<p->y.pTab->nCol)
|
111074
111262
|
&& p->y.pTab->aCol[p->iColumn].notNull==0);
|
@@ -123559,9 +123747,12 @@ SQLITE_PRIVATE void sqlite3CreateView(
|
|
123559
123747
|
** on a view, even though views do not have rowids. The following flag
|
123560
123748
|
** setting fixes this problem. But the fix can be disabled by compiling
|
123561
123749
|
** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
|
123562
|
-
** depend upon the old buggy behavior.
|
123563
|
-
|
123564
|
-
|
123750
|
+
** depend upon the old buggy behavior. The ability can also be toggled
|
123751
|
+
** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */
|
123752
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
123753
|
+
p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */
|
123754
|
+
#else
|
123755
|
+
p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */
|
123565
123756
|
#endif
|
123566
123757
|
|
123567
123758
|
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
@@ -128934,13 +129125,13 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
|
|
128934
129125
|
double r1, r2;
|
128935
129126
|
const char *zVal;
|
128936
129127
|
r1 = sqlite3_value_double(pValue);
|
128937
|
-
sqlite3_str_appendf(pStr, "
|
129128
|
+
sqlite3_str_appendf(pStr, "%!0.15g", r1);
|
128938
129129
|
zVal = sqlite3_str_value(pStr);
|
128939
129130
|
if( zVal ){
|
128940
129131
|
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
|
128941
129132
|
if( r1!=r2 ){
|
128942
129133
|
sqlite3_str_reset(pStr);
|
128943
|
-
sqlite3_str_appendf(pStr, "
|
129134
|
+
sqlite3_str_appendf(pStr, "%!0.20e", r1);
|
128944
129135
|
}
|
128945
129136
|
}
|
128946
129137
|
break;
|
@@ -129242,7 +129433,7 @@ static void replaceFunc(
|
|
129242
129433
|
}
|
129243
129434
|
if( zPattern[0]==0 ){
|
129244
129435
|
assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
|
129245
|
-
|
129436
|
+
sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT);
|
129246
129437
|
return;
|
129247
129438
|
}
|
129248
129439
|
nPattern = sqlite3_value_bytes(argv[1]);
|
@@ -129725,7 +129916,7 @@ static void sumFinalize(sqlite3_context *context){
|
|
129725
129916
|
if( p->approx ){
|
129726
129917
|
if( p->ovrfl ){
|
129727
129918
|
sqlite3_result_error(context,"integer overflow",-1);
|
129728
|
-
}else if( !
|
129919
|
+
}else if( !sqlite3IsOverflow(p->rErr) ){
|
129729
129920
|
sqlite3_result_double(context, p->rSum+p->rErr);
|
129730
129921
|
}else{
|
129731
129922
|
sqlite3_result_double(context, p->rSum);
|
@@ -129742,7 +129933,7 @@ static void avgFinalize(sqlite3_context *context){
|
|
129742
129933
|
double r;
|
129743
129934
|
if( p->approx ){
|
129744
129935
|
r = p->rSum;
|
129745
|
-
if( !
|
129936
|
+
if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr;
|
129746
129937
|
}else{
|
129747
129938
|
r = (double)(p->iSum);
|
129748
129939
|
}
|
@@ -129756,7 +129947,7 @@ static void totalFinalize(sqlite3_context *context){
|
|
129756
129947
|
if( p ){
|
129757
129948
|
if( p->approx ){
|
129758
129949
|
r = p->rSum;
|
129759
|
-
if( !
|
129950
|
+
if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr;
|
129760
129951
|
}else{
|
129761
129952
|
r = (double)(p->iSum);
|
129762
129953
|
}
|
@@ -133162,7 +133353,7 @@ SQLITE_PRIVATE void sqlite3Insert(
|
|
133162
133353
|
pNx->iDataCur = iDataCur;
|
133163
133354
|
pNx->iIdxCur = iIdxCur;
|
133164
133355
|
if( pNx->pUpsertTarget ){
|
133165
|
-
if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
|
133356
|
+
if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){
|
133166
133357
|
goto insert_cleanup;
|
133167
133358
|
}
|
133168
133359
|
}
|
@@ -135054,7 +135245,10 @@ static int xferOptimization(
|
|
135054
135245
|
}
|
135055
135246
|
}
|
135056
135247
|
#ifndef SQLITE_OMIT_CHECK
|
135057
|
-
if( pDest->pCheck
|
135248
|
+
if( pDest->pCheck
|
135249
|
+
&& (db->mDbFlags & DBFLAG_Vacuum)==0
|
135250
|
+
&& sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
|
135251
|
+
){
|
135058
135252
|
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
|
135059
135253
|
}
|
135060
135254
|
#endif
|
@@ -139461,31 +139655,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
|
|
139461
139655
|
int mxCol; /* Maximum non-virtual column number */
|
139462
139656
|
|
139463
139657
|
if( pObjTab && pObjTab!=pTab ) continue;
|
139464
|
-
if( !IsOrdinaryTable(pTab) )
|
139465
|
-
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
139466
|
-
sqlite3_vtab *pVTab;
|
139467
|
-
int a1;
|
139468
|
-
if( !IsVirtual(pTab) ) continue;
|
139469
|
-
if( pTab->nCol<=0 ){
|
139470
|
-
const char *zMod = pTab->u.vtab.azArg[0];
|
139471
|
-
if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
|
139472
|
-
}
|
139473
|
-
sqlite3ViewGetColumnNames(pParse, pTab);
|
139474
|
-
if( pTab->u.vtab.p==0 ) continue;
|
139475
|
-
pVTab = pTab->u.vtab.p->pVtab;
|
139476
|
-
if( NEVER(pVTab==0) ) continue;
|
139477
|
-
if( NEVER(pVTab->pModule==0) ) continue;
|
139478
|
-
if( pVTab->pModule->iVersion<4 ) continue;
|
139479
|
-
if( pVTab->pModule->xIntegrity==0 ) continue;
|
139480
|
-
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
|
139481
|
-
pTab->nTabRef++;
|
139482
|
-
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
|
139483
|
-
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
|
139484
|
-
integrityCheckResultRow(v);
|
139485
|
-
sqlite3VdbeJumpHere(v, a1);
|
139486
|
-
#endif
|
139487
|
-
continue;
|
139488
|
-
}
|
139658
|
+
if( !IsOrdinaryTable(pTab) ) continue;
|
139489
139659
|
if( isQuick || HasRowid(pTab) ){
|
139490
139660
|
pPk = 0;
|
139491
139661
|
r2 = 0;
|
@@ -139620,6 +139790,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
|
|
139620
139790
|
** is REAL, we have to load the actual data using OP_Column
|
139621
139791
|
** to reliably determine if the value is a NULL. */
|
139622
139792
|
sqlite3VdbeAddOp3(v, OP_Column, p1, p3, 3);
|
139793
|
+
sqlite3ColumnDefault(v, pTab, j, 3);
|
139623
139794
|
jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk);
|
139624
139795
|
VdbeCoverage(v);
|
139625
139796
|
}
|
@@ -139810,6 +139981,38 @@ SQLITE_PRIVATE void sqlite3Pragma(
|
|
139810
139981
|
}
|
139811
139982
|
}
|
139812
139983
|
}
|
139984
|
+
|
139985
|
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
139986
|
+
/* Second pass to invoke the xIntegrity method on all virtual
|
139987
|
+
** tables.
|
139988
|
+
*/
|
139989
|
+
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
139990
|
+
Table *pTab = sqliteHashData(x);
|
139991
|
+
sqlite3_vtab *pVTab;
|
139992
|
+
int a1;
|
139993
|
+
if( pObjTab && pObjTab!=pTab ) continue;
|
139994
|
+
if( IsOrdinaryTable(pTab) ) continue;
|
139995
|
+
if( !IsVirtual(pTab) ) continue;
|
139996
|
+
if( pTab->nCol<=0 ){
|
139997
|
+
const char *zMod = pTab->u.vtab.azArg[0];
|
139998
|
+
if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
|
139999
|
+
}
|
140000
|
+
sqlite3ViewGetColumnNames(pParse, pTab);
|
140001
|
+
if( pTab->u.vtab.p==0 ) continue;
|
140002
|
+
pVTab = pTab->u.vtab.p->pVtab;
|
140003
|
+
if( NEVER(pVTab==0) ) continue;
|
140004
|
+
if( NEVER(pVTab->pModule==0) ) continue;
|
140005
|
+
if( pVTab->pModule->iVersion<4 ) continue;
|
140006
|
+
if( pVTab->pModule->xIntegrity==0 ) continue;
|
140007
|
+
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
|
140008
|
+
pTab->nTabRef++;
|
140009
|
+
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
|
140010
|
+
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
|
140011
|
+
integrityCheckResultRow(v);
|
140012
|
+
sqlite3VdbeJumpHere(v, a1);
|
140013
|
+
continue;
|
140014
|
+
}
|
140015
|
+
#endif
|
139813
140016
|
}
|
139814
140017
|
{
|
139815
140018
|
static const int iLn = VDBE_OFFSET_LINENO(2);
|
@@ -140446,7 +140649,11 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
|
140446
140649
|
j = seen[0]-1;
|
140447
140650
|
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
|
140448
140651
|
pIdxInfo->aConstraintUsage[j].omit = 1;
|
140449
|
-
if( seen[1]==0 )
|
140652
|
+
if( seen[1]==0 ){
|
140653
|
+
pIdxInfo->estimatedCost = (double)1000;
|
140654
|
+
pIdxInfo->estimatedRows = 1000;
|
140655
|
+
return SQLITE_OK;
|
140656
|
+
}
|
140450
140657
|
pIdxInfo->estimatedCost = (double)20;
|
140451
140658
|
pIdxInfo->estimatedRows = 20;
|
140452
140659
|
j = seen[1]-1;
|
@@ -143673,11 +143880,7 @@ static const char *columnTypeImpl(
|
|
143673
143880
|
** data for the result-set column of the sub-select.
|
143674
143881
|
*/
|
143675
143882
|
if( iCol<pS->pEList->nExpr
|
143676
|
-
|
143677
|
-
&& iCol>=0
|
143678
|
-
#else
|
143679
|
-
&& ALWAYS(iCol>=0)
|
143680
|
-
#endif
|
143883
|
+
&& (!ViewCanHaveRowid || iCol>=0)
|
143681
143884
|
){
|
143682
143885
|
/* If iCol is less than zero, then the expression requests the
|
143683
143886
|
** rowid of the sub-select or view. This expression is legal (see
|
@@ -146852,6 +147055,10 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
|
|
146852
147055
|
**
|
146853
147056
|
** (11) The subquery is not a VALUES clause
|
146854
147057
|
**
|
147058
|
+
** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This
|
147059
|
+
** case only comes up if SQLite is compiled using
|
147060
|
+
** SQLITE_ALLOW_ROWID_IN_VIEW.
|
147061
|
+
**
|
146855
147062
|
** Return 0 if no changes are made and non-zero if one or more WHERE clause
|
146856
147063
|
** terms are duplicated into the subquery.
|
146857
147064
|
*/
|
@@ -146962,6 +147169,18 @@ static int pushDownWhereTerms(
|
|
146962
147169
|
}
|
146963
147170
|
#endif
|
146964
147171
|
|
147172
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
147173
|
+
if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){
|
147174
|
+
Expr *pLeft = pWhere->pLeft;
|
147175
|
+
if( ALWAYS(pLeft)
|
147176
|
+
&& pLeft->op==TK_COLUMN
|
147177
|
+
&& pLeft->iColumn < 0
|
147178
|
+
){
|
147179
|
+
return 0; /* Restriction (12) */
|
147180
|
+
}
|
147181
|
+
}
|
147182
|
+
#endif
|
147183
|
+
|
146965
147184
|
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
|
146966
147185
|
nChng++;
|
146967
147186
|
pSubq->selFlags |= SF_PushDown;
|
@@ -147589,12 +147808,14 @@ SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
|
|
147589
147808
|
while( pSel->pPrior ){ pSel = pSel->pPrior; }
|
147590
147809
|
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
|
147591
147810
|
pTab->iPKey = -1;
|
147811
|
+
pTab->eTabType = TABTYP_VIEW;
|
147592
147812
|
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
|
147593
147813
|
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
147594
147814
|
/* The usual case - do not allow ROWID on a subquery */
|
147595
147815
|
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
|
147596
147816
|
#else
|
147597
|
-
|
147817
|
+
/* Legacy compatibility mode */
|
147818
|
+
pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid;
|
147598
147819
|
#endif
|
147599
147820
|
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
|
147600
147821
|
}
|
@@ -147862,7 +148083,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|
147862
148083
|
pNestedFrom = pFrom->pSelect->pEList;
|
147863
148084
|
assert( pNestedFrom!=0 );
|
147864
148085
|
assert( pNestedFrom->nExpr==pTab->nCol );
|
147865
|
-
assert( VisibleRowid(pTab)==0 );
|
148086
|
+
assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
|
147866
148087
|
}else{
|
147867
148088
|
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
|
147868
148089
|
continue;
|
@@ -147894,7 +148115,8 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|
147894
148115
|
pUsing = 0;
|
147895
148116
|
}
|
147896
148117
|
|
147897
|
-
nAdd = pTab->nCol
|
148118
|
+
nAdd = pTab->nCol;
|
148119
|
+
if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++;
|
147898
148120
|
for(j=0; j<nAdd; j++){
|
147899
148121
|
const char *zName;
|
147900
148122
|
struct ExprList_item *pX; /* Newly added ExprList term */
|
@@ -147976,7 +148198,8 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|
147976
148198
|
pX = &pNew->a[pNew->nExpr-1];
|
147977
148199
|
assert( pX->zEName==0 );
|
147978
148200
|
if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
|
147979
|
-
if( pNestedFrom ){
|
148201
|
+
if( pNestedFrom && (!ViewCanHaveRowid || j<pNestedFrom->nExpr) ){
|
148202
|
+
assert( j<pNestedFrom->nExpr );
|
147980
148203
|
pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName);
|
147981
148204
|
testcase( pX->zEName==0 );
|
147982
148205
|
}else{
|
@@ -152910,6 +153133,9 @@ SQLITE_PRIVATE void sqlite3Update(
|
|
152910
153133
|
}
|
152911
153134
|
}
|
152912
153135
|
if( chngRowid==0 && pPk==0 ){
|
153136
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
153137
|
+
if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
|
153138
|
+
#endif
|
152913
153139
|
sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
|
152914
153140
|
}
|
152915
153141
|
}
|
@@ -153447,7 +153673,8 @@ SQLITE_PRIVATE Upsert *sqlite3UpsertNew(
|
|
153447
153673
|
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
|
153448
153674
|
Parse *pParse, /* The parsing context */
|
153449
153675
|
SrcList *pTabList, /* Table into which we are inserting */
|
153450
|
-
Upsert *pUpsert
|
153676
|
+
Upsert *pUpsert, /* The ON CONFLICT clauses */
|
153677
|
+
Upsert *pAll /* Complete list of all ON CONFLICT clauses */
|
153451
153678
|
){
|
153452
153679
|
Table *pTab; /* That table into which we are inserting */
|
153453
153680
|
int rc; /* Result code */
|
@@ -153550,6 +153777,14 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
|
|
153550
153777
|
continue;
|
153551
153778
|
}
|
153552
153779
|
pUpsert->pUpsertIdx = pIdx;
|
153780
|
+
if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){
|
153781
|
+
/* Really this should be an error. The isDup ON CONFLICT clause will
|
153782
|
+
** never fire. But this problem was not discovered until three years
|
153783
|
+
** after multi-CONFLICT upsert was added, and so we silently ignore
|
153784
|
+
** the problem to prevent breaking applications that might actually
|
153785
|
+
** have redundant ON CONFLICT clauses. */
|
153786
|
+
pUpsert->isDup = 1;
|
153787
|
+
}
|
153553
153788
|
break;
|
153554
153789
|
}
|
153555
153790
|
if( pUpsert->pUpsertIdx==0 ){
|
@@ -153576,9 +153811,13 @@ SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
|
|
153576
153811
|
Upsert *pNext;
|
153577
153812
|
if( NEVER(pUpsert==0) ) return 0;
|
153578
153813
|
pNext = pUpsert->pNextUpsert;
|
153579
|
-
|
153580
|
-
|
153581
|
-
|
153814
|
+
while( 1 /*exit-by-return*/ ){
|
153815
|
+
if( pNext==0 ) return 1;
|
153816
|
+
if( pNext->pUpsertTarget==0 ) return 1;
|
153817
|
+
if( pNext->pUpsertIdx==0 ) return 1;
|
153818
|
+
if( !pNext->isDup ) return 0;
|
153819
|
+
pNext = pNext->pNextUpsert;
|
153820
|
+
}
|
153582
153821
|
return 0;
|
153583
153822
|
}
|
153584
153823
|
|
@@ -166606,16 +166845,10 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
|
166606
166845
|
for(i=0; i<pIdx->nColumn; i++){
|
166607
166846
|
Expr *pExpr;
|
166608
166847
|
int j = pIdx->aiColumn[i];
|
166609
|
-
int bMaybeNullRow;
|
166610
166848
|
if( j==XN_EXPR ){
|
166611
166849
|
pExpr = pIdx->aColExpr->a[i].pExpr;
|
166612
|
-
testcase( pTabItem->fg.jointype & JT_LEFT );
|
166613
|
-
testcase( pTabItem->fg.jointype & JT_RIGHT );
|
166614
|
-
testcase( pTabItem->fg.jointype & JT_LTORJ );
|
166615
|
-
bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
|
166616
166850
|
}else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
|
166617
166851
|
pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
|
166618
|
-
bMaybeNullRow = 0;
|
166619
166852
|
}else{
|
166620
166853
|
continue;
|
166621
166854
|
}
|
@@ -166647,7 +166880,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
|
|
166647
166880
|
p->iDataCur = pTabItem->iCursor;
|
166648
166881
|
p->iIdxCur = iIdxCur;
|
166649
166882
|
p->iIdxCol = i;
|
166650
|
-
p->bMaybeNullRow =
|
166883
|
+
p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
|
166651
166884
|
if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
|
166652
166885
|
p->aff = pIdx->zColAff[i];
|
166653
166886
|
}
|
@@ -166812,7 +167045,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
|
|
166812
167045
|
|
166813
167046
|
/* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
|
166814
167047
|
testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
|
166815
|
-
if( pOrderBy && pOrderBy->nExpr>=BMS )
|
167048
|
+
if( pOrderBy && pOrderBy->nExpr>=BMS ){
|
167049
|
+
pOrderBy = 0;
|
167050
|
+
wctrlFlags &= ~WHERE_WANT_DISTINCT;
|
167051
|
+
}
|
166816
167052
|
|
166817
167053
|
/* The number of tables in the FROM clause is limited by the number of
|
166818
167054
|
** bits in a Bitmask
|
@@ -178849,6 +179085,18 @@ SQLITE_API int sqlite3_config(int op, ...){
|
|
178849
179085
|
}
|
178850
179086
|
#endif /* SQLITE_OMIT_DESERIALIZE */
|
178851
179087
|
|
179088
|
+
case SQLITE_CONFIG_ROWID_IN_VIEW: {
|
179089
|
+
int *pVal = va_arg(ap,int*);
|
179090
|
+
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
179091
|
+
if( 0==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = TF_NoVisibleRowid;
|
179092
|
+
if( 1==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = 0;
|
179093
|
+
*pVal = (sqlite3GlobalConfig.mNoVisibleRowid==0);
|
179094
|
+
#else
|
179095
|
+
*pVal = 0;
|
179096
|
+
#endif
|
179097
|
+
break;
|
179098
|
+
}
|
179099
|
+
|
178852
179100
|
default: {
|
178853
179101
|
rc = SQLITE_ERROR;
|
178854
179102
|
break;
|
@@ -184749,6 +184997,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
|
|
184749
184997
|
|
184750
184998
|
SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*);
|
184751
184999
|
|
185000
|
+
SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
|
185001
|
+
|
184752
185002
|
#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
|
184753
185003
|
#endif /* _FTSINT_H */
|
184754
185004
|
|
@@ -188471,7 +188721,7 @@ static int fts3ShadowName(const char *zName){
|
|
188471
188721
|
** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual
|
188472
188722
|
** table.
|
188473
188723
|
*/
|
188474
|
-
static int
|
188724
|
+
static int fts3IntegrityMethod(
|
188475
188725
|
sqlite3_vtab *pVtab, /* The virtual table to be checked */
|
188476
188726
|
const char *zSchema, /* Name of schema in which pVtab lives */
|
188477
188727
|
const char *zTabname, /* Name of the pVTab table */
|
@@ -188479,30 +188729,21 @@ static int fts3Integrity(
|
|
188479
188729
|
char **pzErr /* Write error message here */
|
188480
188730
|
){
|
188481
188731
|
Fts3Table *p = (Fts3Table*)pVtab;
|
188482
|
-
char *zSql;
|
188483
188732
|
int rc;
|
188484
|
-
|
188733
|
+
int bOk = 0;
|
188485
188734
|
|
188486
|
-
assert( pzErr!=0 );
|
188487
|
-
assert( *pzErr==0 );
|
188488
188735
|
UNUSED_PARAMETER(isQuick);
|
188489
|
-
|
188490
|
-
|
188491
|
-
|
188492
|
-
if( zSql==0 ){
|
188493
|
-
return SQLITE_NOMEM;
|
188494
|
-
}
|
188495
|
-
rc = sqlite3_exec(p->db, zSql, 0, 0, &zErr);
|
188496
|
-
sqlite3_free(zSql);
|
188497
|
-
if( (rc&0xff)==SQLITE_CORRUPT ){
|
188498
|
-
*pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
|
188499
|
-
p->bFts4 ? 4 : 3, zSchema, zTabname);
|
188500
|
-
}else if( rc!=SQLITE_OK ){
|
188736
|
+
rc = sqlite3Fts3IntegrityCheck(p, &bOk);
|
188737
|
+
assert( rc!=SQLITE_CORRUPT_VTAB || bOk==0 );
|
188738
|
+
if( rc!=SQLITE_OK && rc!=SQLITE_CORRUPT_VTAB ){
|
188501
188739
|
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
188502
188740
|
" FTS%d table %s.%s: %s",
|
188503
|
-
p->bFts4 ? 4 : 3, zSchema, zTabname,
|
188741
|
+
p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc));
|
188742
|
+
}else if( bOk==0 ){
|
188743
|
+
*pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
|
188744
|
+
p->bFts4 ? 4 : 3, zSchema, zTabname);
|
188504
188745
|
}
|
188505
|
-
|
188746
|
+
sqlite3Fts3SegmentsClose(p);
|
188506
188747
|
return SQLITE_OK;
|
188507
188748
|
}
|
188508
188749
|
|
@@ -188533,7 +188774,7 @@ static const sqlite3_module fts3Module = {
|
|
188533
188774
|
/* xRelease */ fts3ReleaseMethod,
|
188534
188775
|
/* xRollbackTo */ fts3RollbackToMethod,
|
188535
188776
|
/* xShadowName */ fts3ShadowName,
|
188536
|
-
/* xIntegrity */
|
188777
|
+
/* xIntegrity */ fts3IntegrityMethod,
|
188537
188778
|
};
|
188538
188779
|
|
188539
188780
|
/*
|
@@ -200087,7 +200328,7 @@ static u64 fts3ChecksumIndex(
|
|
200087
200328
|
** If an error occurs (e.g. an OOM or IO error), return an SQLite error
|
200088
200329
|
** code. The final value of *pbOk is undefined in this case.
|
200089
200330
|
*/
|
200090
|
-
|
200331
|
+
SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
|
200091
200332
|
int rc = SQLITE_OK; /* Return code */
|
200092
200333
|
u64 cksum1 = 0; /* Checksum based on FTS index contents */
|
200093
200334
|
u64 cksum2 = 0; /* Checksum based on %_content contents */
|
@@ -200165,7 +200406,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
|
|
200165
200406
|
sqlite3_finalize(pStmt);
|
200166
200407
|
}
|
200167
200408
|
|
200168
|
-
*pbOk = (cksum1==cksum2);
|
200409
|
+
*pbOk = (rc==SQLITE_OK && cksum1==cksum2);
|
200169
200410
|
return rc;
|
200170
200411
|
}
|
200171
200412
|
|
@@ -200205,7 +200446,7 @@ static int fts3DoIntegrityCheck(
|
|
200205
200446
|
){
|
200206
200447
|
int rc;
|
200207
200448
|
int bOk = 0;
|
200208
|
-
rc =
|
200449
|
+
rc = sqlite3Fts3IntegrityCheck(p, &bOk);
|
200209
200450
|
if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
|
200210
200451
|
return rc;
|
200211
200452
|
}
|
@@ -203758,6 +203999,16 @@ static void jsonAppendChar(JsonString *p, char c){
|
|
203758
203999
|
}
|
203759
204000
|
}
|
203760
204001
|
|
204002
|
+
/* Remove a single character from the end of the string
|
204003
|
+
*/
|
204004
|
+
static void jsonStringTrimOneChar(JsonString *p){
|
204005
|
+
if( p->eErr==0 ){
|
204006
|
+
assert( p->nUsed>0 );
|
204007
|
+
p->nUsed--;
|
204008
|
+
}
|
204009
|
+
}
|
204010
|
+
|
204011
|
+
|
203761
204012
|
/* Make sure there is a zero terminator on p->zBuf[]
|
203762
204013
|
**
|
203763
204014
|
** Return true on success. Return false if an OOM prevents this
|
@@ -203765,7 +204016,7 @@ static void jsonAppendChar(JsonString *p, char c){
|
|
203765
204016
|
*/
|
203766
204017
|
static int jsonStringTerminate(JsonString *p){
|
203767
204018
|
jsonAppendChar(p, 0);
|
203768
|
-
p
|
204019
|
+
jsonStringTrimOneChar(p);
|
203769
204020
|
return p->eErr==0;
|
203770
204021
|
}
|
203771
204022
|
|
@@ -204766,6 +205017,7 @@ json_parse_restart:
|
|
204766
205017
|
case '[': {
|
204767
205018
|
/* Parse array */
|
204768
205019
|
iThis = pParse->nBlob;
|
205020
|
+
assert( i<=(u32)pParse->nJson );
|
204769
205021
|
jsonBlobAppendNode(pParse, JSONB_ARRAY, pParse->nJson - i, 0);
|
204770
205022
|
iStart = pParse->nBlob;
|
204771
205023
|
if( pParse->oom ) return -1;
|
@@ -205164,6 +205416,10 @@ static void jsonReturnStringAsBlob(JsonString *pStr){
|
|
205164
205416
|
JsonParse px;
|
205165
205417
|
memset(&px, 0, sizeof(px));
|
205166
205418
|
jsonStringTerminate(pStr);
|
205419
|
+
if( pStr->eErr ){
|
205420
|
+
sqlite3_result_error_nomem(pStr->pCtx);
|
205421
|
+
return;
|
205422
|
+
}
|
205167
205423
|
px.zJson = pStr->zBuf;
|
205168
205424
|
px.nJson = pStr->nUsed;
|
205169
205425
|
px.db = sqlite3_context_db_handle(pStr->pCtx);
|
@@ -205231,8 +205487,8 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
|
|
205231
205487
|
(pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
|
205232
205488
|
n = 9;
|
205233
205489
|
}
|
205234
|
-
if( i+sz+n > pParse->nBlob
|
205235
|
-
&& i+sz+n > pParse->nBlob-pParse->delta
|
205490
|
+
if( (i64)i+sz+n > pParse->nBlob
|
205491
|
+
&& (i64)i+sz+n > pParse->nBlob-pParse->delta
|
205236
205492
|
){
|
205237
205493
|
sz = 0;
|
205238
205494
|
n = 0;
|
@@ -205282,6 +205538,7 @@ static u32 jsonTranslateBlobToText(
|
|
205282
205538
|
}
|
205283
205539
|
case JSONB_INT:
|
205284
205540
|
case JSONB_FLOAT: {
|
205541
|
+
if( sz==0 ) goto malformed_jsonb;
|
205285
205542
|
jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz);
|
205286
205543
|
break;
|
205287
205544
|
}
|
@@ -205290,6 +205547,7 @@ static u32 jsonTranslateBlobToText(
|
|
205290
205547
|
sqlite3_uint64 u = 0;
|
205291
205548
|
const char *zIn = (const char*)&pParse->aBlob[i+n];
|
205292
205549
|
int bOverflow = 0;
|
205550
|
+
if( sz==0 ) goto malformed_jsonb;
|
205293
205551
|
if( zIn[0]=='-' ){
|
205294
205552
|
jsonAppendChar(pOut, '-');
|
205295
205553
|
k++;
|
@@ -205312,6 +205570,7 @@ static u32 jsonTranslateBlobToText(
|
|
205312
205570
|
case JSONB_FLOAT5: { /* Float literal missing digits beside "." */
|
205313
205571
|
u32 k = 0;
|
205314
205572
|
const char *zIn = (const char*)&pParse->aBlob[i+n];
|
205573
|
+
if( sz==0 ) goto malformed_jsonb;
|
205315
205574
|
if( zIn[0]=='-' ){
|
205316
205575
|
jsonAppendChar(pOut, '-');
|
205317
205576
|
k++;
|
@@ -205425,11 +205684,12 @@ static u32 jsonTranslateBlobToText(
|
|
205425
205684
|
jsonAppendChar(pOut, '[');
|
205426
205685
|
j = i+n;
|
205427
205686
|
iEnd = j+sz;
|
205428
|
-
while( j<iEnd ){
|
205687
|
+
while( j<iEnd && pOut->eErr==0 ){
|
205429
205688
|
j = jsonTranslateBlobToText(pParse, j, pOut);
|
205430
205689
|
jsonAppendChar(pOut, ',');
|
205431
205690
|
}
|
205432
|
-
if(
|
205691
|
+
if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
|
205692
|
+
if( sz>0 ) jsonStringTrimOneChar(pOut);
|
205433
205693
|
jsonAppendChar(pOut, ']');
|
205434
205694
|
break;
|
205435
205695
|
}
|
@@ -205438,17 +205698,18 @@ static u32 jsonTranslateBlobToText(
|
|
205438
205698
|
jsonAppendChar(pOut, '{');
|
205439
205699
|
j = i+n;
|
205440
205700
|
iEnd = j+sz;
|
205441
|
-
while( j<iEnd ){
|
205701
|
+
while( j<iEnd && pOut->eErr==0 ){
|
205442
205702
|
j = jsonTranslateBlobToText(pParse, j, pOut);
|
205443
205703
|
jsonAppendChar(pOut, (x++ & 1) ? ',' : ':');
|
205444
205704
|
}
|
205445
|
-
if( x & 1 ) pOut->eErr |= JSTRING_MALFORMED;
|
205446
|
-
if( sz>0 ) pOut
|
205705
|
+
if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
|
205706
|
+
if( sz>0 ) jsonStringTrimOneChar(pOut);
|
205447
205707
|
jsonAppendChar(pOut, '}');
|
205448
205708
|
break;
|
205449
205709
|
}
|
205450
205710
|
|
205451
205711
|
default: {
|
205712
|
+
malformed_jsonb:
|
205452
205713
|
pOut->eErr |= JSTRING_MALFORMED;
|
205453
205714
|
break;
|
205454
205715
|
}
|
@@ -206375,6 +206636,38 @@ jsonInsertIntoBlob_patherror:
|
|
206375
206636
|
return;
|
206376
206637
|
}
|
206377
206638
|
|
206639
|
+
/*
|
206640
|
+
** If pArg is a blob that seems like a JSONB blob, then initialize
|
206641
|
+
** p to point to that JSONB and return TRUE. If pArg does not seem like
|
206642
|
+
** a JSONB blob, then return FALSE;
|
206643
|
+
**
|
206644
|
+
** This routine is only called if it is already known that pArg is a
|
206645
|
+
** blob. The only open question is whether or not the blob appears
|
206646
|
+
** to be a JSONB blob.
|
206647
|
+
*/
|
206648
|
+
static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){
|
206649
|
+
u32 n, sz = 0;
|
206650
|
+
p->aBlob = (u8*)sqlite3_value_blob(pArg);
|
206651
|
+
p->nBlob = (u32)sqlite3_value_bytes(pArg);
|
206652
|
+
if( p->nBlob==0 ){
|
206653
|
+
p->aBlob = 0;
|
206654
|
+
return 0;
|
206655
|
+
}
|
206656
|
+
if( NEVER(p->aBlob==0) ){
|
206657
|
+
return 0;
|
206658
|
+
}
|
206659
|
+
if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT
|
206660
|
+
&& (n = jsonbPayloadSize(p, 0, &sz))>0
|
206661
|
+
&& sz+n==p->nBlob
|
206662
|
+
&& ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0)
|
206663
|
+
){
|
206664
|
+
return 1;
|
206665
|
+
}
|
206666
|
+
p->aBlob = 0;
|
206667
|
+
p->nBlob = 0;
|
206668
|
+
return 0;
|
206669
|
+
}
|
206670
|
+
|
206378
206671
|
/*
|
206379
206672
|
** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob,
|
206380
206673
|
** from the SQL function argument pArg. Return a pointer to the new
|
@@ -206431,34 +206724,30 @@ rebuild_from_cache:
|
|
206431
206724
|
return p;
|
206432
206725
|
}
|
206433
206726
|
if( eType==SQLITE_BLOB ){
|
206434
|
-
|
206435
|
-
|
206436
|
-
|
206437
|
-
|
206438
|
-
|
206439
|
-
}
|
206440
|
-
if( NEVER(p->aBlob==0) ){
|
206441
|
-
goto json_pfa_oom;
|
206442
|
-
}
|
206443
|
-
if( (p->aBlob[0] & 0x0f)>JSONB_OBJECT ){
|
206444
|
-
goto json_pfa_malformed;
|
206445
|
-
}
|
206446
|
-
n = jsonbPayloadSize(p, 0, &sz);
|
206447
|
-
if( n==0
|
206448
|
-
|| sz+n!=p->nBlob
|
206449
|
-
|| ((p->aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0)
|
206450
|
-
){
|
206451
|
-
goto json_pfa_malformed;
|
206452
|
-
}
|
206453
|
-
if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){
|
206454
|
-
goto json_pfa_oom;
|
206727
|
+
if( jsonArgIsJsonb(pArg,p) ){
|
206728
|
+
if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){
|
206729
|
+
goto json_pfa_oom;
|
206730
|
+
}
|
206731
|
+
return p;
|
206455
206732
|
}
|
206456
|
-
|
206733
|
+
/* If the blob is not valid JSONB, fall through into trying to cast
|
206734
|
+
** the blob into text which is then interpreted as JSON. (tag-20240123-a)
|
206735
|
+
**
|
206736
|
+
** This goes against all historical documentation about how the SQLite
|
206737
|
+
** JSON functions were suppose to work. From the beginning, blob was
|
206738
|
+
** reserved for expansion and a blob value should have raised an error.
|
206739
|
+
** But it did not, due to a bug. And many applications came to depend
|
206740
|
+
** upon this buggy behavior, espeically when using the CLI and reading
|
206741
|
+
** JSON text using readfile(), which returns a blob. For this reason
|
206742
|
+
** we will continue to support the bug moving forward.
|
206743
|
+
** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
|
206744
|
+
*/
|
206457
206745
|
}
|
206458
206746
|
p->zJson = (char*)sqlite3_value_text(pArg);
|
206459
206747
|
p->nJson = sqlite3_value_bytes(pArg);
|
206748
|
+
if( db->mallocFailed ) goto json_pfa_oom;
|
206460
206749
|
if( p->nJson==0 ) goto json_pfa_malformed;
|
206461
|
-
|
206750
|
+
assert( p->zJson!=0 );
|
206462
206751
|
if( jsonConvertTextToBlob(p, (flgs & JSON_KEEPERROR) ? 0 : ctx) ){
|
206463
206752
|
if( flgs & JSON_KEEPERROR ){
|
206464
206753
|
p->nErr = 1;
|
@@ -206624,10 +206913,10 @@ static void jsonDebugPrintBlob(
|
|
206624
206913
|
if( sz==0 && x<=JSONB_FALSE ){
|
206625
206914
|
sqlite3_str_append(pOut, "\n", 1);
|
206626
206915
|
}else{
|
206627
|
-
u32
|
206916
|
+
u32 j;
|
206628
206917
|
sqlite3_str_appendall(pOut, ": \"");
|
206629
|
-
for(
|
206630
|
-
u8 c = pParse->aBlob[
|
206918
|
+
for(j=iStart+n; j<iStart+n+sz; j++){
|
206919
|
+
u8 c = pParse->aBlob[j];
|
206631
206920
|
if( c<0x20 || c>=0x7f ) c = '.';
|
206632
206921
|
sqlite3_str_append(pOut, (char*)&c, 1);
|
206633
206922
|
}
|
@@ -207429,12 +207718,12 @@ static void jsonValidFunc(
|
|
207429
207718
|
return;
|
207430
207719
|
}
|
207431
207720
|
case SQLITE_BLOB: {
|
207432
|
-
if(
|
207721
|
+
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
207433
207722
|
if( flags & 0x04 ){
|
207434
207723
|
/* Superficial checking only - accomplished by the
|
207435
207724
|
** jsonFuncArgMightBeBinary() call above. */
|
207436
207725
|
res = 1;
|
207437
|
-
}else{
|
207726
|
+
}else if( flags & 0x08 ){
|
207438
207727
|
/* Strict checking. Check by translating BLOB->TEXT->BLOB. If
|
207439
207728
|
** no errors occur, call that a "strict check". */
|
207440
207729
|
JsonParse px;
|
@@ -207445,8 +207734,11 @@ static void jsonValidFunc(
|
|
207445
207734
|
iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
|
207446
207735
|
res = iErr==0;
|
207447
207736
|
}
|
207737
|
+
break;
|
207448
207738
|
}
|
207449
|
-
|
207739
|
+
/* Fall through into interpreting the input as text. See note
|
207740
|
+
** above at tag-20240123-a. */
|
207741
|
+
/* no break */ deliberate_fall_through
|
207450
207742
|
}
|
207451
207743
|
default: {
|
207452
207744
|
JsonParse px;
|
@@ -207571,7 +207863,7 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
|
|
207571
207863
|
if( isFinal ){
|
207572
207864
|
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
|
207573
207865
|
}else{
|
207574
|
-
pStr
|
207866
|
+
jsonStringTrimOneChar(pStr);
|
207575
207867
|
}
|
207576
207868
|
return;
|
207577
207869
|
}else if( isFinal ){
|
@@ -207581,7 +207873,7 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
|
|
207581
207873
|
pStr->bStatic = 1;
|
207582
207874
|
}else{
|
207583
207875
|
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
|
207584
|
-
pStr
|
207876
|
+
jsonStringTrimOneChar(pStr);
|
207585
207877
|
}
|
207586
207878
|
}else{
|
207587
207879
|
sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
|
@@ -207691,7 +207983,7 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
|
207691
207983
|
if( isFinal ){
|
207692
207984
|
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
|
207693
207985
|
}else{
|
207694
|
-
pStr
|
207986
|
+
jsonStringTrimOneChar(pStr);
|
207695
207987
|
}
|
207696
207988
|
return;
|
207697
207989
|
}else if( isFinal ){
|
@@ -207701,7 +207993,7 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
|
|
207701
207993
|
pStr->bStatic = 1;
|
207702
207994
|
}else{
|
207703
207995
|
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
|
207704
|
-
pStr
|
207996
|
+
jsonStringTrimOneChar(pStr);
|
207705
207997
|
}
|
207706
207998
|
}else{
|
207707
207999
|
sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
|
@@ -208032,6 +208324,9 @@ static int jsonEachColumn(
|
|
208032
208324
|
case JEACH_VALUE: {
|
208033
208325
|
u32 i = jsonSkipLabel(p);
|
208034
208326
|
jsonReturnFromBlob(&p->sParse, i, ctx, 1);
|
208327
|
+
if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){
|
208328
|
+
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
208329
|
+
}
|
208035
208330
|
break;
|
208036
208331
|
}
|
208037
208332
|
case JEACH_TYPE: {
|
@@ -208078,9 +208373,9 @@ static int jsonEachColumn(
|
|
208078
208373
|
case JEACH_JSON: {
|
208079
208374
|
if( p->sParse.zJson==0 ){
|
208080
208375
|
sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
|
208081
|
-
|
208376
|
+
SQLITE_TRANSIENT);
|
208082
208377
|
}else{
|
208083
|
-
sqlite3_result_text(ctx, p->sParse.zJson, -1,
|
208378
|
+
sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT);
|
208084
208379
|
}
|
208085
208380
|
break;
|
208086
208381
|
}
|
@@ -208182,13 +208477,9 @@ static int jsonEachFilter(
|
|
208182
208477
|
memset(&p->sParse, 0, sizeof(p->sParse));
|
208183
208478
|
p->sParse.nJPRef = 1;
|
208184
208479
|
p->sParse.db = p->db;
|
208185
|
-
if(
|
208186
|
-
|
208187
|
-
|
208188
|
-
p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
208189
|
-
}else{
|
208190
|
-
goto json_each_malformed_input;
|
208191
|
-
}
|
208480
|
+
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
208481
|
+
p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
|
208482
|
+
p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
208192
208483
|
}else{
|
208193
208484
|
p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
|
208194
208485
|
p->sParse.nJson = sqlite3_value_bytes(argv[0]);
|
@@ -209110,11 +209401,9 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
|
|
209110
209401
|
** Clear the Rtree.pNodeBlob object
|
209111
209402
|
*/
|
209112
209403
|
static void nodeBlobReset(Rtree *pRtree){
|
209113
|
-
|
209114
|
-
|
209115
|
-
|
209116
|
-
sqlite3_blob_close(pBlob);
|
209117
|
-
}
|
209404
|
+
sqlite3_blob *pBlob = pRtree->pNodeBlob;
|
209405
|
+
pRtree->pNodeBlob = 0;
|
209406
|
+
sqlite3_blob_close(pBlob);
|
209118
209407
|
}
|
209119
209408
|
|
209120
209409
|
/*
|
@@ -209158,7 +209447,6 @@ static int nodeAcquire(
|
|
209158
209447
|
&pRtree->pNodeBlob);
|
209159
209448
|
}
|
209160
209449
|
if( rc ){
|
209161
|
-
nodeBlobReset(pRtree);
|
209162
209450
|
*ppNode = 0;
|
209163
209451
|
/* If unable to open an sqlite3_blob on the desired row, that can only
|
209164
209452
|
** be because the shadow tables hold erroneous data. */
|
@@ -209218,6 +209506,7 @@ static int nodeAcquire(
|
|
209218
209506
|
}
|
209219
209507
|
*ppNode = pNode;
|
209220
209508
|
}else{
|
209509
|
+
nodeBlobReset(pRtree);
|
209221
209510
|
if( pNode ){
|
209222
209511
|
pRtree->nNodeRef--;
|
209223
209512
|
sqlite3_free(pNode);
|
@@ -209362,6 +209651,7 @@ static void nodeGetCoord(
|
|
209362
209651
|
int iCoord, /* Which coordinate to extract */
|
209363
209652
|
RtreeCoord *pCoord /* OUT: Space to write result to */
|
209364
209653
|
){
|
209654
|
+
assert( iCell<NCELL(pNode) );
|
209365
209655
|
readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
|
209366
209656
|
}
|
209367
209657
|
|
@@ -209551,7 +209841,9 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
|
|
209551
209841
|
sqlite3_finalize(pCsr->pReadAux);
|
209552
209842
|
sqlite3_free(pCsr);
|
209553
209843
|
pRtree->nCursor--;
|
209554
|
-
|
209844
|
+
if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){
|
209845
|
+
nodeBlobReset(pRtree);
|
209846
|
+
}
|
209555
209847
|
return SQLITE_OK;
|
209556
209848
|
}
|
209557
209849
|
|
@@ -210136,7 +210428,11 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
|
|
210136
210428
|
int rc = SQLITE_OK;
|
210137
210429
|
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
|
210138
210430
|
if( rc==SQLITE_OK && ALWAYS(p) ){
|
210139
|
-
|
210431
|
+
if( p->iCell>=NCELL(pNode) ){
|
210432
|
+
rc = SQLITE_ABORT;
|
210433
|
+
}else{
|
210434
|
+
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
|
210435
|
+
}
|
210140
210436
|
}
|
210141
210437
|
return rc;
|
210142
210438
|
}
|
@@ -210154,6 +210450,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
|
210154
210450
|
|
210155
210451
|
if( rc ) return rc;
|
210156
210452
|
if( NEVER(p==0) ) return SQLITE_OK;
|
210453
|
+
if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT;
|
210157
210454
|
if( i==0 ){
|
210158
210455
|
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
|
210159
210456
|
}else if( i<=pRtree->nDim2 ){
|
@@ -211635,8 +211932,7 @@ constraint:
|
|
211635
211932
|
*/
|
211636
211933
|
static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
|
211637
211934
|
Rtree *pRtree = (Rtree *)pVtab;
|
211638
|
-
|
211639
|
-
pRtree->inWrTrans++;
|
211935
|
+
pRtree->inWrTrans = 1;
|
211640
211936
|
return SQLITE_OK;
|
211641
211937
|
}
|
211642
211938
|
|
@@ -211650,6 +211946,9 @@ static int rtreeEndTransaction(sqlite3_vtab *pVtab){
|
|
211650
211946
|
nodeBlobReset(pRtree);
|
211651
211947
|
return SQLITE_OK;
|
211652
211948
|
}
|
211949
|
+
static int rtreeRollback(sqlite3_vtab *pVtab){
|
211950
|
+
return rtreeEndTransaction(pVtab);
|
211951
|
+
}
|
211653
211952
|
|
211654
211953
|
/*
|
211655
211954
|
** The xRename method for rtree module virtual tables.
|
@@ -211768,7 +212067,7 @@ static sqlite3_module rtreeModule = {
|
|
211768
212067
|
rtreeBeginTransaction, /* xBegin - begin transaction */
|
211769
212068
|
rtreeEndTransaction, /* xSync - sync transaction */
|
211770
212069
|
rtreeEndTransaction, /* xCommit - commit transaction */
|
211771
|
-
|
212070
|
+
rtreeRollback, /* xRollback - rollback transaction */
|
211772
212071
|
0, /* xFindFunction - function overloading */
|
211773
212072
|
rtreeRename, /* xRename - rename the table */
|
211774
212073
|
rtreeSavepoint, /* xSavepoint */
|
@@ -245327,23 +245626,26 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
|
|
245327
245626
|
static void fts5TokendataIterNext(Fts5Iter *pIter, int bFrom, i64 iFrom){
|
245328
245627
|
int ii;
|
245329
245628
|
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
|
245629
|
+
Fts5Index *pIndex = pIter->pIndex;
|
245330
245630
|
|
245331
245631
|
for(ii=0; ii<pT->nIter; ii++){
|
245332
245632
|
Fts5Iter *p = pT->apIter[ii];
|
245333
245633
|
if( p->base.bEof==0
|
245334
245634
|
&& (p->base.iRowid==pIter->base.iRowid || (bFrom && p->base.iRowid<iFrom))
|
245335
245635
|
){
|
245336
|
-
fts5MultiIterNext(
|
245636
|
+
fts5MultiIterNext(pIndex, p, bFrom, iFrom);
|
245337
245637
|
while( bFrom && p->base.bEof==0
|
245338
245638
|
&& p->base.iRowid<iFrom
|
245339
|
-
&&
|
245639
|
+
&& pIndex->rc==SQLITE_OK
|
245340
245640
|
){
|
245341
|
-
fts5MultiIterNext(
|
245641
|
+
fts5MultiIterNext(pIndex, p, 0, 0);
|
245342
245642
|
}
|
245343
245643
|
}
|
245344
245644
|
}
|
245345
245645
|
|
245346
|
-
|
245646
|
+
if( pIndex->rc==SQLITE_OK ){
|
245647
|
+
fts5IterSetOutputsTokendata(pIter);
|
245648
|
+
}
|
245347
245649
|
}
|
245348
245650
|
|
245349
245651
|
/*
|
@@ -250497,7 +250799,7 @@ static void fts5SourceIdFunc(
|
|
250497
250799
|
){
|
250498
250800
|
assert( nArg==0 );
|
250499
250801
|
UNUSED_PARAM2(nArg, apUnused);
|
250500
|
-
sqlite3_result_text(pCtx, "fts5: 2024-
|
250802
|
+
sqlite3_result_text(pCtx, "fts5: 2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1e8355", -1, SQLITE_TRANSIENT);
|
250501
250803
|
}
|
250502
250804
|
|
250503
250805
|
/*
|
@@ -250528,27 +250830,21 @@ static int fts5IntegrityMethod(
|
|
250528
250830
|
char **pzErr /* Write error message here */
|
250529
250831
|
){
|
250530
250832
|
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
|
250531
|
-
Fts5Config *pConfig = pTab->p.pConfig;
|
250532
|
-
char *zSql;
|
250533
|
-
char *zErr = 0;
|
250534
250833
|
int rc;
|
250834
|
+
|
250535
250835
|
assert( pzErr!=0 && *pzErr==0 );
|
250536
250836
|
UNUSED_PARAM(isQuick);
|
250537
|
-
|
250538
|
-
"INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');",
|
250539
|
-
zSchema, zTabname, pConfig->zName);
|
250540
|
-
if( zSql==0 ) return SQLITE_NOMEM;
|
250541
|
-
rc = sqlite3_exec(pConfig->db, zSql, 0, 0, &zErr);
|
250542
|
-
sqlite3_free(zSql);
|
250837
|
+
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
|
250543
250838
|
if( (rc&0xff)==SQLITE_CORRUPT ){
|
250544
250839
|
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
250545
250840
|
zSchema, zTabname);
|
250546
250841
|
}else if( rc!=SQLITE_OK ){
|
250547
250842
|
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
250548
250843
|
" FTS5 table %s.%s: %s",
|
250549
|
-
zSchema, zTabname,
|
250844
|
+
zSchema, zTabname, sqlite3_errstr(rc));
|
250550
250845
|
}
|
250551
|
-
|
250846
|
+
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
|
250847
|
+
|
250552
250848
|
return SQLITE_OK;
|
250553
250849
|
}
|
250554
250850
|
|