Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
sqlite: update to 3.45.2
Baptiste Daroussin committed 2 years ago
commit 6b43cffa1ec27b9ca0bbb61a51c765442a543f1b
parent f13d616
3 files changed +399 -199
modified external/sqlite/shell.c
@@ -580,6 +580,9 @@ zSkipValidUtf8(const char *z, int nAccept, long ccm);
#ifndef HAVE_CONSOLE_IO_H
# include "console_io.h"
#endif
+
#if defined(_MSC_VER)
+
# pragma warning(disable : 4204)
+
#endif

#ifndef SQLITE_CIO_NO_TRANSLATE
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
@@ -678,6 +681,10 @@ static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
# endif
}

+
# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+
#  define ENABLE_VIRTUAL_TERMINAL_PROCESSING  (0x4)
+
# endif
+

# if CIO_WIN_WC_XLATE
/* Define console modes for use with the Windows Console API. */
#  define SHELL_CONI_MODE \
@@ -1228,6 +1235,10 @@ SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
}
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */

+
#if defined(_MSC_VER)
+
# pragma warning(default : 4204)
+
#endif
+

#undef SHELL_INVALID_FILE_PTR

/************************* End ../ext/consio/console_io.c ********************/
@@ -20619,6 +20630,7 @@ static void exec_prepared_stmt_columnar(
  rc = sqlite3_step(pStmt);
  if( rc!=SQLITE_ROW ) return;
  nColumn = sqlite3_column_count(pStmt);
+
  if( nColumn==0 ) goto columnar_end;
  nAlloc = nColumn*4;
  if( nAlloc<=0 ) nAlloc = 1;
  azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
@@ -20704,7 +20716,6 @@ static void exec_prepared_stmt_columnar(
    if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
  }
  if( seenInterrupt ) goto columnar_end;
-
  if( nColumn==0 ) goto columnar_end;
  switch( p->cMode ){
    case MODE_Column: {
      colSep = "  ";
@@ -25553,16 +25564,15 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifndef SQLITE_SHELL_FIDDLE
  if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
    char *zTable = 0;           /* Insert data into this table */
-
    char *zSchema = 0;          /* within this schema (may default to "main") */
+
    char *zSchema = 0;          /* Schema of zTable */
    char *zFile = 0;            /* Name of file to extra content from */
    sqlite3_stmt *pStmt = NULL; /* A statement */
    int nCol;                   /* Number of columns in the table */
-
    int nByte;                  /* Number of bytes in an SQL string */
+
    i64 nByte;                  /* Number of bytes in an SQL string */
    int i, j;                   /* Loop counters */
    int needCommit;             /* True to COMMIT or ROLLBACK at end */
    int nSep;                   /* Number of bytes in p->colSeparator[] */
-
    char *zSql;                 /* An SQL statement */
-
    char *zFullTabName;         /* Table name with schema if applicable */
+
    char *zSql = 0;             /* An SQL statement */
    ImportCtx sCtx;             /* Reader context */
    char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
    int eVerbose = 0;           /* Larger for more console output */
@@ -25696,24 +25706,14 @@ static int do_meta_command(char *zLine, ShellState *p){
    while( (nSkip--)>0 ){
      while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
    }
-
    if( zSchema!=0 ){
-
      zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
-
    }else{
-
      zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
-
    }
-
    zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
-
    if( zSql==0 || zFullTabName==0 ){
-
      import_cleanup(&sCtx);
-
      shell_out_of_memory();
-
    }
-
    nByte = strlen30(zSql);
-
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
-
    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
+
    if( sqlite3_table_column_metadata(p->db, zSchema, zTable,0,0,0,0,0,0) ){
+
      /* Table does not exist.  Create it. */
      sqlite3 *dbCols = 0;
      char *zRenames = 0;
      char *zColDefs;
-
      zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
+
      zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", 
+
                    zSchema ? zSchema : "main", zTable);
      while( xRead(&sCtx) ){
        zAutoColumn(sCtx.z, &dbCols, 0);
        if( sCtx.cTerm!=sCtx.cColSep ) break;
@@ -25728,34 +25728,50 @@ static int do_meta_command(char *zLine, ShellState *p){
      assert(dbCols==0);
      if( zColDefs==0 ){
        eputf("%s: empty file\n", sCtx.zFile);
-
      import_fail:
-
        sqlite3_free(zCreate);
-
        sqlite3_free(zSql);
-
        sqlite3_free(zFullTabName);
        import_cleanup(&sCtx);
        rc = 1;
        goto meta_command_exit;
      }
      zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
+
      if( zCreate==0 ){
+
        import_cleanup(&sCtx);
+
        shell_out_of_memory();
+
      }
      if( eVerbose>=1 ){
        oputf("%s\n", zCreate);
      }
      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
+
      sqlite3_free(zCreate);
+
      zCreate = 0;
      if( rc ){
        eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
-
        goto import_fail;
+
        import_cleanup(&sCtx);
+
        rc = 1;
+
        goto meta_command_exit;
      }
-
      sqlite3_free(zCreate);
-
      zCreate = 0;
-
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    }
+
    zSql = sqlite3_mprintf("SELECT count(*) FROM pragma_table_info(%Q,%Q);",
+
                           zTable, zSchema);
+
    if( zSql==0 ){
+
      import_cleanup(&sCtx);
+
      shell_out_of_memory();
+
    }
+
    nByte = strlen(zSql);    
+
    rc =  sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+
    sqlite3_free(zSql);
+
    zSql = 0;
    if( rc ){
      if (pStmt) sqlite3_finalize(pStmt);
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
-
      goto import_fail;
+
      import_cleanup(&sCtx);
+
      rc = 1;
+
      goto meta_command_exit;
+
    }
+
    if( sqlite3_step(pStmt)==SQLITE_ROW ){
+
      nCol = sqlite3_column_int(pStmt, 0);
+
    }else{
+
      nCol = 0;
    }
-
    sqlite3_free(zSql);
-
    nCol = sqlite3_column_count(pStmt);
    sqlite3_finalize(pStmt);
    pStmt = 0;
    if( nCol==0 ) return 0; /* no columns, no error */
@@ -25764,7 +25780,12 @@ static int do_meta_command(char *zLine, ShellState *p){
      import_cleanup(&sCtx);
      shell_out_of_memory();
    }
-
    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
+
    if( zSchema ){
+
      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?", 
+
                       zSchema, zTable);
+
    }else{
+
      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
+
    }
    j = strlen30(zSql);
    for(i=1; i<nCol; i++){
      zSql[j++] = ',';
@@ -25776,13 +25797,15 @@ static int do_meta_command(char *zLine, ShellState *p){
      oputf("Insert using: %s\n", zSql);
    }
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+
    sqlite3_free(zSql);
+
    zSql = 0;
    if( rc ){
      eputf("Error: %s\n", sqlite3_errmsg(p->db));
      if (pStmt) sqlite3_finalize(pStmt);
-
      goto import_fail;
+
      import_cleanup(&sCtx);
+
      rc = 1;
+
      goto meta_command_exit;
    }
-
    sqlite3_free(zSql);
-
    sqlite3_free(zFullTabName);
    needCommit = sqlite3_get_autocommit(p->db);
    if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
    do{
modified external/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-
** version 3.45.0.  By combining all the individual C code files into this
+
** version 3.45.2.  By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
@@ -18,7 +18,7 @@
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
-
** 1066602b2b1976fe58b5150777cced894af1.
+
** d8cd6d49b46a395b13955387d05e9e1a2a47.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ -459,9 +459,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.45.0"
-
#define SQLITE_VERSION_NUMBER 3045000
-
#define SQLITE_SOURCE_ID      "2024-01-15 17:01:13 1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d"
+
#define SQLITE_VERSION        "3.45.2"
+
#define SQLITE_VERSION_NUMBER 3045002
+
#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 d8cd6d49b46a395b13955387d05e9e1a2a47e54fb99f3c9b59835bbefad6af77"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -733,6 +733,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
**      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
**      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+
** <li> The application must not dereference the arrays or string pointers
+
**       passed as the 3rd and 4th callback parameters after it returns.
** </ul>
*/
SQLITE_API int sqlite3_exec(
@@ -15097,6 +15099,7 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace;
**   0x00010000     Beginning of DELETE/INSERT/UPDATE processing
**   0x00020000     Transform DISTINCT into GROUP BY
**   0x00040000     SELECT tree dump after all code has been generated
+
**   0x00080000     NOT NULL strength reduction
*/

/*
@@ -19346,6 +19349,7 @@ struct NameContext {
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL   0x040000 /* SQL text comes from sqlite_schema */
#define NC_NoSelect  0x080000 /* Do not descend into sub-selects */
+
#define NC_Where     0x100000 /* Processing WHERE clause of a SELECT */
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */

/*
@@ -19369,6 +19373,7 @@ struct Upsert {
  Expr *pUpsertWhere;       /* WHERE clause for the ON CONFLICT UPDATE */
  Upsert *pNextUpsert;      /* Next ON CONFLICT clause in the list */
  u8 isDoUpdate;            /* True for DO UPDATE.  False for DO NOTHING */
+
  u8 isDup;                 /* True if 2nd or later with same pUpsertIdx */
  /* Above this point is the parse tree for the ON CONFLICT clauses.
  ** The next group of fields stores intermediate data. */
  void *pToFree;            /* Free memory when deleting the Upsert object */
@@ -21444,7 +21449,7 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8);
SQLITE_PRIVATE   Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
SQLITE_PRIVATE   void sqlite3UpsertDelete(sqlite3*,Upsert*);
SQLITE_PRIVATE   Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
-
SQLITE_PRIVATE   int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
+
SQLITE_PRIVATE   int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*);
SQLITE_PRIVATE   void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
SQLITE_PRIVATE   Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
SQLITE_PRIVATE   int sqlite3UpsertNextIsIPK(Upsert*);
@@ -31309,6 +31314,7 @@ SQLITE_API void sqlite3_str_vappendf(
        if( xtype==etFLOAT ){
          iRound = -precision;
        }else if( xtype==etGENERIC ){
+
          if( precision==0 ) precision = 1;
          iRound = precision;
        }else{
          iRound = precision+1;
@@ -35199,6 +35205,9 @@ do_atof_calc:
    u64 s2;
    rr[0] = (double)s;
    s2 = (u64)rr[0];
+
#if defined(_MSC_VER) && _MSC_VER<1700
+
    if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
+
#endif
    rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
    if( e>0 ){
      while( e>=100  ){
@@ -35641,7 +35650,7 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
  assert( p->n>0 );
  assert( p->n<sizeof(p->zBuf) );
  p->iDP = p->n + exp;
-
  if( iRound<0 ){
+
  if( iRound<=0 ){
    iRound = p->iDP - iRound;
    if( iRound==0 && p->zBuf[i+1]>='5' ){
      iRound = 1;
@@ -43408,11 +43417,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFd->mmapSizeMax>0 ){
+
    /* Ensure that there is always at least a 256 byte buffer of addressable
+
    ** memory following the returned page. If the database is corrupt,
+
    ** SQLite may overread the page slightly (in practice only a few bytes,
+
    ** but 256 is safe, round, number).  */
+
    const int nEofBuffer = 256;
    if( pFd->pMapRegion==0 ){
      int rc = unixMapfile(pFd, -1);
      if( rc!=SQLITE_OK ) return rc;
    }
-
    if( pFd->mmapSize >= iOff+nAmt ){
+
    if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
      *pp = &((u8 *)pFd->pMapRegion)[iOff];
      pFd->nFetchOut++;
    }
@@ -50765,6 +50779,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFd->mmapSizeMax>0 ){
+
    /* Ensure that there is always at least a 256 byte buffer of addressable
+
    ** memory following the returned page. If the database is corrupt,
+
    ** SQLite may overread the page slightly (in practice only a few bytes,
+
    ** but 256 is safe, round, number).  */
+
    const int nEofBuffer = 256;
    if( pFd->pMapRegion==0 ){
      int rc = winMapfile(pFd, -1);
      if( rc!=SQLITE_OK ){
@@ -50773,7 +50792,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
        return rc;
      }
    }
-
    if( pFd->mmapSize >= iOff+nAmt ){
+
    if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
      assert( pFd->pMapRegion!=0 );
      *pp = &((u8 *)pFd->pMapRegion)[iOff];
      pFd->nFetchOut++;
@@ -53252,6 +53271,14 @@ SQLITE_API unsigned char *sqlite3_serialize(
    pOut = 0;
  }else{
    sz = sqlite3_column_int64(pStmt, 0)*szPage;
+
    if( sz==0 ){
+
      sqlite3_reset(pStmt);
+
      sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0);
+
      rc = sqlite3_step(pStmt);
+
      if( rc==SQLITE_ROW ){
+
        sz = sqlite3_column_int64(pStmt, 0)*szPage;
+
      }
+
    }
    if( piSize ) *piSize = sz;
    if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
      pOut = 0;
@@ -76402,7 +76429,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
  }

  pPage = pCur->pPage;
-
  assert( pPage->isInit );
+
  if( sqlite3FaultSim(412) ) pPage->isInit = 0;
+
  if( !pPage->isInit ){
+
    return SQLITE_CORRUPT_BKPT;
+
  }
  if( !pPage->leaf ){
    int idx = pCur->ix;
    rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
@@ -77075,7 +77105,10 @@ static int fillInCell(
    n = nHeader + nPayload;
    testcase( n==3 );
    testcase( n==4 );
-
    if( n<4 ) n = 4;
+
    if( n<4 ){
+
      n = 4;
+
      pPayload[nPayload] = 0;
+
    }
    *pnSize = n;
    assert( nSrc<=nPayload );
    testcase( nSrc<nPayload );
@@ -79521,7 +79554,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
  if( flags & BTREE_PREFORMAT ){
    rc = SQLITE_OK;
    szNew = p->pBt->nPreformatSize;
-
    if( szNew<4 ) szNew = 4;
+
    if( szNew<4 ){
+
      szNew = 4;
+
      newCell[3] = 0;
+
    }
    if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){
      CellInfo info;
      pPage->xParseCell(pPage, newCell, &info);
@@ -88366,6 +88402,23 @@ static void serialGet(
    pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
  }
}
+
static int serialGet7(
+
  const unsigned char *buf,     /* Buffer to deserialize from */
+
  Mem *pMem                     /* Memory cell to write value into */
+
){
+
  u64 x = FOUR_BYTE_UINT(buf);
+
  u32 y = FOUR_BYTE_UINT(buf+4);
+
  x = (x<<32) + y;
+
  assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
+
  swapMixedEndianFloat(x);
+
  memcpy(&pMem->u.r, &x, sizeof(x));
+
  if( IsNaN(x) ){
+
    pMem->flags = MEM_Null;
+
    return 1;
+
  }
+
  pMem->flags = MEM_Real;
+
  return 0;
+
}
SQLITE_PRIVATE void sqlite3VdbeSerialGet(
  const unsigned char *buf,     /* Buffer to deserialize from */
  u32 serial_type,              /* Serial type to deserialize */
@@ -89045,7 +89098,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
      }else if( serial_type==0 ){
        rc = -1;
      }else if( serial_type==7 ){
-
        sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+
        serialGet7(&aKey1[d1], &mem1);
        rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
      }else{
        i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
@@ -89070,14 +89123,18 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
      }else if( serial_type==0 ){
        rc = -1;
      }else{
-
        sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
        if( serial_type==7 ){
-
          if( mem1.u.r<pRhs->u.r ){
+
          if( serialGet7(&aKey1[d1], &mem1) ){
+
            rc = -1;  /* mem1 is a NaN */
+
          }else if( mem1.u.r<pRhs->u.r ){
            rc = -1;
          }else if( mem1.u.r>pRhs->u.r ){
            rc = +1;
+
          }else{
+
            assert( rc==0 );
          }
        }else{
+
          sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
          rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
        }
      }
@@ -89147,7 +89204,14 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
    /* RHS is null */
    else{
      serial_type = aKey1[idx1];
-
      rc = (serial_type!=0 && serial_type!=10);
+
      if( serial_type==0
+
       || serial_type==10
+
       || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0)
+
      ){
+
        assert( rc==0 );
+
      }else{
+
        rc = 1;
+
      }
    }

    if( rc!=0 ){
@@ -94845,7 +94909,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
        }
      }
    }else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){
-
      if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
+
      if( (flags1 & MEM_Str)!=0 ){
+
        pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
+
      }else if( (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
        testcase( pIn1->flags & MEM_Int );
        testcase( pIn1->flags & MEM_Real );
        testcase( pIn1->flags & MEM_IntReal );
@@ -94854,7 +94920,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
        flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
        if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
      }
-
      if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
+
      if( (flags3 & MEM_Str)!=0 ){
+
        pIn3->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
+
      }else if( (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
        testcase( pIn3->flags & MEM_Int );
        testcase( pIn3->flags & MEM_Real );
        testcase( pIn3->flags & MEM_IntReal );
@@ -106199,6 +106267,8 @@ static void resolveAlias(
  assert( iCol>=0 && iCol<pEList->nExpr );
  pOrig = pEList->a[iCol].pExpr;
  assert( pOrig!=0 );
+
  assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
+
  if( pExpr->pAggInfo ) return;
  db = pParse->db;
  pDup = sqlite3ExprDup(db, pOrig, 0);
  if( db->mallocFailed ){
@@ -107084,6 +107154,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
    ** resolved.  This prevents "column" from being counted as having been
    ** referenced, which might prevent a SELECT from being erroneously
    ** marked as correlated.
+
    **
+
    ** 2024-03-28: Beware of aggregates.  A bare column of aggregated table
+
    ** can still evaluate to NULL even though it is marked as NOT NULL.
+
    ** Example:
+
    **
+
    **       CREATE TABLE t1(a INT NOT NULL);
+
    **       SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1;
+
    **
+
    ** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized
+
    ** here because at the time this case is hit, we do not yet know whether
+
    ** or not t1 is being aggregated.  We have to assume the worst and omit
+
    ** the optimization.  The only time it is safe to apply this optimization
+
    ** is within the WHERE clause.
    */
    case TK_NOTNULL:
    case TK_ISNULL: {
@@ -107094,19 +107177,36 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
        anRef[i] = p->nRef;
      }
      sqlite3WalkExpr(pWalker, pExpr->pLeft);
-
      if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
-
        testcase( ExprHasProperty(pExpr, EP_OuterON) );
-
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
-
        pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
-
        pExpr->flags |= EP_IntValue;
-
        pExpr->op = TK_INTEGER;
+
      if( IN_RENAME_OBJECT ) return WRC_Prune;
+
      if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
+
        /* The expression can be NULL.  So the optimization does not apply */
+
        return WRC_Prune;
+
      }

-
        for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
-
          p->nRef = anRef[i];
+
      for(i=0, p=pNC; p; p=p->pNext, i++){
+
        if( (p->ncFlags & NC_Where)==0 ){
+
          return WRC_Prune;  /* Not in a WHERE clause.  Unsafe to optimize. */
        }
-
        sqlite3ExprDelete(pParse->db, pExpr->pLeft);
-
        pExpr->pLeft = 0;
      }
+
      testcase( ExprHasProperty(pExpr, EP_OuterON) );
+
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
+
#if TREETRACE_ENABLED
+
      if( sqlite3TreeTrace & 0x80000 ){
+
        sqlite3DebugPrintf(
+
           "NOT NULL strength reduction converts the following to %d:\n",
+
           pExpr->op==TK_NOTNULL
+
        );
+
        sqlite3ShowExpr(pExpr);
+
      }
+
#endif /* TREETRACE_ENABLED */
+
      pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
+
      pExpr->flags |= EP_IntValue;
+
      pExpr->op = TK_INTEGER;
+
      for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
+
        p->nRef = anRef[i];
+
      }
+
      sqlite3ExprDelete(pParse->db, pExpr->pLeft);
+
      pExpr->pLeft = 0;
      return WRC_Prune;
    }

@@ -108006,7 +108106,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
      }
      if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
    }
+
    sNC.ncFlags |= NC_Where;
    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
+
    sNC.ncFlags &= ~NC_Where;

    /* Resolve names in table-valued-function arguments */
    for(i=0; i<p->pSrc->nSrc; i++){
@@ -128934,13 +129036,13 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
      double r1, r2;
      const char *zVal;
      r1 = sqlite3_value_double(pValue);
-
      sqlite3_str_appendf(pStr, "%!.15g", r1);
+
      sqlite3_str_appendf(pStr, "%!0.15g", r1);
      zVal = sqlite3_str_value(pStr);
      if( zVal ){
        sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
        if( r1!=r2 ){
          sqlite3_str_reset(pStr);
-
          sqlite3_str_appendf(pStr, "%!.20e", r1);
+
          sqlite3_str_appendf(pStr, "%!0.20e", r1);
        }
      }
      break;
@@ -129242,7 +129344,7 @@ static void replaceFunc(
  }
  if( zPattern[0]==0 ){
    assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
-
    sqlite3_result_value(context, argv[0]);
+
    sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT);
    return;
  }
  nPattern = sqlite3_value_bytes(argv[1]);
@@ -133162,7 +133264,7 @@ SQLITE_PRIVATE void sqlite3Insert(
      pNx->iDataCur = iDataCur;
      pNx->iIdxCur = iIdxCur;
      if( pNx->pUpsertTarget ){
-
        if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
+
        if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){
          goto insert_cleanup;
        }
      }
@@ -139461,31 +139563,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
        int mxCol;              /* Maximum non-virtual column number */

        if( pObjTab && pObjTab!=pTab ) continue;
-
        if( !IsOrdinaryTable(pTab) ){
-
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
          sqlite3_vtab *pVTab;
-
          int a1;
-
          if( !IsVirtual(pTab) ) continue;
-
          if( pTab->nCol<=0 ){
-
            const char *zMod = pTab->u.vtab.azArg[0];
-
            if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
-
          }
-
          sqlite3ViewGetColumnNames(pParse, pTab);
-
          if( pTab->u.vtab.p==0 ) continue;
-
          pVTab = pTab->u.vtab.p->pVtab;
-
          if( NEVER(pVTab==0) ) continue;
-
          if( NEVER(pVTab->pModule==0) ) continue;
-
          if( pVTab->pModule->iVersion<4 ) continue;
-
          if( pVTab->pModule->xIntegrity==0 ) continue;
-
          sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
-
          pTab->nTabRef++;
-
          sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
-
          a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
-
          integrityCheckResultRow(v);
-
          sqlite3VdbeJumpHere(v, a1);
-
#endif
-
          continue;
-
        }
+
        if( !IsOrdinaryTable(pTab) ) continue;
        if( isQuick || HasRowid(pTab) ){
          pPk = 0;
          r2 = 0;
@@ -139620,6 +139698,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
              ** is REAL, we have to load the actual data using OP_Column
              ** to reliably determine if the value is a NULL. */
              sqlite3VdbeAddOp3(v, OP_Column, p1, p3, 3);
+
              sqlite3ColumnDefault(v, pTab, j, 3);
              jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk);
              VdbeCoverage(v);
            }
@@ -139810,6 +139889,38 @@ SQLITE_PRIVATE void sqlite3Pragma(
          }
        }
      }
+

+
#ifndef SQLITE_OMIT_VIRTUALTABLE
+
      /* Second pass to invoke the xIntegrity method on all virtual
+
      ** tables.
+
      */
+
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+
        Table *pTab = sqliteHashData(x);
+
        sqlite3_vtab *pVTab;
+
        int a1;
+
        if( pObjTab && pObjTab!=pTab ) continue;
+
        if( IsOrdinaryTable(pTab) ) continue;
+
        if( !IsVirtual(pTab) ) continue;
+
        if( pTab->nCol<=0 ){
+
          const char *zMod = pTab->u.vtab.azArg[0];
+
          if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
+
        }
+
        sqlite3ViewGetColumnNames(pParse, pTab);
+
        if( pTab->u.vtab.p==0 ) continue;
+
        pVTab = pTab->u.vtab.p->pVtab;
+
        if( NEVER(pVTab==0) ) continue;
+
        if( NEVER(pVTab->pModule==0) ) continue;
+
        if( pVTab->pModule->iVersion<4 ) continue;
+
        if( pVTab->pModule->xIntegrity==0 ) continue;
+
        sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
+
        pTab->nTabRef++;
+
        sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
+
        a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
+
        integrityCheckResultRow(v);
+
        sqlite3VdbeJumpHere(v, a1);
+
        continue;
+
      }
+
#endif
    }
    {
      static const int iLn = VDBE_OFFSET_LINENO(2);
@@ -153447,7 +153558,8 @@ SQLITE_PRIVATE Upsert *sqlite3UpsertNew(
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
  Parse *pParse,     /* The parsing context */
  SrcList *pTabList, /* Table into which we are inserting */
-
  Upsert *pUpsert    /* The ON CONFLICT clauses */
+
  Upsert *pUpsert,   /* The ON CONFLICT clauses */
+
  Upsert *pAll       /* Complete list of all ON CONFLICT clauses */
){
  Table *pTab;            /* That table into which we are inserting */
  int rc;                 /* Result code */
@@ -153550,6 +153662,14 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
        continue;
      }
      pUpsert->pUpsertIdx = pIdx;
+
      if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){
+
        /* Really this should be an error.  The isDup ON CONFLICT clause will
+
        ** never fire.  But this problem was not discovered until three years
+
        ** after multi-CONFLICT upsert was added, and so we silently ignore
+
        ** the problem to prevent breaking applications that might actually
+
        ** have redundant ON CONFLICT clauses. */
+
        pUpsert->isDup = 1;
+
      }
      break;
    }
    if( pUpsert->pUpsertIdx==0 ){
@@ -153576,9 +153696,13 @@ SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
  Upsert *pNext;
  if( NEVER(pUpsert==0) ) return 0;
  pNext = pUpsert->pNextUpsert;
-
  if( pNext==0 ) return 1;
-
  if( pNext->pUpsertTarget==0 ) return 1;
-
  if( pNext->pUpsertIdx==0 ) return 1;
+
  while( 1 /*exit-by-return*/ ){
+
    if( pNext==0 ) return 1;
+
    if( pNext->pUpsertTarget==0 ) return 1;
+
    if( pNext->pUpsertIdx==0 ) return 1;
+
    if( !pNext->isDup ) return 0;
+
    pNext = pNext->pNextUpsert;
+
  }
  return 0;
}

@@ -166812,7 +166936,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(

  /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
  testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
-
  if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
+
  if( pOrderBy && pOrderBy->nExpr>=BMS ){
+
    pOrderBy = 0;
+
    wctrlFlags &= ~WHERE_WANT_DISTINCT;
+
  }

  /* The number of tables in the FROM clause is limited by the number of
  ** bits in a Bitmask
@@ -184749,6 +184876,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);

SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*);

+
SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
+

#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

@@ -188471,7 +188600,7 @@ static int fts3ShadowName(const char *zName){
** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual
** table.
*/
-
static int fts3Integrity(
+
static int fts3IntegrityMethod(
  sqlite3_vtab *pVtab,      /* The virtual table to be checked */
  const char *zSchema,      /* Name of schema in which pVtab lives */
  const char *zTabname,     /* Name of the pVTab table */
@@ -188479,30 +188608,21 @@ static int fts3Integrity(
  char **pzErr              /* Write error message here */
){
  Fts3Table *p = (Fts3Table*)pVtab;
-
  char *zSql;
  int rc;
-
  char *zErr = 0;
+
  int bOk = 0;

-
  assert( pzErr!=0 );
-
  assert( *pzErr==0 );
  UNUSED_PARAMETER(isQuick);
-
  zSql = sqlite3_mprintf(
-
            "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');",
-
            zSchema, zTabname, zTabname);
-
  if( zSql==0 ){
-
    return SQLITE_NOMEM;
-
  }
-
  rc = sqlite3_exec(p->db, zSql, 0, 0, &zErr);
-
  sqlite3_free(zSql);
-
  if( (rc&0xff)==SQLITE_CORRUPT ){
-
    *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
-
                p->bFts4 ? 4 : 3, zSchema, zTabname);
-
  }else if( rc!=SQLITE_OK ){
+
  rc = sqlite3Fts3IntegrityCheck(p, &bOk);
+
  assert( rc!=SQLITE_CORRUPT_VTAB || bOk==0 );
+
  if( rc!=SQLITE_OK && rc!=SQLITE_CORRUPT_VTAB ){
    *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
                             " FTS%d table %s.%s: %s",
-
                p->bFts4 ? 4 : 3, zSchema, zTabname, zErr);
+
                p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc));
+
  }else if( bOk==0 ){
+
    *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
+
                p->bFts4 ? 4 : 3, zSchema, zTabname);
  }
-
  sqlite3_free(zErr);
+
  sqlite3Fts3SegmentsClose(p);
  return SQLITE_OK;
}

@@ -188533,7 +188653,7 @@ static const sqlite3_module fts3Module = {
  /* xRelease      */ fts3ReleaseMethod,
  /* xRollbackTo   */ fts3RollbackToMethod,
  /* xShadowName   */ fts3ShadowName,
-
  /* xIntegrity    */ fts3Integrity,
+
  /* xIntegrity    */ fts3IntegrityMethod,
};

/*
@@ -200087,7 +200207,7 @@ static u64 fts3ChecksumIndex(
** If an error occurs (e.g. an OOM or IO error), return an SQLite error
** code. The final value of *pbOk is undefined in this case.
*/
-
static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
+
SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
  int rc = SQLITE_OK;             /* Return code */
  u64 cksum1 = 0;                 /* Checksum based on FTS index contents */
  u64 cksum2 = 0;                 /* Checksum based on %_content contents */
@@ -200165,7 +200285,7 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
    sqlite3_finalize(pStmt);
  }

-
  *pbOk = (cksum1==cksum2);
+
  *pbOk = (rc==SQLITE_OK && cksum1==cksum2);
  return rc;
}

@@ -200205,7 +200325,7 @@ static int fts3DoIntegrityCheck(
){
  int rc;
  int bOk = 0;
-
  rc = fts3IntegrityCheck(p, &bOk);
+
  rc = sqlite3Fts3IntegrityCheck(p, &bOk);
  if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
  return rc;
}
@@ -203758,6 +203878,16 @@ static void jsonAppendChar(JsonString *p, char c){
  }
}

+
/* Remove a single character from the end of the string
+
*/
+
static void jsonStringTrimOneChar(JsonString *p){
+
  if( p->eErr==0 ){
+
    assert( p->nUsed>0 );
+
    p->nUsed--;
+
  }
+
}
+

+

/* Make sure there is a zero terminator on p->zBuf[]
**
** Return true on success.  Return false if an OOM prevents this
@@ -203765,7 +203895,7 @@ static void jsonAppendChar(JsonString *p, char c){
*/
static int jsonStringTerminate(JsonString *p){
  jsonAppendChar(p, 0);
-
  p->nUsed--;
+
  jsonStringTrimOneChar(p);
  return p->eErr==0;
}

@@ -204766,6 +204896,7 @@ json_parse_restart:
  case '[': {
    /* Parse array */
    iThis = pParse->nBlob;
+
    assert( i<=(u32)pParse->nJson );
    jsonBlobAppendNode(pParse, JSONB_ARRAY, pParse->nJson - i, 0);
    iStart = pParse->nBlob;
    if( pParse->oom ) return -1;
@@ -205164,6 +205295,10 @@ static void jsonReturnStringAsBlob(JsonString *pStr){
  JsonParse px;
  memset(&px, 0, sizeof(px));
  jsonStringTerminate(pStr);
+
  if( pStr->eErr ){
+
    sqlite3_result_error_nomem(pStr->pCtx);
+
    return;
+
  }
  px.zJson = pStr->zBuf;
  px.nJson = pStr->nUsed;
  px.db = sqlite3_context_db_handle(pStr->pCtx);
@@ -205231,8 +205366,8 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
         (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
    n = 9;
  }
-
  if( i+sz+n > pParse->nBlob
-
   && i+sz+n > pParse->nBlob-pParse->delta
+
  if( (i64)i+sz+n > pParse->nBlob
+
   && (i64)i+sz+n > pParse->nBlob-pParse->delta
  ){
    sz = 0;
    n = 0;
@@ -205282,6 +205417,7 @@ static u32 jsonTranslateBlobToText(
    }
    case JSONB_INT:
    case JSONB_FLOAT: {
+
      if( sz==0 ) goto malformed_jsonb;
      jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz);
      break;
    }
@@ -205290,6 +205426,7 @@ static u32 jsonTranslateBlobToText(
      sqlite3_uint64 u = 0;
      const char *zIn = (const char*)&pParse->aBlob[i+n];
      int bOverflow = 0;
+
      if( sz==0 ) goto malformed_jsonb;
      if( zIn[0]=='-' ){
        jsonAppendChar(pOut, '-');
        k++;
@@ -205312,6 +205449,7 @@ static u32 jsonTranslateBlobToText(
    case JSONB_FLOAT5: { /* Float literal missing digits beside "." */
      u32 k = 0;
      const char *zIn = (const char*)&pParse->aBlob[i+n];
+
      if( sz==0 ) goto malformed_jsonb;
      if( zIn[0]=='-' ){
        jsonAppendChar(pOut, '-');
        k++;
@@ -205425,11 +205563,12 @@ static u32 jsonTranslateBlobToText(
      jsonAppendChar(pOut, '[');
      j = i+n;
      iEnd = j+sz;
-
      while( j<iEnd ){
+
      while( j<iEnd && pOut->eErr==0 ){
        j = jsonTranslateBlobToText(pParse, j, pOut);
        jsonAppendChar(pOut, ',');
      }
-
      if( sz>0 ) pOut->nUsed--;
+
      if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
+
      if( sz>0 ) jsonStringTrimOneChar(pOut);
      jsonAppendChar(pOut, ']');
      break;
    }
@@ -205438,17 +205577,18 @@ static u32 jsonTranslateBlobToText(
      jsonAppendChar(pOut, '{');
      j = i+n;
      iEnd = j+sz;
-
      while( j<iEnd ){
+
      while( j<iEnd && pOut->eErr==0 ){
        j = jsonTranslateBlobToText(pParse, j, pOut);
        jsonAppendChar(pOut, (x++ & 1) ? ',' : ':');
      }
-
      if( x & 1 ) pOut->eErr |= JSTRING_MALFORMED;
-
      if( sz>0 ) pOut->nUsed--;
+
      if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
+
      if( sz>0 ) jsonStringTrimOneChar(pOut);
      jsonAppendChar(pOut, '}');
      break;
    }

    default: {
+
      malformed_jsonb:
      pOut->eErr |= JSTRING_MALFORMED;
      break;
    }
@@ -206376,6 +206516,38 @@ jsonInsertIntoBlob_patherror:
}

/*
+
** If pArg is a blob that seems like a JSONB blob, then initialize
+
** p to point to that JSONB and return TRUE.  If pArg does not seem like
+
** a JSONB blob, then return FALSE;
+
**
+
** This routine is only called if it is already known that pArg is a
+
** blob.  The only open question is whether or not the blob appears
+
** to be a JSONB blob.
+
*/
+
static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){
+
  u32 n, sz = 0;
+
  p->aBlob = (u8*)sqlite3_value_blob(pArg);
+
  p->nBlob = (u32)sqlite3_value_bytes(pArg);
+
  if( p->nBlob==0 ){
+
    p->aBlob = 0;
+
    return 0;
+
  }
+
  if( NEVER(p->aBlob==0) ){
+
    return 0;
+
  }
+
  if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT
+
   && (n = jsonbPayloadSize(p, 0, &sz))>0
+
   && sz+n==p->nBlob
+
   && ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0)
+
  ){
+
    return 1;
+
  }
+
  p->aBlob = 0;
+
  p->nBlob = 0;
+
  return 0;
+
}
+

+
/*
** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob,
** from the SQL function argument pArg.  Return a pointer to the new
** JsonParse object.
@@ -206431,34 +206603,30 @@ rebuild_from_cache:
    return p;
  }
  if( eType==SQLITE_BLOB ){
-
    u32 n, sz = 0;
-
    p->aBlob = (u8*)sqlite3_value_blob(pArg);
-
    p->nBlob = (u32)sqlite3_value_bytes(pArg);
-
    if( p->nBlob==0 ){
-
      goto json_pfa_malformed;
-
    }
-
    if( NEVER(p->aBlob==0) ){
-
      goto json_pfa_oom;
-
    }
-
    if( (p->aBlob[0] & 0x0f)>JSONB_OBJECT ){
-
      goto json_pfa_malformed;
-
    }
-
    n = jsonbPayloadSize(p, 0, &sz);
-
    if( n==0
-
     || sz+n!=p->nBlob
-
     || ((p->aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0)
-
    ){
-
      goto json_pfa_malformed;
-
    }
-
    if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){
-
      goto json_pfa_oom;
+
    if( jsonArgIsJsonb(pArg,p) ){
+
      if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){
+
        goto json_pfa_oom;
+
      }
+
      return p;
    }
-
    return p;
+
    /* If the blob is not valid JSONB, fall through into trying to cast
+
    ** the blob into text which is then interpreted as JSON.  (tag-20240123-a)
+
    **
+
    ** This goes against all historical documentation about how the SQLite
+
    ** JSON functions were suppose to work.  From the beginning, blob was
+
    ** reserved for expansion and a blob value should have raised an error.
+
    ** But it did not, due to a bug.  And many applications came to depend
+
    ** upon this buggy behavior, espeically when using the CLI and reading
+
    ** JSON text using readfile(), which returns a blob.  For this reason
+
    ** we will continue to support the bug moving forward.
+
    ** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
+
    */
  }
  p->zJson = (char*)sqlite3_value_text(pArg);
  p->nJson = sqlite3_value_bytes(pArg);
+
  if( db->mallocFailed ) goto json_pfa_oom;
  if( p->nJson==0 ) goto json_pfa_malformed;
-
  if( NEVER(p->zJson==0) ) goto json_pfa_oom;
+
  assert( p->zJson!=0 );
  if( jsonConvertTextToBlob(p, (flgs & JSON_KEEPERROR) ? 0 : ctx) ){
    if( flgs & JSON_KEEPERROR ){
      p->nErr = 1;
@@ -206624,10 +206792,10 @@ static void jsonDebugPrintBlob(
      if( sz==0 && x<=JSONB_FALSE ){
        sqlite3_str_append(pOut, "\n", 1);
      }else{
-
        u32 i;
+
        u32 j;
        sqlite3_str_appendall(pOut, ": \"");
-
        for(i=iStart+n; i<iStart+n+sz; i++){
-
          u8 c = pParse->aBlob[i];
+
        for(j=iStart+n; j<iStart+n+sz; j++){
+
          u8 c = pParse->aBlob[j];
          if( c<0x20 || c>=0x7f ) c = '.';
          sqlite3_str_append(pOut, (char*)&c, 1);
        }
@@ -207429,12 +207597,12 @@ static void jsonValidFunc(
      return;
    }
    case SQLITE_BLOB: {
-
      if( (flags & 0x0c)!=0 && jsonFuncArgMightBeBinary(argv[0]) ){
+
      if( jsonFuncArgMightBeBinary(argv[0]) ){
        if( flags & 0x04 ){
          /* Superficial checking only - accomplished by the
          ** jsonFuncArgMightBeBinary() call above. */
          res = 1;
-
        }else{
+
        }else if( flags & 0x08 ){
          /* Strict checking.  Check by translating BLOB->TEXT->BLOB.  If
          ** no errors occur, call that a "strict check". */
          JsonParse px;
@@ -207445,8 +207613,11 @@ static void jsonValidFunc(
          iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
          res = iErr==0;
        }
+
        break;
      }
-
      break;
+
      /* Fall through into interpreting the input as text.  See note
+
      ** above at tag-20240123-a. */
+
      /* no break */ deliberate_fall_through
    }
    default: {
      JsonParse px;
@@ -207571,7 +207742,7 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
      if( isFinal ){
        if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
      }else{
-
        pStr->nUsed--;
+
        jsonStringTrimOneChar(pStr);
      }
      return;
    }else if( isFinal ){
@@ -207581,7 +207752,7 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
      pStr->bStatic = 1;
    }else{
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
-
      pStr->nUsed--;
+
      jsonStringTrimOneChar(pStr);
    }
  }else{
    sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
@@ -207691,7 +207862,7 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
      if( isFinal ){
        if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
      }else{
-
        pStr->nUsed--;
+
        jsonStringTrimOneChar(pStr);
      }
      return;
    }else if( isFinal ){
@@ -207701,7 +207872,7 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
      pStr->bStatic = 1;
    }else{
      sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
-
      pStr->nUsed--;
+
      jsonStringTrimOneChar(pStr);
    }
  }else{
    sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
@@ -208032,6 +208203,9 @@ static int jsonEachColumn(
    case JEACH_VALUE: {
      u32 i = jsonSkipLabel(p);
      jsonReturnFromBlob(&p->sParse, i, ctx, 1);
+
      if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){
+
        sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+
      }
      break;
    }
    case JEACH_TYPE: {
@@ -208078,9 +208252,9 @@ static int jsonEachColumn(
    case JEACH_JSON: {
      if( p->sParse.zJson==0 ){
        sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
-
                            SQLITE_STATIC);
+
                            SQLITE_TRANSIENT);
      }else{
-
        sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
+
        sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT);
      }
      break;
    }
@@ -208182,13 +208356,9 @@ static int jsonEachFilter(
  memset(&p->sParse, 0, sizeof(p->sParse));
  p->sParse.nJPRef = 1;
  p->sParse.db = p->db;
-
  if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
-
    if( jsonFuncArgMightBeBinary(argv[0]) ){
-
      p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
-
      p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
-
    }else{
-
      goto json_each_malformed_input;
-
    }
+
  if( jsonFuncArgMightBeBinary(argv[0]) ){
+
    p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
+
    p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
  }else{
    p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
    p->sParse.nJson = sqlite3_value_bytes(argv[0]);
@@ -209110,11 +209280,9 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
** Clear the Rtree.pNodeBlob object
*/
static void nodeBlobReset(Rtree *pRtree){
-
  if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
-
    sqlite3_blob *pBlob = pRtree->pNodeBlob;
-
    pRtree->pNodeBlob = 0;
-
    sqlite3_blob_close(pBlob);
-
  }
+
  sqlite3_blob *pBlob = pRtree->pNodeBlob;
+
  pRtree->pNodeBlob = 0;
+
  sqlite3_blob_close(pBlob);
}

/*
@@ -209158,7 +209326,6 @@ static int nodeAcquire(
                           &pRtree->pNodeBlob);
  }
  if( rc ){
-
    nodeBlobReset(pRtree);
    *ppNode = 0;
    /* If unable to open an sqlite3_blob on the desired row, that can only
    ** be because the shadow tables hold erroneous data. */
@@ -209218,6 +209385,7 @@ static int nodeAcquire(
    }
    *ppNode = pNode;
  }else{
+
    nodeBlobReset(pRtree);
    if( pNode ){
      pRtree->nNodeRef--;
      sqlite3_free(pNode);
@@ -209362,6 +209530,7 @@ static void nodeGetCoord(
  int iCoord,                  /* Which coordinate to extract */
  RtreeCoord *pCoord           /* OUT: Space to write result to */
){
+
  assert( iCell<NCELL(pNode) );
  readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
}

@@ -209551,7 +209720,9 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
  sqlite3_finalize(pCsr->pReadAux);
  sqlite3_free(pCsr);
  pRtree->nCursor--;
-
  nodeBlobReset(pRtree);
+
  if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){
+
    nodeBlobReset(pRtree);
+
  }
  return SQLITE_OK;
}

@@ -210136,7 +210307,11 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
  int rc = SQLITE_OK;
  RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
  if( rc==SQLITE_OK && ALWAYS(p) ){
-
    *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
+
    if( p->iCell>=NCELL(pNode) ){
+
      rc = SQLITE_ABORT;
+
    }else{
+
      *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
+
    }
  }
  return rc;
}
@@ -210154,6 +210329,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){

  if( rc ) return rc;
  if( NEVER(p==0) ) return SQLITE_OK;
+
  if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT;
  if( i==0 ){
    sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
  }else if( i<=pRtree->nDim2 ){
@@ -211635,8 +211811,7 @@ constraint:
*/
static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
  Rtree *pRtree = (Rtree *)pVtab;
-
  assert( pRtree->inWrTrans==0 );
-
  pRtree->inWrTrans++;
+
  pRtree->inWrTrans = 1;
  return SQLITE_OK;
}

@@ -211650,6 +211825,9 @@ static int rtreeEndTransaction(sqlite3_vtab *pVtab){
  nodeBlobReset(pRtree);
  return SQLITE_OK;
}
+
static int rtreeRollback(sqlite3_vtab *pVtab){
+
  return rtreeEndTransaction(pVtab);
+
}

/*
** The xRename method for rtree module virtual tables.
@@ -211768,7 +211946,7 @@ static sqlite3_module rtreeModule = {
  rtreeBeginTransaction,      /* xBegin - begin transaction */
  rtreeEndTransaction,        /* xSync - sync transaction */
  rtreeEndTransaction,        /* xCommit - commit transaction */
-
  rtreeEndTransaction,        /* xRollback - rollback transaction */
+
  rtreeRollback,              /* xRollback - rollback transaction */
  0,                          /* xFindFunction - function overloading */
  rtreeRename,                /* xRename - rename the table */
  rtreeSavepoint,             /* xSavepoint */
@@ -245327,23 +245505,26 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
static void fts5TokendataIterNext(Fts5Iter *pIter, int bFrom, i64 iFrom){
  int ii;
  Fts5TokenDataIter *pT = pIter->pTokenDataIter;
+
  Fts5Index *pIndex = pIter->pIndex;

  for(ii=0; ii<pT->nIter; ii++){
    Fts5Iter *p = pT->apIter[ii];
    if( p->base.bEof==0
     && (p->base.iRowid==pIter->base.iRowid || (bFrom && p->base.iRowid<iFrom))
    ){
-
      fts5MultiIterNext(p->pIndex, p, bFrom, iFrom);
+
      fts5MultiIterNext(pIndex, p, bFrom, iFrom);
      while( bFrom && p->base.bEof==0
          && p->base.iRowid<iFrom
-
          && p->pIndex->rc==SQLITE_OK
+
          && pIndex->rc==SQLITE_OK
      ){
-
        fts5MultiIterNext(p->pIndex, p, 0, 0);
+
        fts5MultiIterNext(pIndex, p, 0, 0);
      }
    }
  }

-
  fts5IterSetOutputsTokendata(pIter);
+
  if( pIndex->rc==SQLITE_OK ){
+
    fts5IterSetOutputsTokendata(pIter);
+
  }
}

/*
@@ -250497,7 +250678,7 @@ static void fts5SourceIdFunc(
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
-
  sqlite3_result_text(pCtx, "fts5: 2024-01-15 17:01:13 1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d", -1, SQLITE_TRANSIENT);
+
  sqlite3_result_text(pCtx, "fts5: 2024-03-12 11:06:23 d8cd6d49b46a395b13955387d05e9e1a2a47e54fb99f3c9b59835bbefad6af77", -1, SQLITE_TRANSIENT);
}

/*
@@ -250528,27 +250709,21 @@ static int fts5IntegrityMethod(
  char **pzErr            /* Write error message here */
){
  Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
-
  Fts5Config *pConfig = pTab->p.pConfig;
-
  char *zSql;
-
  char *zErr = 0;
  int rc;
+

  assert( pzErr!=0 && *pzErr==0 );
  UNUSED_PARAM(isQuick);
-
  zSql = sqlite3_mprintf(
-
            "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');",
-
            zSchema, zTabname, pConfig->zName);
-
  if( zSql==0 ) return SQLITE_NOMEM;
-
  rc = sqlite3_exec(pConfig->db, zSql, 0, 0, &zErr);
-
  sqlite3_free(zSql);
+
  rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
  if( (rc&0xff)==SQLITE_CORRUPT ){
    *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
                zSchema, zTabname);
  }else if( rc!=SQLITE_OK ){
    *pzErr = sqlite3_mprintf("unable to validate the inverted index for"
                             " FTS5 table %s.%s: %s",
-
                zSchema, zTabname, zErr);
+
                zSchema, zTabname, sqlite3_errstr(rc));
  }
-
  sqlite3_free(zErr);
+
  sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
+

  return SQLITE_OK;
}

modified external/sqlite/sqlite3.h
@@ -146,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.45.0"
-
#define SQLITE_VERSION_NUMBER 3045000
-
#define SQLITE_SOURCE_ID      "2024-01-15 17:01:13 1066602b2b1976fe58b5150777cced894af17c803e068f5918390d6915b46e1d"
+
#define SQLITE_VERSION        "3.45.2"
+
#define SQLITE_VERSION_NUMBER 3045002
+
#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 d8cd6d49b46a395b13955387d05e9e1a2a47e54fb99f3c9b59835bbefad6af77"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -420,6 +420,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
**      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
**      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+
** <li> The application must not dereference the arrays or string pointers
+
**       passed as the 3rd and 4th callback parameters after it returns.
** </ul>
*/
SQLITE_API int sqlite3_exec(