Skip to content

Commit 7251ec0

Browse files
authored
Merge upstream SQLite 3.46.1 (#2238)
Updates libSQL's vendored SQLite from 3.45.1 → 3.46.1 (upstream tag version-3.46.1, f3d536d). Despite libSQL claiming to be 3.46.1 in the version strings, it was based on upstream version 3.45.1 (9ed72eb). What's in here: - libsql-sqlite3/ — the vendored SQLite source tree merged up to 3.46.1, with libSQL's modifications preserved (vector indexes, extra pragmas, WASM tweaks, etc.). - libsql-ffi/bundled/ — regenerated amalgamation (sqlite3.c/sqlite3.h now report SQLITE_VERSION "3.46.1" with the …alt1 libSQL source-id marker) and session_bindgen.rs, via LIBSQL_DEV=1 cargo build --features multiple-ciphers,session. The SQLite3MultipleCiphers fileio.c/series.c were out-of-band synced to match 3.46.1. - Tooling — scripts/sqlite-diff (diffs only upstream's src/ artifacts between two trees) and scripts/update-sqlite-bundle.sh, so future bumps are reproducible. - ext/intck/ is new from upstream and was relocated under libsql-sqlite3/ where Makefile.in already expects it. Conflicts resolved: - src/pragma.c (integrity_check) — upstream replaced the per-table count loop with a single pre-pass using b-tree counts from OP_IntegrityCk. Took upstream's refactored form and re-added the IsVectorIndex(pIdx) skip in the relocated loop, keeping cnt++ unconditional so aRoot register indexing stays aligned. The existing per-row vector-index skip was untouched. - src/where.c — kept libSQL's if (pProbe->idxIsVector) opMask = 0; alongside upstream's refined bLowQual && pSrc->fg.isIndexedBy==0 (cherry-pick 626d619); took upstream's WHERE_KEEP_ALL_JOINS (cherry-pick 2fdb323). - src/shell.c.in — libSQL's .init_wasm_func_table and upstream's new .intck command coexist. - ext/wasm/GNUmakefile — preserved libSQL's -DSQLITE_OMIT_SHARED_MEM and -lm next to upstream's new SEE filter hook (c-pp preprocessor only; no effect on WASM output). - tool/mksqlite3c.tcl — kept wasmedge_bindings.c in the amalgamation source list. - FTS3/FTS5 + mechanical files — taken from upstream; these were merge-base artifacts (base 3.45.0 vs HEAD already at 3.45.1). libSQL's local trigram-tokenizer crash fix (3e56d28) is now superseded by upstream's a751fdd. How this was verified: The `libsql-sqlite3/src` tree was diffed against both clean upstream bases using scripts/sqlite-diff and compared the two patches — they should differ only in context lines and hunk offsets (upstream code that changed between releases), never in libSQL's actual +/- content. ``` scripts/sqlite-diff <clean-3.45.1> libsql-sqlite3 > libsql-sqlite3-3.45.1.patch scripts/sqlite-diff <clean-3.46.1> libsql-sqlite3 > libsql-sqlite3-3.46.1.patch ``` The diffs are the same except for a single divergence is the `PRAGMA integrity_check vector-index` guard, which is the same libSQL change in two shapes because upstream refactored that loop between releases: - vs 3.45.1: if( IsVectorIndex(pIdx) ) continue; - vs 3.46.1: folded into upstream's new check → if( pIdx->pPartIdxWhere==0 && !IsVectorIndex(pIdx) ){ Both skip vector indexes during integrity check — identical semantics. Ground truth confirms the tree is correctly ported (src/pragma.c:1804). Test plan: * SQLite TCL test suite
2 parents f542f03 + f7c6c70 commit 7251ec0

253 files changed

Lines changed: 26732 additions & 13087 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

libsql-ffi/bundled/SQLite3MultipleCiphers/src/fileio.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,9 @@ static int writeFile(
372372
#if !defined(_WIN32) && !defined(WIN32)
373373
if( S_ISLNK(mode) ){
374374
const char *zTo = (const char*)sqlite3_value_text(pData);
375-
if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
375+
if( zTo==0 ) return 1;
376+
unlink(zFile);
377+
if( symlink(zTo, zFile)<0 ) return 1;
376378
}else
377379
#endif
378380
{
@@ -458,13 +460,19 @@ static int writeFile(
458460
return 1;
459461
}
460462
#else
461-
/* Legacy unix */
462-
struct timeval times[2];
463-
times[0].tv_usec = times[1].tv_usec = 0;
464-
times[0].tv_sec = time(0);
465-
times[1].tv_sec = mtime;
466-
if( utimes(zFile, times) ){
467-
return 1;
463+
/* Legacy unix.
464+
**
465+
** Do not use utimes() on a symbolic link - it sees through the link and
466+
** modifies the timestamps on the target. Or fails if the target does
467+
** not exist. */
468+
if( 0==S_ISLNK(mode) ){
469+
struct timeval times[2];
470+
times[0].tv_usec = times[1].tv_usec = 0;
471+
times[0].tv_sec = time(0);
472+
times[1].tv_sec = mtime;
473+
if( utimes(zFile, times) ){
474+
return 1;
475+
}
468476
}
469477
#endif
470478
}

libsql-ffi/bundled/SQLite3MultipleCiphers/src/series.c

Lines changed: 88 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,20 @@ SQLITE_EXTENSION_INIT1
103103
** index is ix. The 0th member is given by smBase. The sequence members
104104
** progress per ix increment by smStep.
105105
*/
106-
static sqlite3_int64 genSeqMember(sqlite3_int64 smBase,
107-
sqlite3_int64 smStep,
108-
sqlite3_uint64 ix){
109-
if( ix>=(sqlite3_uint64)LLONG_MAX ){
106+
static sqlite3_int64 genSeqMember(
107+
sqlite3_int64 smBase,
108+
sqlite3_int64 smStep,
109+
sqlite3_uint64 ix
110+
){
111+
static const sqlite3_uint64 mxI64 =
112+
((sqlite3_uint64)0x7fffffff)<<32 | 0xffffffff;
113+
if( ix>=mxI64 ){
110114
/* Get ix into signed i64 range. */
111-
ix -= (sqlite3_uint64)LLONG_MAX;
115+
ix -= mxI64;
112116
/* With 2's complement ALU, this next can be 1 step, but is split into
113117
* 2 for UBSAN's satisfaction (and hypothetical 1's complement ALUs.) */
114-
smBase += (LLONG_MAX/2) * smStep;
115-
smBase += (LLONG_MAX - LLONG_MAX/2) * smStep;
118+
smBase += (mxI64/2) * smStep;
119+
smBase += (mxI64 - mxI64/2) * smStep;
116120
}
117121
/* Under UBSAN (or on 1's complement machines), must do this last term
118122
* in steps to avoid the dreaded (and harmless) signed multiply overlow. */
@@ -372,13 +376,13 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
372376
** parameter. (idxStr is not used in this implementation.) idxNum
373377
** is a bitmask showing which constraints are available:
374378
**
375-
** 1: start=VALUE
376-
** 2: stop=VALUE
377-
** 4: step=VALUE
378-
**
379-
** Also, if bit 8 is set, that means that the series should be output
380-
** in descending order rather than in ascending order. If bit 16 is
381-
** set, then output must appear in ascending order.
379+
** 0x01: start=VALUE
380+
** 0x02: stop=VALUE
381+
** 0x04: step=VALUE
382+
** 0x08: descending order
383+
** 0x10: ascending order
384+
** 0x20: LIMIT VALUE
385+
** 0x40: OFFSET VALUE
382386
**
383387
** This routine should initialize the cursor and position it so that it
384388
** is pointing at the first row, or pointing off the end of the table
@@ -392,26 +396,44 @@ static int seriesFilter(
392396
series_cursor *pCur = (series_cursor *)pVtabCursor;
393397
int i = 0;
394398
(void)idxStrUnused;
395-
if( idxNum & 1 ){
399+
if( idxNum & 0x01 ){
396400
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
397401
}else{
398402
pCur->ss.iBase = 0;
399403
}
400-
if( idxNum & 2 ){
404+
if( idxNum & 0x02 ){
401405
pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
402406
}else{
403407
pCur->ss.iTerm = 0xffffffff;
404408
}
405-
if( idxNum & 4 ){
409+
if( idxNum & 0x04 ){
406410
pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
407411
if( pCur->ss.iStep==0 ){
408412
pCur->ss.iStep = 1;
409413
}else if( pCur->ss.iStep<0 ){
410-
if( (idxNum & 16)==0 ) idxNum |= 8;
414+
if( (idxNum & 0x10)==0 ) idxNum |= 0x08;
411415
}
412416
}else{
413417
pCur->ss.iStep = 1;
414418
}
419+
if( idxNum & 0x20 ){
420+
sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]);
421+
sqlite3_int64 iTerm;
422+
if( idxNum & 0x40 ){
423+
sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]);
424+
if( iOffset>0 ){
425+
pCur->ss.iBase += pCur->ss.iStep*iOffset;
426+
}
427+
}
428+
if( iLimit>=0 ){
429+
iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep;
430+
if( pCur->ss.iStep<0 ){
431+
if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
432+
}else{
433+
if( iTerm<pCur->ss.iTerm ) pCur->ss.iTerm = iTerm;
434+
}
435+
}
436+
}
415437
for(i=0; i<argc; i++){
416438
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
417439
/* If any of the constraints have a NULL value, then return no rows.
@@ -422,7 +444,7 @@ static int seriesFilter(
422444
break;
423445
}
424446
}
425-
if( idxNum & 8 ){
447+
if( idxNum & 0x08 ){
426448
pCur->ss.isReversing = pCur->ss.iStep > 0;
427449
}else{
428450
pCur->ss.isReversing = pCur->ss.iStep < 0;
@@ -442,50 +464,81 @@ static int seriesFilter(
442464
**
443465
** The query plan is represented by bits in idxNum:
444466
**
445-
** (1) start = $value -- constraint exists
446-
** (2) stop = $value -- constraint exists
447-
** (4) step = $value -- constraint exists
448-
** (8) output in descending order
467+
** 0x01 start = $value -- constraint exists
468+
** 0x02 stop = $value -- constraint exists
469+
** 0x04 step = $value -- constraint exists
470+
** 0x08 output is in descending order
471+
** 0x10 output is in ascending order
472+
** 0x20 LIMIT $value -- constraint exists
473+
** 0x40 OFFSET $value -- constraint exists
449474
*/
450475
static int seriesBestIndex(
451476
sqlite3_vtab *pVTab,
452477
sqlite3_index_info *pIdxInfo
453478
){
454479
int i, j; /* Loop over constraints */
455480
int idxNum = 0; /* The query plan bitmask */
481+
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
456482
int bStartSeen = 0; /* EQ constraint seen on the START column */
483+
#endif
457484
int unusableMask = 0; /* Mask of unusable constraints */
458485
int nArg = 0; /* Number of arguments that seriesFilter() expects */
459-
int aIdx[3]; /* Constraints on start, stop, and step */
486+
int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */
460487
const struct sqlite3_index_constraint *pConstraint;
461488

462489
/* This implementation assumes that the start, stop, and step columns
463490
** are the last three columns in the virtual table. */
464491
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
465492
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
466493

467-
aIdx[0] = aIdx[1] = aIdx[2] = -1;
494+
aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1;
468495
pConstraint = pIdxInfo->aConstraint;
469496
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
470497
int iCol; /* 0 for start, 1 for stop, 2 for step */
471498
int iMask; /* bitmask for those column */
499+
int op = pConstraint->op;
500+
if( op>=SQLITE_INDEX_CONSTRAINT_LIMIT
501+
&& op<=SQLITE_INDEX_CONSTRAINT_OFFSET
502+
){
503+
if( pConstraint->usable==0 ){
504+
/* do nothing */
505+
}else if( op==SQLITE_INDEX_CONSTRAINT_LIMIT ){
506+
aIdx[3] = i;
507+
idxNum |= 0x20;
508+
}else{
509+
assert( op==SQLITE_INDEX_CONSTRAINT_OFFSET );
510+
aIdx[4] = i;
511+
idxNum |= 0x40;
512+
}
513+
continue;
514+
}
472515
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
473516
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
474517
assert( iCol>=0 && iCol<=2 );
475518
iMask = 1 << iCol;
476-
if( iCol==0 ) bStartSeen = 1;
519+
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
520+
if( iCol==0 && op==SQLITE_INDEX_CONSTRAINT_EQ ){
521+
bStartSeen = 1;
522+
}
523+
#endif
477524
if( pConstraint->usable==0 ){
478525
unusableMask |= iMask;
479526
continue;
480-
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
527+
}else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
481528
idxNum |= iMask;
482529
aIdx[iCol] = i;
483530
}
484531
}
485-
for(i=0; i<3; i++){
532+
if( aIdx[3]==0 ){
533+
/* Ignore OFFSET if LIMIT is omitted */
534+
idxNum &= ~0x60;
535+
aIdx[4] = 0;
536+
}
537+
for(i=0; i<5; i++){
486538
if( (j = aIdx[i])>=0 ){
487539
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
488-
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
540+
pIdxInfo->aConstraintUsage[j].omit =
541+
!SQLITE_SERIES_CONSTRAINT_VERIFY || i>=3;
489542
}
490543
}
491544
/* The current generate_column() implementation requires at least one
@@ -506,19 +559,22 @@ static int seriesBestIndex(
506559
** this plan is unusable */
507560
return SQLITE_CONSTRAINT;
508561
}
509-
if( (idxNum & 3)==3 ){
562+
if( (idxNum & 0x03)==0x03 ){
510563
/* Both start= and stop= boundaries are available. This is the
511564
** the preferred case */
512565
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
513566
pIdxInfo->estimatedRows = 1000;
514567
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
515568
if( pIdxInfo->aOrderBy[0].desc ){
516-
idxNum |= 8;
569+
idxNum |= 0x08;
517570
}else{
518-
idxNum |= 16;
571+
idxNum |= 0x10;
519572
}
520573
pIdxInfo->orderByConsumed = 1;
521574
}
575+
}else if( (idxNum & 0x21)==0x21 ){
576+
/* We have start= and LIMIT */
577+
pIdxInfo->estimatedRows = 2500;
522578
}else{
523579
/* If either boundary is missing, we have to generate a huge span
524580
** of numbers. Make this case very expensive so that the query

0 commit comments

Comments
 (0)