| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 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 | | -** 2f1f4f73535386549c12694dc57cfe555eec with changes in files: |
| 21 | +** bdc841de10fef65b627deb8b770702c97617 with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -467,14 +467,14 @@ |
| 467 | 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | 469 | */ |
| 470 | 470 | #define SQLITE_VERSION "3.54.0" |
| 471 | 471 | #define SQLITE_VERSION_NUMBER 3054000 |
| 472 | | -#define SQLITE_SOURCE_ID "2026-07-24 16:28:47 2f1f4f73535386549c12694dc57cfe555eec689ae6824c6241aaf8d5befcd74d" |
| 472 | +#define SQLITE_SOURCE_ID "2026-08-04 14:55:51 bdc841de10fef65b627deb8b770702c976174a66af847c96ebecf24d91798744" |
| 473 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | 474 | #define SQLITE_SCM_TAGS "" |
| 475 | | -#define SQLITE_SCM_DATETIME "2026-07-24T16:28:47.830Z" |
| 475 | +#define SQLITE_SCM_DATETIME "2026-08-04T14:55:51.598Z" |
| 476 | 476 | |
| 477 | 477 | /* |
| 478 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | 480 | ** |
| | @@ -96610,11 +96610,11 @@ |
| 96610 | 96610 | }else if( p->flags & MEM_Real ){ |
| 96611 | 96611 | h += sqlite3VdbeIntValue(p); |
| 96612 | 96612 | }else if( p->flags & MEM_Str ){ |
| 96613 | 96613 | u64 x; |
| 96614 | 96614 | h += p->n; |
| 96615 | | - if( p->n >= sizeof(x) ){ |
| 96615 | + if( p->n >= (int)sizeof(x) ){ |
| 96616 | 96616 | memcpy(&x, p->z, sizeof(x)); |
| 96617 | 96617 | h += x; |
| 96618 | 96618 | memcpy(&x, p->z + p->n - sizeof(x), sizeof(x)); |
| 96619 | 96619 | h += x; |
| 96620 | 96620 | }else{ |
| | @@ -96624,11 +96624,11 @@ |
| 96624 | 96624 | } |
| 96625 | 96625 | }else if( p->flags & MEM_Blob ){ |
| 96626 | 96626 | int n = p->n; |
| 96627 | 96627 | u64 x = 0; |
| 96628 | 96628 | if( n ){ |
| 96629 | | - memcpy(&x, p->z, MIN(n, sizeof(x))); |
| 96629 | + memcpy(&x, p->z, MIN(n, (int)sizeof(x))); |
| 96630 | 96630 | h += x; |
| 96631 | 96631 | } |
| 96632 | 96632 | h += n; |
| 96633 | 96633 | if( p->flags & MEM_Zero ) h += p->u.nZero; |
| 96634 | 96634 | } |
| | @@ -106272,10 +106272,11 @@ |
| 106272 | 106272 | /* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */ |
| 106273 | 106273 | #define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask)) |
| 106274 | 106274 | |
| 106275 | 106275 | #define SORTER_TYPE_INTEGER 0x01 |
| 106276 | 106276 | #define SORTER_TYPE_TEXT 0x02 |
| 106277 | +#define SORTER_TYPE_REAL 0x04 |
| 106277 | 106278 | |
| 106278 | 106279 | /* |
| 106279 | 106280 | ** An instance of the following object is used to read records out of a |
| 106280 | 106281 | ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. |
| 106281 | 106282 | ** aKey might point into aMap or into aBuffer. If neither of those locations |
| | @@ -106844,10 +106845,182 @@ |
| 106844 | 106845 | res = res * -1; |
| 106845 | 106846 | } |
| 106846 | 106847 | |
| 106847 | 106848 | return res; |
| 106848 | 106849 | } |
| 106850 | + |
| 106851 | +/* Helper function for vdbeSorterCompareReal(). |
| 106852 | +** |
| 106853 | +** The first elements of both pKey1 and pKey2 have been decoded into double |
| 106854 | +** values r1 and r2. Do the comparison between those keys and return the |
| 106855 | +** result. If r1==r2, break the tie with a comparison of subsequent elements |
| 106856 | +** from each key. |
| 106857 | +*/ |
| 106858 | +static int vdbeSorterFinishRealCompare( |
| 106859 | + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ |
| 106860 | + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ |
| 106861 | + const void *pKey1, int nKey1, /* Left side of comparison */ |
| 106862 | + const void *pKey2, int nKey2, /* Right side of comparison */ |
| 106863 | + double r1, /* REAL value of first element of pKey1 */ |
| 106864 | + double r2 /* REAL value of first element of pKey2 */ |
| 106865 | +){ |
| 106866 | + int res; |
| 106867 | + if( r1<r2 ){ |
| 106868 | + res = -1; |
| 106869 | + }else if( r1>r2 ){ |
| 106870 | + res = +1; |
| 106871 | + }else{ |
| 106872 | + res = 0; |
| 106873 | + } |
| 106874 | + assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 ); |
| 106875 | + if( res==0 ){ |
| 106876 | + if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ |
| 106877 | + res = vdbeSorterCompareTail( |
| 106878 | + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 |
| 106879 | + ); |
| 106880 | + } |
| 106881 | + }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ |
| 106882 | + assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); |
| 106883 | + res = res * -1; |
| 106884 | + } |
| 106885 | + return res; |
| 106886 | +} |
| 106887 | + |
| 106888 | +/* Helper function for vdbeSorterCompareReal(). |
| 106889 | +** |
| 106890 | +** Read the bits of an 8-byte big-endian IEEE-754 value and store them |
| 106891 | +** into a u64. Do any necessary byte-swapping so that the bits are in |
| 106892 | +** the right order for the host machine. |
| 106893 | +** |
| 106894 | +** Copied and slightly modified from the readInt64() routine in rtree.c |
| 106895 | +*/ |
| 106896 | +static u64 vdbeSorterDecodeU64(const u8 *p){ |
| 106897 | +#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 |
| 106898 | + u64 x; |
| 106899 | + memcpy(&x, p, 8); |
| 106900 | + return _byteswap_uint64(x); |
| 106901 | +#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 |
| 106902 | + u64 x; |
| 106903 | + memcpy(&x, p, 8); |
| 106904 | + return __builtin_bswap64(x); |
| 106905 | +#elif SQLITE_BYTEORDER==4321 |
| 106906 | + i64 x; |
| 106907 | + memcpy(&x, p, 8); |
| 106908 | + return x; |
| 106909 | +#else |
| 106910 | + return (i64)( |
| 106911 | + (((u64)p[0]) << 56) + |
| 106912 | + (((u64)p[1]) << 48) + |
| 106913 | + (((u64)p[2]) << 40) + |
| 106914 | + (((u64)p[3]) << 32) + |
| 106915 | + (((u64)p[4]) << 24) + |
| 106916 | + (((u64)p[5]) << 16) + |
| 106917 | + (((u64)p[6]) << 8) + |
| 106918 | + (((u64)p[7]) << 0) |
| 106919 | + ); |
| 106920 | +#endif |
| 106921 | +} |
| 106922 | + |
| 106923 | +/* Helper function for vdbeSorterCompareReal(). |
| 106924 | +** |
| 106925 | +** Buffer p[] is a record where the first term is guaranteed to be either |
| 106926 | +** a floating-point value, or an integer stand-in for a floating point |
| 106927 | +** value (a MEM_IntReal). Whatever its format, extract the value and |
| 106928 | +** return it. |
| 106929 | +*/ |
| 106930 | +static double vdbeSorterGetReal(const u8 *p){ |
| 106931 | + double r; /* the return value */ |
| 106932 | + |
| 106933 | + assert( p[0]<0x80 ); /* 1-byte headers: nAllField<13 */ |
| 106934 | + assert( p[1]>0 && p[1]<10 ); /* first fields proven numeric */ |
| 106935 | + |
| 106936 | + if( p[1]==7 ){ |
| 106937 | + u64 x = vdbeSorterDecodeU64(p + p[0]); |
| 106938 | + swapMixedEndianFloat(x); |
| 106939 | + assert( !IsNaN(x) ); |
| 106940 | + memcpy(&r, &x, sizeof(r)); |
| 106941 | + }else{ |
| 106942 | + Mem m; |
| 106943 | + m.u.i = 0; |
| 106944 | + sqlite3VdbeSerialGet(p + p[0], p[1], &m); |
| 106945 | + assert( m.flags==MEM_Int ); |
| 106946 | + r = (double)m.u.i; |
| 106947 | + } |
| 106948 | + return r; |
| 106949 | +} |
| 106950 | + |
| 106951 | +/* Helper function for vdbeSorterCompareReal() |
| 106952 | +** |
| 106953 | +** This routine handles the case of comparing two floating-point values |
| 106954 | +** where one or both of the floating-point are represented by integers. |
| 106955 | +** In other words, where one both is an MEM_RealInt. |
| 106956 | +** |
| 106957 | +** This subroutine is factored out from vdbeSorterCompareReal() for |
| 106958 | +** efficiency. If inlined into vdbeSorterCompareReal(), this routine |
| 106959 | +** will use extra stack space and consume CPU cycles setting up and |
| 106960 | +** breaking down that stack space, even if in the common case where |
| 106961 | +** this path is not used. |
| 106962 | +*/ |
| 106963 | +static SQLITE_NOINLINE int vdbeSorterCompareRealInt( |
| 106964 | + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ |
| 106965 | + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ |
| 106966 | + const void *pKey1, int nKey1, /* Left side of comparison */ |
| 106967 | + const void *pKey2, int nKey2 /* Right side of comparison */ |
| 106968 | +){ |
| 106969 | + const u8 * const p1 = (const u8 * const)pKey1; |
| 106970 | + const u8 * const p2 = (const u8 * const)pKey2; |
| 106971 | + double r1 = vdbeSorterGetReal(p1); |
| 106972 | + double r2 = vdbeSorterGetReal(p2); |
| 106973 | + return vdbeSorterFinishRealCompare(pTask,pbKey2Cached, |
| 106974 | + pKey1,nKey1,pKey2,nKey2,r1,r2); |
| 106975 | +} |
| 106976 | + |
| 106977 | +/* |
| 106978 | +** Comparison function optimized for the case where the first term |
| 106979 | +** of both keys are either MEM_Real or MEM_RealInt. |
| 106980 | +** |
| 106981 | +** See also vdbeSorterCompareInt() for MEM_Int values and |
| 106982 | +** vdbeSorterCompareText() for MEM_Str values. The general |
| 106983 | +** case is vdbeSorterCompare() which handles anything, but is slower. |
| 106984 | +*/ |
| 106985 | +static int vdbeSorterCompareReal( |
| 106986 | + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ |
| 106987 | + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ |
| 106988 | + const void *pKey1, int nKey1, /* Left side of comparison */ |
| 106989 | + const void *pKey2, int nKey2 /* Right side of comparison */ |
| 106990 | +){ |
| 106991 | + const u8*const p1 = (const u8*const)pKey1; /* Left key record */ |
| 106992 | + const u8*const p2 = (const u8*const)pKey2; /* Right key record */ |
| 106993 | + u64 x; /* A real value stored as an integer */ |
| 106994 | + double r1; /* First element of pKey1 */ |
| 106995 | + double r2; /* First element of pKey2 */ |
| 106996 | + |
| 106997 | + assert( p1[0]<0x80 && p2[0]<0x80 ); /* 1-byte headers: nAllField<13 */ |
| 106998 | + assert( p1[1]>0 && p1[1]<10 ); /* first field guaranteed numeric */ |
| 106999 | + assert( p2[1]>0 && p2[1]<10 ); /* first field guaranteed numeric */ |
| 107000 | + |
| 107001 | + if( p1[1]!=7 || p2[1]!=7 ){ |
| 107002 | + /* One or both floating point values are stored as INTEGER (MEM_RealInt). |
| 107003 | + ** Handle this case separately for efficiency */ |
| 107004 | + return vdbeSorterCompareRealInt(pTask, |
| 107005 | + pbKey2Cached, pKey1,nKey1, pKey2,nKey2 |
| 107006 | + ); |
| 107007 | + } |
| 107008 | + assert( p1[0]<=nKey1-8 && p2[0]<=nKey2-8 ); |
| 107009 | + |
| 107010 | + x = vdbeSorterDecodeU64(p1 + *p1); |
| 107011 | + swapMixedEndianFloat(x); |
| 107012 | + assert( !IsNaN(x) ); |
| 107013 | + memcpy(&r1, &x, sizeof(r1)); |
| 107014 | + x = vdbeSorterDecodeU64(p2 + *p2); |
| 107015 | + swapMixedEndianFloat(x); |
| 107016 | + assert( !IsNaN(x) ); |
| 107017 | + memcpy(&r2, &x, sizeof(r2)); |
| 107018 | + return vdbeSorterFinishRealCompare(pTask, |
| 107019 | + pbKey2Cached, pKey1,nKey1, pKey2,nKey2, r1, r2 |
| 107020 | + ); |
| 107021 | +} |
| 106849 | 107022 | |
| 106850 | 107023 | /* |
| 106851 | 107024 | ** Initialize the temporary index cursor just opened as a sorter cursor. |
| 106852 | 107025 | ** |
| 106853 | 107026 | ** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField) |
| | @@ -106967,11 +107140,11 @@ |
| 106967 | 107140 | |
| 106968 | 107141 | if( pKeyInfo->nAllField<13 |
| 106969 | 107142 | && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) |
| 106970 | 107143 | && (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0 |
| 106971 | 107144 | ){ |
| 106972 | | - pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; |
| 107145 | + pSorter->typeMask = SORTER_TYPE_INTEGER|SORTER_TYPE_TEXT|SORTER_TYPE_REAL; |
| 106973 | 107146 | } |
| 106974 | 107147 | } |
| 106975 | 107148 | |
| 106976 | 107149 | return rc; |
| 106977 | 107150 | } |
| | @@ -107339,14 +107512,16 @@ |
| 107339 | 107512 | /* |
| 107340 | 107513 | ** Return the SorterCompare function to compare values collected by the |
| 107341 | 107514 | ** sorter object passed as the only argument. |
| 107342 | 107515 | */ |
| 107343 | 107516 | static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ |
| 107344 | | - if( p->typeMask==SORTER_TYPE_INTEGER ){ |
| 107517 | + if( p->typeMask & SORTER_TYPE_INTEGER ){ |
| 107345 | 107518 | return vdbeSorterCompareInt; |
| 107346 | | - }else if( p->typeMask==SORTER_TYPE_TEXT ){ |
| 107519 | + }else if( p->typeMask & SORTER_TYPE_TEXT ){ |
| 107347 | 107520 | return vdbeSorterCompareText; |
| 107521 | + }else if( p->typeMask & SORTER_TYPE_REAL ){ |
| 107522 | + return vdbeSorterCompareReal; |
| 107348 | 107523 | } |
| 107349 | 107524 | return vdbeSorterCompare; |
| 107350 | 107525 | } |
| 107351 | 107526 | |
| 107352 | 107527 | /* |
| | @@ -107740,12 +107915,16 @@ |
| 107740 | 107915 | int t; /* serial type of first record field */ |
| 107741 | 107916 | |
| 107742 | 107917 | assert( pCsr->eCurType==CURTYPE_SORTER ); |
| 107743 | 107918 | pSorter = pCsr->uc.pSorter; |
| 107744 | 107919 | getVarint32NR((const u8*)&pVal->z[1], t); |
| 107745 | | - if( t>0 && t<10 && t!=7 ){ |
| 107746 | | - pSorter->typeMask &= SORTER_TYPE_INTEGER; |
| 107920 | + if( t>0 && t<10 ){ |
| 107921 | + if( t==7 ){ |
| 107922 | + pSorter->typeMask &= SORTER_TYPE_REAL; |
| 107923 | + }else{ |
| 107924 | + pSorter->typeMask &= (SORTER_TYPE_INTEGER|SORTER_TYPE_REAL); |
| 107925 | + } |
| 107747 | 107926 | }else if( t>10 && (t & 0x01) ){ |
| 107748 | 107927 | pSorter->typeMask &= SORTER_TYPE_TEXT; |
| 107749 | 107928 | }else{ |
| 107750 | 107929 | pSorter->typeMask = 0; |
| 107751 | 107930 | } |
| | @@ -115337,14 +115516,12 @@ |
| 115337 | 115516 | int i; |
| 115338 | 115517 | if( !ExprUseXSelect(pX) ) return 0; /* Not a subquery */ |
| 115339 | 115518 | if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */ |
| 115340 | 115519 | p = pX->x.pSelect; |
| 115341 | 115520 | if( p->pPrior ) return 0; /* Not a compound SELECT */ |
| 115342 | | - if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ |
| 115343 | | - testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); |
| 115344 | | - testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); |
| 115345 | | - return 0; /* No DISTINCT keyword and no aggregate functions */ |
| 115521 | + if( p->selFlags & SF_Aggregate ){ |
| 115522 | + return 0; /* No GROUP BY keyword or aggregate functions */ |
| 115346 | 115523 | } |
| 115347 | 115524 | assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ |
| 115348 | 115525 | if( p->pLimit ) return 0; /* Has no LIMIT clause */ |
| 115349 | 115526 | if( p->pWhere ) return 0; /* Has no WHERE clause */ |
| 115350 | 115527 | pSrc = p->pSrc; |
| | @@ -116424,11 +116601,25 @@ |
| 116424 | 116601 | /* If this IN operator will use an index, then the order of columns in the |
| 116425 | 116602 | ** vector might be different from the order in the index. In that case, |
| 116426 | 116603 | ** we need to reorder the LHS values to be in index order. Run Affinity |
| 116427 | 116604 | ** before reordering the columns, so that the affinity is correct. |
| 116428 | 116605 | */ |
| 116429 | | - sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); |
| 116606 | + if( nVector==1 ){ |
| 116607 | + char aff = zAff[0]; |
| 116608 | + if( aff>=SQLITE_AFF_TEXT && aff!=sqlite3ExprAffinity(pLeft) ){ |
| 116609 | + /* The OP_Affinity below may change the value. In this case, create a |
| 116610 | + ** copy of rLhs to run OP_Affinity on, in case the original register |
| 116611 | + ** is used again (e.g. if it is TK_AGG_COLUMN). */ |
| 116612 | + int rTmp = sqlite3GetTempReg(pParse); |
| 116613 | + sqlite3VdbeAddOp3(v, OP_Copy, rLhs, rTmp, 0); |
| 116614 | + rLhs = rTmp; |
| 116615 | + sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, 1, 0, zAff, 1); |
| 116616 | + } |
| 116617 | + }else{ |
| 116618 | + sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); |
| 116619 | + } |
| 116620 | + |
| 116430 | 116621 | for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ |
| 116431 | 116622 | if( i!=nVector ){ |
| 116432 | 116623 | /* Need to reorder the LHS fields according to aiMap */ |
| 116433 | 116624 | int rLhsOrig = rLhs; |
| 116434 | 116625 | rLhs = sqlite3GetTempRange(pParse, nVector); |
| | @@ -136450,11 +136641,11 @@ |
| 136450 | 136641 | }else{ |
| 136451 | 136642 | i++; |
| 136452 | 136643 | } |
| 136453 | 136644 | }while( i<iGt ); |
| 136454 | 136645 | |
| 136455 | | - assert( iLt>0 && iLt<iGt && iGt<n ); |
| 136646 | + assert( iLt>0 && iLt<iGt && (unsigned)iGt<n ); |
| 136456 | 136647 | testcase( iGt>iLt+1 ); |
| 136457 | 136648 | assert( a[iLt]==rPivot ); |
| 136458 | 136649 | assert( a[iLt-1]<=rPivot ); |
| 136459 | 136650 | assert( a[iGt]>=rPivot ); |
| 136460 | 136651 | assert( a[iLt+1]>=rPivot ); |
| | @@ -156097,10 +156288,11 @@ |
| 156097 | 156288 | p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere); |
| 156098 | 156289 | pSub->pWhere = 0; |
| 156099 | 156290 | } |
| 156100 | 156291 | pSub->pSrc = 0; |
| 156101 | 156292 | sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSub); |
| 156293 | + recomputeColumnsUsed(p, &p->pSrc->a[p->pSrc->nSrc-1]); |
| 156102 | 156294 | #if TREETRACE_ENABLED |
| 156103 | 156295 | if( sqlite3TreeTrace & 0x100000 ){ |
| 156104 | 156296 | TREETRACE(0x100000,pParse,p, |
| 156105 | 156297 | ("After EXISTS-to-JOIN optimization:\n")); |
| 156106 | 156298 | sqlite3TreeViewSelect(0, p, 0); |
| | @@ -156114,14 +156306,14 @@ |
| 156114 | 156306 | /* |
| 156115 | 156307 | ** Type used for Walker callbacks by selectCheckOnClauses(). |
| 156116 | 156308 | */ |
| 156117 | 156309 | typedef struct CheckOnCtx CheckOnCtx; |
| 156118 | 156310 | struct CheckOnCtx { |
| 156119 | | - SrcList *pSrc; /* SrcList for this context */ |
| 156120 | | - int iJoin; /* Cursor numbers must be =< than this */ |
| 156121 | | - int bFuncArg; /* True for table-function arg */ |
| 156122 | | - CheckOnCtx *pParent; /* Parent context */ |
| 156311 | + SrcList *pSrc; /* SrcList for this context */ |
| 156312 | + int iJoin; /* Cursors must be left of this one, if not zero */ |
| 156313 | + int bFuncArg; /* True for table-function arg */ |
| 156314 | + CheckOnCtx *pParent; /* Parent context */ |
| 156123 | 156315 | }; |
| 156124 | 156316 | |
| 156125 | 156317 | /* |
| 156126 | 156318 | ** True if the SrcList passed as the only argument contains at least |
| 156127 | 156319 | ** one RIGHT or FULL JOIN. False otherwise. |
| | @@ -156162,23 +156354,29 @@ |
| 156162 | 156354 | if( pExpr->op==TK_COLUMN ){ |
| 156163 | 156355 | /* A column expression. Find the SrcList (if any) to which it refers. |
| 156164 | 156356 | ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an |
| 156165 | 156357 | ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it |
| 156166 | 156358 | ** does not refer to a table to the right of CheckOnCtx.iJoin. */ |
| 156359 | + int iTab = pExpr->iTable; |
| 156167 | 156360 | do { |
| 156168 | 156361 | SrcList *pSrc = pCtx->pSrc; |
| 156169 | 156362 | int nSrc = pSrc->nSrc; |
| 156170 | | - int iTab = pExpr->iTable; |
| 156171 | 156363 | int ii; |
| 156172 | 156364 | for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){} |
| 156173 | 156365 | if( ii<nSrc ){ |
| 156174 | | - if( pCtx->iJoin && iTab>pCtx->iJoin ){ |
| 156175 | | - sqlite3ErrorMsg(pWalker->pParse, |
| 156176 | | - "%s references tables to its right", |
| 156177 | | - (pCtx->bFuncArg ? "table-function argument" : "ON clause") |
| 156178 | | - ); |
| 156179 | | - return WRC_Abort; |
| 156366 | + /* pSrc is the FROM clause that contains iTab */ |
| 156367 | + if( pCtx->iJoin ){ |
| 156368 | + for(ii--; ii>=0 && pSrc->a[ii].iCursor!=pCtx->iJoin; ii--){} |
| 156369 | + if( ii>=0 ){ |
| 156370 | + /* Table iJoin appears to the left of table iTab in the SrcList. |
| 156371 | + ** Therefore the expression refers to a table to its right. */ |
| 156372 | + sqlite3ErrorMsg(pWalker->pParse, |
| 156373 | + "%s references tables to its right", |
| 156374 | + (pCtx->bFuncArg ? "table-function argument" : "ON clause") |
| 156375 | + ); |
| 156376 | + return WRC_Abort; |
| 156377 | + } |
| 156180 | 156378 | } |
| 156181 | 156379 | break; |
| 156182 | 156380 | } |
| 156183 | 156381 | pCtx = pCtx->pParent; |
| 156184 | 156382 | }while( pCtx ); |
| | @@ -164626,11 +164824,16 @@ |
| 164626 | 164824 | ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ |
| 164627 | 164825 | testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); |
| 164628 | 164826 | testcase( pTerm->wtFlags & TERM_VIRTUAL ); |
| 164629 | 164827 | r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j); |
| 164630 | 164828 | if( r1!=regBase+j ){ |
| 164631 | | - if( nReg==1 ){ |
| 164829 | + /* If this routine is being called as part of a RIGHT JOIN loop, then |
| 164830 | + ** register r1 may be used by the body of the loop that the RIGHT JOIN |
| 164831 | + ** will jump back into (e.g. if pTerm is a sub-query). This can cause |
| 164832 | + ** problems if (say) the affinity of r1 is modified by the caller of |
| 164833 | + ** this routine. So, always take a copy of the value in this case. */ |
| 164834 | + if( nReg==1 && pParse->withinRJSubrtn==0 ){ |
| 164632 | 164835 | sqlite3ReleaseTempReg(pParse, regBase); |
| 164633 | 164836 | regBase = r1; |
| 164634 | 164837 | }else{ |
| 164635 | 164838 | sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j); |
| 164636 | 164839 | } |
| | @@ -167811,10 +168014,11 @@ |
| 167811 | 168014 | #endif |
| 167812 | 168015 | pMaskSet = &pWInfo->sMaskSet; |
| 167813 | 168016 | pExpr = pTerm->pExpr; |
| 167814 | 168017 | assert( pExpr!=0 ); /* Because malloc() has not failed */ |
| 167815 | 168018 | assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); |
| 168019 | +exprAnalyze_restart: |
| 167816 | 168020 | pMaskSet->bVarSelect = 0; |
| 167817 | 168021 | prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); |
| 167818 | 168022 | op = pExpr->op; |
| 167819 | 168023 | if( op==TK_IN ){ |
| 167820 | 168024 | assert( pExpr->pRight==0 ); |
| | @@ -167977,10 +168181,15 @@ |
| 167977 | 168181 | #if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) |
| 167978 | 168182 | /* Analyze a term that is composed of two or more subterms connected by |
| 167979 | 168183 | ** an OR operator. |
| 167980 | 168184 | */ |
| 167981 | 168185 | else if( pExpr->op==TK_OR && !ExprHasProperty(pExpr, EP_Collate) ){ |
| 168186 | + Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); |
| 168187 | + if( pAlt!=pExpr ){ |
| 168188 | + pTerm->pExpr = pExpr = sqlite3ExprSkipCollateAndLikely(pAlt); |
| 168189 | + goto exprAnalyze_restart; |
| 168190 | + } |
| 167982 | 168191 | assert( pWC->op==TK_AND ); |
| 167983 | 168192 | exprAnalyzeOrTerm(pSrc, pWC, idxTerm); |
| 167984 | 168193 | pTerm = &pWC->a[idxTerm]; |
| 167985 | 168194 | } |
| 167986 | 168195 | #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ |
| | @@ -168165,10 +168374,11 @@ |
| 168165 | 168374 | && ALWAYS( ExprUseXSelect(pExpr) ) |
| 168166 | 168375 | && (pExpr->x.pSelect->pPrior==0 || (pExpr->x.pSelect->selFlags & SF_Values)) |
| 168167 | 168376 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 168168 | 168377 | && pExpr->x.pSelect->pWin==0 |
| 168169 | 168378 | #endif |
| 168379 | + && (pExpr->x.pSelect->selFlags & SF_MinMaxAgg)==0 |
| 168170 | 168380 | && pWC->op==TK_AND |
| 168171 | 168381 | && pExpr->x.pSelect->pEList->nExpr <= UMXV(pTerm->nChild) |
| 168172 | 168382 | /* ^-- See bug 2026-06-04T10:00:49Z */ |
| 168173 | 168383 | ){ |
| 168174 | 168384 | int i; |
| | @@ -197537,10 +197747,11 @@ |
| 197537 | 197747 | static void fts3SnippetFunc( |
| 197538 | 197748 | sqlite3_context *pContext, /* SQLite function call context */ |
| 197539 | 197749 | int nVal, /* Size of apVal[] array */ |
| 197540 | 197750 | sqlite3_value **apVal /* Array of arguments */ |
| 197541 | 197751 | ){ |
| 197752 | + Fts3Table *pTab = 0; |
| 197542 | 197753 | Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ |
| 197543 | 197754 | const char *zStart = "<b>"; |
| 197544 | 197755 | const char *zEnd = "</b>"; |
| 197545 | 197756 | const char *zEllipsis = "<b>...</b>"; |
| 197546 | 197757 | int iCol = -1; |
| | @@ -197555,10 +197766,11 @@ |
| 197555 | 197766 | sqlite3_result_error(pContext, |
| 197556 | 197767 | "wrong number of arguments to function snippet()", -1); |
| 197557 | 197768 | return; |
| 197558 | 197769 | } |
| 197559 | 197770 | if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; |
| 197771 | + pTab = (Fts3Table *)pCsr->base.pVtab; |
| 197560 | 197772 | |
| 197561 | 197773 | switch( nVal ){ |
| 197562 | 197774 | case 6: nToken = sqlite3_value_int(apVal[5]); |
| 197563 | 197775 | /* no break */ deliberate_fall_through |
| 197564 | 197776 | case 5: iCol = sqlite3_value_int(apVal[4]); |
| | @@ -197569,11 +197781,11 @@ |
| 197569 | 197781 | /* no break */ deliberate_fall_through |
| 197570 | 197782 | case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); |
| 197571 | 197783 | } |
| 197572 | 197784 | if( !zEllipsis || !zEnd || !zStart ){ |
| 197573 | 197785 | sqlite3_result_error_nomem(pContext); |
| 197574 | | - }else if( nToken==0 ){ |
| 197786 | + }else if( nToken==0 || iCol>=pTab->nColumn ){ |
| 197575 | 197787 | sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); |
| 197576 | 197788 | }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ |
| 197577 | 197789 | sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); |
| 197578 | 197790 | } |
| 197579 | 197791 | } |
| | @@ -201149,11 +201361,11 @@ |
| 201149 | 201361 | */ |
| 201150 | 201362 | iCol = pParse->iDefaultCol; |
| 201151 | 201363 | iColLen = 0; |
| 201152 | 201364 | for(ii=0; ii<pParse->nCol; ii++){ |
| 201153 | 201365 | const char *zStr = pParse->azCol[ii]; |
| 201154 | | - int nStr = (int)strlen(zStr); |
| 201366 | + int nStr = zStr ? (int)strlen(zStr) : 0; |
| 201155 | 201367 | if( nInput>nStr && zInput[nStr]==':' |
| 201156 | 201368 | && sqlite3_strnicmp(zStr, zInput, nStr)==0 |
| 201157 | 201369 | ){ |
| 201158 | 201370 | iCol = ii; |
| 201159 | 201371 | iColLen = (int)((zInput - z) + nStr + 1); |
| | @@ -201864,11 +202076,13 @@ |
| 201864 | 202076 | rc = fts3ExprParseUnbalanced( |
| 201865 | 202077 | pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr |
| 201866 | 202078 | ); |
| 201867 | 202079 | } |
| 201868 | 202080 | |
| 201869 | | - if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ |
| 202081 | + if( rc==SQLITE_OK && fts3ExprCheckDepth(pExpr, SQLITE_FTS3_MAX_EXPR_DEPTH) ){ |
| 202082 | + sqlite3_result_error(context, "Expression nested too deep", -1); |
| 202083 | + }else if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ |
| 201870 | 202084 | sqlite3_result_error(context, "Error parsing expression", -1); |
| 201871 | 202085 | }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){ |
| 201872 | 202086 | sqlite3_result_error_nomem(context); |
| 201873 | 202087 | }else{ |
| 201874 | 202088 | sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); |
| | @@ -256851,24 +257065,24 @@ |
| 256851 | 257065 | Fts5Buffer out; |
| 256852 | 257066 | |
| 256853 | 257067 | (void)nBuf; |
| 256854 | 257068 | memset(&out, 0, sizeof(out)); |
| 256855 | 257069 | assert( nBuf==1 ); |
| 256856 | | - sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n); |
| 257070 | + sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9); |
| 256857 | 257071 | if( p->rc ) return; |
| 256858 | 257072 | |
| 256859 | 257073 | fts5NextRowid(p1, &i1, &iRowid1); |
| 256860 | 257074 | fts5NextRowid(p2, &i2, &iRowid2); |
| 256861 | 257075 | while( i1>=0 || i2>=0 ){ |
| 256862 | 257076 | if( i1>=0 && (i2<0 || iRowid1<iRowid2) ){ |
| 256863 | 257077 | assert( iOut==0 || iRowid1>iOut ); |
| 256864 | | - fts5BufferSafeAppendVarint(&out, iRowid1 - iOut); |
| 257078 | + fts5BufferSafeAppendVarint(&out, (u64)iRowid1 - (u64)iOut); |
| 256865 | 257079 | iOut = iRowid1; |
| 256866 | 257080 | fts5NextRowid(p1, &i1, &iRowid1); |
| 256867 | 257081 | }else{ |
| 256868 | 257082 | assert( iOut==0 || iRowid2>iOut ); |
| 256869 | | - fts5BufferSafeAppendVarint(&out, iRowid2 - iOut); |
| 257083 | + fts5BufferSafeAppendVarint(&out, (u64)iRowid2 - (u64)iOut); |
| 256870 | 257084 | iOut = iRowid2; |
| 256871 | 257085 | if( i1>=0 && iRowid1==iRowid2 ){ |
| 256872 | 257086 | fts5NextRowid(p1, &i1, &iRowid1); |
| 256873 | 257087 | } |
| 256874 | 257088 | fts5NextRowid(p2, &i2, &iRowid2); |
| | @@ -263950,11 +264164,11 @@ |
| 263950 | 264164 | int nArg, /* Number of args */ |
| 263951 | 264165 | sqlite3_value **apUnused /* Function arguments */ |
| 263952 | 264166 | ){ |
| 263953 | 264167 | assert( nArg==0 ); |
| 263954 | 264168 | UNUSED_PARAM2(nArg, apUnused); |
| 263955 | | - sqlite3_result_text(pCtx, "fts5: 2026-07-24 16:28:47 2f1f4f73535386549c12694dc57cfe555eec689ae6824c6241aaf8d5befcd74d", -1, SQLITE_TRANSIENT); |
| 264169 | + sqlite3_result_text(pCtx, "fts5: 2026-08-04 14:55:51 bdc841de10fef65b627deb8b770702c976174a66af847c96ebecf24d91798744", -1, SQLITE_TRANSIENT); |
| 263956 | 264170 | } |
| 263957 | 264171 | |
| 263958 | 264172 | /* |
| 263959 | 264173 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 263960 | 264174 | ** |
| 263961 | 264175 | |