Fossil SCM
Update the built-in SQLite to 3.11.0 beta 1.
Commit
56283544079cf6e79b1c17762c090e14d3b8979c
Parent
5c0dc2d3528a85e…
2 files changed
+3021
-2367
+2
-2
+3021
-2367
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -121,10 +121,11 @@ | ||
| 121 | 121 | #else |
| 122 | 122 | /* This is not VxWorks. */ |
| 123 | 123 | #define OS_VXWORKS 0 |
| 124 | 124 | #define HAVE_FCHOWN 1 |
| 125 | 125 | #define HAVE_READLINK 1 |
| 126 | +#define HAVE_LSTAT 1 | |
| 126 | 127 | #endif /* defined(_WRS_KERNEL) */ |
| 127 | 128 | |
| 128 | 129 | /************** End of vxworks.h *********************************************/ |
| 129 | 130 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| 130 | 131 | |
| @@ -327,11 +328,11 @@ | ||
| 327 | 328 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 328 | 329 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 329 | 330 | */ |
| 330 | 331 | #define SQLITE_VERSION "3.11.0" |
| 331 | 332 | #define SQLITE_VERSION_NUMBER 3011000 |
| 332 | -#define SQLITE_SOURCE_ID "2016-01-20 14:22:41 204432ee72fda8e82d244c4aa18de7ec4811b8e1" | |
| 333 | +#define SQLITE_SOURCE_ID "2016-02-09 02:12:20 ca72be8618e5d466d6f35819ca8bbd2b84269959" | |
| 333 | 334 | |
| 334 | 335 | /* |
| 335 | 336 | ** CAPI3REF: Run-Time Library Version Numbers |
| 336 | 337 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 337 | 338 | ** |
| @@ -5911,11 +5912,11 @@ | ||
| 5911 | 5912 | */ |
| 5912 | 5913 | struct sqlite3_index_info { |
| 5913 | 5914 | /* Inputs */ |
| 5914 | 5915 | int nConstraint; /* Number of entries in aConstraint */ |
| 5915 | 5916 | struct sqlite3_index_constraint { |
| 5916 | - int iColumn; /* Column on left-hand side of constraint */ | |
| 5917 | + int iColumn; /* Column constrained. -1 for ROWID */ | |
| 5917 | 5918 | unsigned char op; /* Constraint operator */ |
| 5918 | 5919 | unsigned char usable; /* True if this constraint is usable */ |
| 5919 | 5920 | int iTermOffset; /* Used internally - xBestIndex should ignore */ |
| 5920 | 5921 | } *aConstraint; /* Table of WHERE clause constraints */ |
| 5921 | 5922 | int nOrderBy; /* Number of terms in the ORDER BY clause */ |
| @@ -10468,18 +10469,28 @@ | ||
| 10468 | 10469 | |
| 10469 | 10470 | /* |
| 10470 | 10471 | ** Flags passed as the third argument to sqlite3BtreeCursor(). |
| 10471 | 10472 | ** |
| 10472 | 10473 | ** For read-only cursors the wrFlag argument is always zero. For read-write |
| 10473 | -** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or | |
| 10474 | -** (BTREE_WRCSR). If the BTREE_FORDELETE flag is set, then the cursor will | |
| 10474 | +** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or just | |
| 10475 | +** (BTREE_WRCSR). If the BTREE_FORDELETE bit is set, then the cursor will | |
| 10475 | 10476 | ** only be used by SQLite for the following: |
| 10476 | 10477 | ** |
| 10477 | -** * to seek to and delete specific entries, and/or | |
| 10478 | +** * to seek to and then delete specific entries, and/or | |
| 10478 | 10479 | ** |
| 10479 | 10480 | ** * to read values that will be used to create keys that other |
| 10480 | 10481 | ** BTREE_FORDELETE cursors will seek to and delete. |
| 10482 | +** | |
| 10483 | +** The BTREE_FORDELETE flag is an optimization hint. It is not used by | |
| 10484 | +** by this, the native b-tree engine of SQLite, but it is available to | |
| 10485 | +** alternative storage engines that might be substituted in place of this | |
| 10486 | +** b-tree system. For alternative storage engines in which a delete of | |
| 10487 | +** the main table row automatically deletes corresponding index rows, | |
| 10488 | +** the FORDELETE flag hint allows those alternative storage engines to | |
| 10489 | +** skip a lot of work. Namely: FORDELETE cursors may treat all SEEK | |
| 10490 | +** and DELETE operations as no-ops, and any READ operation against a | |
| 10491 | +** FORDELETE cursor may return a null row: 0x01 0x00. | |
| 10481 | 10492 | */ |
| 10482 | 10493 | #define BTREE_WRCSR 0x00000004 /* read-write cursor */ |
| 10483 | 10494 | #define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */ |
| 10484 | 10495 | |
| 10485 | 10496 | SQLITE_PRIVATE int sqlite3BtreeCursor( |
| @@ -10504,11 +10515,16 @@ | ||
| 10504 | 10515 | int bias, |
| 10505 | 10516 | int *pRes |
| 10506 | 10517 | ); |
| 10507 | 10518 | SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); |
| 10508 | 10519 | SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); |
| 10509 | -SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, int); | |
| 10520 | +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); | |
| 10521 | + | |
| 10522 | +/* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */ | |
| 10523 | +#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ | |
| 10524 | +#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */ | |
| 10525 | + | |
| 10510 | 10526 | SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, |
| 10511 | 10527 | const void *pData, int nData, |
| 10512 | 10528 | int nZero, int bias, int seekResult); |
| 10513 | 10529 | SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); |
| 10514 | 10530 | SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); |
| @@ -10762,94 +10778,95 @@ | ||
| 10762 | 10778 | */ |
| 10763 | 10779 | /************** Include opcodes.h in the middle of vdbe.h ********************/ |
| 10764 | 10780 | /************** Begin file opcodes.h *****************************************/ |
| 10765 | 10781 | /* Automatically generated. Do not edit */ |
| 10766 | 10782 | /* See the tool/mkopcodeh.tcl script for details */ |
| 10767 | -#define OP_Savepoint 1 | |
| 10768 | -#define OP_AutoCommit 2 | |
| 10769 | -#define OP_Transaction 3 | |
| 10770 | -#define OP_SorterNext 4 | |
| 10771 | -#define OP_PrevIfOpen 5 | |
| 10772 | -#define OP_NextIfOpen 6 | |
| 10773 | -#define OP_Prev 7 | |
| 10774 | -#define OP_Next 8 | |
| 10775 | -#define OP_Checkpoint 9 | |
| 10776 | -#define OP_JournalMode 10 | |
| 10777 | -#define OP_Vacuum 11 | |
| 10778 | -#define OP_VFilter 12 /* synopsis: iplan=r[P3] zplan='P4' */ | |
| 10779 | -#define OP_VUpdate 13 /* synopsis: data=r[P3@P2] */ | |
| 10780 | -#define OP_Goto 14 | |
| 10781 | -#define OP_Gosub 15 | |
| 10782 | -#define OP_Return 16 | |
| 10783 | -#define OP_InitCoroutine 17 | |
| 10784 | -#define OP_EndCoroutine 18 | |
| 10783 | +#define OP_Savepoint 0 | |
| 10784 | +#define OP_AutoCommit 1 | |
| 10785 | +#define OP_Transaction 2 | |
| 10786 | +#define OP_SorterNext 3 | |
| 10787 | +#define OP_PrevIfOpen 4 | |
| 10788 | +#define OP_NextIfOpen 5 | |
| 10789 | +#define OP_Prev 6 | |
| 10790 | +#define OP_Next 7 | |
| 10791 | +#define OP_Checkpoint 8 | |
| 10792 | +#define OP_JournalMode 9 | |
| 10793 | +#define OP_Vacuum 10 | |
| 10794 | +#define OP_VFilter 11 /* synopsis: iplan=r[P3] zplan='P4' */ | |
| 10795 | +#define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */ | |
| 10796 | +#define OP_Goto 13 | |
| 10797 | +#define OP_Gosub 14 | |
| 10798 | +#define OP_Return 15 | |
| 10799 | +#define OP_InitCoroutine 16 | |
| 10800 | +#define OP_EndCoroutine 17 | |
| 10801 | +#define OP_Yield 18 | |
| 10785 | 10802 | #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ |
| 10786 | -#define OP_Yield 20 | |
| 10787 | -#define OP_HaltIfNull 21 /* synopsis: if r[P3]=null halt */ | |
| 10788 | -#define OP_Halt 22 | |
| 10789 | -#define OP_Integer 23 /* synopsis: r[P2]=P1 */ | |
| 10790 | -#define OP_Int64 24 /* synopsis: r[P2]=P4 */ | |
| 10791 | -#define OP_String 25 /* synopsis: r[P2]='P4' (len=P1) */ | |
| 10792 | -#define OP_Null 26 /* synopsis: r[P2..P3]=NULL */ | |
| 10793 | -#define OP_SoftNull 27 /* synopsis: r[P1]=NULL */ | |
| 10794 | -#define OP_Blob 28 /* synopsis: r[P2]=P4 (len=P1) */ | |
| 10795 | -#define OP_Variable 29 /* synopsis: r[P2]=parameter(P1,P4) */ | |
| 10796 | -#define OP_Move 30 /* synopsis: r[P2@P3]=r[P1@P3] */ | |
| 10797 | -#define OP_Copy 31 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ | |
| 10798 | -#define OP_SCopy 32 /* synopsis: r[P2]=r[P1] */ | |
| 10799 | -#define OP_IntCopy 33 /* synopsis: r[P2]=r[P1] */ | |
| 10800 | -#define OP_ResultRow 34 /* synopsis: output=r[P1@P2] */ | |
| 10801 | -#define OP_CollSeq 35 | |
| 10802 | -#define OP_Function0 36 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 10803 | -#define OP_Function 37 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 10804 | -#define OP_AddImm 38 /* synopsis: r[P1]=r[P1]+P2 */ | |
| 10805 | -#define OP_MustBeInt 39 | |
| 10806 | -#define OP_RealAffinity 40 | |
| 10807 | -#define OP_Cast 41 /* synopsis: affinity(r[P1]) */ | |
| 10808 | -#define OP_Permutation 42 | |
| 10809 | -#define OP_Compare 43 /* synopsis: r[P1@P3] <-> r[P2@P3] */ | |
| 10810 | -#define OP_Jump 44 | |
| 10811 | -#define OP_Once 45 | |
| 10812 | -#define OP_If 46 | |
| 10813 | -#define OP_IfNot 47 | |
| 10814 | -#define OP_Column 48 /* synopsis: r[P3]=PX */ | |
| 10815 | -#define OP_Affinity 49 /* synopsis: affinity(r[P1@P2]) */ | |
| 10816 | -#define OP_MakeRecord 50 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ | |
| 10817 | -#define OP_Count 51 /* synopsis: r[P2]=count() */ | |
| 10818 | -#define OP_ReadCookie 52 | |
| 10819 | -#define OP_SetCookie 53 | |
| 10820 | -#define OP_ReopenIdx 54 /* synopsis: root=P2 iDb=P3 */ | |
| 10821 | -#define OP_OpenRead 55 /* synopsis: root=P2 iDb=P3 */ | |
| 10822 | -#define OP_OpenWrite 56 /* synopsis: root=P2 iDb=P3 */ | |
| 10823 | -#define OP_OpenAutoindex 57 /* synopsis: nColumn=P2 */ | |
| 10824 | -#define OP_OpenEphemeral 58 /* synopsis: nColumn=P2 */ | |
| 10825 | -#define OP_SorterOpen 59 | |
| 10826 | -#define OP_SequenceTest 60 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ | |
| 10827 | -#define OP_OpenPseudo 61 /* synopsis: P3 columns in r[P2] */ | |
| 10828 | -#define OP_Close 62 | |
| 10829 | -#define OP_ColumnsUsed 63 | |
| 10830 | -#define OP_SeekLT 64 /* synopsis: key=r[P3@P4] */ | |
| 10831 | -#define OP_SeekLE 65 /* synopsis: key=r[P3@P4] */ | |
| 10832 | -#define OP_SeekGE 66 /* synopsis: key=r[P3@P4] */ | |
| 10833 | -#define OP_SeekGT 67 /* synopsis: key=r[P3@P4] */ | |
| 10834 | -#define OP_Seek 68 /* synopsis: intkey=r[P2] */ | |
| 10835 | -#define OP_NoConflict 69 /* synopsis: key=r[P3@P4] */ | |
| 10836 | -#define OP_NotFound 70 /* synopsis: key=r[P3@P4] */ | |
| 10803 | +#define OP_HaltIfNull 20 /* synopsis: if r[P3]=null halt */ | |
| 10804 | +#define OP_Halt 21 | |
| 10805 | +#define OP_Integer 22 /* synopsis: r[P2]=P1 */ | |
| 10806 | +#define OP_Int64 23 /* synopsis: r[P2]=P4 */ | |
| 10807 | +#define OP_String 24 /* synopsis: r[P2]='P4' (len=P1) */ | |
| 10808 | +#define OP_Null 25 /* synopsis: r[P2..P3]=NULL */ | |
| 10809 | +#define OP_SoftNull 26 /* synopsis: r[P1]=NULL */ | |
| 10810 | +#define OP_Blob 27 /* synopsis: r[P2]=P4 (len=P1) */ | |
| 10811 | +#define OP_Variable 28 /* synopsis: r[P2]=parameter(P1,P4) */ | |
| 10812 | +#define OP_Move 29 /* synopsis: r[P2@P3]=r[P1@P3] */ | |
| 10813 | +#define OP_Copy 30 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ | |
| 10814 | +#define OP_SCopy 31 /* synopsis: r[P2]=r[P1] */ | |
| 10815 | +#define OP_IntCopy 32 /* synopsis: r[P2]=r[P1] */ | |
| 10816 | +#define OP_ResultRow 33 /* synopsis: output=r[P1@P2] */ | |
| 10817 | +#define OP_CollSeq 34 | |
| 10818 | +#define OP_Function0 35 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 10819 | +#define OP_Function 36 /* synopsis: r[P3]=func(r[P2@P5]) */ | |
| 10820 | +#define OP_AddImm 37 /* synopsis: r[P1]=r[P1]+P2 */ | |
| 10821 | +#define OP_MustBeInt 38 | |
| 10822 | +#define OP_RealAffinity 39 | |
| 10823 | +#define OP_Cast 40 /* synopsis: affinity(r[P1]) */ | |
| 10824 | +#define OP_Permutation 41 | |
| 10825 | +#define OP_Compare 42 /* synopsis: r[P1@P3] <-> r[P2@P3] */ | |
| 10826 | +#define OP_Jump 43 | |
| 10827 | +#define OP_Once 44 | |
| 10828 | +#define OP_If 45 | |
| 10829 | +#define OP_IfNot 46 | |
| 10830 | +#define OP_Column 47 /* synopsis: r[P3]=PX */ | |
| 10831 | +#define OP_Affinity 48 /* synopsis: affinity(r[P1@P2]) */ | |
| 10832 | +#define OP_MakeRecord 49 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ | |
| 10833 | +#define OP_Count 50 /* synopsis: r[P2]=count() */ | |
| 10834 | +#define OP_ReadCookie 51 | |
| 10835 | +#define OP_SetCookie 52 | |
| 10836 | +#define OP_ReopenIdx 53 /* synopsis: root=P2 iDb=P3 */ | |
| 10837 | +#define OP_OpenRead 54 /* synopsis: root=P2 iDb=P3 */ | |
| 10838 | +#define OP_OpenWrite 55 /* synopsis: root=P2 iDb=P3 */ | |
| 10839 | +#define OP_OpenAutoindex 56 /* synopsis: nColumn=P2 */ | |
| 10840 | +#define OP_OpenEphemeral 57 /* synopsis: nColumn=P2 */ | |
| 10841 | +#define OP_SorterOpen 58 | |
| 10842 | +#define OP_SequenceTest 59 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ | |
| 10843 | +#define OP_OpenPseudo 60 /* synopsis: P3 columns in r[P2] */ | |
| 10844 | +#define OP_Close 61 | |
| 10845 | +#define OP_ColumnsUsed 62 | |
| 10846 | +#define OP_SeekLT 63 /* synopsis: key=r[P3@P4] */ | |
| 10847 | +#define OP_SeekLE 64 /* synopsis: key=r[P3@P4] */ | |
| 10848 | +#define OP_SeekGE 65 /* synopsis: key=r[P3@P4] */ | |
| 10849 | +#define OP_SeekGT 66 /* synopsis: key=r[P3@P4] */ | |
| 10850 | +#define OP_NoConflict 67 /* synopsis: key=r[P3@P4] */ | |
| 10851 | +#define OP_NotFound 68 /* synopsis: key=r[P3@P4] */ | |
| 10852 | +#define OP_Found 69 /* synopsis: key=r[P3@P4] */ | |
| 10853 | +#define OP_NotExists 70 /* synopsis: intkey=r[P3] */ | |
| 10837 | 10854 | #define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ |
| 10838 | 10855 | #define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ |
| 10839 | -#define OP_Found 73 /* synopsis: key=r[P3@P4] */ | |
| 10840 | -#define OP_NotExists 74 /* synopsis: intkey=r[P3] */ | |
| 10841 | -#define OP_Sequence 75 /* synopsis: r[P2]=cursor[P1].ctr++ */ | |
| 10856 | +#define OP_Sequence 73 /* synopsis: r[P2]=cursor[P1].ctr++ */ | |
| 10857 | +#define OP_NewRowid 74 /* synopsis: r[P2]=rowid */ | |
| 10858 | +#define OP_Insert 75 /* synopsis: intkey=r[P3] data=r[P2] */ | |
| 10842 | 10859 | #define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ |
| 10843 | 10860 | #define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ |
| 10844 | 10861 | #define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ |
| 10845 | 10862 | #define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ |
| 10846 | 10863 | #define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ |
| 10847 | 10864 | #define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ |
| 10848 | 10865 | #define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */ |
| 10849 | 10866 | #define OP_Ge 83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */ |
| 10850 | -#define OP_NewRowid 84 /* synopsis: r[P2]=rowid */ | |
| 10867 | +#define OP_InsertInt 84 /* synopsis: intkey=P3 data=r[P2] */ | |
| 10851 | 10868 | #define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ |
| 10852 | 10869 | #define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ |
| 10853 | 10870 | #define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ |
| 10854 | 10871 | #define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */ |
| 10855 | 10872 | #define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ |
| @@ -10856,111 +10873,110 @@ | ||
| 10856 | 10873 | #define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ |
| 10857 | 10874 | #define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ |
| 10858 | 10875 | #define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ |
| 10859 | 10876 | #define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ |
| 10860 | 10877 | #define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ |
| 10861 | -#define OP_Insert 95 /* synopsis: intkey=r[P3] data=r[P2] */ | |
| 10878 | +#define OP_Delete 95 | |
| 10862 | 10879 | #define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ |
| 10863 | 10880 | #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ |
| 10864 | -#define OP_InsertInt 98 /* synopsis: intkey=P3 data=r[P2] */ | |
| 10865 | -#define OP_Delete 99 | |
| 10866 | -#define OP_ResetCount 100 | |
| 10867 | -#define OP_SorterCompare 101 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ | |
| 10868 | -#define OP_SorterData 102 /* synopsis: r[P2]=data */ | |
| 10869 | -#define OP_RowKey 103 /* synopsis: r[P2]=key */ | |
| 10870 | -#define OP_RowData 104 /* synopsis: r[P2]=data */ | |
| 10871 | -#define OP_Rowid 105 /* synopsis: r[P2]=rowid */ | |
| 10872 | -#define OP_NullRow 106 | |
| 10873 | -#define OP_Last 107 | |
| 10874 | -#define OP_SorterSort 108 | |
| 10875 | -#define OP_Sort 109 | |
| 10876 | -#define OP_Rewind 110 | |
| 10877 | -#define OP_SorterInsert 111 | |
| 10878 | -#define OP_IdxInsert 112 /* synopsis: key=r[P2] */ | |
| 10879 | -#define OP_IdxDelete 113 /* synopsis: key=r[P2@P3] */ | |
| 10880 | -#define OP_IdxRowid 114 /* synopsis: r[P2]=rowid */ | |
| 10881 | -#define OP_IdxLE 115 /* synopsis: key=r[P3@P4] */ | |
| 10882 | -#define OP_IdxGT 116 /* synopsis: key=r[P3@P4] */ | |
| 10883 | -#define OP_IdxLT 117 /* synopsis: key=r[P3@P4] */ | |
| 10884 | -#define OP_IdxGE 118 /* synopsis: key=r[P3@P4] */ | |
| 10885 | -#define OP_Destroy 119 | |
| 10886 | -#define OP_Clear 120 | |
| 10887 | -#define OP_ResetSorter 121 | |
| 10888 | -#define OP_CreateIndex 122 /* synopsis: r[P2]=root iDb=P1 */ | |
| 10889 | -#define OP_CreateTable 123 /* synopsis: r[P2]=root iDb=P1 */ | |
| 10890 | -#define OP_ParseSchema 124 | |
| 10891 | -#define OP_LoadAnalysis 125 | |
| 10892 | -#define OP_DropTable 126 | |
| 10893 | -#define OP_DropIndex 127 | |
| 10894 | -#define OP_DropTrigger 128 | |
| 10895 | -#define OP_IntegrityCk 129 | |
| 10896 | -#define OP_RowSetAdd 130 /* synopsis: rowset(P1)=r[P2] */ | |
| 10897 | -#define OP_RowSetRead 131 /* synopsis: r[P3]=rowset(P1) */ | |
| 10898 | -#define OP_RowSetTest 132 /* synopsis: if r[P3] in rowset(P1) goto P2 */ | |
| 10881 | +#define OP_ResetCount 98 | |
| 10882 | +#define OP_SorterCompare 99 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ | |
| 10883 | +#define OP_SorterData 100 /* synopsis: r[P2]=data */ | |
| 10884 | +#define OP_RowKey 101 /* synopsis: r[P2]=key */ | |
| 10885 | +#define OP_RowData 102 /* synopsis: r[P2]=data */ | |
| 10886 | +#define OP_Rowid 103 /* synopsis: r[P2]=rowid */ | |
| 10887 | +#define OP_NullRow 104 | |
| 10888 | +#define OP_Last 105 | |
| 10889 | +#define OP_SorterSort 106 | |
| 10890 | +#define OP_Sort 107 | |
| 10891 | +#define OP_Rewind 108 | |
| 10892 | +#define OP_SorterInsert 109 | |
| 10893 | +#define OP_IdxInsert 110 /* synopsis: key=r[P2] */ | |
| 10894 | +#define OP_IdxDelete 111 /* synopsis: key=r[P2@P3] */ | |
| 10895 | +#define OP_Seek 112 /* synopsis: Move P3 to P1.rowid */ | |
| 10896 | +#define OP_IdxRowid 113 /* synopsis: r[P2]=rowid */ | |
| 10897 | +#define OP_IdxLE 114 /* synopsis: key=r[P3@P4] */ | |
| 10898 | +#define OP_IdxGT 115 /* synopsis: key=r[P3@P4] */ | |
| 10899 | +#define OP_IdxLT 116 /* synopsis: key=r[P3@P4] */ | |
| 10900 | +#define OP_IdxGE 117 /* synopsis: key=r[P3@P4] */ | |
| 10901 | +#define OP_Destroy 118 | |
| 10902 | +#define OP_Clear 119 | |
| 10903 | +#define OP_ResetSorter 120 | |
| 10904 | +#define OP_CreateIndex 121 /* synopsis: r[P2]=root iDb=P1 */ | |
| 10905 | +#define OP_CreateTable 122 /* synopsis: r[P2]=root iDb=P1 */ | |
| 10906 | +#define OP_ParseSchema 123 | |
| 10907 | +#define OP_LoadAnalysis 124 | |
| 10908 | +#define OP_DropTable 125 | |
| 10909 | +#define OP_DropIndex 126 | |
| 10910 | +#define OP_DropTrigger 127 | |
| 10911 | +#define OP_IntegrityCk 128 | |
| 10912 | +#define OP_RowSetAdd 129 /* synopsis: rowset(P1)=r[P2] */ | |
| 10913 | +#define OP_RowSetRead 130 /* synopsis: r[P3]=rowset(P1) */ | |
| 10914 | +#define OP_RowSetTest 131 /* synopsis: if r[P3] in rowset(P1) goto P2 */ | |
| 10915 | +#define OP_Program 132 | |
| 10899 | 10916 | #define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 10900 | -#define OP_Program 134 | |
| 10901 | -#define OP_Param 135 | |
| 10902 | -#define OP_FkCounter 136 /* synopsis: fkctr[P1]+=P2 */ | |
| 10903 | -#define OP_FkIfZero 137 /* synopsis: if fkctr[P1]==0 goto P2 */ | |
| 10904 | -#define OP_MemMax 138 /* synopsis: r[P1]=max(r[P1],r[P2]) */ | |
| 10905 | -#define OP_IfPos 139 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ | |
| 10906 | -#define OP_SetIfNotPos 140 /* synopsis: if r[P1]<=0 then r[P2]=P3 */ | |
| 10907 | -#define OP_IfNotZero 141 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ | |
| 10908 | -#define OP_DecrJumpZero 142 /* synopsis: if (--r[P1])==0 goto P2 */ | |
| 10909 | -#define OP_JumpZeroIncr 143 /* synopsis: if (r[P1]++)==0 ) goto P2 */ | |
| 10910 | -#define OP_AggStep0 144 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 10911 | -#define OP_AggStep 145 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 10912 | -#define OP_AggFinal 146 /* synopsis: accum=r[P1] N=P2 */ | |
| 10913 | -#define OP_IncrVacuum 147 | |
| 10914 | -#define OP_Expire 148 | |
| 10915 | -#define OP_TableLock 149 /* synopsis: iDb=P1 root=P2 write=P3 */ | |
| 10916 | -#define OP_VBegin 150 | |
| 10917 | -#define OP_VCreate 151 | |
| 10918 | -#define OP_VDestroy 152 | |
| 10919 | -#define OP_VOpen 153 | |
| 10920 | -#define OP_VColumn 154 /* synopsis: r[P3]=vcolumn(P2) */ | |
| 10921 | -#define OP_VNext 155 | |
| 10922 | -#define OP_VRename 156 | |
| 10923 | -#define OP_Pagecount 157 | |
| 10924 | -#define OP_MaxPgcnt 158 | |
| 10925 | -#define OP_Init 159 /* synopsis: Start at P2 */ | |
| 10926 | -#define OP_CursorHint 160 | |
| 10927 | -#define OP_Noop 161 | |
| 10928 | -#define OP_Explain 162 | |
| 10917 | +#define OP_Param 134 | |
| 10918 | +#define OP_FkCounter 135 /* synopsis: fkctr[P1]+=P2 */ | |
| 10919 | +#define OP_FkIfZero 136 /* synopsis: if fkctr[P1]==0 goto P2 */ | |
| 10920 | +#define OP_MemMax 137 /* synopsis: r[P1]=max(r[P1],r[P2]) */ | |
| 10921 | +#define OP_IfPos 138 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ | |
| 10922 | +#define OP_OffsetLimit 139 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ | |
| 10923 | +#define OP_IfNotZero 140 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ | |
| 10924 | +#define OP_DecrJumpZero 141 /* synopsis: if (--r[P1])==0 goto P2 */ | |
| 10925 | +#define OP_JumpZeroIncr 142 /* synopsis: if (r[P1]++)==0 ) goto P2 */ | |
| 10926 | +#define OP_AggStep0 143 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 10927 | +#define OP_AggStep 144 /* synopsis: accum=r[P3] step(r[P2@P5]) */ | |
| 10928 | +#define OP_AggFinal 145 /* synopsis: accum=r[P1] N=P2 */ | |
| 10929 | +#define OP_IncrVacuum 146 | |
| 10930 | +#define OP_Expire 147 | |
| 10931 | +#define OP_TableLock 148 /* synopsis: iDb=P1 root=P2 write=P3 */ | |
| 10932 | +#define OP_VBegin 149 | |
| 10933 | +#define OP_VCreate 150 | |
| 10934 | +#define OP_VDestroy 151 | |
| 10935 | +#define OP_VOpen 152 | |
| 10936 | +#define OP_VColumn 153 /* synopsis: r[P3]=vcolumn(P2) */ | |
| 10937 | +#define OP_VNext 154 | |
| 10938 | +#define OP_VRename 155 | |
| 10939 | +#define OP_Pagecount 156 | |
| 10940 | +#define OP_MaxPgcnt 157 | |
| 10941 | +#define OP_Init 158 /* synopsis: Start at P2 */ | |
| 10942 | +#define OP_CursorHint 159 | |
| 10943 | +#define OP_Noop 160 | |
| 10944 | +#define OP_Explain 161 | |
| 10929 | 10945 | |
| 10930 | 10946 | /* Properties such as "out2" or "jump" that are specified in |
| 10931 | 10947 | ** comments following the "case" for each opcode in the vdbe.c |
| 10932 | 10948 | ** are encoded into bitvectors as follows: |
| 10933 | 10949 | */ |
| 10934 | -#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ | |
| 10935 | -#define OPFLG_IN1 0x0002 /* in1: P1 is an input */ | |
| 10936 | -#define OPFLG_IN2 0x0004 /* in2: P2 is an input */ | |
| 10937 | -#define OPFLG_IN3 0x0008 /* in3: P3 is an input */ | |
| 10938 | -#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */ | |
| 10939 | -#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ | |
| 10950 | +#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */ | |
| 10951 | +#define OPFLG_IN1 0x02 /* in1: P1 is an input */ | |
| 10952 | +#define OPFLG_IN2 0x04 /* in2: P2 is an input */ | |
| 10953 | +#define OPFLG_IN3 0x08 /* in3: P3 is an input */ | |
| 10954 | +#define OPFLG_OUT2 0x10 /* out2: P2 is an output */ | |
| 10955 | +#define OPFLG_OUT3 0x20 /* out3: P3 is an output */ | |
| 10940 | 10956 | #define OPFLG_INITIALIZER {\ |
| 10941 | -/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,\ | |
| 10942 | -/* 8 */ 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01,\ | |
| 10943 | -/* 16 */ 0x02, 0x01, 0x02, 0x12, 0x03, 0x08, 0x00, 0x10,\ | |
| 10944 | -/* 24 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00,\ | |
| 10945 | -/* 32 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,\ | |
| 10946 | -/* 40 */ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03,\ | |
| 10947 | -/* 48 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00,\ | |
| 10948 | -/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ | |
| 10949 | -/* 64 */ 0x09, 0x09, 0x09, 0x09, 0x04, 0x09, 0x09, 0x26,\ | |
| 10950 | -/* 72 */ 0x26, 0x09, 0x09, 0x10, 0x03, 0x03, 0x0b, 0x0b,\ | |
| 10951 | -/* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x10, 0x26, 0x26, 0x26,\ | |
| 10957 | +/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\ | |
| 10958 | +/* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x02,\ | |
| 10959 | +/* 16 */ 0x01, 0x02, 0x03, 0x12, 0x08, 0x00, 0x10, 0x10,\ | |
| 10960 | +/* 24 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\ | |
| 10961 | +/* 32 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02,\ | |
| 10962 | +/* 40 */ 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x00,\ | |
| 10963 | +/* 48 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ | |
| 10964 | +/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,\ | |
| 10965 | +/* 64 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x26,\ | |
| 10966 | +/* 72 */ 0x26, 0x10, 0x10, 0x00, 0x03, 0x03, 0x0b, 0x0b,\ | |
| 10967 | +/* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x26, 0x26, 0x26,\ | |
| 10952 | 10968 | /* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ |
| 10953 | -/* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ | |
| 10954 | -/* 104 */ 0x00, 0x10, 0x00, 0x01, 0x01, 0x01, 0x01, 0x04,\ | |
| 10955 | -/* 112 */ 0x04, 0x00, 0x10, 0x01, 0x01, 0x01, 0x01, 0x10,\ | |
| 10956 | -/* 120 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ | |
| 10957 | -/* 128 */ 0x00, 0x00, 0x06, 0x23, 0x0b, 0x10, 0x01, 0x10,\ | |
| 10958 | -/* 136 */ 0x00, 0x01, 0x04, 0x03, 0x06, 0x03, 0x03, 0x03,\ | |
| 10959 | -/* 144 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\ | |
| 10960 | -/* 152 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x01,\ | |
| 10961 | -/* 160 */ 0x00, 0x00, 0x00,} | |
| 10969 | +/* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ | |
| 10970 | +/* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x00,\ | |
| 10971 | +/* 112 */ 0x00, 0x10, 0x01, 0x01, 0x01, 0x01, 0x10, 0x00,\ | |
| 10972 | +/* 120 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ | |
| 10973 | +/* 128 */ 0x00, 0x06, 0x23, 0x0b, 0x01, 0x10, 0x10, 0x00,\ | |
| 10974 | +/* 136 */ 0x01, 0x04, 0x03, 0x1a, 0x03, 0x03, 0x03, 0x00,\ | |
| 10975 | +/* 144 */ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\ | |
| 10976 | +/* 152 */ 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x01, 0x00,\ | |
| 10977 | +/* 160 */ 0x00, 0x00,} | |
| 10962 | 10978 | |
| 10963 | 10979 | /************** End of opcodes.h *********************************************/ |
| 10964 | 10980 | /************** Continuing where we left off in vdbe.h ***********************/ |
| 10965 | 10981 | |
| 10966 | 10982 | /* |
| @@ -10976,10 +10992,11 @@ | ||
| 10976 | 10992 | SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...); |
| 10977 | 10993 | SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); |
| 10978 | 10994 | SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); |
| 10979 | 10995 | SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); |
| 10980 | 10996 | SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); |
| 10997 | +SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int); | |
| 10981 | 10998 | #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) |
| 10982 | 10999 | SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); |
| 10983 | 11000 | #else |
| 10984 | 11001 | # define sqlite3VdbeVerifyNoMallocRequired(A,B) |
| 10985 | 11002 | #endif |
| @@ -11199,15 +11216,16 @@ | ||
| 11199 | 11216 | ** Flags for sqlite3PagerSetFlags() |
| 11200 | 11217 | */ |
| 11201 | 11218 | #define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ |
| 11202 | 11219 | #define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ |
| 11203 | 11220 | #define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ |
| 11204 | -#define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */ | |
| 11205 | -#define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */ | |
| 11206 | -#define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */ | |
| 11207 | -#define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */ | |
| 11208 | -#define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */ | |
| 11221 | +#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */ | |
| 11222 | +#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */ | |
| 11223 | +#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */ | |
| 11224 | +#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */ | |
| 11225 | +#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */ | |
| 11226 | +#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */ | |
| 11209 | 11227 | |
| 11210 | 11228 | /* |
| 11211 | 11229 | ** The remainder of this file contains the declarations of the functions |
| 11212 | 11230 | ** that make up the Pager sub-system API. See source code comments for |
| 11213 | 11231 | ** a detailed description of each routine. |
| @@ -11963,12 +11981,12 @@ | ||
| 11963 | 11981 | ** is shared by multiple database connections. Therefore, while parsing |
| 11964 | 11982 | ** schema information, the Lookaside.bEnabled flag is cleared so that |
| 11965 | 11983 | ** lookaside allocations are not used to construct the schema objects. |
| 11966 | 11984 | */ |
| 11967 | 11985 | struct Lookaside { |
| 11986 | + u32 bDisable; /* Only operate the lookaside when zero */ | |
| 11968 | 11987 | u16 sz; /* Size of each buffer in bytes */ |
| 11969 | - u8 bEnabled; /* False to disable new lookaside allocations */ | |
| 11970 | 11988 | u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ |
| 11971 | 11989 | int nOut; /* Number of buffers currently checked out */ |
| 11972 | 11990 | int mxOut; /* Highwater mark for nOut */ |
| 11973 | 11991 | int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ |
| 11974 | 11992 | LookasideSlot *pFree; /* List of available buffers */ |
| @@ -12047,10 +12065,11 @@ | ||
| 12047 | 12065 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 12048 | 12066 | u8 enc; /* Text encoding */ |
| 12049 | 12067 | u8 autoCommit; /* The auto-commit flag. */ |
| 12050 | 12068 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 12051 | 12069 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 12070 | + u8 bBenignMalloc; /* Do not require OOMs if true */ | |
| 12052 | 12071 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 12053 | 12072 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| 12054 | 12073 | u8 suppressErr; /* Do not issue error messages if true */ |
| 12055 | 12074 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
| 12056 | 12075 | u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ |
| @@ -12155,14 +12174,14 @@ | ||
| 12155 | 12174 | /* |
| 12156 | 12175 | ** Possible values for the sqlite3.flags. |
| 12157 | 12176 | */ |
| 12158 | 12177 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| 12159 | 12178 | #define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ |
| 12160 | -#define SQLITE_FullFSync 0x00000004 /* Use full fsync on the backend */ | |
| 12161 | -#define SQLITE_CkptFullFSync 0x00000008 /* Use full fsync for checkpoint */ | |
| 12162 | -#define SQLITE_CacheSpill 0x00000010 /* OK to spill pager cache */ | |
| 12163 | -#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ | |
| 12179 | +#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ | |
| 12180 | +#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */ | |
| 12181 | +#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */ | |
| 12182 | +#define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */ | |
| 12164 | 12183 | #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ |
| 12165 | 12184 | #define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ |
| 12166 | 12185 | /* DELETE, or UPDATE and return */ |
| 12167 | 12186 | /* the count using a callback. */ |
| 12168 | 12187 | #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ |
| @@ -13510,11 +13529,11 @@ | ||
| 13510 | 13529 | /* |
| 13511 | 13530 | ** During code generation of statements that do inserts into AUTOINCREMENT |
| 13512 | 13531 | ** tables, the following information is attached to the Table.u.autoInc.p |
| 13513 | 13532 | ** pointer of each autoincrement table to record some side information that |
| 13514 | 13533 | ** the code generator needs. We have to keep per-table autoincrement |
| 13515 | -** information in case inserts are down within triggers. Triggers do not | |
| 13534 | +** information in case inserts are done within triggers. Triggers do not | |
| 13516 | 13535 | ** normally coordinate their activities, but we do need to coordinate the |
| 13517 | 13536 | ** loading and saving of autoincrement information. |
| 13518 | 13537 | */ |
| 13519 | 13538 | struct AutoincInfo { |
| 13520 | 13539 | AutoincInfo *pNext; /* Next info block in a list of them all */ |
| @@ -13602,10 +13621,11 @@ | ||
| 13602 | 13621 | u8 nTempReg; /* Number of temporary registers in aTempReg[] */ |
| 13603 | 13622 | u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ |
| 13604 | 13623 | u8 mayAbort; /* True if statement may throw an ABORT exception */ |
| 13605 | 13624 | u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ |
| 13606 | 13625 | u8 okConstFactor; /* OK to factor out constants */ |
| 13626 | + u8 disableLookaside; /* Number of times lookaside has been disabled */ | |
| 13607 | 13627 | int aTempReg[8]; /* Holding area for temporary registers */ |
| 13608 | 13628 | int nRangeReg; /* Size of the temporary register block */ |
| 13609 | 13629 | int iRangeReg; /* First register in temporary register block */ |
| 13610 | 13630 | int nErr; /* Number of errors seen */ |
| 13611 | 13631 | int nTab; /* Number of previously allocated VDBE cursors */ |
| @@ -13716,23 +13736,26 @@ | ||
| 13716 | 13736 | }; |
| 13717 | 13737 | |
| 13718 | 13738 | /* |
| 13719 | 13739 | ** Bitfield flags for P5 value in various opcodes. |
| 13720 | 13740 | */ |
| 13721 | -#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ | |
| 13741 | +#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ | |
| 13742 | + /* Also used in P2 (not P5) of OP_Delete */ | |
| 13722 | 13743 | #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ |
| 13723 | 13744 | #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ |
| 13724 | 13745 | #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ |
| 13725 | 13746 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ |
| 13726 | 13747 | #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ |
| 13727 | 13748 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 13728 | 13749 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 13729 | 13750 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 13730 | 13751 | #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ |
| 13731 | -#define OPFLAG_FORDELETE 0x08 /* OP_Open is opening for-delete csr */ | |
| 13752 | +#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ | |
| 13732 | 13753 | #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ |
| 13733 | 13754 | #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ |
| 13755 | +#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */ | |
| 13756 | +#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ | |
| 13734 | 13757 | |
| 13735 | 13758 | /* |
| 13736 | 13759 | * Each trigger present in the database schema is stored as an instance of |
| 13737 | 13760 | * struct Trigger. |
| 13738 | 13761 | * |
| @@ -13847,14 +13870,20 @@ | ||
| 13847 | 13870 | char *zText; /* The string collected so far */ |
| 13848 | 13871 | u32 nChar; /* Length of the string so far */ |
| 13849 | 13872 | u32 nAlloc; /* Amount of space allocated in zText */ |
| 13850 | 13873 | u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ |
| 13851 | 13874 | u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ |
| 13852 | - u8 bMalloced; /* zText points to allocated space */ | |
| 13875 | + u8 printfFlags; /* SQLITE_PRINTF flags below */ | |
| 13853 | 13876 | }; |
| 13854 | 13877 | #define STRACCUM_NOMEM 1 |
| 13855 | 13878 | #define STRACCUM_TOOBIG 2 |
| 13879 | +#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ | |
| 13880 | +#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ | |
| 13881 | +#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */ | |
| 13882 | + | |
| 13883 | +#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) | |
| 13884 | + | |
| 13856 | 13885 | |
| 13857 | 13886 | /* |
| 13858 | 13887 | ** A pointer to this structure is used to communicate information |
| 13859 | 13888 | ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. |
| 13860 | 13889 | */ |
| @@ -14085,10 +14114,11 @@ | ||
| 14085 | 14114 | SQLITE_PRIVATE void sqlite3MallocEnd(void); |
| 14086 | 14115 | SQLITE_PRIVATE void *sqlite3Malloc(u64); |
| 14087 | 14116 | SQLITE_PRIVATE void *sqlite3MallocZero(u64); |
| 14088 | 14117 | SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); |
| 14089 | 14118 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); |
| 14119 | +SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64); | |
| 14090 | 14120 | SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); |
| 14091 | 14121 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); |
| 14092 | 14122 | SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); |
| 14093 | 14123 | SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); |
| 14094 | 14124 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); |
| @@ -14167,14 +14197,12 @@ | ||
| 14167 | 14197 | int nArg; /* Total number of arguments */ |
| 14168 | 14198 | int nUsed; /* Number of arguments used so far */ |
| 14169 | 14199 | sqlite3_value **apArg; /* The argument values */ |
| 14170 | 14200 | }; |
| 14171 | 14201 | |
| 14172 | -#define SQLITE_PRINTF_INTERNAL 0x01 | |
| 14173 | -#define SQLITE_PRINTF_SQLFUNC 0x02 | |
| 14174 | -SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list); | |
| 14175 | -SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...); | |
| 14202 | +SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, const char*, va_list); | |
| 14203 | +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); | |
| 14176 | 14204 | SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); |
| 14177 | 14205 | SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); |
| 14178 | 14206 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 14179 | 14207 | SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); |
| 14180 | 14208 | #endif |
| @@ -14191,10 +14219,11 @@ | ||
| 14191 | 14219 | |
| 14192 | 14220 | |
| 14193 | 14221 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); |
| 14194 | 14222 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 14195 | 14223 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 14224 | +SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); | |
| 14196 | 14225 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 14197 | 14226 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 14198 | 14227 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 14199 | 14228 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| 14200 | 14229 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); |
| @@ -14638,10 +14667,12 @@ | ||
| 14638 | 14667 | SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, |
| 14639 | 14668 | void (*)(sqlite3_context*,int,sqlite3_value **), |
| 14640 | 14669 | void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), |
| 14641 | 14670 | FuncDestructor *pDestructor |
| 14642 | 14671 | ); |
| 14672 | +SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); | |
| 14673 | +SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); | |
| 14643 | 14674 | SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); |
| 14644 | 14675 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); |
| 14645 | 14676 | |
| 14646 | 14677 | SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); |
| 14647 | 14678 | SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); |
| @@ -15734,18 +15765,20 @@ | ||
| 15734 | 15765 | ** - On either an index or a table |
| 15735 | 15766 | ** * A sorter |
| 15736 | 15767 | ** * A virtual table |
| 15737 | 15768 | ** * A one-row "pseudotable" stored in a single register |
| 15738 | 15769 | */ |
| 15770 | +typedef struct VdbeCursor VdbeCursor; | |
| 15739 | 15771 | struct VdbeCursor { |
| 15740 | 15772 | u8 eCurType; /* One of the CURTYPE_* values above */ |
| 15741 | 15773 | i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ |
| 15742 | 15774 | u8 nullRow; /* True if pointing to a row with no data */ |
| 15743 | 15775 | u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ |
| 15744 | 15776 | u8 isTable; /* True for rowid tables. False for indexes */ |
| 15745 | 15777 | #ifdef SQLITE_DEBUG |
| 15746 | 15778 | u8 seekOp; /* Most recent seek operation on this cursor */ |
| 15779 | + u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ | |
| 15747 | 15780 | #endif |
| 15748 | 15781 | Bool isEphemeral:1; /* True for an ephemeral table */ |
| 15749 | 15782 | Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ |
| 15750 | 15783 | Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ |
| 15751 | 15784 | Pgno pgnoRoot; /* Root page of the open btree cursor */ |
| @@ -15760,10 +15793,12 @@ | ||
| 15760 | 15793 | Btree *pBt; /* Separate file holding temporary table */ |
| 15761 | 15794 | KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ |
| 15762 | 15795 | int seekResult; /* Result of previous sqlite3BtreeMoveto() */ |
| 15763 | 15796 | i64 seqCount; /* Sequence counter */ |
| 15764 | 15797 | i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ |
| 15798 | + VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ | |
| 15799 | + int *aAltMap; /* Mapping from table to index column numbers */ | |
| 15765 | 15800 | #ifdef SQLITE_ENABLE_COLUMN_USED_MASK |
| 15766 | 15801 | u64 maskUsed; /* Mask of columns used by this cursor */ |
| 15767 | 15802 | #endif |
| 15768 | 15803 | |
| 15769 | 15804 | /* Cached information about the header for the data record that the |
| @@ -15784,11 +15819,10 @@ | ||
| 15784 | 15819 | u32 aType[1]; /* Type values for all entries in the record */ |
| 15785 | 15820 | /* 2*nField extra array elements allocated for aType[], beyond the one |
| 15786 | 15821 | ** static element declared in the structure. nField total array slots for |
| 15787 | 15822 | ** aType[] and nField+1 array slots for aOffset[] */ |
| 15788 | 15823 | }; |
| 15789 | -typedef struct VdbeCursor VdbeCursor; | |
| 15790 | 15824 | |
| 15791 | 15825 | /* |
| 15792 | 15826 | ** When a sub-program is executed (OP_Program), a structure of this type |
| 15793 | 15827 | ** is allocated to store the current value of the program counter, as |
| 15794 | 15828 | ** well as the current memory cell array and various other frame specific |
| @@ -15895,11 +15929,11 @@ | ||
| 15895 | 15929 | #define MEM_AffMask 0x001f /* Mask of affinity bits */ |
| 15896 | 15930 | #define MEM_RowSet 0x0020 /* Value is a RowSet object */ |
| 15897 | 15931 | #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ |
| 15898 | 15932 | #define MEM_Undefined 0x0080 /* Value is undefined */ |
| 15899 | 15933 | #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ |
| 15900 | -#define MEM_TypeMask 0x01ff /* Mask of type bits */ | |
| 15934 | +#define MEM_TypeMask 0x81ff /* Mask of type bits */ | |
| 15901 | 15935 | |
| 15902 | 15936 | |
| 15903 | 15937 | /* Whenever Mem contains a valid string or blob representation, one of |
| 15904 | 15938 | ** the following flags must be set to determine the memory management |
| 15905 | 15939 | ** policy for Mem.z. The MEM_Term flag tells us whether or not the |
| @@ -15909,14 +15943,21 @@ | ||
| 15909 | 15943 | #define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ |
| 15910 | 15944 | #define MEM_Static 0x0800 /* Mem.z points to a static string */ |
| 15911 | 15945 | #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ |
| 15912 | 15946 | #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ |
| 15913 | 15947 | #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ |
| 15948 | +#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */ | |
| 15914 | 15949 | #ifdef SQLITE_OMIT_INCRBLOB |
| 15915 | 15950 | #undef MEM_Zero |
| 15916 | 15951 | #define MEM_Zero 0x0000 |
| 15917 | 15952 | #endif |
| 15953 | + | |
| 15954 | +/* Return TRUE if Mem X contains dynamically allocated content - anything | |
| 15955 | +** that needs to be deallocated to avoid a leak. | |
| 15956 | +*/ | |
| 15957 | +#define VdbeMemDynamic(X) \ | |
| 15958 | + (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) | |
| 15918 | 15959 | |
| 15919 | 15960 | /* |
| 15920 | 15961 | ** Clear any existing type flags from a Mem and replace them with f |
| 15921 | 15962 | */ |
| 15922 | 15963 | #define MemSetTypeFlag(p, f) \ |
| @@ -16083,11 +16124,11 @@ | ||
| 16083 | 16124 | ** Function prototypes |
| 16084 | 16125 | */ |
| 16085 | 16126 | SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); |
| 16086 | 16127 | SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); |
| 16087 | 16128 | void sqliteVdbePopStack(Vdbe*,int); |
| 16088 | -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); | |
| 16129 | +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); | |
| 16089 | 16130 | SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); |
| 16090 | 16131 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 16091 | 16132 | SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); |
| 16092 | 16133 | #endif |
| 16093 | 16134 | SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); |
| @@ -16129,12 +16170,10 @@ | ||
| 16129 | 16170 | SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); |
| 16130 | 16171 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); |
| 16131 | 16172 | SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); |
| 16132 | 16173 | SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); |
| 16133 | 16174 | SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); |
| 16134 | -#define VdbeMemDynamic(X) \ | |
| 16135 | - (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) | |
| 16136 | 16175 | SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); |
| 16137 | 16176 | SQLITE_PRIVATE const char *sqlite3OpcodeName(int); |
| 16138 | 16177 | SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); |
| 16139 | 16178 | SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); |
| 16140 | 16179 | SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); |
| @@ -17492,11 +17531,11 @@ | ||
| 17492 | 17531 | z = zBuf; |
| 17493 | 17532 | }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 17494 | 17533 | sqlite3_result_error_toobig(context); |
| 17495 | 17534 | return; |
| 17496 | 17535 | }else{ |
| 17497 | - z = sqlite3DbMallocRaw(db, (int)n); | |
| 17536 | + z = sqlite3DbMallocRawNN(db, (int)n); | |
| 17498 | 17537 | if( z==0 ){ |
| 17499 | 17538 | sqlite3_result_error_nomem(context); |
| 17500 | 17539 | return; |
| 17501 | 17540 | } |
| 17502 | 17541 | } |
| @@ -20081,15 +20120,15 @@ | ||
| 20081 | 20120 | mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; |
| 20082 | 20121 | while( ALWAYS(iLogsize<LOGMAX) ){ |
| 20083 | 20122 | int iBuddy; |
| 20084 | 20123 | if( (iBlock>>iLogsize) & 1 ){ |
| 20085 | 20124 | iBuddy = iBlock - size; |
| 20125 | + assert( iBuddy>=0 ); | |
| 20086 | 20126 | }else{ |
| 20087 | 20127 | iBuddy = iBlock + size; |
| 20128 | + if( iBuddy>=mem5.nBlock ) break; | |
| 20088 | 20129 | } |
| 20089 | - assert( iBuddy>=0 ); | |
| 20090 | - if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break; | |
| 20091 | 20130 | if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; |
| 20092 | 20131 | memsys5Unlink(iBuddy, iLogsize); |
| 20093 | 20132 | iLogsize++; |
| 20094 | 20133 | if( iBuddy<iBlock ){ |
| 20095 | 20134 | mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize; |
| @@ -22386,14 +22425,28 @@ | ||
| 22386 | 22425 | /* |
| 22387 | 22426 | ** Allocate and zero memory. If the allocation fails, make |
| 22388 | 22427 | ** the mallocFailed flag in the connection pointer. |
| 22389 | 22428 | */ |
| 22390 | 22429 | SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ |
| 22391 | - void *p = sqlite3DbMallocRaw(db, n); | |
| 22392 | - if( p ){ | |
| 22393 | - memset(p, 0, (size_t)n); | |
| 22394 | - } | |
| 22430 | + void *p; | |
| 22431 | + testcase( db==0 ); | |
| 22432 | + p = sqlite3DbMallocRaw(db, n); | |
| 22433 | + if( p ) memset(p, 0, (size_t)n); | |
| 22434 | + return p; | |
| 22435 | +} | |
| 22436 | + | |
| 22437 | + | |
| 22438 | +/* Finish the work of sqlite3DbMallocRawNN for the unusual and | |
| 22439 | +** slower case when the allocation cannot be fulfilled using lookaside. | |
| 22440 | +*/ | |
| 22441 | +static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ | |
| 22442 | + void *p; | |
| 22443 | + assert( db!=0 ); | |
| 22444 | + p = sqlite3Malloc(n); | |
| 22445 | + if( !p ) sqlite3OomFault(db); | |
| 22446 | + sqlite3MemdebugSetType(p, | |
| 22447 | + (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); | |
| 22395 | 22448 | return p; |
| 22396 | 22449 | } |
| 22397 | 22450 | |
| 22398 | 22451 | /* |
| 22399 | 22452 | ** Allocate memory, either lookaside (if possible) or heap. |
| @@ -22411,71 +22464,77 @@ | ||
| 22411 | 22464 | ** int *b = (int*)sqlite3DbMallocRaw(db, 200); |
| 22412 | 22465 | ** if( b ) a[10] = 9; |
| 22413 | 22466 | ** |
| 22414 | 22467 | ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed |
| 22415 | 22468 | ** that all prior mallocs (ex: "a") worked too. |
| 22469 | +** | |
| 22470 | +** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is | |
| 22471 | +** not a NULL pointer. | |
| 22416 | 22472 | */ |
| 22417 | -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n); | |
| 22418 | 22473 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ |
| 22419 | - assert( db==0 || sqlite3_mutex_held(db->mutex) ); | |
| 22420 | - assert( db==0 || db->pnBytesFreed==0 ); | |
| 22474 | + void *p; | |
| 22475 | + if( db ) return sqlite3DbMallocRawNN(db, n); | |
| 22476 | + p = sqlite3Malloc(n); | |
| 22477 | + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); | |
| 22478 | + return p; | |
| 22479 | +} | |
| 22480 | +SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ | |
| 22421 | 22481 | #ifndef SQLITE_OMIT_LOOKASIDE |
| 22422 | - if( db ){ | |
| 22423 | - LookasideSlot *pBuf; | |
| 22424 | - if( db->mallocFailed ){ | |
| 22425 | - return 0; | |
| 22426 | - } | |
| 22427 | - if( db->lookaside.bEnabled ){ | |
| 22428 | - if( n>db->lookaside.sz ){ | |
| 22429 | - db->lookaside.anStat[1]++; | |
| 22430 | - }else if( (pBuf = db->lookaside.pFree)==0 ){ | |
| 22431 | - db->lookaside.anStat[2]++; | |
| 22432 | - }else{ | |
| 22433 | - db->lookaside.pFree = pBuf->pNext; | |
| 22434 | - db->lookaside.nOut++; | |
| 22435 | - db->lookaside.anStat[0]++; | |
| 22436 | - if( db->lookaside.nOut>db->lookaside.mxOut ){ | |
| 22437 | - db->lookaside.mxOut = db->lookaside.nOut; | |
| 22438 | - } | |
| 22439 | - return (void*)pBuf; | |
| 22440 | - } | |
| 22441 | - } | |
| 22482 | + LookasideSlot *pBuf; | |
| 22483 | + assert( db!=0 ); | |
| 22484 | + assert( sqlite3_mutex_held(db->mutex) ); | |
| 22485 | + assert( db->pnBytesFreed==0 ); | |
| 22486 | + if( db->lookaside.bDisable==0 ){ | |
| 22487 | + assert( db->mallocFailed==0 ); | |
| 22488 | + if( n>db->lookaside.sz ){ | |
| 22489 | + db->lookaside.anStat[1]++; | |
| 22490 | + }else if( (pBuf = db->lookaside.pFree)==0 ){ | |
| 22491 | + db->lookaside.anStat[2]++; | |
| 22492 | + }else{ | |
| 22493 | + db->lookaside.pFree = pBuf->pNext; | |
| 22494 | + db->lookaside.nOut++; | |
| 22495 | + db->lookaside.anStat[0]++; | |
| 22496 | + if( db->lookaside.nOut>db->lookaside.mxOut ){ | |
| 22497 | + db->lookaside.mxOut = db->lookaside.nOut; | |
| 22498 | + } | |
| 22499 | + return (void*)pBuf; | |
| 22500 | + } | |
| 22501 | + }else if( db->mallocFailed ){ | |
| 22502 | + return 0; | |
| 22442 | 22503 | } |
| 22443 | 22504 | #else |
| 22444 | - if( db && db->mallocFailed ){ | |
| 22505 | + assert( db!=0 ); | |
| 22506 | + assert( sqlite3_mutex_held(db->mutex) ); | |
| 22507 | + assert( db->pnBytesFreed==0 ); | |
| 22508 | + if( db->mallocFailed ){ | |
| 22445 | 22509 | return 0; |
| 22446 | 22510 | } |
| 22447 | 22511 | #endif |
| 22448 | 22512 | return dbMallocRawFinish(db, n); |
| 22449 | 22513 | } |
| 22450 | -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ | |
| 22451 | - void *p = sqlite3Malloc(n); | |
| 22452 | - if( !p && db ){ | |
| 22453 | - db->mallocFailed = 1; | |
| 22454 | - } | |
| 22455 | - sqlite3MemdebugSetType(p, | |
| 22456 | - (db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); | |
| 22457 | - return p; | |
| 22458 | -} | |
| 22514 | + | |
| 22515 | +/* Forward declaration */ | |
| 22516 | +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); | |
| 22459 | 22517 | |
| 22460 | 22518 | /* |
| 22461 | 22519 | ** Resize the block of memory pointed to by p to n bytes. If the |
| 22462 | 22520 | ** resize fails, set the mallocFailed flag in the connection object. |
| 22463 | 22521 | */ |
| 22464 | 22522 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ |
| 22523 | + assert( db!=0 ); | |
| 22524 | + if( p==0 ) return sqlite3DbMallocRawNN(db, n); | |
| 22525 | + assert( sqlite3_mutex_held(db->mutex) ); | |
| 22526 | + if( isLookaside(db,p) && n<=db->lookaside.sz ) return p; | |
| 22527 | + return dbReallocFinish(db, p, n); | |
| 22528 | +} | |
| 22529 | +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ | |
| 22465 | 22530 | void *pNew = 0; |
| 22466 | 22531 | assert( db!=0 ); |
| 22467 | - assert( sqlite3_mutex_held(db->mutex) ); | |
| 22532 | + assert( p!=0 ); | |
| 22468 | 22533 | if( db->mallocFailed==0 ){ |
| 22469 | - if( p==0 ){ | |
| 22470 | - return sqlite3DbMallocRaw(db, n); | |
| 22471 | - } | |
| 22472 | 22534 | if( isLookaside(db, p) ){ |
| 22473 | - if( n<=db->lookaside.sz ){ | |
| 22474 | - return p; | |
| 22475 | - } | |
| 22476 | - pNew = sqlite3DbMallocRaw(db, n); | |
| 22535 | + pNew = sqlite3DbMallocRawNN(db, n); | |
| 22477 | 22536 | if( pNew ){ |
| 22478 | 22537 | memcpy(pNew, p, db->lookaside.sz); |
| 22479 | 22538 | sqlite3DbFree(db, p); |
| 22480 | 22539 | } |
| 22481 | 22540 | }else{ |
| @@ -22482,14 +22541,14 @@ | ||
| 22482 | 22541 | assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22483 | 22542 | assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22484 | 22543 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 22485 | 22544 | pNew = sqlite3_realloc64(p, n); |
| 22486 | 22545 | if( !pNew ){ |
| 22487 | - db->mallocFailed = 1; | |
| 22546 | + sqlite3OomFault(db); | |
| 22488 | 22547 | } |
| 22489 | 22548 | sqlite3MemdebugSetType(pNew, |
| 22490 | - (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); | |
| 22549 | + (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); | |
| 22491 | 22550 | } |
| 22492 | 22551 | } |
| 22493 | 22552 | return pNew; |
| 22494 | 22553 | } |
| 22495 | 22554 | |
| @@ -22527,15 +22586,16 @@ | ||
| 22527 | 22586 | } |
| 22528 | 22587 | return zNew; |
| 22529 | 22588 | } |
| 22530 | 22589 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ |
| 22531 | 22590 | char *zNew; |
| 22591 | + assert( db!=0 ); | |
| 22532 | 22592 | if( z==0 ){ |
| 22533 | 22593 | return 0; |
| 22534 | 22594 | } |
| 22535 | 22595 | assert( (n&0x7fffffff)==n ); |
| 22536 | - zNew = sqlite3DbMallocRaw(db, n+1); | |
| 22596 | + zNew = sqlite3DbMallocRawNN(db, n+1); | |
| 22537 | 22597 | if( zNew ){ |
| 22538 | 22598 | memcpy(zNew, z, (size_t)n); |
| 22539 | 22599 | zNew[n] = 0; |
| 22540 | 22600 | } |
| 22541 | 22601 | return zNew; |
| @@ -22546,16 +22606,48 @@ | ||
| 22546 | 22606 | */ |
| 22547 | 22607 | SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ |
| 22548 | 22608 | sqlite3DbFree(db, *pz); |
| 22549 | 22609 | *pz = sqlite3DbStrDup(db, zNew); |
| 22550 | 22610 | } |
| 22611 | + | |
| 22612 | +/* | |
| 22613 | +** Call this routine to record the fact that an OOM (out-of-memory) error | |
| 22614 | +** has happened. This routine will set db->mallocFailed, and also | |
| 22615 | +** temporarily disable the lookaside memory allocator and interrupt | |
| 22616 | +** any running VDBEs. | |
| 22617 | +*/ | |
| 22618 | +SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){ | |
| 22619 | + if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ | |
| 22620 | + db->mallocFailed = 1; | |
| 22621 | + if( db->nVdbeExec>0 ){ | |
| 22622 | + db->u1.isInterrupted = 1; | |
| 22623 | + } | |
| 22624 | + db->lookaside.bDisable++; | |
| 22625 | + } | |
| 22626 | +} | |
| 22627 | + | |
| 22628 | +/* | |
| 22629 | +** This routine reactivates the memory allocator and clears the | |
| 22630 | +** db->mallocFailed flag as necessary. | |
| 22631 | +** | |
| 22632 | +** The memory allocator is not restarted if there are running | |
| 22633 | +** VDBEs. | |
| 22634 | +*/ | |
| 22635 | +SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){ | |
| 22636 | + if( db->mallocFailed && db->nVdbeExec==0 ){ | |
| 22637 | + db->mallocFailed = 0; | |
| 22638 | + db->u1.isInterrupted = 0; | |
| 22639 | + assert( db->lookaside.bDisable>0 ); | |
| 22640 | + db->lookaside.bDisable--; | |
| 22641 | + } | |
| 22642 | +} | |
| 22551 | 22643 | |
| 22552 | 22644 | /* |
| 22553 | 22645 | ** Take actions at the end of an API call to indicate an OOM error |
| 22554 | 22646 | */ |
| 22555 | 22647 | static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ |
| 22556 | - db->mallocFailed = 0; | |
| 22648 | + sqlite3OomClear(db); | |
| 22557 | 22649 | sqlite3Error(db, SQLITE_NOMEM); |
| 22558 | 22650 | return SQLITE_NOMEM; |
| 22559 | 22651 | } |
| 22560 | 22652 | |
| 22561 | 22653 | /* |
| @@ -22756,11 +22848,10 @@ | ||
| 22756 | 22848 | /* |
| 22757 | 22849 | ** Render a string given by "fmt" into the StrAccum object. |
| 22758 | 22850 | */ |
| 22759 | 22851 | SQLITE_PRIVATE void sqlite3VXPrintf( |
| 22760 | 22852 | StrAccum *pAccum, /* Accumulate results here */ |
| 22761 | - u32 bFlags, /* SQLITE_PRINTF_* flags */ | |
| 22762 | 22853 | const char *fmt, /* Format string */ |
| 22763 | 22854 | va_list ap /* arguments */ |
| 22764 | 22855 | ){ |
| 22765 | 22856 | int c; /* Next character in the format string */ |
| 22766 | 22857 | char *bufpt; /* Pointer to the conversion buffer */ |
| @@ -22796,15 +22887,15 @@ | ||
| 22796 | 22887 | #endif |
| 22797 | 22888 | PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ |
| 22798 | 22889 | char buf[etBUFSIZE]; /* Conversion buffer */ |
| 22799 | 22890 | |
| 22800 | 22891 | bufpt = 0; |
| 22801 | - if( bFlags ){ | |
| 22802 | - if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ | |
| 22892 | + if( pAccum->printfFlags ){ | |
| 22893 | + if( (bArgList = (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ | |
| 22803 | 22894 | pArgList = va_arg(ap, PrintfArguments*); |
| 22804 | 22895 | } |
| 22805 | - useIntern = bFlags & SQLITE_PRINTF_INTERNAL; | |
| 22896 | + useIntern = pAccum->printfFlags & SQLITE_PRINTF_INTERNAL; | |
| 22806 | 22897 | }else{ |
| 22807 | 22898 | bArgList = useIntern = 0; |
| 22808 | 22899 | } |
| 22809 | 22900 | for(; (c=(*fmt))!=0; ++fmt){ |
| 22810 | 22901 | if( c!='%' ){ |
| @@ -23351,13 +23442,13 @@ | ||
| 23351 | 23442 | if( p->mxAlloc==0 ){ |
| 23352 | 23443 | N = p->nAlloc - p->nChar - 1; |
| 23353 | 23444 | setStrAccumError(p, STRACCUM_TOOBIG); |
| 23354 | 23445 | return N; |
| 23355 | 23446 | }else{ |
| 23356 | - char *zOld = p->bMalloced ? p->zText : 0; | |
| 23447 | + char *zOld = isMalloced(p) ? p->zText : 0; | |
| 23357 | 23448 | i64 szNew = p->nChar; |
| 23358 | - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); | |
| 23449 | + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); | |
| 23359 | 23450 | szNew += N + 1; |
| 23360 | 23451 | if( szNew+p->nChar<=p->mxAlloc ){ |
| 23361 | 23452 | /* Force exponential buffer size growth as long as it does not overflow, |
| 23362 | 23453 | ** to avoid having to call this routine too often */ |
| 23363 | 23454 | szNew += p->nChar; |
| @@ -23374,14 +23465,14 @@ | ||
| 23374 | 23465 | }else{ |
| 23375 | 23466 | zNew = sqlite3_realloc64(zOld, p->nAlloc); |
| 23376 | 23467 | } |
| 23377 | 23468 | if( zNew ){ |
| 23378 | 23469 | assert( p->zText!=0 || p->nChar==0 ); |
| 23379 | - if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); | |
| 23470 | + if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); | |
| 23380 | 23471 | p->zText = zNew; |
| 23381 | 23472 | p->nAlloc = sqlite3DbMallocSize(p->db, zNew); |
| 23382 | - p->bMalloced = 1; | |
| 23473 | + p->printfFlags |= SQLITE_PRINTF_MALLOCED; | |
| 23383 | 23474 | }else{ |
| 23384 | 23475 | sqlite3StrAccumReset(p); |
| 23385 | 23476 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23386 | 23477 | return 0; |
| 23387 | 23478 | } |
| @@ -23395,11 +23486,11 @@ | ||
| 23395 | 23486 | SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ |
| 23396 | 23487 | testcase( p->nChar + (i64)N > 0x7fffffff ); |
| 23397 | 23488 | if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ |
| 23398 | 23489 | return; |
| 23399 | 23490 | } |
| 23400 | - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); | |
| 23491 | + assert( (p->zText==p->zBase)==!isMalloced(p) ); | |
| 23401 | 23492 | while( (N--)>0 ) p->zText[p->nChar++] = c; |
| 23402 | 23493 | } |
| 23403 | 23494 | |
| 23404 | 23495 | /* |
| 23405 | 23496 | ** The StrAccum "p" is not large enough to accept N new bytes of z[]. |
| @@ -23413,11 +23504,11 @@ | ||
| 23413 | 23504 | N = sqlite3StrAccumEnlarge(p, N); |
| 23414 | 23505 | if( N>0 ){ |
| 23415 | 23506 | memcpy(&p->zText[p->nChar], z, N); |
| 23416 | 23507 | p->nChar += N; |
| 23417 | 23508 | } |
| 23418 | - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); | |
| 23509 | + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); | |
| 23419 | 23510 | } |
| 23420 | 23511 | |
| 23421 | 23512 | /* |
| 23422 | 23513 | ** Append N bytes of text from z to the StrAccum object. Increase the |
| 23423 | 23514 | ** size of the memory allocation for StrAccum if necessary. |
| @@ -23449,17 +23540,17 @@ | ||
| 23449 | 23540 | ** Return a pointer to the resulting string. Return a NULL |
| 23450 | 23541 | ** pointer if any kind of error was encountered. |
| 23451 | 23542 | */ |
| 23452 | 23543 | SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ |
| 23453 | 23544 | if( p->zText ){ |
| 23454 | - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); | |
| 23545 | + assert( (p->zText==p->zBase)==!isMalloced(p) ); | |
| 23455 | 23546 | p->zText[p->nChar] = 0; |
| 23456 | - if( p->mxAlloc>0 && p->bMalloced==0 ){ | |
| 23547 | + if( p->mxAlloc>0 && !isMalloced(p) ){ | |
| 23457 | 23548 | p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
| 23458 | 23549 | if( p->zText ){ |
| 23459 | 23550 | memcpy(p->zText, p->zBase, p->nChar+1); |
| 23460 | - p->bMalloced = 1; | |
| 23551 | + p->printfFlags |= SQLITE_PRINTF_MALLOCED; | |
| 23461 | 23552 | }else{ |
| 23462 | 23553 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23463 | 23554 | } |
| 23464 | 23555 | } |
| 23465 | 23556 | } |
| @@ -23468,14 +23559,14 @@ | ||
| 23468 | 23559 | |
| 23469 | 23560 | /* |
| 23470 | 23561 | ** Reset an StrAccum string. Reclaim all malloced memory. |
| 23471 | 23562 | */ |
| 23472 | 23563 | SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ |
| 23473 | - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); | |
| 23474 | - if( p->bMalloced ){ | |
| 23564 | + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); | |
| 23565 | + if( isMalloced(p) ){ | |
| 23475 | 23566 | sqlite3DbFree(p->db, p->zText); |
| 23476 | - p->bMalloced = 0; | |
| 23567 | + p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; | |
| 23477 | 23568 | } |
| 23478 | 23569 | p->zText = 0; |
| 23479 | 23570 | } |
| 23480 | 23571 | |
| 23481 | 23572 | /* |
| @@ -23497,11 +23588,11 @@ | ||
| 23497 | 23588 | p->db = db; |
| 23498 | 23589 | p->nChar = 0; |
| 23499 | 23590 | p->nAlloc = n; |
| 23500 | 23591 | p->mxAlloc = mx; |
| 23501 | 23592 | p->accError = 0; |
| 23502 | - p->bMalloced = 0; | |
| 23593 | + p->printfFlags = 0; | |
| 23503 | 23594 | } |
| 23504 | 23595 | |
| 23505 | 23596 | /* |
| 23506 | 23597 | ** Print into memory obtained from sqliteMalloc(). Use the internal |
| 23507 | 23598 | ** %-conversion extensions. |
| @@ -23511,14 +23602,15 @@ | ||
| 23511 | 23602 | char zBase[SQLITE_PRINT_BUF_SIZE]; |
| 23512 | 23603 | StrAccum acc; |
| 23513 | 23604 | assert( db!=0 ); |
| 23514 | 23605 | sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), |
| 23515 | 23606 | db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 23516 | - sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); | |
| 23607 | + acc.printfFlags = SQLITE_PRINTF_INTERNAL; | |
| 23608 | + sqlite3VXPrintf(&acc, zFormat, ap); | |
| 23517 | 23609 | z = sqlite3StrAccumFinish(&acc); |
| 23518 | 23610 | if( acc.accError==STRACCUM_NOMEM ){ |
| 23519 | - db->mallocFailed = 1; | |
| 23611 | + sqlite3OomFault(db); | |
| 23520 | 23612 | } |
| 23521 | 23613 | return z; |
| 23522 | 23614 | } |
| 23523 | 23615 | |
| 23524 | 23616 | /* |
| @@ -23551,11 +23643,11 @@ | ||
| 23551 | 23643 | #endif |
| 23552 | 23644 | #ifndef SQLITE_OMIT_AUTOINIT |
| 23553 | 23645 | if( sqlite3_initialize() ) return 0; |
| 23554 | 23646 | #endif |
| 23555 | 23647 | sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); |
| 23556 | - sqlite3VXPrintf(&acc, 0, zFormat, ap); | |
| 23648 | + sqlite3VXPrintf(&acc, zFormat, ap); | |
| 23557 | 23649 | z = sqlite3StrAccumFinish(&acc); |
| 23558 | 23650 | return z; |
| 23559 | 23651 | } |
| 23560 | 23652 | |
| 23561 | 23653 | /* |
| @@ -23596,11 +23688,11 @@ | ||
| 23596 | 23688 | if( zBuf ) zBuf[0] = 0; |
| 23597 | 23689 | return zBuf; |
| 23598 | 23690 | } |
| 23599 | 23691 | #endif |
| 23600 | 23692 | sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); |
| 23601 | - sqlite3VXPrintf(&acc, 0, zFormat, ap); | |
| 23693 | + sqlite3VXPrintf(&acc, zFormat, ap); | |
| 23602 | 23694 | return sqlite3StrAccumFinish(&acc); |
| 23603 | 23695 | } |
| 23604 | 23696 | SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
| 23605 | 23697 | char *z; |
| 23606 | 23698 | va_list ap; |
| @@ -23627,11 +23719,11 @@ | ||
| 23627 | 23719 | static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
| 23628 | 23720 | StrAccum acc; /* String accumulator */ |
| 23629 | 23721 | char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
| 23630 | 23722 | |
| 23631 | 23723 | sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); |
| 23632 | - sqlite3VXPrintf(&acc, 0, zFormat, ap); | |
| 23724 | + sqlite3VXPrintf(&acc, zFormat, ap); | |
| 23633 | 23725 | sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
| 23634 | 23726 | sqlite3StrAccumFinish(&acc)); |
| 23635 | 23727 | } |
| 23636 | 23728 | |
| 23637 | 23729 | /* |
| @@ -23656,11 +23748,11 @@ | ||
| 23656 | 23748 | va_list ap; |
| 23657 | 23749 | StrAccum acc; |
| 23658 | 23750 | char zBuf[500]; |
| 23659 | 23751 | sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); |
| 23660 | 23752 | va_start(ap,zFormat); |
| 23661 | - sqlite3VXPrintf(&acc, 0, zFormat, ap); | |
| 23753 | + sqlite3VXPrintf(&acc, zFormat, ap); | |
| 23662 | 23754 | va_end(ap); |
| 23663 | 23755 | sqlite3StrAccumFinish(&acc); |
| 23664 | 23756 | fprintf(stdout,"%s", zBuf); |
| 23665 | 23757 | fflush(stdout); |
| 23666 | 23758 | } |
| @@ -23669,14 +23761,14 @@ | ||
| 23669 | 23761 | |
| 23670 | 23762 | /* |
| 23671 | 23763 | ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument |
| 23672 | 23764 | ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. |
| 23673 | 23765 | */ |
| 23674 | -SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ | |
| 23766 | +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ | |
| 23675 | 23767 | va_list ap; |
| 23676 | 23768 | va_start(ap,zFormat); |
| 23677 | - sqlite3VXPrintf(p, bFlags, zFormat, ap); | |
| 23769 | + sqlite3VXPrintf(p, zFormat, ap); | |
| 23678 | 23770 | va_end(ap); |
| 23679 | 23771 | } |
| 23680 | 23772 | |
| 23681 | 23773 | /************** End of printf.c **********************************************/ |
| 23682 | 23774 | /************** Begin file treeview.c ****************************************/ |
| @@ -23743,11 +23835,11 @@ | ||
| 23743 | 23835 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); |
| 23744 | 23836 | } |
| 23745 | 23837 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); |
| 23746 | 23838 | } |
| 23747 | 23839 | va_start(ap, zFormat); |
| 23748 | - sqlite3VXPrintf(&acc, 0, zFormat, ap); | |
| 23840 | + sqlite3VXPrintf(&acc, zFormat, ap); | |
| 23749 | 23841 | va_end(ap); |
| 23750 | 23842 | if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); |
| 23751 | 23843 | sqlite3StrAccumFinish(&acc); |
| 23752 | 23844 | fprintf(stdout,"%s", zBuf); |
| 23753 | 23845 | fflush(stdout); |
| @@ -23778,21 +23870,21 @@ | ||
| 23778 | 23870 | for(i=0; i<pWith->nCte; i++){ |
| 23779 | 23871 | StrAccum x; |
| 23780 | 23872 | char zLine[1000]; |
| 23781 | 23873 | const struct Cte *pCte = &pWith->a[i]; |
| 23782 | 23874 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23783 | - sqlite3XPrintf(&x, 0, "%s", pCte->zName); | |
| 23875 | + sqlite3XPrintf(&x, "%s", pCte->zName); | |
| 23784 | 23876 | if( pCte->pCols && pCte->pCols->nExpr>0 ){ |
| 23785 | 23877 | char cSep = '('; |
| 23786 | 23878 | int j; |
| 23787 | 23879 | for(j=0; j<pCte->pCols->nExpr; j++){ |
| 23788 | - sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName); | |
| 23880 | + sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); | |
| 23789 | 23881 | cSep = ','; |
| 23790 | 23882 | } |
| 23791 | - sqlite3XPrintf(&x, 0, ")"); | |
| 23883 | + sqlite3XPrintf(&x, ")"); | |
| 23792 | 23884 | } |
| 23793 | - sqlite3XPrintf(&x, 0, " AS"); | |
| 23885 | + sqlite3XPrintf(&x, " AS"); | |
| 23794 | 23886 | sqlite3StrAccumFinish(&x); |
| 23795 | 23887 | sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1); |
| 23796 | 23888 | sqlite3TreeViewSelect(pView, pCte->pSelect, 0); |
| 23797 | 23889 | sqlite3TreeViewPop(pView); |
| 23798 | 23890 | } |
| @@ -23839,24 +23931,24 @@ | ||
| 23839 | 23931 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 23840 | 23932 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 23841 | 23933 | StrAccum x; |
| 23842 | 23934 | char zLine[100]; |
| 23843 | 23935 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23844 | - sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); | |
| 23936 | + sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); | |
| 23845 | 23937 | if( pItem->zDatabase ){ |
| 23846 | - sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); | |
| 23938 | + sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); | |
| 23847 | 23939 | }else if( pItem->zName ){ |
| 23848 | - sqlite3XPrintf(&x, 0, " %s", pItem->zName); | |
| 23940 | + sqlite3XPrintf(&x, " %s", pItem->zName); | |
| 23849 | 23941 | } |
| 23850 | 23942 | if( pItem->pTab ){ |
| 23851 | - sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); | |
| 23943 | + sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); | |
| 23852 | 23944 | } |
| 23853 | 23945 | if( pItem->zAlias ){ |
| 23854 | - sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); | |
| 23946 | + sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); | |
| 23855 | 23947 | } |
| 23856 | 23948 | if( pItem->fg.jointype & JT_LEFT ){ |
| 23857 | - sqlite3XPrintf(&x, 0, " LEFT-JOIN"); | |
| 23949 | + sqlite3XPrintf(&x, " LEFT-JOIN"); | |
| 23858 | 23950 | } |
| 23859 | 23951 | sqlite3StrAccumFinish(&x); |
| 23860 | 23952 | sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); |
| 23861 | 23953 | if( pItem->pSelect ){ |
| 23862 | 23954 | sqlite3TreeViewSelect(pView, pItem->pSelect, 0); |
| @@ -24899,11 +24991,11 @@ | ||
| 24899 | 24991 | *z = 0; |
| 24900 | 24992 | assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); |
| 24901 | 24993 | |
| 24902 | 24994 | c = pMem->flags; |
| 24903 | 24995 | sqlite3VdbeMemRelease(pMem); |
| 24904 | - pMem->flags = MEM_Str|MEM_Term|(c&MEM_AffMask); | |
| 24996 | + pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype)); | |
| 24905 | 24997 | pMem->enc = desiredEnc; |
| 24906 | 24998 | pMem->z = (char*)zOut; |
| 24907 | 24999 | pMem->zMalloc = pMem->z; |
| 24908 | 25000 | pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); |
| 24909 | 25001 | |
| @@ -25349,10 +25441,18 @@ | ||
| 25349 | 25441 | } |
| 25350 | 25442 | } |
| 25351 | 25443 | z[j] = 0; |
| 25352 | 25444 | return j; |
| 25353 | 25445 | } |
| 25446 | + | |
| 25447 | +/* | |
| 25448 | +** Generate a Token object from a string | |
| 25449 | +*/ | |
| 25450 | +SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ | |
| 25451 | + p->z = z; | |
| 25452 | + p->n = sqlite3Strlen30(z); | |
| 25453 | +} | |
| 25354 | 25454 | |
| 25355 | 25455 | /* Convenient short-hand */ |
| 25356 | 25456 | #define UpperToLower sqlite3UpperToLower |
| 25357 | 25457 | |
| 25358 | 25458 | /* |
| @@ -26258,11 +26358,11 @@ | ||
| 26258 | 26358 | */ |
| 26259 | 26359 | SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ |
| 26260 | 26360 | char *zBlob; |
| 26261 | 26361 | int i; |
| 26262 | 26362 | |
| 26263 | - zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1); | |
| 26363 | + zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1); | |
| 26264 | 26364 | n--; |
| 26265 | 26365 | if( zBlob ){ |
| 26266 | 26366 | for(i=0; i<n; i+=2){ |
| 26267 | 26367 | zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]); |
| 26268 | 26368 | } |
| @@ -26796,95 +26896,96 @@ | ||
| 26796 | 26896 | # define OpHelp(X) "\0" X |
| 26797 | 26897 | #else |
| 26798 | 26898 | # define OpHelp(X) |
| 26799 | 26899 | #endif |
| 26800 | 26900 | SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ |
| 26801 | - static const char *const azName[] = { "?", | |
| 26802 | - /* 1 */ "Savepoint" OpHelp(""), | |
| 26803 | - /* 2 */ "AutoCommit" OpHelp(""), | |
| 26804 | - /* 3 */ "Transaction" OpHelp(""), | |
| 26805 | - /* 4 */ "SorterNext" OpHelp(""), | |
| 26806 | - /* 5 */ "PrevIfOpen" OpHelp(""), | |
| 26807 | - /* 6 */ "NextIfOpen" OpHelp(""), | |
| 26808 | - /* 7 */ "Prev" OpHelp(""), | |
| 26809 | - /* 8 */ "Next" OpHelp(""), | |
| 26810 | - /* 9 */ "Checkpoint" OpHelp(""), | |
| 26811 | - /* 10 */ "JournalMode" OpHelp(""), | |
| 26812 | - /* 11 */ "Vacuum" OpHelp(""), | |
| 26813 | - /* 12 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), | |
| 26814 | - /* 13 */ "VUpdate" OpHelp("data=r[P3@P2]"), | |
| 26815 | - /* 14 */ "Goto" OpHelp(""), | |
| 26816 | - /* 15 */ "Gosub" OpHelp(""), | |
| 26817 | - /* 16 */ "Return" OpHelp(""), | |
| 26818 | - /* 17 */ "InitCoroutine" OpHelp(""), | |
| 26819 | - /* 18 */ "EndCoroutine" OpHelp(""), | |
| 26901 | + static const char *const azName[] = { | |
| 26902 | + /* 0 */ "Savepoint" OpHelp(""), | |
| 26903 | + /* 1 */ "AutoCommit" OpHelp(""), | |
| 26904 | + /* 2 */ "Transaction" OpHelp(""), | |
| 26905 | + /* 3 */ "SorterNext" OpHelp(""), | |
| 26906 | + /* 4 */ "PrevIfOpen" OpHelp(""), | |
| 26907 | + /* 5 */ "NextIfOpen" OpHelp(""), | |
| 26908 | + /* 6 */ "Prev" OpHelp(""), | |
| 26909 | + /* 7 */ "Next" OpHelp(""), | |
| 26910 | + /* 8 */ "Checkpoint" OpHelp(""), | |
| 26911 | + /* 9 */ "JournalMode" OpHelp(""), | |
| 26912 | + /* 10 */ "Vacuum" OpHelp(""), | |
| 26913 | + /* 11 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), | |
| 26914 | + /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"), | |
| 26915 | + /* 13 */ "Goto" OpHelp(""), | |
| 26916 | + /* 14 */ "Gosub" OpHelp(""), | |
| 26917 | + /* 15 */ "Return" OpHelp(""), | |
| 26918 | + /* 16 */ "InitCoroutine" OpHelp(""), | |
| 26919 | + /* 17 */ "EndCoroutine" OpHelp(""), | |
| 26920 | + /* 18 */ "Yield" OpHelp(""), | |
| 26820 | 26921 | /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), |
| 26821 | - /* 20 */ "Yield" OpHelp(""), | |
| 26822 | - /* 21 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), | |
| 26823 | - /* 22 */ "Halt" OpHelp(""), | |
| 26824 | - /* 23 */ "Integer" OpHelp("r[P2]=P1"), | |
| 26825 | - /* 24 */ "Int64" OpHelp("r[P2]=P4"), | |
| 26826 | - /* 25 */ "String" OpHelp("r[P2]='P4' (len=P1)"), | |
| 26827 | - /* 26 */ "Null" OpHelp("r[P2..P3]=NULL"), | |
| 26828 | - /* 27 */ "SoftNull" OpHelp("r[P1]=NULL"), | |
| 26829 | - /* 28 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), | |
| 26830 | - /* 29 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), | |
| 26831 | - /* 30 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), | |
| 26832 | - /* 31 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), | |
| 26833 | - /* 32 */ "SCopy" OpHelp("r[P2]=r[P1]"), | |
| 26834 | - /* 33 */ "IntCopy" OpHelp("r[P2]=r[P1]"), | |
| 26835 | - /* 34 */ "ResultRow" OpHelp("output=r[P1@P2]"), | |
| 26836 | - /* 35 */ "CollSeq" OpHelp(""), | |
| 26837 | - /* 36 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 26838 | - /* 37 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 26839 | - /* 38 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), | |
| 26840 | - /* 39 */ "MustBeInt" OpHelp(""), | |
| 26841 | - /* 40 */ "RealAffinity" OpHelp(""), | |
| 26842 | - /* 41 */ "Cast" OpHelp("affinity(r[P1])"), | |
| 26843 | - /* 42 */ "Permutation" OpHelp(""), | |
| 26844 | - /* 43 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), | |
| 26845 | - /* 44 */ "Jump" OpHelp(""), | |
| 26846 | - /* 45 */ "Once" OpHelp(""), | |
| 26847 | - /* 46 */ "If" OpHelp(""), | |
| 26848 | - /* 47 */ "IfNot" OpHelp(""), | |
| 26849 | - /* 48 */ "Column" OpHelp("r[P3]=PX"), | |
| 26850 | - /* 49 */ "Affinity" OpHelp("affinity(r[P1@P2])"), | |
| 26851 | - /* 50 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), | |
| 26852 | - /* 51 */ "Count" OpHelp("r[P2]=count()"), | |
| 26853 | - /* 52 */ "ReadCookie" OpHelp(""), | |
| 26854 | - /* 53 */ "SetCookie" OpHelp(""), | |
| 26855 | - /* 54 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), | |
| 26856 | - /* 55 */ "OpenRead" OpHelp("root=P2 iDb=P3"), | |
| 26857 | - /* 56 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), | |
| 26858 | - /* 57 */ "OpenAutoindex" OpHelp("nColumn=P2"), | |
| 26859 | - /* 58 */ "OpenEphemeral" OpHelp("nColumn=P2"), | |
| 26860 | - /* 59 */ "SorterOpen" OpHelp(""), | |
| 26861 | - /* 60 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), | |
| 26862 | - /* 61 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), | |
| 26863 | - /* 62 */ "Close" OpHelp(""), | |
| 26864 | - /* 63 */ "ColumnsUsed" OpHelp(""), | |
| 26865 | - /* 64 */ "SeekLT" OpHelp("key=r[P3@P4]"), | |
| 26866 | - /* 65 */ "SeekLE" OpHelp("key=r[P3@P4]"), | |
| 26867 | - /* 66 */ "SeekGE" OpHelp("key=r[P3@P4]"), | |
| 26868 | - /* 67 */ "SeekGT" OpHelp("key=r[P3@P4]"), | |
| 26869 | - /* 68 */ "Seek" OpHelp("intkey=r[P2]"), | |
| 26870 | - /* 69 */ "NoConflict" OpHelp("key=r[P3@P4]"), | |
| 26871 | - /* 70 */ "NotFound" OpHelp("key=r[P3@P4]"), | |
| 26922 | + /* 20 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), | |
| 26923 | + /* 21 */ "Halt" OpHelp(""), | |
| 26924 | + /* 22 */ "Integer" OpHelp("r[P2]=P1"), | |
| 26925 | + /* 23 */ "Int64" OpHelp("r[P2]=P4"), | |
| 26926 | + /* 24 */ "String" OpHelp("r[P2]='P4' (len=P1)"), | |
| 26927 | + /* 25 */ "Null" OpHelp("r[P2..P3]=NULL"), | |
| 26928 | + /* 26 */ "SoftNull" OpHelp("r[P1]=NULL"), | |
| 26929 | + /* 27 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), | |
| 26930 | + /* 28 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), | |
| 26931 | + /* 29 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), | |
| 26932 | + /* 30 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), | |
| 26933 | + /* 31 */ "SCopy" OpHelp("r[P2]=r[P1]"), | |
| 26934 | + /* 32 */ "IntCopy" OpHelp("r[P2]=r[P1]"), | |
| 26935 | + /* 33 */ "ResultRow" OpHelp("output=r[P1@P2]"), | |
| 26936 | + /* 34 */ "CollSeq" OpHelp(""), | |
| 26937 | + /* 35 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 26938 | + /* 36 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), | |
| 26939 | + /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), | |
| 26940 | + /* 38 */ "MustBeInt" OpHelp(""), | |
| 26941 | + /* 39 */ "RealAffinity" OpHelp(""), | |
| 26942 | + /* 40 */ "Cast" OpHelp("affinity(r[P1])"), | |
| 26943 | + /* 41 */ "Permutation" OpHelp(""), | |
| 26944 | + /* 42 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), | |
| 26945 | + /* 43 */ "Jump" OpHelp(""), | |
| 26946 | + /* 44 */ "Once" OpHelp(""), | |
| 26947 | + /* 45 */ "If" OpHelp(""), | |
| 26948 | + /* 46 */ "IfNot" OpHelp(""), | |
| 26949 | + /* 47 */ "Column" OpHelp("r[P3]=PX"), | |
| 26950 | + /* 48 */ "Affinity" OpHelp("affinity(r[P1@P2])"), | |
| 26951 | + /* 49 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), | |
| 26952 | + /* 50 */ "Count" OpHelp("r[P2]=count()"), | |
| 26953 | + /* 51 */ "ReadCookie" OpHelp(""), | |
| 26954 | + /* 52 */ "SetCookie" OpHelp(""), | |
| 26955 | + /* 53 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), | |
| 26956 | + /* 54 */ "OpenRead" OpHelp("root=P2 iDb=P3"), | |
| 26957 | + /* 55 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), | |
| 26958 | + /* 56 */ "OpenAutoindex" OpHelp("nColumn=P2"), | |
| 26959 | + /* 57 */ "OpenEphemeral" OpHelp("nColumn=P2"), | |
| 26960 | + /* 58 */ "SorterOpen" OpHelp(""), | |
| 26961 | + /* 59 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), | |
| 26962 | + /* 60 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), | |
| 26963 | + /* 61 */ "Close" OpHelp(""), | |
| 26964 | + /* 62 */ "ColumnsUsed" OpHelp(""), | |
| 26965 | + /* 63 */ "SeekLT" OpHelp("key=r[P3@P4]"), | |
| 26966 | + /* 64 */ "SeekLE" OpHelp("key=r[P3@P4]"), | |
| 26967 | + /* 65 */ "SeekGE" OpHelp("key=r[P3@P4]"), | |
| 26968 | + /* 66 */ "SeekGT" OpHelp("key=r[P3@P4]"), | |
| 26969 | + /* 67 */ "NoConflict" OpHelp("key=r[P3@P4]"), | |
| 26970 | + /* 68 */ "NotFound" OpHelp("key=r[P3@P4]"), | |
| 26971 | + /* 69 */ "Found" OpHelp("key=r[P3@P4]"), | |
| 26972 | + /* 70 */ "NotExists" OpHelp("intkey=r[P3]"), | |
| 26872 | 26973 | /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), |
| 26873 | 26974 | /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), |
| 26874 | - /* 73 */ "Found" OpHelp("key=r[P3@P4]"), | |
| 26875 | - /* 74 */ "NotExists" OpHelp("intkey=r[P3]"), | |
| 26876 | - /* 75 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), | |
| 26975 | + /* 73 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), | |
| 26976 | + /* 74 */ "NewRowid" OpHelp("r[P2]=rowid"), | |
| 26977 | + /* 75 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), | |
| 26877 | 26978 | /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), |
| 26878 | 26979 | /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), |
| 26879 | 26980 | /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), |
| 26880 | 26981 | /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), |
| 26881 | 26982 | /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), |
| 26882 | 26983 | /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), |
| 26883 | 26984 | /* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"), |
| 26884 | 26985 | /* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"), |
| 26885 | - /* 84 */ "NewRowid" OpHelp("r[P2]=rowid"), | |
| 26986 | + /* 84 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), | |
| 26886 | 26987 | /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), |
| 26887 | 26988 | /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), |
| 26888 | 26989 | /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), |
| 26889 | 26990 | /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), |
| 26890 | 26991 | /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), |
| @@ -26891,78 +26992,77 @@ | ||
| 26891 | 26992 | /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), |
| 26892 | 26993 | /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), |
| 26893 | 26994 | /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), |
| 26894 | 26995 | /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), |
| 26895 | 26996 | /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), |
| 26896 | - /* 95 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), | |
| 26997 | + /* 95 */ "Delete" OpHelp(""), | |
| 26897 | 26998 | /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), |
| 26898 | 26999 | /* 97 */ "String8" OpHelp("r[P2]='P4'"), |
| 26899 | - /* 98 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), | |
| 26900 | - /* 99 */ "Delete" OpHelp(""), | |
| 26901 | - /* 100 */ "ResetCount" OpHelp(""), | |
| 26902 | - /* 101 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), | |
| 26903 | - /* 102 */ "SorterData" OpHelp("r[P2]=data"), | |
| 26904 | - /* 103 */ "RowKey" OpHelp("r[P2]=key"), | |
| 26905 | - /* 104 */ "RowData" OpHelp("r[P2]=data"), | |
| 26906 | - /* 105 */ "Rowid" OpHelp("r[P2]=rowid"), | |
| 26907 | - /* 106 */ "NullRow" OpHelp(""), | |
| 26908 | - /* 107 */ "Last" OpHelp(""), | |
| 26909 | - /* 108 */ "SorterSort" OpHelp(""), | |
| 26910 | - /* 109 */ "Sort" OpHelp(""), | |
| 26911 | - /* 110 */ "Rewind" OpHelp(""), | |
| 26912 | - /* 111 */ "SorterInsert" OpHelp(""), | |
| 26913 | - /* 112 */ "IdxInsert" OpHelp("key=r[P2]"), | |
| 26914 | - /* 113 */ "IdxDelete" OpHelp("key=r[P2@P3]"), | |
| 26915 | - /* 114 */ "IdxRowid" OpHelp("r[P2]=rowid"), | |
| 26916 | - /* 115 */ "IdxLE" OpHelp("key=r[P3@P4]"), | |
| 26917 | - /* 116 */ "IdxGT" OpHelp("key=r[P3@P4]"), | |
| 26918 | - /* 117 */ "IdxLT" OpHelp("key=r[P3@P4]"), | |
| 26919 | - /* 118 */ "IdxGE" OpHelp("key=r[P3@P4]"), | |
| 26920 | - /* 119 */ "Destroy" OpHelp(""), | |
| 26921 | - /* 120 */ "Clear" OpHelp(""), | |
| 26922 | - /* 121 */ "ResetSorter" OpHelp(""), | |
| 26923 | - /* 122 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), | |
| 26924 | - /* 123 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), | |
| 26925 | - /* 124 */ "ParseSchema" OpHelp(""), | |
| 26926 | - /* 125 */ "LoadAnalysis" OpHelp(""), | |
| 26927 | - /* 126 */ "DropTable" OpHelp(""), | |
| 26928 | - /* 127 */ "DropIndex" OpHelp(""), | |
| 26929 | - /* 128 */ "DropTrigger" OpHelp(""), | |
| 26930 | - /* 129 */ "IntegrityCk" OpHelp(""), | |
| 26931 | - /* 130 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), | |
| 26932 | - /* 131 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), | |
| 26933 | - /* 132 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), | |
| 27000 | + /* 98 */ "ResetCount" OpHelp(""), | |
| 27001 | + /* 99 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), | |
| 27002 | + /* 100 */ "SorterData" OpHelp("r[P2]=data"), | |
| 27003 | + /* 101 */ "RowKey" OpHelp("r[P2]=key"), | |
| 27004 | + /* 102 */ "RowData" OpHelp("r[P2]=data"), | |
| 27005 | + /* 103 */ "Rowid" OpHelp("r[P2]=rowid"), | |
| 27006 | + /* 104 */ "NullRow" OpHelp(""), | |
| 27007 | + /* 105 */ "Last" OpHelp(""), | |
| 27008 | + /* 106 */ "SorterSort" OpHelp(""), | |
| 27009 | + /* 107 */ "Sort" OpHelp(""), | |
| 27010 | + /* 108 */ "Rewind" OpHelp(""), | |
| 27011 | + /* 109 */ "SorterInsert" OpHelp(""), | |
| 27012 | + /* 110 */ "IdxInsert" OpHelp("key=r[P2]"), | |
| 27013 | + /* 111 */ "IdxDelete" OpHelp("key=r[P2@P3]"), | |
| 27014 | + /* 112 */ "Seek" OpHelp("Move P3 to P1.rowid"), | |
| 27015 | + /* 113 */ "IdxRowid" OpHelp("r[P2]=rowid"), | |
| 27016 | + /* 114 */ "IdxLE" OpHelp("key=r[P3@P4]"), | |
| 27017 | + /* 115 */ "IdxGT" OpHelp("key=r[P3@P4]"), | |
| 27018 | + /* 116 */ "IdxLT" OpHelp("key=r[P3@P4]"), | |
| 27019 | + /* 117 */ "IdxGE" OpHelp("key=r[P3@P4]"), | |
| 27020 | + /* 118 */ "Destroy" OpHelp(""), | |
| 27021 | + /* 119 */ "Clear" OpHelp(""), | |
| 27022 | + /* 120 */ "ResetSorter" OpHelp(""), | |
| 27023 | + /* 121 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), | |
| 27024 | + /* 122 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), | |
| 27025 | + /* 123 */ "ParseSchema" OpHelp(""), | |
| 27026 | + /* 124 */ "LoadAnalysis" OpHelp(""), | |
| 27027 | + /* 125 */ "DropTable" OpHelp(""), | |
| 27028 | + /* 126 */ "DropIndex" OpHelp(""), | |
| 27029 | + /* 127 */ "DropTrigger" OpHelp(""), | |
| 27030 | + /* 128 */ "IntegrityCk" OpHelp(""), | |
| 27031 | + /* 129 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), | |
| 27032 | + /* 130 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), | |
| 27033 | + /* 131 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), | |
| 27034 | + /* 132 */ "Program" OpHelp(""), | |
| 26934 | 27035 | /* 133 */ "Real" OpHelp("r[P2]=P4"), |
| 26935 | - /* 134 */ "Program" OpHelp(""), | |
| 26936 | - /* 135 */ "Param" OpHelp(""), | |
| 26937 | - /* 136 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), | |
| 26938 | - /* 137 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), | |
| 26939 | - /* 138 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), | |
| 26940 | - /* 139 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), | |
| 26941 | - /* 140 */ "SetIfNotPos" OpHelp("if r[P1]<=0 then r[P2]=P3"), | |
| 26942 | - /* 141 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), | |
| 26943 | - /* 142 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), | |
| 26944 | - /* 143 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), | |
| 26945 | - /* 144 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 26946 | - /* 145 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 26947 | - /* 146 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), | |
| 26948 | - /* 147 */ "IncrVacuum" OpHelp(""), | |
| 26949 | - /* 148 */ "Expire" OpHelp(""), | |
| 26950 | - /* 149 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), | |
| 26951 | - /* 150 */ "VBegin" OpHelp(""), | |
| 26952 | - /* 151 */ "VCreate" OpHelp(""), | |
| 26953 | - /* 152 */ "VDestroy" OpHelp(""), | |
| 26954 | - /* 153 */ "VOpen" OpHelp(""), | |
| 26955 | - /* 154 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), | |
| 26956 | - /* 155 */ "VNext" OpHelp(""), | |
| 26957 | - /* 156 */ "VRename" OpHelp(""), | |
| 26958 | - /* 157 */ "Pagecount" OpHelp(""), | |
| 26959 | - /* 158 */ "MaxPgcnt" OpHelp(""), | |
| 26960 | - /* 159 */ "Init" OpHelp("Start at P2"), | |
| 26961 | - /* 160 */ "CursorHint" OpHelp(""), | |
| 26962 | - /* 161 */ "Noop" OpHelp(""), | |
| 26963 | - /* 162 */ "Explain" OpHelp(""), | |
| 27036 | + /* 134 */ "Param" OpHelp(""), | |
| 27037 | + /* 135 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), | |
| 27038 | + /* 136 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), | |
| 27039 | + /* 137 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), | |
| 27040 | + /* 138 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), | |
| 27041 | + /* 139 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), | |
| 27042 | + /* 140 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), | |
| 27043 | + /* 141 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), | |
| 27044 | + /* 142 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), | |
| 27045 | + /* 143 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 27046 | + /* 144 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), | |
| 27047 | + /* 145 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), | |
| 27048 | + /* 146 */ "IncrVacuum" OpHelp(""), | |
| 27049 | + /* 147 */ "Expire" OpHelp(""), | |
| 27050 | + /* 148 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), | |
| 27051 | + /* 149 */ "VBegin" OpHelp(""), | |
| 27052 | + /* 150 */ "VCreate" OpHelp(""), | |
| 27053 | + /* 151 */ "VDestroy" OpHelp(""), | |
| 27054 | + /* 152 */ "VOpen" OpHelp(""), | |
| 27055 | + /* 153 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), | |
| 27056 | + /* 154 */ "VNext" OpHelp(""), | |
| 27057 | + /* 155 */ "VRename" OpHelp(""), | |
| 27058 | + /* 156 */ "Pagecount" OpHelp(""), | |
| 27059 | + /* 157 */ "MaxPgcnt" OpHelp(""), | |
| 27060 | + /* 158 */ "Init" OpHelp("Start at P2"), | |
| 27061 | + /* 159 */ "CursorHint" OpHelp(""), | |
| 27062 | + /* 160 */ "Noop" OpHelp(""), | |
| 27063 | + /* 161 */ "Explain" OpHelp(""), | |
| 26964 | 27064 | }; |
| 26965 | 27065 | return azName[i]; |
| 26966 | 27066 | } |
| 26967 | 27067 | #endif |
| 26968 | 27068 | |
| @@ -27117,10 +27217,15 @@ | ||
| 27117 | 27217 | /* |
| 27118 | 27218 | ** Maximum supported path-length. |
| 27119 | 27219 | */ |
| 27120 | 27220 | #define MAX_PATHNAME 512 |
| 27121 | 27221 | |
| 27222 | +/* | |
| 27223 | +** Maximum supported symbolic links | |
| 27224 | +*/ | |
| 27225 | +#define SQLITE_MAX_SYMLINKS 100 | |
| 27226 | + | |
| 27122 | 27227 | /* Always cast the getpid() return type for compatibility with |
| 27123 | 27228 | ** kernel modules in VxWorks. */ |
| 27124 | 27229 | #define osGetpid(X) (pid_t)getpid() |
| 27125 | 27230 | |
| 27126 | 27231 | /* |
| @@ -27641,10 +27746,16 @@ | ||
| 27641 | 27746 | #else |
| 27642 | 27747 | { "readlink", (sqlite3_syscall_ptr)0, 0 }, |
| 27643 | 27748 | #endif |
| 27644 | 27749 | #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) |
| 27645 | 27750 | |
| 27751 | +#if defined(HAVE_LSTAT) | |
| 27752 | + { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, | |
| 27753 | +#else | |
| 27754 | + { "lstat", (sqlite3_syscall_ptr)0, 0 }, | |
| 27755 | +#endif | |
| 27756 | +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) | |
| 27646 | 27757 | |
| 27647 | 27758 | }; /* End of the overrideable system calls */ |
| 27648 | 27759 | |
| 27649 | 27760 | |
| 27650 | 27761 | /* |
| @@ -33042,16 +33153,11 @@ | ||
| 33042 | 33153 | #ifndef SQLITE_DISABLE_DIRSYNC |
| 33043 | 33154 | if( (dirSync & 1)!=0 ){ |
| 33044 | 33155 | int fd; |
| 33045 | 33156 | rc = osOpenDirectory(zPath, &fd); |
| 33046 | 33157 | if( rc==SQLITE_OK ){ |
| 33047 | -#if OS_VXWORKS | |
| 33048 | - if( fsync(fd)==-1 ) | |
| 33049 | -#else | |
| 33050 | - if( fsync(fd) ) | |
| 33051 | -#endif | |
| 33052 | - { | |
| 33158 | + if( full_fsync(fd,0,0) ){ | |
| 33053 | 33159 | rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); |
| 33054 | 33160 | } |
| 33055 | 33161 | robust_close(0, fd, __LINE__); |
| 33056 | 33162 | }else{ |
| 33057 | 33163 | assert( rc==SQLITE_CANTOPEN ); |
| @@ -33093,10 +33199,36 @@ | ||
| 33093 | 33199 | *pResOut = osAccess(zPath, W_OK|R_OK)==0; |
| 33094 | 33200 | } |
| 33095 | 33201 | return SQLITE_OK; |
| 33096 | 33202 | } |
| 33097 | 33203 | |
| 33204 | +/* | |
| 33205 | +** | |
| 33206 | +*/ | |
| 33207 | +static int mkFullPathname( | |
| 33208 | + const char *zPath, /* Input path */ | |
| 33209 | + char *zOut, /* Output buffer */ | |
| 33210 | + int nOut /* Allocated size of buffer zOut */ | |
| 33211 | +){ | |
| 33212 | + int nPath = sqlite3Strlen30(zPath); | |
| 33213 | + int iOff = 0; | |
| 33214 | + if( zPath[0]!='/' ){ | |
| 33215 | + if( osGetcwd(zOut, nOut-2)==0 ){ | |
| 33216 | + return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); | |
| 33217 | + } | |
| 33218 | + iOff = sqlite3Strlen30(zOut); | |
| 33219 | + zOut[iOff++] = '/'; | |
| 33220 | + } | |
| 33221 | + if( (iOff+nPath+1)>nOut ){ | |
| 33222 | + /* SQLite assumes that xFullPathname() nul-terminates the output buffer | |
| 33223 | + ** even if it returns an error. */ | |
| 33224 | + zOut[iOff] = '\0'; | |
| 33225 | + return SQLITE_CANTOPEN_BKPT; | |
| 33226 | + } | |
| 33227 | + sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); | |
| 33228 | + return SQLITE_OK; | |
| 33229 | +} | |
| 33098 | 33230 | |
| 33099 | 33231 | /* |
| 33100 | 33232 | ** Turn a relative pathname into a full pathname. The relative path |
| 33101 | 33233 | ** is stored as a nul-terminated string in the buffer pointed to by |
| 33102 | 33234 | ** zPath. |
| @@ -33109,73 +33241,85 @@ | ||
| 33109 | 33241 | sqlite3_vfs *pVfs, /* Pointer to vfs object */ |
| 33110 | 33242 | const char *zPath, /* Possibly relative input path */ |
| 33111 | 33243 | int nOut, /* Size of output buffer in bytes */ |
| 33112 | 33244 | char *zOut /* Output buffer */ |
| 33113 | 33245 | ){ |
| 33246 | +#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT) | |
| 33247 | + return mkFullPathname(zPath, zOut, nOut); | |
| 33248 | +#else | |
| 33249 | + int rc = SQLITE_OK; | |
| 33114 | 33250 | int nByte; |
| 33251 | + int nLink = 1; /* Number of symbolic links followed so far */ | |
| 33252 | + const char *zIn = zPath; /* Input path for each iteration of loop */ | |
| 33253 | + char *zDel = 0; | |
| 33254 | + | |
| 33255 | + assert( pVfs->mxPathname==MAX_PATHNAME ); | |
| 33256 | + UNUSED_PARAMETER(pVfs); | |
| 33115 | 33257 | |
| 33116 | 33258 | /* It's odd to simulate an io-error here, but really this is just |
| 33117 | 33259 | ** using the io-error infrastructure to test that SQLite handles this |
| 33118 | 33260 | ** function failing. This function could fail if, for example, the |
| 33119 | 33261 | ** current working directory has been unlinked. |
| 33120 | 33262 | */ |
| 33121 | 33263 | SimulateIOError( return SQLITE_ERROR ); |
| 33122 | 33264 | |
| 33123 | - assert( pVfs->mxPathname==MAX_PATHNAME ); | |
| 33124 | - UNUSED_PARAMETER(pVfs); | |
| 33125 | - | |
| 33126 | -#if defined(HAVE_READLINK) | |
| 33127 | - /* Attempt to resolve the path as if it were a symbolic link. If it is | |
| 33128 | - ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if | |
| 33129 | - ** the identified file is not a symbolic link or does not exist, then | |
| 33130 | - ** zPath is copied directly into zOut. Either way, nByte is left set to | |
| 33131 | - ** the size of the string copied into zOut[] in bytes. */ | |
| 33132 | - nByte = osReadlink(zPath, zOut, nOut-1); | |
| 33133 | - if( nByte<0 ){ | |
| 33134 | - if( errno!=EINVAL && errno!=ENOENT ){ | |
| 33135 | - return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); | |
| 33136 | - } | |
| 33137 | - sqlite3_snprintf(nOut, zOut, "%s", zPath); | |
| 33138 | - nByte = sqlite3Strlen30(zOut); | |
| 33139 | - }else{ | |
| 33140 | - zOut[nByte] = '\0'; | |
| 33141 | - } | |
| 33142 | -#endif | |
| 33143 | - | |
| 33144 | - /* If buffer zOut[] now contains an absolute path there is nothing more | |
| 33145 | - ** to do. If it contains a relative path, do the following: | |
| 33146 | - ** | |
| 33147 | - ** * move the relative path string so that it is at the end of th | |
| 33148 | - ** zOut[] buffer. | |
| 33149 | - ** * Call getcwd() to read the path of the current working directory | |
| 33150 | - ** into the start of the zOut[] buffer. | |
| 33151 | - ** * Append a '/' character to the cwd string and move the | |
| 33152 | - ** relative path back within the buffer so that it immediately | |
| 33153 | - ** follows the '/'. | |
| 33154 | - ** | |
| 33155 | - ** This code is written so that if the combination of the CWD and relative | |
| 33156 | - ** path are larger than the allocated size of zOut[] the CWD is silently | |
| 33157 | - ** truncated to make it fit. This is Ok, as SQLite refuses to open any | |
| 33158 | - ** file for which this function returns a full path larger than (nOut-8) | |
| 33159 | - ** bytes in size. */ | |
| 33160 | - testcase( nByte==nOut-5 ); | |
| 33161 | - testcase( nByte==nOut-4 ); | |
| 33162 | - if( zOut[0]!='/' && nByte<nOut-4 ){ | |
| 33163 | - int nCwd; | |
| 33164 | - int nRem = nOut-nByte-1; | |
| 33165 | - memmove(&zOut[nRem], zOut, nByte+1); | |
| 33166 | - zOut[nRem-1] = '\0'; | |
| 33167 | - if( osGetcwd(zOut, nRem-1)==0 ){ | |
| 33168 | - return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); | |
| 33169 | - } | |
| 33170 | - nCwd = sqlite3Strlen30(zOut); | |
| 33171 | - assert( nCwd<=nRem-1 ); | |
| 33172 | - zOut[nCwd] = '/'; | |
| 33173 | - memmove(&zOut[nCwd+1], &zOut[nRem], nByte+1); | |
| 33174 | - } | |
| 33175 | - | |
| 33176 | - return SQLITE_OK; | |
| 33265 | + do { | |
| 33266 | + | |
| 33267 | + /* Call stat() on path zIn. Set bLink to true if the path is a symbolic | |
| 33268 | + ** link, or false otherwise. */ | |
| 33269 | + int bLink = 0; | |
| 33270 | + struct stat buf; | |
| 33271 | + if( osLstat(zIn, &buf)!=0 ){ | |
| 33272 | + if( errno!=ENOENT ){ | |
| 33273 | + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); | |
| 33274 | + } | |
| 33275 | + }else{ | |
| 33276 | + bLink = S_ISLNK(buf.st_mode); | |
| 33277 | + } | |
| 33278 | + | |
| 33279 | + if( bLink ){ | |
| 33280 | + if( zDel==0 ){ | |
| 33281 | + zDel = sqlite3_malloc(nOut); | |
| 33282 | + if( zDel==0 ) rc = SQLITE_NOMEM; | |
| 33283 | + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ | |
| 33284 | + rc = SQLITE_CANTOPEN_BKPT; | |
| 33285 | + } | |
| 33286 | + | |
| 33287 | + if( rc==SQLITE_OK ){ | |
| 33288 | + nByte = osReadlink(zIn, zDel, nOut-1); | |
| 33289 | + if( nByte<0 ){ | |
| 33290 | + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); | |
| 33291 | + }else{ | |
| 33292 | + if( zDel[0]!='/' ){ | |
| 33293 | + int n; | |
| 33294 | + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); | |
| 33295 | + if( nByte+n+1>nOut ){ | |
| 33296 | + rc = SQLITE_CANTOPEN_BKPT; | |
| 33297 | + }else{ | |
| 33298 | + memmove(&zDel[n], zDel, nByte+1); | |
| 33299 | + memcpy(zDel, zIn, n); | |
| 33300 | + nByte += n; | |
| 33301 | + } | |
| 33302 | + } | |
| 33303 | + zDel[nByte] = '\0'; | |
| 33304 | + } | |
| 33305 | + } | |
| 33306 | + | |
| 33307 | + zIn = zDel; | |
| 33308 | + } | |
| 33309 | + | |
| 33310 | + assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' ); | |
| 33311 | + if( rc==SQLITE_OK && zIn!=zOut ){ | |
| 33312 | + rc = mkFullPathname(zIn, zOut, nOut); | |
| 33313 | + } | |
| 33314 | + if( bLink==0 ) break; | |
| 33315 | + zIn = zOut; | |
| 33316 | + }while( rc==SQLITE_OK ); | |
| 33317 | + | |
| 33318 | + sqlite3_free(zDel); | |
| 33319 | + return rc; | |
| 33320 | +#endif /* HAVE_READLINK && HAVE_LSTAT */ | |
| 33177 | 33321 | } |
| 33178 | 33322 | |
| 33179 | 33323 | |
| 33180 | 33324 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 33181 | 33325 | /* |
| @@ -33353,11 +33497,11 @@ | ||
| 33353 | 33497 | #endif |
| 33354 | 33498 | UNUSED_PARAMETER(NotUsed); |
| 33355 | 33499 | return rc; |
| 33356 | 33500 | } |
| 33357 | 33501 | |
| 33358 | -#if 0 /* Not used */ | |
| 33502 | +#ifndef SQLITE_OMIT_DEPRECATED | |
| 33359 | 33503 | /* |
| 33360 | 33504 | ** Find the current time (in Universal Coordinated Time). Write the |
| 33361 | 33505 | ** current time and date as a Julian Day number into *prNow and |
| 33362 | 33506 | ** return 0. Return 1 if the time and date cannot be found. |
| 33363 | 33507 | */ |
| @@ -33371,11 +33515,11 @@ | ||
| 33371 | 33515 | } |
| 33372 | 33516 | #else |
| 33373 | 33517 | # define unixCurrentTime 0 |
| 33374 | 33518 | #endif |
| 33375 | 33519 | |
| 33376 | -#if 0 /* Not used */ | |
| 33520 | +#ifndef SQLITE_OMIT_DEPRECATED | |
| 33377 | 33521 | /* |
| 33378 | 33522 | ** We added the xGetLastError() method with the intention of providing |
| 33379 | 33523 | ** better low-level error messages when operating-system problems come up |
| 33380 | 33524 | ** during SQLite operation. But so far, none of that has been implemented |
| 33381 | 33525 | ** in the core. So this routine is never called. For now, it is merely |
| @@ -34053,11 +34197,11 @@ | ||
| 34053 | 34197 | strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); |
| 34054 | 34198 | } |
| 34055 | 34199 | writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); |
| 34056 | 34200 | robust_ftruncate(conchFile->h, writeSize); |
| 34057 | 34201 | rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); |
| 34058 | - fsync(conchFile->h); | |
| 34202 | + full_fsync(conchFile->h,0,0); | |
| 34059 | 34203 | /* If we created a new conch file (not just updated the contents of a |
| 34060 | 34204 | ** valid conch file), try to match the permissions of the database |
| 34061 | 34205 | */ |
| 34062 | 34206 | if( rc==SQLITE_OK && createConch ){ |
| 34063 | 34207 | struct stat buf; |
| @@ -34670,11 +34814,11 @@ | ||
| 34670 | 34814 | }; |
| 34671 | 34815 | unsigned int i; /* Loop counter */ |
| 34672 | 34816 | |
| 34673 | 34817 | /* Double-check that the aSyscall[] array has been constructed |
| 34674 | 34818 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 34675 | - assert( ArraySize(aSyscall)==27 ); | |
| 34819 | + assert( ArraySize(aSyscall)==28 ); | |
| 34676 | 34820 | |
| 34677 | 34821 | /* Register all VFSes defined in the aVfs[] array */ |
| 34678 | 34822 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 34679 | 34823 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 34680 | 34824 | } |
| @@ -34970,10 +35114,14 @@ | ||
| 34970 | 35114 | |
| 34971 | 35115 | #ifndef NTDDI_WINBLUE |
| 34972 | 35116 | # define NTDDI_WINBLUE 0x06030000 |
| 34973 | 35117 | #endif |
| 34974 | 35118 | |
| 35119 | +#ifndef NTDDI_WINTHRESHOLD | |
| 35120 | +# define NTDDI_WINTHRESHOLD 0x06040000 | |
| 35121 | +#endif | |
| 35122 | + | |
| 34975 | 35123 | /* |
| 34976 | 35124 | ** Check to see if the GetVersionEx[AW] functions are deprecated on the |
| 34977 | 35125 | ** target system. GetVersionEx was first deprecated in Win8.1. |
| 34978 | 35126 | */ |
| 34979 | 35127 | #ifndef SQLITE_WIN32_GETVERSIONEX |
| @@ -34982,10 +35130,23 @@ | ||
| 34982 | 35130 | # else |
| 34983 | 35131 | # define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ |
| 34984 | 35132 | # endif |
| 34985 | 35133 | #endif |
| 34986 | 35134 | |
| 35135 | +/* | |
| 35136 | +** Check to see if the CreateFileMappingA function is supported on the | |
| 35137 | +** target system. It is unavailable when using "mincore.lib" on Win10. | |
| 35138 | +** When compiling for Windows 10, always assume "mincore.lib" is in use. | |
| 35139 | +*/ | |
| 35140 | +#ifndef SQLITE_WIN32_CREATEFILEMAPPINGA | |
| 35141 | +# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD | |
| 35142 | +# define SQLITE_WIN32_CREATEFILEMAPPINGA 0 | |
| 35143 | +# else | |
| 35144 | +# define SQLITE_WIN32_CREATEFILEMAPPINGA 1 | |
| 35145 | +# endif | |
| 35146 | +#endif | |
| 35147 | + | |
| 34987 | 35148 | /* |
| 34988 | 35149 | ** This constant should already be defined (in the "WinDef.h" SDK file). |
| 34989 | 35150 | */ |
| 34990 | 35151 | #ifndef MAX_PATH |
| 34991 | 35152 | # define MAX_PATH (260) |
| @@ -35388,12 +35549,13 @@ | ||
| 35388 | 35549 | #endif |
| 35389 | 35550 | |
| 35390 | 35551 | #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ |
| 35391 | 35552 | LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) |
| 35392 | 35553 | |
| 35393 | -#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ | |
| 35394 | - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) | |
| 35554 | +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ | |
| 35555 | + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ | |
| 35556 | + SQLITE_WIN32_CREATEFILEMAPPINGA | |
| 35395 | 35557 | { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, |
| 35396 | 35558 | #else |
| 35397 | 35559 | { "CreateFileMappingA", (SYSCALL)0, 0 }, |
| 35398 | 35560 | #endif |
| 35399 | 35561 | |
| @@ -35619,22 +35781,21 @@ | ||
| 35619 | 35781 | { "GetTickCount", (SYSCALL)0, 0 }, |
| 35620 | 35782 | #endif |
| 35621 | 35783 | |
| 35622 | 35784 | #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) |
| 35623 | 35785 | |
| 35624 | -#if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \ | |
| 35625 | - SQLITE_WIN32_GETVERSIONEX | |
| 35786 | +#if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX | |
| 35626 | 35787 | { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, |
| 35627 | 35788 | #else |
| 35628 | 35789 | { "GetVersionExA", (SYSCALL)0, 0 }, |
| 35629 | 35790 | #endif |
| 35630 | 35791 | |
| 35631 | 35792 | #define osGetVersionExA ((BOOL(WINAPI*)( \ |
| 35632 | 35793 | LPOSVERSIONINFOA))aSyscall[34].pCurrent) |
| 35633 | 35794 | |
| 35634 | 35795 | #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ |
| 35635 | - defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX | |
| 35796 | + SQLITE_WIN32_GETVERSIONEX | |
| 35636 | 35797 | { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, |
| 35637 | 35798 | #else |
| 35638 | 35799 | { "GetVersionExW", (SYSCALL)0, 0 }, |
| 35639 | 35800 | #endif |
| 35640 | 35801 | |
| @@ -36241,11 +36402,11 @@ | ||
| 36241 | 36402 | ** this routine is used to determine if the host is Win95/98/ME or |
| 36242 | 36403 | ** WinNT/2K/XP so that we will know whether or not we can safely call |
| 36243 | 36404 | ** the LockFileEx() API. |
| 36244 | 36405 | */ |
| 36245 | 36406 | |
| 36246 | -#if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX | |
| 36407 | +#if !SQLITE_WIN32_GETVERSIONEX | |
| 36247 | 36408 | # define osIsNT() (1) |
| 36248 | 36409 | #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) |
| 36249 | 36410 | # define osIsNT() (1) |
| 36250 | 36411 | #elif !defined(SQLITE_WIN32_HAS_WIDE) |
| 36251 | 36412 | # define osIsNT() (0) |
| @@ -36262,11 +36423,11 @@ | ||
| 36262 | 36423 | /* |
| 36263 | 36424 | ** NOTE: The WinRT sub-platform is always assumed to be based on the NT |
| 36264 | 36425 | ** kernel. |
| 36265 | 36426 | */ |
| 36266 | 36427 | return 1; |
| 36267 | -#elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX | |
| 36428 | +#elif SQLITE_WIN32_GETVERSIONEX | |
| 36268 | 36429 | if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ |
| 36269 | 36430 | #if defined(SQLITE_WIN32_HAS_ANSI) |
| 36270 | 36431 | OSVERSIONINFOA sInfo; |
| 36271 | 36432 | sInfo.dwOSVersionInfoSize = sizeof(sInfo); |
| 36272 | 36433 | osGetVersionExA(&sInfo); |
| @@ -38846,11 +39007,11 @@ | ||
| 38846 | 39007 | ); |
| 38847 | 39008 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 38848 | 39009 | hMap = osCreateFileMappingW(pShmNode->hFile.h, |
| 38849 | 39010 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 38850 | 39011 | ); |
| 38851 | -#elif defined(SQLITE_WIN32_HAS_ANSI) | |
| 39012 | +#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA | |
| 38852 | 39013 | hMap = osCreateFileMappingA(pShmNode->hFile.h, |
| 38853 | 39014 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 38854 | 39015 | ); |
| 38855 | 39016 | #endif |
| 38856 | 39017 | OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", |
| @@ -39002,11 +39163,11 @@ | ||
| 39002 | 39163 | pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); |
| 39003 | 39164 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 39004 | 39165 | pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, |
| 39005 | 39166 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39006 | 39167 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39007 | -#elif defined(SQLITE_WIN32_HAS_ANSI) | |
| 39168 | +#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA | |
| 39008 | 39169 | pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, |
| 39009 | 39170 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39010 | 39171 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39011 | 39172 | #endif |
| 39012 | 39173 | if( pFd->hMap==NULL ){ |
| @@ -43066,11 +43227,11 @@ | ||
| 43066 | 43227 | */ |
| 43067 | 43228 | static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ |
| 43068 | 43229 | assert( p!=0 ); |
| 43069 | 43230 | if( p->nFresh==0 ){ |
| 43070 | 43231 | struct RowSetChunk *pNew; |
| 43071 | - pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); | |
| 43232 | + pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew)); | |
| 43072 | 43233 | if( pNew==0 ){ |
| 43073 | 43234 | return 0; |
| 43074 | 43235 | } |
| 43075 | 43236 | pNew->pNextChunk = p->pChunk; |
| 43076 | 43237 | p->pChunk = pNew; |
| @@ -43973,10 +44134,24 @@ | ||
| 43973 | 44134 | ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. |
| 43974 | 44135 | ** This could conceivably cause corruption following a power failure on |
| 43975 | 44136 | ** such a system. This is currently an undocumented limit. |
| 43976 | 44137 | */ |
| 43977 | 44138 | #define MAX_SECTOR_SIZE 0x10000 |
| 44139 | + | |
| 44140 | +/* | |
| 44141 | +** If the option SQLITE_EXTRA_DURABLE option is set at compile-time, then | |
| 44142 | +** SQLite will do extra fsync() operations when synchronous==FULL to help | |
| 44143 | +** ensure that transactions are durable across a power failure. Most | |
| 44144 | +** applications are happy as long as transactions are consistent across | |
| 44145 | +** a power failure, and are perfectly willing to lose the last transaction | |
| 44146 | +** in exchange for the extra performance of avoiding directory syncs. | |
| 44147 | +** And so the default SQLITE_EXTRA_DURABLE setting is off. | |
| 44148 | +*/ | |
| 44149 | +#ifndef SQLITE_EXTRA_DURABLE | |
| 44150 | +# define SQLITE_EXTRA_DURABLE 0 | |
| 44151 | +#endif | |
| 44152 | + | |
| 43978 | 44153 | |
| 43979 | 44154 | /* |
| 43980 | 44155 | ** An instance of the following structure is allocated for each active |
| 43981 | 44156 | ** savepoint and statement transaction in the system. All such structures |
| 43982 | 44157 | ** are stored in the Pager.aSavepoint[] array, which is allocated and |
| @@ -44169,10 +44344,11 @@ | ||
| 44169 | 44344 | u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ |
| 44170 | 44345 | u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
| 44171 | 44346 | u8 useJournal; /* Use a rollback journal on this file */ |
| 44172 | 44347 | u8 noSync; /* Do not sync the journal if true */ |
| 44173 | 44348 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 44349 | + u8 extraSync; /* sync directory after journal delete */ | |
| 44174 | 44350 | u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ |
| 44175 | 44351 | u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ |
| 44176 | 44352 | u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ |
| 44177 | 44353 | u8 tempFile; /* zFilename is a temporary or immutable file */ |
| 44178 | 44354 | u8 noLock; /* Do not lock (except in WAL mode) */ |
| @@ -45529,11 +45705,11 @@ | ||
| 45529 | 45705 | || pPager->journalMode==PAGER_JOURNALMODE_MEMORY |
| 45530 | 45706 | || pPager->journalMode==PAGER_JOURNALMODE_WAL |
| 45531 | 45707 | ); |
| 45532 | 45708 | sqlite3OsClose(pPager->jfd); |
| 45533 | 45709 | if( bDelete ){ |
| 45534 | - rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); | |
| 45710 | + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync); | |
| 45535 | 45711 | } |
| 45536 | 45712 | } |
| 45537 | 45713 | } |
| 45538 | 45714 | |
| 45539 | 45715 | #ifdef SQLITE_CHECK_PAGES |
| @@ -47035,13 +47211,19 @@ | ||
| 47035 | 47211 | SQLITE_PRIVATE void sqlite3PagerSetFlags( |
| 47036 | 47212 | Pager *pPager, /* The pager to set safety level for */ |
| 47037 | 47213 | unsigned pgFlags /* Various flags */ |
| 47038 | 47214 | ){ |
| 47039 | 47215 | unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; |
| 47040 | - assert( level>=1 && level<=3 ); | |
| 47041 | - pPager->noSync = (level==1 || pPager->tempFile) ?1:0; | |
| 47042 | - pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; | |
| 47216 | + if( pPager->tempFile ){ | |
| 47217 | + pPager->noSync = 1; | |
| 47218 | + pPager->fullSync = 0; | |
| 47219 | + pPager->extraSync = 0; | |
| 47220 | + }else{ | |
| 47221 | + pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; | |
| 47222 | + pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; | |
| 47223 | + pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; | |
| 47224 | + } | |
| 47043 | 47225 | if( pPager->noSync ){ |
| 47044 | 47226 | pPager->syncFlags = 0; |
| 47045 | 47227 | pPager->ckptSyncFlags = 0; |
| 47046 | 47228 | }else if( pgFlags & PAGER_FULLFSYNC ){ |
| 47047 | 47229 | pPager->syncFlags = SQLITE_SYNC_FULL; |
| @@ -48342,15 +48524,21 @@ | ||
| 48342 | 48524 | pPager->readOnly = (u8)readOnly; |
| 48343 | 48525 | assert( useJournal || pPager->tempFile ); |
| 48344 | 48526 | pPager->noSync = pPager->tempFile; |
| 48345 | 48527 | if( pPager->noSync ){ |
| 48346 | 48528 | assert( pPager->fullSync==0 ); |
| 48529 | + assert( pPager->extraSync==0 ); | |
| 48347 | 48530 | assert( pPager->syncFlags==0 ); |
| 48348 | 48531 | assert( pPager->walSyncFlags==0 ); |
| 48349 | 48532 | assert( pPager->ckptSyncFlags==0 ); |
| 48350 | 48533 | }else{ |
| 48351 | 48534 | pPager->fullSync = 1; |
| 48535 | +#if SQLITE_EXTRA_DURABLE | |
| 48536 | + pPager->extraSync = 1; | |
| 48537 | +#else | |
| 48538 | + pPager->extraSync = 0; | |
| 48539 | +#endif | |
| 48352 | 48540 | pPager->syncFlags = SQLITE_SYNC_NORMAL; |
| 48353 | 48541 | pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; |
| 48354 | 48542 | pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; |
| 48355 | 48543 | } |
| 48356 | 48544 | /* pPager->pFirst = 0; */ |
| @@ -57680,11 +57868,10 @@ | ||
| 57680 | 57868 | MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) |
| 57681 | 57869 | if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ |
| 57682 | 57870 | pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); |
| 57683 | 57871 | if( pBt->mutex==0 ){ |
| 57684 | 57872 | rc = SQLITE_NOMEM; |
| 57685 | - db->mallocFailed = 0; | |
| 57686 | 57873 | goto btree_open_out; |
| 57687 | 57874 | } |
| 57688 | 57875 | } |
| 57689 | 57876 | sqlite3_mutex_enter(mutexShared); |
| 57690 | 57877 | pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList); |
| @@ -59391,17 +59578,17 @@ | ||
| 59391 | 59578 | ** iTable. If a read-only cursor is requested, it is assumed that |
| 59392 | 59579 | ** the caller already has at least a read-only transaction open |
| 59393 | 59580 | ** on the database already. If a write-cursor is requested, then |
| 59394 | 59581 | ** the caller is assumed to have an open write transaction. |
| 59395 | 59582 | ** |
| 59396 | -** If wrFlag==0, then the cursor can only be used for reading. | |
| 59397 | -** If wrFlag==1, then the cursor can be used for reading or for | |
| 59398 | -** writing if other conditions for writing are also met. These | |
| 59399 | -** are the conditions that must be met in order for writing to | |
| 59400 | -** be allowed: | |
| 59583 | +** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only | |
| 59584 | +** be used for reading. If the BTREE_WRCSR bit is set, then the cursor | |
| 59585 | +** can be used for reading or for writing if other conditions for writing | |
| 59586 | +** are also met. These are the conditions that must be met in order | |
| 59587 | +** for writing to be allowed: | |
| 59401 | 59588 | ** |
| 59402 | -** 1: The cursor must have been opened with wrFlag==1 | |
| 59589 | +** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR | |
| 59403 | 59590 | ** |
| 59404 | 59591 | ** 2: Other database connections that share the same pager cache |
| 59405 | 59592 | ** but which are not in the READ_UNCOMMITTED state may not have |
| 59406 | 59593 | ** cursors open with wrFlag==0 on the same table. Otherwise |
| 59407 | 59594 | ** the changes made by this write cursor would be visible to |
| @@ -59408,10 +59595,20 @@ | ||
| 59408 | 59595 | ** the read cursors in the other database connection. |
| 59409 | 59596 | ** |
| 59410 | 59597 | ** 3: The database must be writable (not on read-only media) |
| 59411 | 59598 | ** |
| 59412 | 59599 | ** 4: There must be an active transaction. |
| 59600 | +** | |
| 59601 | +** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR | |
| 59602 | +** is set. If FORDELETE is set, that is a hint to the implementation that | |
| 59603 | +** this cursor will only be used to seek to and delete entries of an index | |
| 59604 | +** as part of a larger DELETE statement. The FORDELETE hint is not used by | |
| 59605 | +** this implementation. But in a hypothetical alternative storage engine | |
| 59606 | +** in which index entries are automatically deleted when corresponding table | |
| 59607 | +** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE | |
| 59608 | +** operations on this cursor can be no-ops and all READ operations can | |
| 59609 | +** return a null row (2-bytes: 0x01 0x00). | |
| 59413 | 59610 | ** |
| 59414 | 59611 | ** No checking is done to make sure that page iTable really is the |
| 59415 | 59612 | ** root page of a b-tree. If it is not, then the cursor acquired |
| 59416 | 59613 | ** will not work correctly. |
| 59417 | 59614 | ** |
| @@ -61481,11 +61678,11 @@ | ||
| 61481 | 61678 | */ |
| 61482 | 61679 | #if SQLITE_DEBUG |
| 61483 | 61680 | { |
| 61484 | 61681 | CellInfo info; |
| 61485 | 61682 | pPage->xParseCell(pPage, pCell, &info); |
| 61486 | - assert( nHeader=(int)(info.pPayload - pCell) ); | |
| 61683 | + assert( nHeader==(int)(info.pPayload - pCell) ); | |
| 61487 | 61684 | assert( info.nKey==nKey ); |
| 61488 | 61685 | assert( *pnSize == info.nSize ); |
| 61489 | 61686 | assert( spaceLeft == info.nLocal ); |
| 61490 | 61687 | } |
| 61491 | 61688 | #endif |
| @@ -63140,12 +63337,12 @@ | ||
| 63140 | 63337 | int rc = SQLITE_OK; |
| 63141 | 63338 | const int nMin = pCur->pBt->usableSize * 2 / 3; |
| 63142 | 63339 | u8 aBalanceQuickSpace[13]; |
| 63143 | 63340 | u8 *pFree = 0; |
| 63144 | 63341 | |
| 63145 | - TESTONLY( int balance_quick_called = 0 ); | |
| 63146 | - TESTONLY( int balance_deeper_called = 0 ); | |
| 63342 | + VVA_ONLY( int balance_quick_called = 0 ); | |
| 63343 | + VVA_ONLY( int balance_deeper_called = 0 ); | |
| 63147 | 63344 | |
| 63148 | 63345 | do { |
| 63149 | 63346 | int iPage = pCur->iPage; |
| 63150 | 63347 | MemPage *pPage = pCur->apPage[iPage]; |
| 63151 | 63348 | |
| @@ -63154,11 +63351,12 @@ | ||
| 63154 | 63351 | /* The root page of the b-tree is overfull. In this case call the |
| 63155 | 63352 | ** balance_deeper() function to create a new child for the root-page |
| 63156 | 63353 | ** and copy the current contents of the root-page to it. The |
| 63157 | 63354 | ** next iteration of the do-loop will balance the child page. |
| 63158 | 63355 | */ |
| 63159 | - assert( (balance_deeper_called++)==0 ); | |
| 63356 | + assert( balance_deeper_called==0 ); | |
| 63357 | + VVA_ONLY( balance_deeper_called++ ); | |
| 63160 | 63358 | rc = balance_deeper(pPage, &pCur->apPage[1]); |
| 63161 | 63359 | if( rc==SQLITE_OK ){ |
| 63162 | 63360 | pCur->iPage = 1; |
| 63163 | 63361 | pCur->aiIdx[0] = 0; |
| 63164 | 63362 | pCur->aiIdx[1] = 0; |
| @@ -63193,11 +63391,12 @@ | ||
| 63193 | 63391 | ** The purpose of the following assert() is to check that only a |
| 63194 | 63392 | ** single call to balance_quick() is made for each call to this |
| 63195 | 63393 | ** function. If this were not verified, a subtle bug involving reuse |
| 63196 | 63394 | ** of the aBalanceQuickSpace[] might sneak in. |
| 63197 | 63395 | */ |
| 63198 | - assert( (balance_quick_called++)==0 ); | |
| 63396 | + assert( balance_quick_called==0 ); | |
| 63397 | + VVA_ONLY( balance_quick_called++ ); | |
| 63199 | 63398 | rc = balance_quick(pParent, pPage, aBalanceQuickSpace); |
| 63200 | 63399 | }else |
| 63201 | 63400 | #endif |
| 63202 | 63401 | { |
| 63203 | 63402 | /* In this case, call balance_nonroot() to redistribute cells |
| @@ -63424,35 +63623,45 @@ | ||
| 63424 | 63623 | } |
| 63425 | 63624 | |
| 63426 | 63625 | /* |
| 63427 | 63626 | ** Delete the entry that the cursor is pointing to. |
| 63428 | 63627 | ** |
| 63429 | -** If the second parameter is zero, then the cursor is left pointing at an | |
| 63430 | -** arbitrary location after the delete. If it is non-zero, then the cursor | |
| 63431 | -** is left in a state such that the next call to BtreeNext() or BtreePrev() | |
| 63432 | -** moves it to the same row as it would if the call to BtreeDelete() had | |
| 63433 | -** been omitted. | |
| 63628 | +** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then | |
| 63629 | +** the cursor is left pointing at an arbitrary location after the delete. | |
| 63630 | +** But if that bit is set, then the cursor is left in a state such that | |
| 63631 | +** the next call to BtreeNext() or BtreePrev() moves it to the same row | |
| 63632 | +** as it would have been on if the call to BtreeDelete() had been omitted. | |
| 63633 | +** | |
| 63634 | +** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes | |
| 63635 | +** associated with a single table entry and its indexes. Only one of those | |
| 63636 | +** deletes is considered the "primary" delete. The primary delete occurs | |
| 63637 | +** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete | |
| 63638 | +** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag. | |
| 63639 | +** The BTREE_AUXDELETE bit is a hint that is not used by this implementation, | |
| 63640 | +** but which might be used by alternative storage engines. | |
| 63434 | 63641 | */ |
| 63435 | -SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ | |
| 63642 | +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ | |
| 63436 | 63643 | Btree *p = pCur->pBtree; |
| 63437 | 63644 | BtShared *pBt = p->pBt; |
| 63438 | 63645 | int rc; /* Return code */ |
| 63439 | 63646 | MemPage *pPage; /* Page to delete cell from */ |
| 63440 | 63647 | unsigned char *pCell; /* Pointer to cell to delete */ |
| 63441 | 63648 | int iCellIdx; /* Index of cell to delete */ |
| 63442 | 63649 | int iCellDepth; /* Depth of node containing pCell */ |
| 63443 | 63650 | u16 szCell; /* Size of the cell being deleted */ |
| 63444 | 63651 | int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ |
| 63652 | + u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ | |
| 63445 | 63653 | |
| 63446 | 63654 | assert( cursorOwnsBtShared(pCur) ); |
| 63447 | 63655 | assert( pBt->inTransaction==TRANS_WRITE ); |
| 63448 | 63656 | assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); |
| 63449 | 63657 | assert( pCur->curFlags & BTCF_WriteFlag ); |
| 63450 | 63658 | assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); |
| 63451 | 63659 | assert( !hasReadConflicts(p, pCur->pgnoRoot) ); |
| 63452 | 63660 | assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); |
| 63453 | 63661 | assert( pCur->eState==CURSOR_VALID ); |
| 63662 | + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); | |
| 63454 | 63663 | |
| 63455 | 63664 | iCellDepth = pCur->iPage; |
| 63456 | 63665 | iCellIdx = pCur->aiIdx[iCellDepth]; |
| 63457 | 63666 | pPage = pCur->apPage[iCellDepth]; |
| 63458 | 63667 | pCell = findCell(pPage, iCellIdx); |
| @@ -63561,11 +63770,11 @@ | ||
| 63561 | 63770 | } |
| 63562 | 63771 | |
| 63563 | 63772 | if( rc==SQLITE_OK ){ |
| 63564 | 63773 | if( bSkipnext ){ |
| 63565 | 63774 | assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); |
| 63566 | - assert( pPage==pCur->apPage[pCur->iPage] ); | |
| 63775 | + assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB ); | |
| 63567 | 63776 | assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); |
| 63568 | 63777 | pCur->eState = CURSOR_SKIPNEXT; |
| 63569 | 63778 | if( iCellIdx>=pPage->nCell ){ |
| 63570 | 63779 | pCur->skipNext = -1; |
| 63571 | 63780 | pCur->aiIdx[iCellDepth] = pPage->nCell-1; |
| @@ -64147,13 +64356,13 @@ | ||
| 64147 | 64356 | va_start(ap, zFormat); |
| 64148 | 64357 | if( pCheck->errMsg.nChar ){ |
| 64149 | 64358 | sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); |
| 64150 | 64359 | } |
| 64151 | 64360 | if( pCheck->zPfx ){ |
| 64152 | - sqlite3XPrintf(&pCheck->errMsg, 0, pCheck->zPfx, pCheck->v1, pCheck->v2); | |
| 64361 | + sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); | |
| 64153 | 64362 | } |
| 64154 | - sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); | |
| 64363 | + sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); | |
| 64155 | 64364 | va_end(ap); |
| 64156 | 64365 | if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ |
| 64157 | 64366 | pCheck->mallocFailed = 1; |
| 64158 | 64367 | } |
| 64159 | 64368 | } |
| @@ -64650,11 +64859,12 @@ | ||
| 64650 | 64859 | char zErr[100]; |
| 64651 | 64860 | VVA_ONLY( int nRef ); |
| 64652 | 64861 | |
| 64653 | 64862 | sqlite3BtreeEnter(p); |
| 64654 | 64863 | assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); |
| 64655 | - assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 ); | |
| 64864 | + VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) ); | |
| 64865 | + assert( nRef>=0 ); | |
| 64656 | 64866 | sCheck.pBt = pBt; |
| 64657 | 64867 | sCheck.pPager = pBt->pPager; |
| 64658 | 64868 | sCheck.nPage = btreePagecount(sCheck.pBt); |
| 64659 | 64869 | sCheck.mxErr = mxErr; |
| 64660 | 64870 | sCheck.nErr = 0; |
| @@ -64663,10 +64873,11 @@ | ||
| 64663 | 64873 | sCheck.v1 = 0; |
| 64664 | 64874 | sCheck.v2 = 0; |
| 64665 | 64875 | sCheck.aPgRef = 0; |
| 64666 | 64876 | sCheck.heap = 0; |
| 64667 | 64877 | sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); |
| 64878 | + sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; | |
| 64668 | 64879 | if( sCheck.nPage==0 ){ |
| 64669 | 64880 | goto integrity_ck_cleanup; |
| 64670 | 64881 | } |
| 64671 | 64882 | |
| 64672 | 64883 | sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); |
| @@ -65939,10 +66150,11 @@ | ||
| 65939 | 66150 | ** in pMem->z is discarded. |
| 65940 | 66151 | */ |
| 65941 | 66152 | SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ |
| 65942 | 66153 | assert( sqlite3VdbeCheckMemInvariants(pMem) ); |
| 65943 | 66154 | assert( (pMem->flags&MEM_RowSet)==0 ); |
| 66155 | + testcase( pMem->db==0 ); | |
| 65944 | 66156 | |
| 65945 | 66157 | /* If the bPreserve flag is set to true, then the memory cell must already |
| 65946 | 66158 | ** contain a valid string or blob value. */ |
| 65947 | 66159 | assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); |
| 65948 | 66160 | testcase( bPreserve && pMem->z==0 ); |
| @@ -66542,11 +66754,11 @@ | ||
| 66542 | 66754 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ |
| 66543 | 66755 | sqlite3 *db = pMem->db; |
| 66544 | 66756 | assert( db!=0 ); |
| 66545 | 66757 | assert( (pMem->flags & MEM_RowSet)==0 ); |
| 66546 | 66758 | sqlite3VdbeMemRelease(pMem); |
| 66547 | - pMem->zMalloc = sqlite3DbMallocRaw(db, 64); | |
| 66759 | + pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); | |
| 66548 | 66760 | if( db->mallocFailed ){ |
| 66549 | 66761 | pMem->flags = MEM_Null; |
| 66550 | 66762 | pMem->szMalloc = 0; |
| 66551 | 66763 | }else{ |
| 66552 | 66764 | assert( pMem->zMalloc ); |
| @@ -67204,11 +67416,11 @@ | ||
| 67204 | 67416 | |
| 67205 | 67417 | *ppVal = pVal; |
| 67206 | 67418 | return rc; |
| 67207 | 67419 | |
| 67208 | 67420 | no_mem: |
| 67209 | - db->mallocFailed = 1; | |
| 67421 | + sqlite3OomFault(db); | |
| 67210 | 67422 | sqlite3DbFree(db, zVal); |
| 67211 | 67423 | assert( *ppVal==0 ); |
| 67212 | 67424 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 67213 | 67425 | if( pCtx==0 ) sqlite3ValueFree(pVal); |
| 67214 | 67426 | #else |
| @@ -67263,11 +67475,11 @@ | ||
| 67263 | 67475 | iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); |
| 67264 | 67476 | nSerial = sqlite3VarintLen(iSerial); |
| 67265 | 67477 | db = sqlite3_context_db_handle(context); |
| 67266 | 67478 | |
| 67267 | 67479 | nRet = 1 + nSerial + nVal; |
| 67268 | - aRet = sqlite3DbMallocRaw(db, nRet); | |
| 67480 | + aRet = sqlite3DbMallocRawNN(db, nRet); | |
| 67269 | 67481 | if( aRet==0 ){ |
| 67270 | 67482 | sqlite3_result_error_nomem(context); |
| 67271 | 67483 | }else{ |
| 67272 | 67484 | aRet[0] = nSerial+1; |
| 67273 | 67485 | putVarint32(&aRet[1], iSerial); |
| @@ -67715,11 +67927,11 @@ | ||
| 67715 | 67927 | int i; |
| 67716 | 67928 | VdbeOp *pOp; |
| 67717 | 67929 | |
| 67718 | 67930 | i = p->nOp; |
| 67719 | 67931 | assert( p->magic==VDBE_MAGIC_INIT ); |
| 67720 | - assert( op>0 && op<0xff ); | |
| 67932 | + assert( op>=0 && op<0xff ); | |
| 67721 | 67933 | if( p->pParse->nOpAlloc<=i ){ |
| 67722 | 67934 | return growOp3(p, op, p1, p2, p3); |
| 67723 | 67935 | } |
| 67724 | 67936 | p->nOp++; |
| 67725 | 67937 | pOp = &p->aOp[i]; |
| @@ -67833,11 +68045,11 @@ | ||
| 67833 | 68045 | int p2, /* The P2 operand */ |
| 67834 | 68046 | int p3, /* The P3 operand */ |
| 67835 | 68047 | const u8 *zP4, /* The P4 operand */ |
| 67836 | 68048 | int p4type /* P4 operand type */ |
| 67837 | 68049 | ){ |
| 67838 | - char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8); | |
| 68050 | + char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8); | |
| 67839 | 68051 | if( p4copy ) memcpy(p4copy, zP4, 8); |
| 67840 | 68052 | return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); |
| 67841 | 68053 | } |
| 67842 | 68054 | |
| 67843 | 68055 | /* |
| @@ -67867,10 +68079,25 @@ | ||
| 67867 | 68079 | ){ |
| 67868 | 68080 | int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); |
| 67869 | 68081 | sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); |
| 67870 | 68082 | return addr; |
| 67871 | 68083 | } |
| 68084 | + | |
| 68085 | +/* Insert the end of a co-routine | |
| 68086 | +*/ | |
| 68087 | +SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ | |
| 68088 | + sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); | |
| 68089 | + | |
| 68090 | + /* Clear the temporary register cache, thereby ensuring that each | |
| 68091 | + ** co-routine has its own independent set of registers, because co-routines | |
| 68092 | + ** might expect their registers to be preserved across an OP_Yield, and | |
| 68093 | + ** that could cause problems if two or more co-routines are using the same | |
| 68094 | + ** temporary register. | |
| 68095 | + */ | |
| 68096 | + v->pParse->nTempReg = 0; | |
| 68097 | + v->pParse->nRangeReg = 0; | |
| 68098 | +} | |
| 67872 | 68099 | |
| 67873 | 68100 | /* |
| 67874 | 68101 | ** Create a new symbolic label for an instruction that has yet to be |
| 67875 | 68102 | ** coded. The symbolic label is really just a negative number. The |
| 67876 | 68103 | ** label can be used as the P2 value of an operation. Later, when |
| @@ -68078,11 +68305,11 @@ | ||
| 68078 | 68305 | p->readOnly = 1; |
| 68079 | 68306 | p->bIsReader = 0; |
| 68080 | 68307 | for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ |
| 68081 | 68308 | u8 opcode = pOp->opcode; |
| 68082 | 68309 | |
| 68083 | - /* NOTE: Be sure to update mkopcodeh.awk when adding or removing | |
| 68310 | + /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing | |
| 68084 | 68311 | ** cases from this switch! */ |
| 68085 | 68312 | switch( opcode ){ |
| 68086 | 68313 | case OP_Transaction: { |
| 68087 | 68314 | if( pOp->p2!=0 ) p->readOnly = 0; |
| 68088 | 68315 | /* fall thru */ |
| @@ -68190,10 +68417,13 @@ | ||
| 68190 | 68417 | } |
| 68191 | 68418 | |
| 68192 | 68419 | /* |
| 68193 | 68420 | ** Add a whole list of operations to the operation stack. Return a |
| 68194 | 68421 | ** pointer to the first operation inserted. |
| 68422 | +** | |
| 68423 | +** Non-zero P2 arguments to jump instructions are automatically adjusted | |
| 68424 | +** so that the jump target is relative to the first operation inserted. | |
| 68195 | 68425 | */ |
| 68196 | 68426 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList( |
| 68197 | 68427 | Vdbe *p, /* Add opcodes to the prepared statement */ |
| 68198 | 68428 | int nOp, /* Number of opcodes to add */ |
| 68199 | 68429 | VdbeOpList const *aOp, /* The opcodes to be added */ |
| @@ -68210,10 +68440,13 @@ | ||
| 68210 | 68440 | for(i=0; i<nOp; i++, aOp++, pOut++){ |
| 68211 | 68441 | pOut->opcode = aOp->opcode; |
| 68212 | 68442 | pOut->p1 = aOp->p1; |
| 68213 | 68443 | pOut->p2 = aOp->p2; |
| 68214 | 68444 | assert( aOp->p2>=0 ); |
| 68445 | + if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){ | |
| 68446 | + pOut->p2 += p->nOp; | |
| 68447 | + } | |
| 68215 | 68448 | pOut->p3 = aOp->p3; |
| 68216 | 68449 | pOut->p4type = P4_NOTUSED; |
| 68217 | 68450 | pOut->p4.p = 0; |
| 68218 | 68451 | pOut->p5 = 0; |
| 68219 | 68452 | #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS |
| @@ -68661,32 +68894,31 @@ | ||
| 68661 | 68894 | #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) |
| 68662 | 68895 | /* |
| 68663 | 68896 | ** Translate the P4.pExpr value for an OP_CursorHint opcode into text |
| 68664 | 68897 | ** that can be displayed in the P4 column of EXPLAIN output. |
| 68665 | 68898 | */ |
| 68666 | -static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ | |
| 68899 | +static void displayP4Expr(StrAccum *p, Expr *pExpr){ | |
| 68667 | 68900 | const char *zOp = 0; |
| 68668 | - int n; | |
| 68669 | 68901 | switch( pExpr->op ){ |
| 68670 | 68902 | case TK_STRING: |
| 68671 | - sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken); | |
| 68903 | + sqlite3XPrintf(p, "%Q", pExpr->u.zToken); | |
| 68672 | 68904 | break; |
| 68673 | 68905 | case TK_INTEGER: |
| 68674 | - sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue); | |
| 68906 | + sqlite3XPrintf(p, "%d", pExpr->u.iValue); | |
| 68675 | 68907 | break; |
| 68676 | 68908 | case TK_NULL: |
| 68677 | - sqlite3_snprintf(nTemp, zTemp, "NULL"); | |
| 68909 | + sqlite3XPrintf(p, "NULL"); | |
| 68678 | 68910 | break; |
| 68679 | 68911 | case TK_REGISTER: { |
| 68680 | - sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable); | |
| 68912 | + sqlite3XPrintf(p, "r[%d]", pExpr->iTable); | |
| 68681 | 68913 | break; |
| 68682 | 68914 | } |
| 68683 | 68915 | case TK_COLUMN: { |
| 68684 | 68916 | if( pExpr->iColumn<0 ){ |
| 68685 | - sqlite3_snprintf(nTemp, zTemp, "rowid"); | |
| 68917 | + sqlite3XPrintf(p, "rowid"); | |
| 68686 | 68918 | }else{ |
| 68687 | - sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn); | |
| 68919 | + sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); | |
| 68688 | 68920 | } |
| 68689 | 68921 | break; |
| 68690 | 68922 | } |
| 68691 | 68923 | case TK_LT: zOp = "LT"; break; |
| 68692 | 68924 | case TK_LE: zOp = "LE"; break; |
| @@ -68714,25 +68946,23 @@ | ||
| 68714 | 68946 | case TK_NOT: zOp = "NOT"; break; |
| 68715 | 68947 | case TK_ISNULL: zOp = "ISNULL"; break; |
| 68716 | 68948 | case TK_NOTNULL: zOp = "NOTNULL"; break; |
| 68717 | 68949 | |
| 68718 | 68950 | default: |
| 68719 | - sqlite3_snprintf(nTemp, zTemp, "%s", "expr"); | |
| 68951 | + sqlite3XPrintf(p, "%s", "expr"); | |
| 68720 | 68952 | break; |
| 68721 | 68953 | } |
| 68722 | 68954 | |
| 68723 | 68955 | if( zOp ){ |
| 68724 | - sqlite3_snprintf(nTemp, zTemp, "%s(", zOp); | |
| 68725 | - n = sqlite3Strlen30(zTemp); | |
| 68726 | - n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft); | |
| 68727 | - if( n<nTemp-1 && pExpr->pRight ){ | |
| 68728 | - zTemp[n++] = ','; | |
| 68729 | - n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight); | |
| 68730 | - } | |
| 68731 | - sqlite3_snprintf(nTemp-n, zTemp+n, ")"); | |
| 68732 | - } | |
| 68733 | - return sqlite3Strlen30(zTemp); | |
| 68956 | + sqlite3XPrintf(p, "%s(", zOp); | |
| 68957 | + displayP4Expr(p, pExpr->pLeft); | |
| 68958 | + if( pExpr->pRight ){ | |
| 68959 | + sqlite3StrAccumAppend(p, ",", 1); | |
| 68960 | + displayP4Expr(p, pExpr->pRight); | |
| 68961 | + } | |
| 68962 | + sqlite3StrAccumAppend(p, ")", 1); | |
| 68963 | + } | |
| 68734 | 68964 | } |
| 68735 | 68965 | #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ |
| 68736 | 68966 | |
| 68737 | 68967 | |
| 68738 | 68968 | #if VDBE_DISPLAY_P4 |
| @@ -68740,107 +68970,100 @@ | ||
| 68740 | 68970 | ** Compute a string that describes the P4 parameter for an opcode. |
| 68741 | 68971 | ** Use zTemp for any required temporary buffer space. |
| 68742 | 68972 | */ |
| 68743 | 68973 | static char *displayP4(Op *pOp, char *zTemp, int nTemp){ |
| 68744 | 68974 | char *zP4 = zTemp; |
| 68975 | + StrAccum x; | |
| 68745 | 68976 | assert( nTemp>=20 ); |
| 68977 | + sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0); | |
| 68746 | 68978 | switch( pOp->p4type ){ |
| 68747 | 68979 | case P4_KEYINFO: { |
| 68748 | - int i, j; | |
| 68980 | + int j; | |
| 68749 | 68981 | KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; |
| 68750 | 68982 | assert( pKeyInfo->aSortOrder!=0 ); |
| 68751 | - sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField); | |
| 68752 | - i = sqlite3Strlen30(zTemp); | |
| 68983 | + sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField); | |
| 68753 | 68984 | for(j=0; j<pKeyInfo->nField; j++){ |
| 68754 | 68985 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 68755 | - const char *zColl = pColl ? pColl->zName : "nil"; | |
| 68756 | - int n = sqlite3Strlen30(zColl); | |
| 68757 | - if( n==6 && memcmp(zColl,"BINARY",6)==0 ){ | |
| 68758 | - zColl = "B"; | |
| 68759 | - n = 1; | |
| 68760 | - } | |
| 68761 | - if( i+n>nTemp-7 ){ | |
| 68762 | - memcpy(&zTemp[i],",...",4); | |
| 68763 | - i += 4; | |
| 68764 | - break; | |
| 68765 | - } | |
| 68766 | - zTemp[i++] = ','; | |
| 68767 | - if( pKeyInfo->aSortOrder[j] ){ | |
| 68768 | - zTemp[i++] = '-'; | |
| 68769 | - } | |
| 68770 | - memcpy(&zTemp[i], zColl, n+1); | |
| 68771 | - i += n; | |
| 68772 | - } | |
| 68773 | - zTemp[i++] = ')'; | |
| 68774 | - zTemp[i] = 0; | |
| 68775 | - assert( i<nTemp ); | |
| 68986 | + const char *zColl = pColl ? pColl->zName : ""; | |
| 68987 | + if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; | |
| 68988 | + sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); | |
| 68989 | + } | |
| 68990 | + sqlite3StrAccumAppend(&x, ")", 1); | |
| 68776 | 68991 | break; |
| 68777 | 68992 | } |
| 68778 | 68993 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 68779 | 68994 | case P4_EXPR: { |
| 68780 | - displayP4Expr(nTemp, zTemp, pOp->p4.pExpr); | |
| 68995 | + displayP4Expr(&x, pOp->p4.pExpr); | |
| 68781 | 68996 | break; |
| 68782 | 68997 | } |
| 68783 | 68998 | #endif |
| 68784 | 68999 | case P4_COLLSEQ: { |
| 68785 | 69000 | CollSeq *pColl = pOp->p4.pColl; |
| 68786 | - sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); | |
| 69001 | + sqlite3XPrintf(&x, "(%.20s)", pColl->zName); | |
| 68787 | 69002 | break; |
| 68788 | 69003 | } |
| 68789 | 69004 | case P4_FUNCDEF: { |
| 68790 | 69005 | FuncDef *pDef = pOp->p4.pFunc; |
| 68791 | - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); | |
| 69006 | + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); | |
| 68792 | 69007 | break; |
| 68793 | 69008 | } |
| 68794 | 69009 | #ifdef SQLITE_DEBUG |
| 68795 | 69010 | case P4_FUNCCTX: { |
| 68796 | 69011 | FuncDef *pDef = pOp->p4.pCtx->pFunc; |
| 68797 | - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); | |
| 69012 | + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); | |
| 68798 | 69013 | break; |
| 68799 | 69014 | } |
| 68800 | 69015 | #endif |
| 68801 | 69016 | case P4_INT64: { |
| 68802 | - sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); | |
| 69017 | + sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); | |
| 68803 | 69018 | break; |
| 68804 | 69019 | } |
| 68805 | 69020 | case P4_INT32: { |
| 68806 | - sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i); | |
| 69021 | + sqlite3XPrintf(&x, "%d", pOp->p4.i); | |
| 68807 | 69022 | break; |
| 68808 | 69023 | } |
| 68809 | 69024 | case P4_REAL: { |
| 68810 | - sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal); | |
| 69025 | + sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); | |
| 68811 | 69026 | break; |
| 68812 | 69027 | } |
| 68813 | 69028 | case P4_MEM: { |
| 68814 | 69029 | Mem *pMem = pOp->p4.pMem; |
| 68815 | 69030 | if( pMem->flags & MEM_Str ){ |
| 68816 | 69031 | zP4 = pMem->z; |
| 68817 | 69032 | }else if( pMem->flags & MEM_Int ){ |
| 68818 | - sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); | |
| 69033 | + sqlite3XPrintf(&x, "%lld", pMem->u.i); | |
| 68819 | 69034 | }else if( pMem->flags & MEM_Real ){ |
| 68820 | - sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r); | |
| 69035 | + sqlite3XPrintf(&x, "%.16g", pMem->u.r); | |
| 68821 | 69036 | }else if( pMem->flags & MEM_Null ){ |
| 68822 | - sqlite3_snprintf(nTemp, zTemp, "NULL"); | |
| 69037 | + zP4 = "NULL"; | |
| 68823 | 69038 | }else{ |
| 68824 | 69039 | assert( pMem->flags & MEM_Blob ); |
| 68825 | 69040 | zP4 = "(blob)"; |
| 68826 | 69041 | } |
| 68827 | 69042 | break; |
| 68828 | 69043 | } |
| 68829 | 69044 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 68830 | 69045 | case P4_VTAB: { |
| 68831 | 69046 | sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; |
| 68832 | - sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); | |
| 69047 | + sqlite3XPrintf(&x, "vtab:%p", pVtab); | |
| 68833 | 69048 | break; |
| 68834 | 69049 | } |
| 68835 | 69050 | #endif |
| 68836 | 69051 | case P4_INTARRAY: { |
| 68837 | - sqlite3_snprintf(nTemp, zTemp, "intarray"); | |
| 69052 | + int i; | |
| 69053 | + int *ai = pOp->p4.ai; | |
| 69054 | + int n = ai[0]; /* The first element of an INTARRAY is always the | |
| 69055 | + ** count of the number of elements to follow */ | |
| 69056 | + for(i=1; i<n; i++){ | |
| 69057 | + sqlite3XPrintf(&x, ",%d", ai[i]); | |
| 69058 | + } | |
| 69059 | + zTemp[0] = '['; | |
| 69060 | + sqlite3StrAccumAppend(&x, "]", 1); | |
| 68838 | 69061 | break; |
| 68839 | 69062 | } |
| 68840 | 69063 | case P4_SUBPROGRAM: { |
| 68841 | - sqlite3_snprintf(nTemp, zTemp, "program"); | |
| 69064 | + sqlite3XPrintf(&x, "program"); | |
| 68842 | 69065 | break; |
| 68843 | 69066 | } |
| 68844 | 69067 | case P4_ADVANCE: { |
| 68845 | 69068 | zTemp[0] = 0; |
| 68846 | 69069 | break; |
| @@ -68851,10 +69074,11 @@ | ||
| 68851 | 69074 | zP4 = zTemp; |
| 68852 | 69075 | zTemp[0] = 0; |
| 68853 | 69076 | } |
| 68854 | 69077 | } |
| 68855 | 69078 | } |
| 69079 | + sqlite3StrAccumFinish(&x); | |
| 68856 | 69080 | assert( zP4!=0 ); |
| 68857 | 69081 | return zP4; |
| 68858 | 69082 | } |
| 68859 | 69083 | #endif /* VDBE_DISPLAY_P4 */ |
| 68860 | 69084 | |
| @@ -68970,11 +69194,10 @@ | ||
| 68970 | 69194 | */ |
| 68971 | 69195 | static void releaseMemArray(Mem *p, int N){ |
| 68972 | 69196 | if( p && N ){ |
| 68973 | 69197 | Mem *pEnd = &p[N]; |
| 68974 | 69198 | sqlite3 *db = p->db; |
| 68975 | - u8 malloc_failed = db->mallocFailed; | |
| 68976 | 69199 | if( db->pnBytesFreed ){ |
| 68977 | 69200 | do{ |
| 68978 | 69201 | if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); |
| 68979 | 69202 | }while( (++p)<pEnd ); |
| 68980 | 69203 | return; |
| @@ -69006,11 +69229,10 @@ | ||
| 69006 | 69229 | p->szMalloc = 0; |
| 69007 | 69230 | } |
| 69008 | 69231 | |
| 69009 | 69232 | p->flags = MEM_Undefined; |
| 69010 | 69233 | }while( (++p)<pEnd ); |
| 69011 | - db->mallocFailed = malloc_failed; | |
| 69012 | 69234 | } |
| 69013 | 69235 | } |
| 69014 | 69236 | |
| 69015 | 69237 | /* |
| 69016 | 69238 | ** Delete a VdbeFrame object and its contents. VdbeFrame objects are |
| @@ -69067,11 +69289,11 @@ | ||
| 69067 | 69289 | p->pResultSet = 0; |
| 69068 | 69290 | |
| 69069 | 69291 | if( p->rc==SQLITE_NOMEM ){ |
| 69070 | 69292 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 69071 | 69293 | ** sqlite3_column_text16() failed. */ |
| 69072 | - db->mallocFailed = 1; | |
| 69294 | + sqlite3OomFault(db); | |
| 69073 | 69295 | return SQLITE_ERROR; |
| 69074 | 69296 | } |
| 69075 | 69297 | |
| 69076 | 69298 | /* When the number of output rows reaches nRow, that means the |
| 69077 | 69299 | ** listing has finished and sqlite3_step() should return SQLITE_DONE. |
| @@ -69265,45 +69487,47 @@ | ||
| 69265 | 69487 | sqlite3IoTrace("SQL %s\n", z); |
| 69266 | 69488 | } |
| 69267 | 69489 | } |
| 69268 | 69490 | #endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ |
| 69269 | 69491 | |
| 69270 | -/* | |
| 69271 | -** Allocate space from a fixed size buffer and return a pointer to | |
| 69272 | -** that space. If insufficient space is available, return NULL. | |
| 69273 | -** | |
| 69274 | -** The pBuf parameter is the initial value of a pointer which will | |
| 69275 | -** receive the new memory. pBuf is normally NULL. If pBuf is not | |
| 69276 | -** NULL, it means that memory space has already been allocated and that | |
| 69277 | -** this routine should not allocate any new memory. When pBuf is not | |
| 69278 | -** NULL simply return pBuf. Only allocate new memory space when pBuf | |
| 69279 | -** is NULL. | |
| 69280 | -** | |
| 69281 | -** nByte is the number of bytes of space needed. | |
| 69282 | -** | |
| 69283 | -** pFrom points to *pnFrom bytes of available space. New space is allocated | |
| 69284 | -** from the end of the pFrom buffer and *pnFrom is decremented. | |
| 69285 | -** | |
| 69286 | -** *pnNeeded is a counter of the number of bytes of space that have failed | |
| 69287 | -** to allocate. If there is insufficient space in pFrom to satisfy the | |
| 69288 | -** request, then increment *pnNeeded by the amount of the request. | |
| 69492 | +/* An instance of this object describes bulk memory available for use | |
| 69493 | +** by subcomponents of a prepared statement. Space is allocated out | |
| 69494 | +** of a ReusableSpace object by the allocSpace() routine below. | |
| 69495 | +*/ | |
| 69496 | +struct ReusableSpace { | |
| 69497 | + u8 *pSpace; /* Available memory */ | |
| 69498 | + int nFree; /* Bytes of available memory */ | |
| 69499 | + int nNeeded; /* Total bytes that could not be allocated */ | |
| 69500 | +}; | |
| 69501 | + | |
| 69502 | +/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf | |
| 69503 | +** from the ReusableSpace object. Return a pointer to the allocated | |
| 69504 | +** memory on success. If insufficient memory is available in the | |
| 69505 | +** ReusableSpace object, increase the ReusableSpace.nNeeded | |
| 69506 | +** value by the amount needed and return NULL. | |
| 69507 | +** | |
| 69508 | +** If pBuf is not initially NULL, that means that the memory has already | |
| 69509 | +** been allocated by a prior call to this routine, so just return a copy | |
| 69510 | +** of pBuf and leave ReusableSpace unchanged. | |
| 69511 | +** | |
| 69512 | +** This allocator is employed to repurpose unused slots at the end of the | |
| 69513 | +** opcode array of prepared state for other memory needs of the prepared | |
| 69514 | +** statement. | |
| 69289 | 69515 | */ |
| 69290 | 69516 | static void *allocSpace( |
| 69291 | - void *pBuf, /* Where return pointer will be stored */ | |
| 69292 | - int nByte, /* Number of bytes to allocate */ | |
| 69293 | - u8 *pFrom, /* Memory available for allocation */ | |
| 69294 | - int *pnFrom, /* IN/OUT: Space available at pFrom */ | |
| 69295 | - int *pnNeeded /* If allocation cannot be made, increment *pnByte */ | |
| 69517 | + struct ReusableSpace *p, /* Bulk memory available for allocation */ | |
| 69518 | + void *pBuf, /* Pointer to a prior allocation */ | |
| 69519 | + int nByte /* Bytes of memory needed */ | |
| 69296 | 69520 | ){ |
| 69297 | - assert( EIGHT_BYTE_ALIGNMENT(pFrom) ); | |
| 69521 | + assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); | |
| 69298 | 69522 | if( pBuf==0 ){ |
| 69299 | 69523 | nByte = ROUND8(nByte); |
| 69300 | - if( nByte <= *pnFrom ){ | |
| 69301 | - *pnFrom -= nByte; | |
| 69302 | - pBuf = &pFrom[*pnFrom]; | |
| 69524 | + if( nByte <= p->nFree ){ | |
| 69525 | + p->nFree -= nByte; | |
| 69526 | + pBuf = &p->pSpace[p->nFree]; | |
| 69303 | 69527 | }else{ |
| 69304 | - *pnNeeded += nByte; | |
| 69528 | + p->nNeeded += nByte; | |
| 69305 | 69529 | } |
| 69306 | 69530 | } |
| 69307 | 69531 | assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); |
| 69308 | 69532 | return pBuf; |
| 69309 | 69533 | } |
| @@ -69332,11 +69556,10 @@ | ||
| 69332 | 69556 | } |
| 69333 | 69557 | #endif |
| 69334 | 69558 | p->pc = -1; |
| 69335 | 69559 | p->rc = SQLITE_OK; |
| 69336 | 69560 | p->errorAction = OE_Abort; |
| 69337 | - p->magic = VDBE_MAGIC_RUN; | |
| 69338 | 69561 | p->nChange = 0; |
| 69339 | 69562 | p->cacheCtr = 1; |
| 69340 | 69563 | p->minWriteFileFormat = 255; |
| 69341 | 69564 | p->iStatement = 0; |
| 69342 | 69565 | p->nFkConstraint = 0; |
| @@ -69375,13 +69598,11 @@ | ||
| 69375 | 69598 | int nMem; /* Number of VM memory registers */ |
| 69376 | 69599 | int nCursor; /* Number of cursors required */ |
| 69377 | 69600 | int nArg; /* Number of arguments in subprograms */ |
| 69378 | 69601 | int nOnce; /* Number of OP_Once instructions */ |
| 69379 | 69602 | int n; /* Loop counter */ |
| 69380 | - int nFree; /* Available free space */ | |
| 69381 | - u8 *zCsr; /* Memory available for allocation */ | |
| 69382 | - int nByte; /* How much extra memory is needed */ | |
| 69603 | + struct ReusableSpace x; /* Reusable bulk memory */ | |
| 69383 | 69604 | |
| 69384 | 69605 | assert( p!=0 ); |
| 69385 | 69606 | assert( p->nOp>0 ); |
| 69386 | 69607 | assert( pParse!=0 ); |
| 69387 | 69608 | assert( p->magic==VDBE_MAGIC_INIT ); |
| @@ -69395,69 +69616,64 @@ | ||
| 69395 | 69616 | nOnce = pParse->nOnce; |
| 69396 | 69617 | if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ |
| 69397 | 69618 | |
| 69398 | 69619 | /* For each cursor required, also allocate a memory cell. Memory |
| 69399 | 69620 | ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by |
| 69400 | - ** the vdbe program. Instead they are used to allocate space for | |
| 69621 | + ** the vdbe program. Instead they are used to allocate memory for | |
| 69401 | 69622 | ** VdbeCursor/BtCursor structures. The blob of memory associated with |
| 69402 | 69623 | ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) |
| 69403 | 69624 | ** stores the blob of memory associated with cursor 1, etc. |
| 69404 | 69625 | ** |
| 69405 | 69626 | ** See also: allocateCursor(). |
| 69406 | 69627 | */ |
| 69407 | 69628 | nMem += nCursor; |
| 69408 | 69629 | |
| 69409 | - /* zCsr will initially point to nFree bytes of unused space at the | |
| 69410 | - ** end of the opcode array, p->aOp. The computation of nFree is | |
| 69411 | - ** conservative - it might be smaller than the true number of free | |
| 69412 | - ** bytes, but never larger. nFree must be a multiple of 8 - it is | |
| 69413 | - ** rounded down if is not. | |
| 69630 | + /* Figure out how much reusable memory is available at the end of the | |
| 69631 | + ** opcode array. This extra memory will be reallocated for other elements | |
| 69632 | + ** of the prepared statement. | |
| 69414 | 69633 | */ |
| 69415 | - n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */ | |
| 69416 | - zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */ | |
| 69417 | - assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); | |
| 69418 | - nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */ | |
| 69419 | - assert( nFree>=0 ); | |
| 69420 | - if( nFree>0 ){ | |
| 69421 | - memset(zCsr, 0, nFree); | |
| 69422 | - assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) ); | |
| 69634 | + n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ | |
| 69635 | + x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ | |
| 69636 | + assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); | |
| 69637 | + x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ | |
| 69638 | + assert( x.nFree>=0 ); | |
| 69639 | + if( x.nFree>0 ){ | |
| 69640 | + memset(x.pSpace, 0, x.nFree); | |
| 69641 | + assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); | |
| 69423 | 69642 | } |
| 69424 | 69643 | |
| 69425 | 69644 | resolveP2Values(p, &nArg); |
| 69426 | 69645 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| 69427 | 69646 | if( pParse->explain && nMem<10 ){ |
| 69428 | 69647 | nMem = 10; |
| 69429 | 69648 | } |
| 69430 | 69649 | p->expired = 0; |
| 69431 | 69650 | |
| 69432 | - /* Memory for registers, parameters, cursor, etc, is allocated in two | |
| 69433 | - ** passes. On the first pass, we try to reuse unused space at the | |
| 69651 | + /* Memory for registers, parameters, cursor, etc, is allocated in one or two | |
| 69652 | + ** passes. On the first pass, we try to reuse unused memory at the | |
| 69434 | 69653 | ** end of the opcode array. If we are unable to satisfy all memory |
| 69435 | 69654 | ** requirements by reusing the opcode array tail, then the second |
| 69436 | - ** pass will fill in the rest using a fresh allocation. | |
| 69655 | + ** pass will fill in the remainder using a fresh memory allocation. | |
| 69437 | 69656 | ** |
| 69438 | 69657 | ** This two-pass approach that reuses as much memory as possible from |
| 69439 | - ** the leftover space at the end of the opcode array can significantly | |
| 69658 | + ** the leftover memory at the end of the opcode array. This can significantly | |
| 69440 | 69659 | ** reduce the amount of memory held by a prepared statement. |
| 69441 | 69660 | */ |
| 69442 | 69661 | do { |
| 69443 | - nByte = 0; | |
| 69444 | - p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte); | |
| 69445 | - p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte); | |
| 69446 | - p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte); | |
| 69447 | - p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), | |
| 69448 | - zCsr, &nFree, &nByte); | |
| 69449 | - p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte); | |
| 69662 | + x.nNeeded = 0; | |
| 69663 | + p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem)); | |
| 69664 | + p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); | |
| 69665 | + p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); | |
| 69666 | + p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); | |
| 69667 | + p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce); | |
| 69450 | 69668 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 69451 | - p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte); | |
| 69669 | + p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); | |
| 69452 | 69670 | #endif |
| 69453 | - if( nByte ){ | |
| 69454 | - p->pFree = sqlite3DbMallocZero(db, nByte); | |
| 69455 | - } | |
| 69456 | - zCsr = p->pFree; | |
| 69457 | - nFree = nByte; | |
| 69458 | - }while( nByte && !db->mallocFailed ); | |
| 69671 | + if( x.nNeeded==0 ) break; | |
| 69672 | + x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); | |
| 69673 | + x.nFree = x.nNeeded; | |
| 69674 | + }while( !db->mallocFailed ); | |
| 69459 | 69675 | |
| 69460 | 69676 | p->nCursor = nCursor; |
| 69461 | 69677 | p->nOnceFlag = nOnce; |
| 69462 | 69678 | if( p->aVar ){ |
| 69463 | 69679 | p->nVar = (ynVar)nVar; |
| @@ -70066,11 +70282,11 @@ | ||
| 70066 | 70282 | ** Then the internal cache might have been left in an inconsistent |
| 70067 | 70283 | ** state. We need to rollback the statement transaction, if there is |
| 70068 | 70284 | ** one, or the complete transaction if there is no statement transaction. |
| 70069 | 70285 | */ |
| 70070 | 70286 | |
| 70071 | - if( p->db->mallocFailed ){ | |
| 70287 | + if( db->mallocFailed ){ | |
| 70072 | 70288 | p->rc = SQLITE_NOMEM; |
| 70073 | 70289 | } |
| 70074 | 70290 | if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); |
| 70075 | 70291 | closeAllCursors(p); |
| 70076 | 70292 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| @@ -70227,11 +70443,11 @@ | ||
| 70227 | 70443 | assert( db->nVdbeRead>=db->nVdbeWrite ); |
| 70228 | 70444 | assert( db->nVdbeWrite>=0 ); |
| 70229 | 70445 | } |
| 70230 | 70446 | p->magic = VDBE_MAGIC_HALT; |
| 70231 | 70447 | checkActiveVdbeCnt(db); |
| 70232 | - if( p->db->mallocFailed ){ | |
| 70448 | + if( db->mallocFailed ){ | |
| 70233 | 70449 | p->rc = SQLITE_NOMEM; |
| 70234 | 70450 | } |
| 70235 | 70451 | |
| 70236 | 70452 | /* If the auto-commit flag is set to true, then any locks that were held |
| 70237 | 70453 | ** by connection db have now been released. Call sqlite3ConnectionUnlocked() |
| @@ -70264,16 +70480,16 @@ | ||
| 70264 | 70480 | */ |
| 70265 | 70481 | SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ |
| 70266 | 70482 | sqlite3 *db = p->db; |
| 70267 | 70483 | int rc = p->rc; |
| 70268 | 70484 | if( p->zErrMsg ){ |
| 70269 | - u8 mallocFailed = db->mallocFailed; | |
| 70485 | + db->bBenignMalloc++; | |
| 70270 | 70486 | sqlite3BeginBenignMalloc(); |
| 70271 | 70487 | if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); |
| 70272 | 70488 | sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); |
| 70273 | 70489 | sqlite3EndBenignMalloc(); |
| 70274 | - db->mallocFailed = mallocFailed; | |
| 70490 | + db->bBenignMalloc--; | |
| 70275 | 70491 | db->errCode = rc; |
| 70276 | 70492 | }else{ |
| 70277 | 70493 | sqlite3Error(db, rc); |
| 70278 | 70494 | } |
| 70279 | 70495 | return rc; |
| @@ -70558,13 +70774,20 @@ | ||
| 70558 | 70774 | ** a NULL row. |
| 70559 | 70775 | ** |
| 70560 | 70776 | ** If the cursor is already pointing to the correct row and that row has |
| 70561 | 70777 | ** not been deleted out from under the cursor, then this routine is a no-op. |
| 70562 | 70778 | */ |
| 70563 | -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ | |
| 70779 | +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ | |
| 70780 | + VdbeCursor *p = *pp; | |
| 70564 | 70781 | if( p->eCurType==CURTYPE_BTREE ){ |
| 70565 | 70782 | if( p->deferredMoveto ){ |
| 70783 | + int iMap; | |
| 70784 | + if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ | |
| 70785 | + *pp = p->pAltCursor; | |
| 70786 | + *piCol = iMap - 1; | |
| 70787 | + return SQLITE_OK; | |
| 70788 | + } | |
| 70566 | 70789 | return handleDeferredMoveto(p); |
| 70567 | 70790 | } |
| 70568 | 70791 | if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ |
| 70569 | 70792 | return handleMovedCursor(p); |
| 70570 | 70793 | } |
| @@ -72191,11 +72414,12 @@ | ||
| 72191 | 72414 | } |
| 72192 | 72415 | SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ |
| 72193 | 72416 | return sqlite3VdbeIntValue((Mem*)pVal); |
| 72194 | 72417 | } |
| 72195 | 72418 | SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){ |
| 72196 | - return ((Mem*)pVal)->eSubtype; | |
| 72419 | + Mem *pMem = (Mem*)pVal; | |
| 72420 | + return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); | |
| 72197 | 72421 | } |
| 72198 | 72422 | SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ |
| 72199 | 72423 | return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); |
| 72200 | 72424 | } |
| 72201 | 72425 | #ifndef SQLITE_OMIT_UTF16 |
| @@ -72372,12 +72596,14 @@ | ||
| 72372 | 72596 | SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ |
| 72373 | 72597 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72374 | 72598 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72375 | 72599 | } |
| 72376 | 72600 | SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ |
| 72377 | - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); | |
| 72378 | - pCtx->pOut->eSubtype = eSubtype & 0xff; | |
| 72601 | + Mem *pOut = pCtx->pOut; | |
| 72602 | + assert( sqlite3_mutex_held(pOut->db->mutex) ); | |
| 72603 | + pOut->eSubtype = eSubtype & 0xff; | |
| 72604 | + pOut->flags |= MEM_Subtype; | |
| 72379 | 72605 | } |
| 72380 | 72606 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text( |
| 72381 | 72607 | sqlite3_context *pCtx, |
| 72382 | 72608 | const char *z, |
| 72383 | 72609 | int n, |
| @@ -72473,11 +72699,11 @@ | ||
| 72473 | 72699 | SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ |
| 72474 | 72700 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72475 | 72701 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72476 | 72702 | pCtx->isError = SQLITE_NOMEM; |
| 72477 | 72703 | pCtx->fErrorOrAux = 1; |
| 72478 | - pCtx->pOut->db->mallocFailed = 1; | |
| 72704 | + sqlite3OomFault(pCtx->pOut->db); | |
| 72479 | 72705 | } |
| 72480 | 72706 | |
| 72481 | 72707 | /* |
| 72482 | 72708 | ** This function is called after a transaction has been committed. It |
| 72483 | 72709 | ** invokes callbacks registered with sqlite3_wal_hook() as required. |
| @@ -73101,11 +73327,11 @@ | ||
| 73101 | 73327 | ret = xFunc(&p->aColName[N]); |
| 73102 | 73328 | /* A malloc may have failed inside of the xFunc() call. If this |
| 73103 | 73329 | ** is the case, clear the mallocFailed flag and return NULL. |
| 73104 | 73330 | */ |
| 73105 | 73331 | if( db->mallocFailed ){ |
| 73106 | - db->mallocFailed = 0; | |
| 73332 | + sqlite3OomClear(db); | |
| 73107 | 73333 | ret = 0; |
| 73108 | 73334 | } |
| 73109 | 73335 | sqlite3_mutex_leave(db->mutex); |
| 73110 | 73336 | } |
| 73111 | 73337 | return ret; |
| @@ -73802,13 +74028,13 @@ | ||
| 73802 | 74028 | assert( idx>0 && idx<=p->nVar ); |
| 73803 | 74029 | pVar = &p->aVar[idx-1]; |
| 73804 | 74030 | if( pVar->flags & MEM_Null ){ |
| 73805 | 74031 | sqlite3StrAccumAppend(&out, "NULL", 4); |
| 73806 | 74032 | }else if( pVar->flags & MEM_Int ){ |
| 73807 | - sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); | |
| 74033 | + sqlite3XPrintf(&out, "%lld", pVar->u.i); | |
| 73808 | 74034 | }else if( pVar->flags & MEM_Real ){ |
| 73809 | - sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r); | |
| 74035 | + sqlite3XPrintf(&out, "%!.15g", pVar->u.r); | |
| 73810 | 74036 | }else if( pVar->flags & MEM_Str ){ |
| 73811 | 74037 | int nOut; /* Number of bytes of the string text to include in output */ |
| 73812 | 74038 | #ifndef SQLITE_OMIT_UTF16 |
| 73813 | 74039 | u8 enc = ENC(db); |
| 73814 | 74040 | Mem utf8; |
| @@ -73825,36 +74051,36 @@ | ||
| 73825 | 74051 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ |
| 73826 | 74052 | nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 73827 | 74053 | while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } |
| 73828 | 74054 | } |
| 73829 | 74055 | #endif |
| 73830 | - sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z); | |
| 74056 | + sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); | |
| 73831 | 74057 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73832 | 74058 | if( nOut<pVar->n ){ |
| 73833 | - sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); | |
| 74059 | + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); | |
| 73834 | 74060 | } |
| 73835 | 74061 | #endif |
| 73836 | 74062 | #ifndef SQLITE_OMIT_UTF16 |
| 73837 | 74063 | if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); |
| 73838 | 74064 | #endif |
| 73839 | 74065 | }else if( pVar->flags & MEM_Zero ){ |
| 73840 | - sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero); | |
| 74066 | + sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); | |
| 73841 | 74067 | }else{ |
| 73842 | 74068 | int nOut; /* Number of bytes of the blob to include in output */ |
| 73843 | 74069 | assert( pVar->flags & MEM_Blob ); |
| 73844 | 74070 | sqlite3StrAccumAppend(&out, "x'", 2); |
| 73845 | 74071 | nOut = pVar->n; |
| 73846 | 74072 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73847 | 74073 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 73848 | 74074 | #endif |
| 73849 | 74075 | for(i=0; i<nOut; i++){ |
| 73850 | - sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff); | |
| 74076 | + sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); | |
| 73851 | 74077 | } |
| 73852 | 74078 | sqlite3StrAccumAppend(&out, "'", 1); |
| 73853 | 74079 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73854 | 74080 | if( nOut<pVar->n ){ |
| 73855 | - sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); | |
| 74081 | + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); | |
| 73856 | 74082 | } |
| 73857 | 74083 | #endif |
| 73858 | 74084 | } |
| 73859 | 74085 | } |
| 73860 | 74086 | } |
| @@ -74336,10 +74562,11 @@ | ||
| 74336 | 74562 | }else{ |
| 74337 | 74563 | char zBuf[200]; |
| 74338 | 74564 | sqlite3VdbeMemPrettyPrint(p, zBuf); |
| 74339 | 74565 | printf(" %s", zBuf); |
| 74340 | 74566 | } |
| 74567 | + if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); | |
| 74341 | 74568 | } |
| 74342 | 74569 | static void registerTrace(int iReg, Mem *p){ |
| 74343 | 74570 | printf("REG[%d] = ", iReg); |
| 74344 | 74571 | memTracePrint(p); |
| 74345 | 74572 | printf("\n"); |
| @@ -74506,10 +74733,13 @@ | ||
| 74506 | 74733 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 74507 | 74734 | Op *pOp = aOp; /* Current operation */ |
| 74508 | 74735 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 74509 | 74736 | Op *pOrigOp; /* Value of pOp at the top of the loop */ |
| 74510 | 74737 | #endif |
| 74738 | +#ifdef SQLITE_DEBUG | |
| 74739 | + int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ | |
| 74740 | +#endif | |
| 74511 | 74741 | int rc = SQLITE_OK; /* Value to return */ |
| 74512 | 74742 | sqlite3 *db = p->db; /* The database */ |
| 74513 | 74743 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ |
| 74514 | 74744 | u8 encoding = ENC(db); /* The database encoding */ |
| 74515 | 74745 | int iCompare = 0; /* Result of last OP_Compare operation */ |
| @@ -74579,11 +74809,10 @@ | ||
| 74579 | 74809 | } |
| 74580 | 74810 | sqlite3EndBenignMalloc(); |
| 74581 | 74811 | #endif |
| 74582 | 74812 | for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ |
| 74583 | 74813 | assert( pOp>=aOp && pOp<&aOp[p->nOp]); |
| 74584 | - if( db->mallocFailed ) goto no_mem; | |
| 74585 | 74814 | #ifdef VDBE_PROFILE |
| 74586 | 74815 | start = sqlite3Hwtime(); |
| 74587 | 74816 | #endif |
| 74588 | 74817 | nVmStep++; |
| 74589 | 74818 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| @@ -75577,11 +75806,11 @@ | ||
| 75577 | 75806 | assert( pOp->p4type==P4_FUNCDEF ); |
| 75578 | 75807 | n = pOp->p5; |
| 75579 | 75808 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 75580 | 75809 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 75581 | 75810 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 75582 | - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); | |
| 75811 | + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); | |
| 75583 | 75812 | if( pCtx==0 ) goto no_mem; |
| 75584 | 75813 | pCtx->pOut = 0; |
| 75585 | 75814 | pCtx->pFunc = pOp->p4.pFunc; |
| 75586 | 75815 | pCtx->iOp = (int)(pOp - aOp); |
| 75587 | 75816 | pCtx->pVdbe = p; |
| @@ -76021,15 +76250,18 @@ | ||
| 76021 | 76250 | ** of integers in P4. |
| 76022 | 76251 | ** |
| 76023 | 76252 | ** The permutation is only valid until the next OP_Compare that has |
| 76024 | 76253 | ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should |
| 76025 | 76254 | ** occur immediately prior to the OP_Compare. |
| 76255 | +** | |
| 76256 | +** The first integer in the P4 integer array is the length of the array | |
| 76257 | +** and does not become part of the permutation. | |
| 76026 | 76258 | */ |
| 76027 | 76259 | case OP_Permutation: { |
| 76028 | 76260 | assert( pOp->p4type==P4_INTARRAY ); |
| 76029 | 76261 | assert( pOp->p4.ai ); |
| 76030 | - aPermute = pOp->p4.ai; | |
| 76262 | + aPermute = pOp->p4.ai + 1; | |
| 76031 | 76263 | break; |
| 76032 | 76264 | } |
| 76033 | 76265 | |
| 76034 | 76266 | /* Opcode: Compare P1 P2 P3 P4 P5 |
| 76035 | 76267 | ** Synopsis: r[P1@P3] <-> r[P2@P3] |
| @@ -76330,26 +76562,28 @@ | ||
| 76330 | 76562 | u64 offset64; /* 64-bit offset */ |
| 76331 | 76563 | u32 avail; /* Number of bytes of available data */ |
| 76332 | 76564 | u32 t; /* A type code from the record header */ |
| 76333 | 76565 | Mem *pReg; /* PseudoTable input register */ |
| 76334 | 76566 | |
| 76567 | + pC = p->apCsr[pOp->p1]; | |
| 76335 | 76568 | p2 = pOp->p2; |
| 76569 | + | |
| 76570 | + /* If the cursor cache is stale, bring it up-to-date */ | |
| 76571 | + rc = sqlite3VdbeCursorMoveto(&pC, &p2); | |
| 76572 | + | |
| 76336 | 76573 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 76337 | 76574 | pDest = &aMem[pOp->p3]; |
| 76338 | 76575 | memAboutToChange(p, pDest); |
| 76339 | 76576 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 76340 | - pC = p->apCsr[pOp->p1]; | |
| 76341 | 76577 | assert( pC!=0 ); |
| 76342 | 76578 | assert( p2<pC->nField ); |
| 76343 | 76579 | aOffset = pC->aOffset; |
| 76344 | 76580 | assert( pC->eCurType!=CURTYPE_VTAB ); |
| 76345 | 76581 | assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); |
| 76346 | 76582 | assert( pC->eCurType!=CURTYPE_SORTER ); |
| 76347 | 76583 | pCrsr = pC->uc.pCursor; |
| 76348 | 76584 | |
| 76349 | - /* If the cursor cache is stale, bring it up-to-date */ | |
| 76350 | - rc = sqlite3VdbeCursorMoveto(pC); | |
| 76351 | 76585 | if( rc ) goto abort_due_to_error; |
| 76352 | 76586 | if( pC->cacheStatus!=p->cacheCtr ){ |
| 76353 | 76587 | if( pC->nullRow ){ |
| 76354 | 76588 | if( pC->eCurType==CURTYPE_PSEUDO ){ |
| 76355 | 76589 | assert( pC->uc.pseudoTableReg>0 ); |
| @@ -76816,11 +77050,11 @@ | ||
| 76816 | 77050 | db->nStatement+db->nSavepoint); |
| 76817 | 77051 | if( rc!=SQLITE_OK ) goto abort_due_to_error; |
| 76818 | 77052 | #endif |
| 76819 | 77053 | |
| 76820 | 77054 | /* Create a new savepoint structure. */ |
| 76821 | - pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); | |
| 77055 | + pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1); | |
| 76822 | 77056 | if( pNew ){ |
| 76823 | 77057 | pNew->zName = (char *)&pNew[1]; |
| 76824 | 77058 | memcpy(pNew->zName, zName, nName+1); |
| 76825 | 77059 | |
| 76826 | 77060 | /* If there is no open transaction, then mark this as a special |
| @@ -76953,32 +77187,31 @@ | ||
| 76953 | 77187 | ** This instruction causes the VM to halt. |
| 76954 | 77188 | */ |
| 76955 | 77189 | case OP_AutoCommit: { |
| 76956 | 77190 | int desiredAutoCommit; |
| 76957 | 77191 | int iRollback; |
| 76958 | - int turnOnAC; | |
| 76959 | 77192 | |
| 76960 | 77193 | desiredAutoCommit = pOp->p1; |
| 76961 | 77194 | iRollback = pOp->p2; |
| 76962 | - turnOnAC = desiredAutoCommit && !db->autoCommit; | |
| 76963 | 77195 | assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); |
| 76964 | 77196 | assert( desiredAutoCommit==1 || iRollback==0 ); |
| 76965 | 77197 | assert( db->nVdbeActive>0 ); /* At least this one VM is active */ |
| 76966 | 77198 | assert( p->bIsReader ); |
| 76967 | 77199 | |
| 76968 | - if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ | |
| 76969 | - /* If this instruction implements a COMMIT and other VMs are writing | |
| 76970 | - ** return an error indicating that the other VMs must complete first. | |
| 76971 | - */ | |
| 76972 | - sqlite3VdbeError(p, "cannot commit transaction - " | |
| 76973 | - "SQL statements in progress"); | |
| 76974 | - rc = SQLITE_BUSY; | |
| 76975 | - }else if( desiredAutoCommit!=db->autoCommit ){ | |
| 77200 | + if( desiredAutoCommit!=db->autoCommit ){ | |
| 76976 | 77201 | if( iRollback ){ |
| 76977 | 77202 | assert( desiredAutoCommit==1 ); |
| 76978 | 77203 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 76979 | 77204 | db->autoCommit = 1; |
| 77205 | + }else if( desiredAutoCommit && db->nVdbeWrite>0 ){ | |
| 77206 | + /* If this instruction implements a COMMIT and other VMs are writing | |
| 77207 | + ** return an error indicating that the other VMs must complete first. | |
| 77208 | + */ | |
| 77209 | + sqlite3VdbeError(p, "cannot commit transaction - " | |
| 77210 | + "SQL statements in progress"); | |
| 77211 | + rc = SQLITE_BUSY; | |
| 77212 | + break; | |
| 76980 | 77213 | }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ |
| 76981 | 77214 | goto vdbe_return; |
| 76982 | 77215 | }else{ |
| 76983 | 77216 | db->autoCommit = (u8)desiredAutoCommit; |
| 76984 | 77217 | } |
| @@ -77159,38 +77392,36 @@ | ||
| 77159 | 77392 | break; |
| 77160 | 77393 | } |
| 77161 | 77394 | |
| 77162 | 77395 | /* Opcode: SetCookie P1 P2 P3 * * |
| 77163 | 77396 | ** |
| 77164 | -** Write the content of register P3 (interpreted as an integer) | |
| 77165 | -** into cookie number P2 of database P1. P2==1 is the schema version. | |
| 77166 | -** P2==2 is the database format. P2==3 is the recommended pager cache | |
| 77397 | +** Write the integer value P3 into cookie number P2 of database P1. | |
| 77398 | +** P2==1 is the schema version. P2==2 is the database format. | |
| 77399 | +** P2==3 is the recommended pager cache | |
| 77167 | 77400 | ** size, and so forth. P1==0 is the main database file and P1==1 is the |
| 77168 | 77401 | ** database file used to store temporary tables. |
| 77169 | 77402 | ** |
| 77170 | 77403 | ** A transaction must be started before executing this opcode. |
| 77171 | 77404 | */ |
| 77172 | -case OP_SetCookie: { /* in3 */ | |
| 77405 | +case OP_SetCookie: { | |
| 77173 | 77406 | Db *pDb; |
| 77174 | 77407 | assert( pOp->p2<SQLITE_N_BTREE_META ); |
| 77175 | 77408 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 77176 | 77409 | assert( DbMaskTest(p->btreeMask, pOp->p1) ); |
| 77177 | 77410 | assert( p->readOnly==0 ); |
| 77178 | 77411 | pDb = &db->aDb[pOp->p1]; |
| 77179 | 77412 | assert( pDb->pBt!=0 ); |
| 77180 | 77413 | assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); |
| 77181 | - pIn3 = &aMem[pOp->p3]; | |
| 77182 | - sqlite3VdbeMemIntegerify(pIn3); | |
| 77183 | 77414 | /* See note about index shifting on OP_ReadCookie */ |
| 77184 | - rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); | |
| 77415 | + rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3); | |
| 77185 | 77416 | if( pOp->p2==BTREE_SCHEMA_VERSION ){ |
| 77186 | 77417 | /* When the schema cookie changes, record the new cookie internally */ |
| 77187 | - pDb->pSchema->schema_cookie = (int)pIn3->u.i; | |
| 77418 | + pDb->pSchema->schema_cookie = pOp->p3; | |
| 77188 | 77419 | db->flags |= SQLITE_InternChanges; |
| 77189 | 77420 | }else if( pOp->p2==BTREE_FILE_FORMAT ){ |
| 77190 | 77421 | /* Record changes in the file format */ |
| 77191 | - pDb->pSchema->file_format = (u8)pIn3->u.i; | |
| 77422 | + pDb->pSchema->file_format = pOp->p3; | |
| 77192 | 77423 | } |
| 77193 | 77424 | if( pOp->p1==1 ){ |
| 77194 | 77425 | /* Invalidate all prepared statements whenever the TEMP database |
| 77195 | 77426 | ** schema is changed. Ticket #1644 */ |
| 77196 | 77427 | sqlite3ExpirePreparedStatements(db); |
| @@ -77346,10 +77577,13 @@ | ||
| 77346 | 77577 | pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); |
| 77347 | 77578 | if( pCur==0 ) goto no_mem; |
| 77348 | 77579 | pCur->nullRow = 1; |
| 77349 | 77580 | pCur->isOrdered = 1; |
| 77350 | 77581 | pCur->pgnoRoot = p2; |
| 77582 | +#ifdef SQLITE_DEBUG | |
| 77583 | + pCur->wrFlag = wrFlag; | |
| 77584 | +#endif | |
| 77351 | 77585 | rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); |
| 77352 | 77586 | pCur->pKeyInfo = pKeyInfo; |
| 77353 | 77587 | /* Set the VdbeCursor.isTable variable. Previous versions of |
| 77354 | 77588 | ** SQLite used to check if the root-page flags were sane at this point |
| 77355 | 77589 | ** and report database corruption if they were not, but this check has |
| @@ -77799,36 +78033,10 @@ | ||
| 77799 | 78033 | assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); |
| 77800 | 78034 | pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ |
| 77801 | 78035 | } |
| 77802 | 78036 | break; |
| 77803 | 78037 | } |
| 77804 | - | |
| 77805 | -/* Opcode: Seek P1 P2 * * * | |
| 77806 | -** Synopsis: intkey=r[P2] | |
| 77807 | -** | |
| 77808 | -** P1 is an open table cursor and P2 is a rowid integer. Arrange | |
| 77809 | -** for P1 to move so that it points to the rowid given by P2. | |
| 77810 | -** | |
| 77811 | -** This is actually a deferred seek. Nothing actually happens until | |
| 77812 | -** the cursor is used to read a record. That way, if no reads | |
| 77813 | -** occur, no unnecessary I/O happens. | |
| 77814 | -*/ | |
| 77815 | -case OP_Seek: { /* in2 */ | |
| 77816 | - VdbeCursor *pC; | |
| 77817 | - | |
| 77818 | - assert( pOp->p1>=0 && pOp->p1<p->nCursor ); | |
| 77819 | - pC = p->apCsr[pOp->p1]; | |
| 77820 | - assert( pC!=0 ); | |
| 77821 | - assert( pC->eCurType==CURTYPE_BTREE ); | |
| 77822 | - assert( pC->uc.pCursor!=0 ); | |
| 77823 | - assert( pC->isTable ); | |
| 77824 | - pC->nullRow = 0; | |
| 77825 | - pIn2 = &aMem[pOp->p2]; | |
| 77826 | - pC->movetoTarget = sqlite3VdbeIntValue(pIn2); | |
| 77827 | - pC->deferredMoveto = 1; | |
| 77828 | - break; | |
| 77829 | -} | |
| 77830 | 78038 | |
| 77831 | 78039 | |
| 77832 | 78040 | /* Opcode: Found P1 P2 P3 P4 * |
| 77833 | 78041 | ** Synopsis: key=r[P3@P4] |
| 77834 | 78042 | ** |
| @@ -78295,18 +78503,26 @@ | ||
| 78295 | 78503 | |
| 78296 | 78504 | /* Opcode: Delete P1 P2 * P4 P5 |
| 78297 | 78505 | ** |
| 78298 | 78506 | ** Delete the record at which the P1 cursor is currently pointing. |
| 78299 | 78507 | ** |
| 78300 | -** If the P5 parameter is non-zero, the cursor will be left pointing at | |
| 78301 | -** either the next or the previous record in the table. If it is left | |
| 78302 | -** pointing at the next record, then the next Next instruction will be a | |
| 78303 | -** no-op. As a result, in this case it is OK to delete a record from within a | |
| 78304 | -** Next loop. If P5 is zero, then the cursor is left in an undefined state. | |
| 78508 | +** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then | |
| 78509 | +** the cursor will be left pointing at either the next or the previous | |
| 78510 | +** record in the table. If it is left pointing at the next record, then | |
| 78511 | +** the next Next instruction will be a no-op. As a result, in this case | |
| 78512 | +** it is ok to delete a record from within a Next loop. If | |
| 78513 | +** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be | |
| 78514 | +** left in an undefined state. | |
| 78305 | 78515 | ** |
| 78306 | -** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is | |
| 78307 | -** incremented (otherwise not). | |
| 78516 | +** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this | |
| 78517 | +** delete one of several associated with deleting a table row and all its | |
| 78518 | +** associated index entries. Exactly one of those deletes is the "primary" | |
| 78519 | +** delete. The others are all on OPFLAG_FORDELETE cursors or else are | |
| 78520 | +** marked with the AUXDELETE flag. | |
| 78521 | +** | |
| 78522 | +** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row | |
| 78523 | +** change count is incremented (otherwise not). | |
| 78308 | 78524 | ** |
| 78309 | 78525 | ** P1 must not be pseudo-table. It has to be a real table with |
| 78310 | 78526 | ** multiple rows. |
| 78311 | 78527 | ** |
| 78312 | 78528 | ** If P4 is not NULL, then it is the name of the table that P1 is |
| @@ -78338,11 +78554,30 @@ | ||
| 78338 | 78554 | i64 iKey = 0; |
| 78339 | 78555 | sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); |
| 78340 | 78556 | assert( pC->movetoTarget==iKey ); |
| 78341 | 78557 | } |
| 78342 | 78558 | #endif |
| 78343 | - | |
| 78559 | + | |
| 78560 | + /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ | |
| 78561 | + assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); | |
| 78562 | + assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); | |
| 78563 | + assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); | |
| 78564 | + | |
| 78565 | +#ifdef SQLITE_DEBUG | |
| 78566 | + if( p->pFrame==0 ){ | |
| 78567 | + if( pC->isEphemeral==0 | |
| 78568 | + && (pOp->p5 & OPFLAG_AUXDELETE)==0 | |
| 78569 | + && (pC->wrFlag & OPFLAG_FORDELETE)==0 | |
| 78570 | + ){ | |
| 78571 | + nExtraDelete++; | |
| 78572 | + } | |
| 78573 | + if( pOp->p2 & OPFLAG_NCHANGE ){ | |
| 78574 | + nExtraDelete--; | |
| 78575 | + } | |
| 78576 | + } | |
| 78577 | +#endif | |
| 78578 | + | |
| 78344 | 78579 | rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); |
| 78345 | 78580 | pC->cacheStatus = CACHE_STALE; |
| 78346 | 78581 | |
| 78347 | 78582 | /* Invoke the update-hook if required. */ |
| 78348 | 78583 | if( rc==SQLITE_OK && hasUpdateCallback ){ |
| @@ -78883,62 +79118,98 @@ | ||
| 78883 | 79118 | assert( pOp->p5==0 ); |
| 78884 | 79119 | r.pKeyInfo = pC->pKeyInfo; |
| 78885 | 79120 | r.nField = (u16)pOp->p3; |
| 78886 | 79121 | r.default_rc = 0; |
| 78887 | 79122 | r.aMem = &aMem[pOp->p2]; |
| 78888 | -#ifdef SQLITE_DEBUG | |
| 78889 | - { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } | |
| 78890 | -#endif | |
| 78891 | 79123 | rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); |
| 78892 | 79124 | if( rc==SQLITE_OK && res==0 ){ |
| 78893 | - rc = sqlite3BtreeDelete(pCrsr, 0); | |
| 79125 | + rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); | |
| 78894 | 79126 | } |
| 78895 | 79127 | assert( pC->deferredMoveto==0 ); |
| 78896 | 79128 | pC->cacheStatus = CACHE_STALE; |
| 78897 | 79129 | break; |
| 78898 | 79130 | } |
| 78899 | 79131 | |
| 79132 | +/* Opcode: Seek P1 * P3 P4 * | |
| 79133 | +** Synopsis: Move P3 to P1.rowid | |
| 79134 | +** | |
| 79135 | +** P1 is an open index cursor and P3 is a cursor on the corresponding | |
| 79136 | +** table. This opcode does a deferred seek of the P3 table cursor | |
| 79137 | +** to the row that corresponds to the current row of P1. | |
| 79138 | +** | |
| 79139 | +** This is a deferred seek. Nothing actually happens until | |
| 79140 | +** the cursor is used to read a record. That way, if no reads | |
| 79141 | +** occur, no unnecessary I/O happens. | |
| 79142 | +** | |
| 79143 | +** P4 may be an array of integers (type P4_INTARRAY) containing | |
| 79144 | +** one entry for each column in the P3 table. If array entry a(i) | |
| 79145 | +** is non-zero, then reading column a(i)-1 from cursor P3 is | |
| 79146 | +** equivalent to performing the deferred seek and then reading column i | |
| 79147 | +** from P1. This information is stored in P3 and used to redirect | |
| 79148 | +** reads against P3 over to P1, thus possibly avoiding the need to | |
| 79149 | +** seek and read cursor P3. | |
| 79150 | +*/ | |
| 78900 | 79151 | /* Opcode: IdxRowid P1 P2 * * * |
| 78901 | 79152 | ** Synopsis: r[P2]=rowid |
| 78902 | 79153 | ** |
| 78903 | 79154 | ** Write into register P2 an integer which is the last entry in the record at |
| 78904 | 79155 | ** the end of the index key pointed to by cursor P1. This integer should be |
| 78905 | 79156 | ** the rowid of the table entry to which this index entry points. |
| 78906 | 79157 | ** |
| 78907 | 79158 | ** See also: Rowid, MakeRecord. |
| 78908 | 79159 | */ |
| 79160 | +case OP_Seek: | |
| 78909 | 79161 | case OP_IdxRowid: { /* out2 */ |
| 78910 | - BtCursor *pCrsr; | |
| 78911 | - VdbeCursor *pC; | |
| 78912 | - i64 rowid; | |
| 79162 | + VdbeCursor *pC; /* The P1 index cursor */ | |
| 79163 | + VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */ | |
| 79164 | + i64 rowid; /* Rowid that P1 current points to */ | |
| 78913 | 79165 | |
| 78914 | - pOut = out2Prerelease(p, pOp); | |
| 78915 | 79166 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 78916 | 79167 | pC = p->apCsr[pOp->p1]; |
| 78917 | 79168 | assert( pC!=0 ); |
| 78918 | 79169 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 78919 | - pCrsr = pC->uc.pCursor; | |
| 78920 | - assert( pCrsr!=0 ); | |
| 78921 | - pOut->flags = MEM_Null; | |
| 79170 | + assert( pC->uc.pCursor!=0 ); | |
| 78922 | 79171 | assert( pC->isTable==0 ); |
| 78923 | 79172 | assert( pC->deferredMoveto==0 ); |
| 79173 | + assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); | |
| 79174 | + | |
| 79175 | + /* The IdxRowid and Seek opcodes are combined because of the commonality | |
| 79176 | + ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ | |
| 79177 | + rc = sqlite3VdbeCursorRestore(pC); | |
| 78924 | 79178 | |
| 78925 | 79179 | /* sqlite3VbeCursorRestore() can only fail if the record has been deleted |
| 78926 | - ** out from under the cursor. That will never happend for an IdxRowid | |
| 78927 | - ** opcode, hence the NEVER() arround the check of the return value. | |
| 78928 | - */ | |
| 78929 | - rc = sqlite3VdbeCursorRestore(pC); | |
| 79180 | + ** out from under the cursor. That will never happens for an IdxRowid | |
| 79181 | + ** or Seek opcode */ | |
| 78930 | 79182 | if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; |
| 78931 | 79183 | |
| 78932 | 79184 | if( !pC->nullRow ){ |
| 78933 | 79185 | rowid = 0; /* Not needed. Only used to silence a warning. */ |
| 78934 | - rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); | |
| 79186 | + rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid); | |
| 78935 | 79187 | if( rc!=SQLITE_OK ){ |
| 78936 | 79188 | goto abort_due_to_error; |
| 78937 | 79189 | } |
| 78938 | - pOut->u.i = rowid; | |
| 78939 | - pOut->flags = MEM_Int; | |
| 79190 | + if( pOp->opcode==OP_Seek ){ | |
| 79191 | + assert( pOp->p3>=0 && pOp->p3<p->nCursor ); | |
| 79192 | + pTabCur = p->apCsr[pOp->p3]; | |
| 79193 | + assert( pTabCur!=0 ); | |
| 79194 | + assert( pTabCur->eCurType==CURTYPE_BTREE ); | |
| 79195 | + assert( pTabCur->uc.pCursor!=0 ); | |
| 79196 | + assert( pTabCur->isTable ); | |
| 79197 | + pTabCur->nullRow = 0; | |
| 79198 | + pTabCur->movetoTarget = rowid; | |
| 79199 | + pTabCur->deferredMoveto = 1; | |
| 79200 | + assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); | |
| 79201 | + pTabCur->aAltMap = pOp->p4.ai; | |
| 79202 | + pTabCur->pAltCursor = pC; | |
| 79203 | + }else{ | |
| 79204 | + pOut = out2Prerelease(p, pOp); | |
| 79205 | + pOut->u.i = rowid; | |
| 79206 | + pOut->flags = MEM_Int; | |
| 79207 | + } | |
| 79208 | + }else{ | |
| 79209 | + assert( pOp->opcode==OP_IdxRowid ); | |
| 79210 | + sqlite3VdbeMemSetNull(&aMem[pOp->p2]); | |
| 78940 | 79211 | } |
| 78941 | 79212 | break; |
| 78942 | 79213 | } |
| 78943 | 79214 | |
| 78944 | 79215 | /* Opcode: IdxGE P1 P2 P3 P4 P5 |
| @@ -79329,11 +79600,11 @@ | ||
| 79329 | 79600 | Mem *pnErr; /* Register keeping track of errors remaining */ |
| 79330 | 79601 | |
| 79331 | 79602 | assert( p->bIsReader ); |
| 79332 | 79603 | nRoot = pOp->p2; |
| 79333 | 79604 | assert( nRoot>0 ); |
| 79334 | - aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); | |
| 79605 | + aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(nRoot+1) ); | |
| 79335 | 79606 | if( aRoot==0 ) goto no_mem; |
| 79336 | 79607 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 79337 | 79608 | pnErr = &aMem[pOp->p3]; |
| 79338 | 79609 | assert( (pnErr->flags & MEM_Int)!=0 ); |
| 79339 | 79610 | assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); |
| @@ -79711,24 +79982,35 @@ | ||
| 79711 | 79982 | goto jump_to_p2; |
| 79712 | 79983 | } |
| 79713 | 79984 | break; |
| 79714 | 79985 | } |
| 79715 | 79986 | |
| 79716 | -/* Opcode: SetIfNotPos P1 P2 P3 * * | |
| 79717 | -** Synopsis: if r[P1]<=0 then r[P2]=P3 | |
| 79987 | +/* Opcode: OffsetLimit P1 P2 P3 * * | |
| 79988 | +** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) | |
| 79718 | 79989 | ** |
| 79719 | -** Register P1 must contain an integer. | |
| 79720 | -** If the value of register P1 is not positive (if it is less than 1) then | |
| 79721 | -** set the value of register P2 to be the integer P3. | |
| 79990 | +** This opcode performs a commonly used computation associated with | |
| 79991 | +** LIMIT and OFFSET process. r[P1] holds the limit counter. r[P3] | |
| 79992 | +** holds the offset counter. The opcode computes the combined value | |
| 79993 | +** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2] | |
| 79994 | +** value computed is the total number of rows that will need to be | |
| 79995 | +** visited in order to complete the query. | |
| 79996 | +** | |
| 79997 | +** If r[P3] is zero or negative, that means there is no OFFSET | |
| 79998 | +** and r[P2] is set to be the value of the LIMIT, r[P1]. | |
| 79999 | +** | |
| 80000 | +** if r[P1] is zero or negative, that means there is no LIMIT | |
| 80001 | +** and r[P2] is set to -1. | |
| 80002 | +** | |
| 80003 | +** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. | |
| 79722 | 80004 | */ |
| 79723 | -case OP_SetIfNotPos: { /* in1, in2 */ | |
| 80005 | +case OP_OffsetLimit: { /* in1, out2, in3 */ | |
| 79724 | 80006 | pIn1 = &aMem[pOp->p1]; |
| 79725 | - assert( pIn1->flags&MEM_Int ); | |
| 79726 | - if( pIn1->u.i<=0 ){ | |
| 79727 | - pOut = out2Prerelease(p, pOp); | |
| 79728 | - pOut->u.i = pOp->p3; | |
| 79729 | - } | |
| 80007 | + pIn3 = &aMem[pOp->p3]; | |
| 80008 | + pOut = out2Prerelease(p, pOp); | |
| 80009 | + assert( pIn1->flags & MEM_Int ); | |
| 80010 | + assert( pIn3->flags & MEM_Int ); | |
| 80011 | + pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0); | |
| 79730 | 80012 | break; |
| 79731 | 80013 | } |
| 79732 | 80014 | |
| 79733 | 80015 | /* Opcode: IfNotZero P1 P2 P3 * * |
| 79734 | 80016 | ** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 |
| @@ -79815,11 +80097,11 @@ | ||
| 79815 | 80097 | assert( pOp->p4type==P4_FUNCDEF ); |
| 79816 | 80098 | n = pOp->p5; |
| 79817 | 80099 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 79818 | 80100 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 79819 | 80101 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 79820 | - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); | |
| 80102 | + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); | |
| 79821 | 80103 | if( pCtx==0 ) goto no_mem; |
| 79822 | 80104 | pCtx->pMem = 0; |
| 79823 | 80105 | pCtx->pFunc = pOp->p4.pFunc; |
| 79824 | 80106 | pCtx->iOp = (int)(pOp - aOp); |
| 79825 | 80107 | pCtx->pVdbe = p; |
| @@ -80682,11 +80964,11 @@ | ||
| 80682 | 80964 | p->rc = rc; |
| 80683 | 80965 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 80684 | 80966 | sqlite3_log(rc, "statement aborts at %d: [%s] %s", |
| 80685 | 80967 | (int)(pOp - aOp), p->zSql, p->zErrMsg); |
| 80686 | 80968 | sqlite3VdbeHalt(p); |
| 80687 | - if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; | |
| 80969 | + if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); | |
| 80688 | 80970 | rc = SQLITE_ERROR; |
| 80689 | 80971 | if( resetSchemaOnFault>0 ){ |
| 80690 | 80972 | sqlite3ResetOneSchema(db, resetSchemaOnFault-1); |
| 80691 | 80973 | } |
| 80692 | 80974 | |
| @@ -80696,10 +80978,13 @@ | ||
| 80696 | 80978 | vdbe_return: |
| 80697 | 80979 | db->lastRowid = lastRowid; |
| 80698 | 80980 | testcase( nVmStep>0 ); |
| 80699 | 80981 | p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; |
| 80700 | 80982 | sqlite3VdbeLeave(p); |
| 80983 | + assert( rc!=SQLITE_OK || nExtraDelete==0 | |
| 80984 | + || sqlite3_strlike("DELETE%",p->zSql,0)!=0 | |
| 80985 | + ); | |
| 80701 | 80986 | return rc; |
| 80702 | 80987 | |
| 80703 | 80988 | /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH |
| 80704 | 80989 | ** is encountered. |
| 80705 | 80990 | */ |
| @@ -80709,11 +80994,11 @@ | ||
| 80709 | 80994 | goto vdbe_error_halt; |
| 80710 | 80995 | |
| 80711 | 80996 | /* Jump to here if a malloc() fails. |
| 80712 | 80997 | */ |
| 80713 | 80998 | no_mem: |
| 80714 | - db->mallocFailed = 1; | |
| 80999 | + sqlite3OomFault(db); | |
| 80715 | 81000 | sqlite3VdbeError(p, "out of memory"); |
| 80716 | 81001 | rc = SQLITE_NOMEM; |
| 80717 | 81002 | goto vdbe_error_halt; |
| 80718 | 81003 | |
| 80719 | 81004 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| @@ -80730,11 +81015,11 @@ | ||
| 80730 | 81015 | /* Jump to here if the sqlite3_interrupt() API sets the interrupt |
| 80731 | 81016 | ** flag. |
| 80732 | 81017 | */ |
| 80733 | 81018 | abort_due_to_interrupt: |
| 80734 | 81019 | assert( db->u1.isInterrupted ); |
| 80735 | - rc = SQLITE_INTERRUPT; | |
| 81020 | + rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_INTERRUPT; | |
| 80736 | 81021 | p->rc = rc; |
| 80737 | 81022 | sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); |
| 80738 | 81023 | goto vdbe_error_halt; |
| 80739 | 81024 | } |
| 80740 | 81025 | |
| @@ -80990,23 +81275,21 @@ | ||
| 80990 | 81275 | ** |
| 80991 | 81276 | ** The sqlite3_blob_close() function finalizes the vdbe program, |
| 80992 | 81277 | ** which closes the b-tree cursor and (possibly) commits the |
| 80993 | 81278 | ** transaction. |
| 80994 | 81279 | */ |
| 80995 | - static const int iLn = VDBE_OFFSET_LINENO(4); | |
| 81280 | + static const int iLn = VDBE_OFFSET_LINENO(2); | |
| 80996 | 81281 | static const VdbeOpList openBlob[] = { |
| 80997 | - /* addr/ofst */ | |
| 80998 | - /* {OP_Transaction, 0, 0, 0}, // 0/ inserted separately */ | |
| 80999 | - {OP_TableLock, 0, 0, 0}, /* 1/0: Acquire a read or write lock */ | |
| 81000 | - {OP_OpenRead, 0, 0, 0}, /* 2/1: Open a cursor */ | |
| 81001 | - {OP_Variable, 1, 1, 0}, /* 3/2: Move ?1 into reg[1] */ | |
| 81002 | - {OP_NotExists, 0, 8, 1}, /* 4/3: Seek the cursor */ | |
| 81003 | - {OP_Column, 0, 0, 1}, /* 5/4 */ | |
| 81004 | - {OP_ResultRow, 1, 0, 0}, /* 6/5 */ | |
| 81005 | - {OP_Goto, 0, 3, 0}, /* 7/6 */ | |
| 81006 | - {OP_Close, 0, 0, 0}, /* 8/7 */ | |
| 81007 | - {OP_Halt, 0, 0, 0}, /* 9/8 */ | |
| 81282 | + {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ | |
| 81283 | + {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ | |
| 81284 | + {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */ | |
| 81285 | + {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */ | |
| 81286 | + {OP_Column, 0, 0, 1}, /* 4 */ | |
| 81287 | + {OP_ResultRow, 1, 0, 0}, /* 5 */ | |
| 81288 | + {OP_Goto, 0, 2, 0}, /* 6 */ | |
| 81289 | + {OP_Close, 0, 0, 0}, /* 7 */ | |
| 81290 | + {OP_Halt, 0, 0, 0}, /* 8 */ | |
| 81008 | 81291 | }; |
| 81009 | 81292 | Vdbe *v = (Vdbe *)pBlob->pStmt; |
| 81010 | 81293 | int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 81011 | 81294 | VdbeOp *aOp; |
| 81012 | 81295 | |
| @@ -83044,27 +83327,28 @@ | ||
| 83044 | 83327 | if( pSorter->list.aMemory ){ |
| 83045 | 83328 | int nMin = pSorter->iMemory + nReq; |
| 83046 | 83329 | |
| 83047 | 83330 | if( nMin>pSorter->nMemory ){ |
| 83048 | 83331 | u8 *aNew; |
| 83332 | + int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; | |
| 83049 | 83333 | int nNew = pSorter->nMemory * 2; |
| 83050 | 83334 | while( nNew < nMin ) nNew = nNew*2; |
| 83051 | 83335 | if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; |
| 83052 | 83336 | if( nNew < nMin ) nNew = nMin; |
| 83053 | 83337 | |
| 83054 | 83338 | aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); |
| 83055 | 83339 | if( !aNew ) return SQLITE_NOMEM; |
| 83056 | - pSorter->list.pList = (SorterRecord*)( | |
| 83057 | - aNew + ((u8*)pSorter->list.pList - pSorter->list.aMemory) | |
| 83058 | - ); | |
| 83340 | + pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; | |
| 83059 | 83341 | pSorter->list.aMemory = aNew; |
| 83060 | 83342 | pSorter->nMemory = nNew; |
| 83061 | 83343 | } |
| 83062 | 83344 | |
| 83063 | 83345 | pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; |
| 83064 | 83346 | pSorter->iMemory += ROUND8(nReq); |
| 83065 | - pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); | |
| 83347 | + if( pSorter->list.pList ){ | |
| 83348 | + pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); | |
| 83349 | + } | |
| 83066 | 83350 | }else{ |
| 83067 | 83351 | pNew = (SorterRecord *)sqlite3Malloc(nReq); |
| 83068 | 83352 | if( pNew==0 ){ |
| 83069 | 83353 | return SQLITE_NOMEM; |
| 83070 | 83354 | } |
| @@ -86230,12 +86514,11 @@ | ||
| 86230 | 86514 | return pExpr; |
| 86231 | 86515 | } |
| 86232 | 86516 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
| 86233 | 86517 | Token s; |
| 86234 | 86518 | assert( zC!=0 ); |
| 86235 | - s.z = zC; | |
| 86236 | - s.n = sqlite3Strlen30(s.z); | |
| 86519 | + sqlite3TokenInit(&s, (char*)zC); | |
| 86237 | 86520 | return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); |
| 86238 | 86521 | } |
| 86239 | 86522 | |
| 86240 | 86523 | /* |
| 86241 | 86524 | ** Skip over any TK_COLLATE operators and any unlikely() |
| @@ -86599,18 +86882,19 @@ | ||
| 86599 | 86882 | ){ |
| 86600 | 86883 | Expr *pNew; |
| 86601 | 86884 | int nExtra = 0; |
| 86602 | 86885 | int iValue = 0; |
| 86603 | 86886 | |
| 86887 | + assert( db!=0 ); | |
| 86604 | 86888 | if( pToken ){ |
| 86605 | 86889 | if( op!=TK_INTEGER || pToken->z==0 |
| 86606 | 86890 | || sqlite3GetInt32(pToken->z, &iValue)==0 ){ |
| 86607 | 86891 | nExtra = pToken->n+1; |
| 86608 | 86892 | assert( iValue>=0 ); |
| 86609 | 86893 | } |
| 86610 | 86894 | } |
| 86611 | - pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra); | |
| 86895 | + pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); | |
| 86612 | 86896 | if( pNew ){ |
| 86613 | 86897 | memset(pNew, 0, sizeof(Expr)); |
| 86614 | 86898 | pNew->op = (u8)op; |
| 86615 | 86899 | pNew->iAgg = -1; |
| 86616 | 86900 | if( pToken ){ |
| @@ -86845,11 +87129,14 @@ | ||
| 86845 | 87129 | } |
| 86846 | 87130 | if( x>0 ){ |
| 86847 | 87131 | if( x>pParse->nzVar ){ |
| 86848 | 87132 | char **a; |
| 86849 | 87133 | a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); |
| 86850 | - if( a==0 ) return; /* Error reported through db->mallocFailed */ | |
| 87134 | + if( a==0 ){ | |
| 87135 | + assert( db->mallocFailed ); /* Error reported through mallocFailed */ | |
| 87136 | + return; | |
| 87137 | + } | |
| 86851 | 87138 | pParse->azVar = a; |
| 86852 | 87139 | memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); |
| 86853 | 87140 | pParse->nzVar = x; |
| 86854 | 87141 | } |
| 86855 | 87142 | if( z[0]!='?' || pParse->azVar[x-1]==0 ){ |
| @@ -87000,10 +87287,11 @@ | ||
| 87000 | 87287 | ** portion of the buffer copied into by this function. |
| 87001 | 87288 | */ |
| 87002 | 87289 | static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ |
| 87003 | 87290 | Expr *pNew = 0; /* Value to return */ |
| 87004 | 87291 | assert( flags==0 || flags==EXPRDUP_REDUCE ); |
| 87292 | + assert( db!=0 ); | |
| 87005 | 87293 | if( p ){ |
| 87006 | 87294 | const int isReduced = (flags&EXPRDUP_REDUCE); |
| 87007 | 87295 | u8 *zAlloc; |
| 87008 | 87296 | u32 staticFlag = 0; |
| 87009 | 87297 | |
| @@ -87012,11 +87300,11 @@ | ||
| 87012 | 87300 | /* Figure out where to write the new Expr structure. */ |
| 87013 | 87301 | if( pzBuffer ){ |
| 87014 | 87302 | zAlloc = *pzBuffer; |
| 87015 | 87303 | staticFlag = EP_Static; |
| 87016 | 87304 | }else{ |
| 87017 | - zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); | |
| 87305 | + zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, flags)); | |
| 87018 | 87306 | } |
| 87019 | 87307 | pNew = (Expr *)zAlloc; |
| 87020 | 87308 | |
| 87021 | 87309 | if( pNew ){ |
| 87022 | 87310 | /* Set nNewSize to the size allocated for the structure pointed to |
| @@ -87135,16 +87423,17 @@ | ||
| 87135 | 87423 | } |
| 87136 | 87424 | SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ |
| 87137 | 87425 | ExprList *pNew; |
| 87138 | 87426 | struct ExprList_item *pItem, *pOldItem; |
| 87139 | 87427 | int i; |
| 87428 | + assert( db!=0 ); | |
| 87140 | 87429 | if( p==0 ) return 0; |
| 87141 | - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); | |
| 87430 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); | |
| 87142 | 87431 | if( pNew==0 ) return 0; |
| 87143 | 87432 | pNew->nExpr = i = p->nExpr; |
| 87144 | 87433 | if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){} |
| 87145 | - pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) ); | |
| 87434 | + pNew->a = pItem = sqlite3DbMallocRawNN(db, i*sizeof(p->a[0]) ); | |
| 87146 | 87435 | if( pItem==0 ){ |
| 87147 | 87436 | sqlite3DbFree(db, pNew); |
| 87148 | 87437 | return 0; |
| 87149 | 87438 | } |
| 87150 | 87439 | pOldItem = p->a; |
| @@ -87171,13 +87460,14 @@ | ||
| 87171 | 87460 | || !defined(SQLITE_OMIT_SUBQUERY) |
| 87172 | 87461 | SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ |
| 87173 | 87462 | SrcList *pNew; |
| 87174 | 87463 | int i; |
| 87175 | 87464 | int nByte; |
| 87465 | + assert( db!=0 ); | |
| 87176 | 87466 | if( p==0 ) return 0; |
| 87177 | 87467 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); |
| 87178 | - pNew = sqlite3DbMallocRaw(db, nByte ); | |
| 87468 | + pNew = sqlite3DbMallocRawNN(db, nByte ); | |
| 87179 | 87469 | if( pNew==0 ) return 0; |
| 87180 | 87470 | pNew->nSrc = pNew->nAlloc = p->nSrc; |
| 87181 | 87471 | for(i=0; i<p->nSrc; i++){ |
| 87182 | 87472 | struct SrcList_item *pNewItem = &pNew->a[i]; |
| 87183 | 87473 | struct SrcList_item *pOldItem = &p->a[i]; |
| @@ -87210,15 +87500,16 @@ | ||
| 87210 | 87500 | return pNew; |
| 87211 | 87501 | } |
| 87212 | 87502 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ |
| 87213 | 87503 | IdList *pNew; |
| 87214 | 87504 | int i; |
| 87505 | + assert( db!=0 ); | |
| 87215 | 87506 | if( p==0 ) return 0; |
| 87216 | - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); | |
| 87507 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); | |
| 87217 | 87508 | if( pNew==0 ) return 0; |
| 87218 | 87509 | pNew->nId = p->nId; |
| 87219 | - pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); | |
| 87510 | + pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) ); | |
| 87220 | 87511 | if( pNew->a==0 ){ |
| 87221 | 87512 | sqlite3DbFree(db, pNew); |
| 87222 | 87513 | return 0; |
| 87223 | 87514 | } |
| 87224 | 87515 | /* Note that because the size of the allocation for p->a[] is not |
| @@ -87232,12 +87523,13 @@ | ||
| 87232 | 87523 | } |
| 87233 | 87524 | return pNew; |
| 87234 | 87525 | } |
| 87235 | 87526 | SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ |
| 87236 | 87527 | Select *pNew, *pPrior; |
| 87528 | + assert( db!=0 ); | |
| 87237 | 87529 | if( p==0 ) return 0; |
| 87238 | - pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); | |
| 87530 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); | |
| 87239 | 87531 | if( pNew==0 ) return 0; |
| 87240 | 87532 | pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); |
| 87241 | 87533 | pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); |
| 87242 | 87534 | pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); |
| 87243 | 87535 | pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); |
| @@ -87279,17 +87571,18 @@ | ||
| 87279 | 87571 | Parse *pParse, /* Parsing context */ |
| 87280 | 87572 | ExprList *pList, /* List to which to append. Might be NULL */ |
| 87281 | 87573 | Expr *pExpr /* Expression to be appended. Might be NULL */ |
| 87282 | 87574 | ){ |
| 87283 | 87575 | sqlite3 *db = pParse->db; |
| 87576 | + assert( db!=0 ); | |
| 87284 | 87577 | if( pList==0 ){ |
| 87285 | - pList = sqlite3DbMallocRaw(db, sizeof(ExprList) ); | |
| 87578 | + pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) ); | |
| 87286 | 87579 | if( pList==0 ){ |
| 87287 | 87580 | goto no_mem; |
| 87288 | 87581 | } |
| 87289 | 87582 | pList->nExpr = 0; |
| 87290 | - pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0])); | |
| 87583 | + pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0])); | |
| 87291 | 87584 | if( pList->a==0 ) goto no_mem; |
| 87292 | 87585 | }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ |
| 87293 | 87586 | struct ExprList_item *a; |
| 87294 | 87587 | assert( pList->nExpr>0 ); |
| 87295 | 87588 | a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0])); |
| @@ -91009,11 +91302,11 @@ | ||
| 91009 | 91302 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); |
| 91010 | 91303 | sqlite3VdbeUsesBtree(v, iDb); |
| 91011 | 91304 | sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); |
| 91012 | 91305 | addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); |
| 91013 | 91306 | sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); |
| 91014 | - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); | |
| 91307 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, minFormat); | |
| 91015 | 91308 | sqlite3VdbeJumpHere(v, addr1); |
| 91016 | 91309 | sqlite3ReleaseTempReg(pParse, r1); |
| 91017 | 91310 | sqlite3ReleaseTempReg(pParse, r2); |
| 91018 | 91311 | } |
| 91019 | 91312 | } |
| @@ -91096,11 +91389,11 @@ | ||
| 91096 | 91389 | sqlite3_value *pVal = 0; |
| 91097 | 91390 | int rc; |
| 91098 | 91391 | rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); |
| 91099 | 91392 | assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); |
| 91100 | 91393 | if( rc!=SQLITE_OK ){ |
| 91101 | - db->mallocFailed = 1; | |
| 91394 | + assert( db->mallocFailed == 1 ); | |
| 91102 | 91395 | return; |
| 91103 | 91396 | } |
| 91104 | 91397 | if( !pVal ){ |
| 91105 | 91398 | sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); |
| 91106 | 91399 | return; |
| @@ -91204,11 +91497,11 @@ | ||
| 91204 | 91497 | nAlloc = (((pNew->nCol-1)/8)*8)+8; |
| 91205 | 91498 | assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); |
| 91206 | 91499 | pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); |
| 91207 | 91500 | pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); |
| 91208 | 91501 | if( !pNew->aCol || !pNew->zName ){ |
| 91209 | - db->mallocFailed = 1; | |
| 91502 | + assert( db->mallocFailed ); | |
| 91210 | 91503 | goto exit_begin_add_column; |
| 91211 | 91504 | } |
| 91212 | 91505 | memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); |
| 91213 | 91506 | for(i=0; i<pNew->nCol; i++){ |
| 91214 | 91507 | Column *pCol = &pNew->aCol[i]; |
| @@ -91549,11 +91842,11 @@ | ||
| 91549 | 91842 | */ |
| 91550 | 91843 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 91551 | 91844 | static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ |
| 91552 | 91845 | assert( db!=0 ); |
| 91553 | 91846 | if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); |
| 91554 | - p->u.aRowid = sqlite3DbMallocRaw(db, n); | |
| 91847 | + p->u.aRowid = sqlite3DbMallocRawNN(db, n); | |
| 91555 | 91848 | if( p->u.aRowid ){ |
| 91556 | 91849 | p->nRowid = n; |
| 91557 | 91850 | memcpy(p->u.aRowid, pData, n); |
| 91558 | 91851 | }else{ |
| 91559 | 91852 | p->nRowid = 0; |
| @@ -92351,11 +92644,11 @@ | ||
| 92351 | 92644 | addrNextRow = sqlite3VdbeCurrentAddr(v); |
| 92352 | 92645 | |
| 92353 | 92646 | if( nColTest>0 ){ |
| 92354 | 92647 | int endDistinctTest = sqlite3VdbeMakeLabel(v); |
| 92355 | 92648 | int *aGotoChng; /* Array of jump instruction addresses */ |
| 92356 | - aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest); | |
| 92649 | + aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest); | |
| 92357 | 92650 | if( aGotoChng==0 ) continue; |
| 92358 | 92651 | |
| 92359 | 92652 | /* |
| 92360 | 92653 | ** next_row: |
| 92361 | 92654 | ** regChng = 0 |
| @@ -92759,11 +93052,11 @@ | ||
| 92759 | 93052 | /* Index.aiRowEst may already be set here if there are duplicate |
| 92760 | 93053 | ** sqlite_stat1 entries for this index. In that case just clobber |
| 92761 | 93054 | ** the old data with the new instead of allocating a new array. */ |
| 92762 | 93055 | if( pIndex->aiRowEst==0 ){ |
| 92763 | 93056 | pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); |
| 92764 | - if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; | |
| 93057 | + if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db); | |
| 92765 | 93058 | } |
| 92766 | 93059 | aiRowEst = pIndex->aiRowEst; |
| 92767 | 93060 | #endif |
| 92768 | 93061 | pIndex->bUnordered = 0; |
| 92769 | 93062 | decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); |
| @@ -92906,11 +93199,11 @@ | ||
| 92906 | 93199 | sqlite3_stmt *pStmt = 0; /* An SQL statement being run */ |
| 92907 | 93200 | char *zSql; /* Text of the SQL statement */ |
| 92908 | 93201 | Index *pPrevIdx = 0; /* Previous index in the loop */ |
| 92909 | 93202 | IndexSample *pSample; /* A slot in pIdx->aSample[] */ |
| 92910 | 93203 | |
| 92911 | - assert( db->lookaside.bEnabled==0 ); | |
| 93204 | + assert( db->lookaside.bDisable ); | |
| 92912 | 93205 | zSql = sqlite3MPrintf(db, zSql1, zDb); |
| 92913 | 93206 | if( !zSql ){ |
| 92914 | 93207 | return SQLITE_NOMEM; |
| 92915 | 93208 | } |
| 92916 | 93209 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| @@ -93020,11 +93313,11 @@ | ||
| 93020 | 93313 | ** the Index.aSample[] arrays of all indices. |
| 93021 | 93314 | */ |
| 93022 | 93315 | static int loadStat4(sqlite3 *db, const char *zDb){ |
| 93023 | 93316 | int rc = SQLITE_OK; /* Result codes from subroutines */ |
| 93024 | 93317 | |
| 93025 | - assert( db->lookaside.bEnabled==0 ); | |
| 93318 | + assert( db->lookaside.bDisable ); | |
| 93026 | 93319 | if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ |
| 93027 | 93320 | rc = loadStatTbl(db, 0, |
| 93028 | 93321 | "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", |
| 93029 | 93322 | "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", |
| 93030 | 93323 | zDb |
| @@ -93102,24 +93395,23 @@ | ||
| 93102 | 93395 | |
| 93103 | 93396 | |
| 93104 | 93397 | /* Load the statistics from the sqlite_stat4 table. */ |
| 93105 | 93398 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 93106 | 93399 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 93107 | - int lookasideEnabled = db->lookaside.bEnabled; | |
| 93108 | - db->lookaside.bEnabled = 0; | |
| 93400 | + db->lookaside.bDisable++; | |
| 93109 | 93401 | rc = loadStat4(db, sInfo.zDatabase); |
| 93110 | - db->lookaside.bEnabled = lookasideEnabled; | |
| 93402 | + db->lookaside.bDisable--; | |
| 93111 | 93403 | } |
| 93112 | 93404 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 93113 | 93405 | Index *pIdx = sqliteHashData(i); |
| 93114 | 93406 | sqlite3_free(pIdx->aiRowEst); |
| 93115 | 93407 | pIdx->aiRowEst = 0; |
| 93116 | 93408 | } |
| 93117 | 93409 | #endif |
| 93118 | 93410 | |
| 93119 | 93411 | if( rc==SQLITE_NOMEM ){ |
| 93120 | - db->mallocFailed = 1; | |
| 93412 | + sqlite3OomFault(db); | |
| 93121 | 93413 | } |
| 93122 | 93414 | return rc; |
| 93123 | 93415 | } |
| 93124 | 93416 | |
| 93125 | 93417 | |
| @@ -93236,11 +93528,11 @@ | ||
| 93236 | 93528 | |
| 93237 | 93529 | /* Allocate the new entry in the db->aDb[] array and initialize the schema |
| 93238 | 93530 | ** hash tables. |
| 93239 | 93531 | */ |
| 93240 | 93532 | if( db->aDb==db->aDbStatic ){ |
| 93241 | - aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); | |
| 93533 | + aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); | |
| 93242 | 93534 | if( aNew==0 ) return; |
| 93243 | 93535 | memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); |
| 93244 | 93536 | }else{ |
| 93245 | 93537 | aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); |
| 93246 | 93538 | if( aNew==0 ) return; |
| @@ -93254,11 +93546,11 @@ | ||
| 93254 | 93546 | ** or may not be initialized. |
| 93255 | 93547 | */ |
| 93256 | 93548 | flags = db->openFlags; |
| 93257 | 93549 | rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); |
| 93258 | 93550 | if( rc!=SQLITE_OK ){ |
| 93259 | - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; | |
| 93551 | + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); | |
| 93260 | 93552 | sqlite3_result_error(context, zErr, -1); |
| 93261 | 93553 | sqlite3_free(zErr); |
| 93262 | 93554 | return; |
| 93263 | 93555 | } |
| 93264 | 93556 | assert( pVfs ); |
| @@ -93283,11 +93575,12 @@ | ||
| 93283 | 93575 | pPager = sqlite3BtreePager(aNew->pBt); |
| 93284 | 93576 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 93285 | 93577 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 93286 | 93578 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 93287 | 93579 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 93288 | - sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); | |
| 93580 | + sqlite3BtreeSetPagerFlags(aNew->pBt, | |
| 93581 | + PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); | |
| 93289 | 93582 | #endif |
| 93290 | 93583 | sqlite3BtreeLeave(aNew->pBt); |
| 93291 | 93584 | } |
| 93292 | 93585 | aNew->safety_level = 3; |
| 93293 | 93586 | aNew->zName = sqlite3DbStrDup(db, zName); |
| @@ -93356,11 +93649,11 @@ | ||
| 93356 | 93649 | db->aDb[iDb].pSchema = 0; |
| 93357 | 93650 | } |
| 93358 | 93651 | sqlite3ResetAllSchemasOfConnection(db); |
| 93359 | 93652 | db->nDb = iDb; |
| 93360 | 93653 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 93361 | - db->mallocFailed = 1; | |
| 93654 | + sqlite3OomFault(db); | |
| 93362 | 93655 | sqlite3DbFree(db, zErrDyn); |
| 93363 | 93656 | zErrDyn = sqlite3MPrintf(db, "out of memory"); |
| 93364 | 93657 | }else if( zErrDyn==0 ){ |
| 93365 | 93658 | zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); |
| 93366 | 93659 | } |
| @@ -94053,11 +94346,11 @@ | ||
| 94053 | 94346 | p->iTab = iTab; |
| 94054 | 94347 | p->isWriteLock = isWriteLock; |
| 94055 | 94348 | p->zName = zName; |
| 94056 | 94349 | }else{ |
| 94057 | 94350 | pToplevel->nTableLock = 0; |
| 94058 | - pToplevel->db->mallocFailed = 1; | |
| 94351 | + sqlite3OomFault(pToplevel->db); | |
| 94059 | 94352 | } |
| 94060 | 94353 | } |
| 94061 | 94354 | |
| 94062 | 94355 | /* |
| 94063 | 94356 | ** Code an OP_TableLock instruction for each table locked by the |
| @@ -94901,11 +95194,11 @@ | ||
| 94901 | 95194 | } |
| 94902 | 95195 | } |
| 94903 | 95196 | |
| 94904 | 95197 | pTable = sqlite3DbMallocZero(db, sizeof(Table)); |
| 94905 | 95198 | if( pTable==0 ){ |
| 94906 | - db->mallocFailed = 1; | |
| 95199 | + assert( db->mallocFailed ); | |
| 94907 | 95200 | pParse->rc = SQLITE_NOMEM; |
| 94908 | 95201 | pParse->nErr++; |
| 94909 | 95202 | goto begin_table_error; |
| 94910 | 95203 | } |
| 94911 | 95204 | pTable->zName = zName; |
| @@ -94958,14 +95251,12 @@ | ||
| 94958 | 95251 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); |
| 94959 | 95252 | sqlite3VdbeUsesBtree(v, iDb); |
| 94960 | 95253 | addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); |
| 94961 | 95254 | fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? |
| 94962 | 95255 | 1 : SQLITE_MAX_FILE_FORMAT; |
| 94963 | - sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); | |
| 94964 | - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3); | |
| 94965 | - sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); | |
| 94966 | - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3); | |
| 95256 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat); | |
| 95257 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db)); | |
| 94967 | 95258 | sqlite3VdbeJumpHere(v, addr1); |
| 94968 | 95259 | |
| 94969 | 95260 | /* This just creates a place-holder record in the sqlite_master table. |
| 94970 | 95261 | ** The record created does not contain anything yet. It will be replaced |
| 94971 | 95262 | ** by the real entry in code generated at sqlite3EndTable(). |
| @@ -95446,17 +95737,15 @@ | ||
| 95446 | 95737 | ** set back to prior value. But schema changes are infrequent |
| 95447 | 95738 | ** and the probability of hitting the same cookie value is only |
| 95448 | 95739 | ** 1 chance in 2^32. So we're safe enough. |
| 95449 | 95740 | */ |
| 95450 | 95741 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ |
| 95451 | - int r1 = sqlite3GetTempReg(pParse); | |
| 95452 | 95742 | sqlite3 *db = pParse->db; |
| 95453 | 95743 | Vdbe *v = pParse->pVdbe; |
| 95454 | 95744 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 95455 | - sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); | |
| 95456 | - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1); | |
| 95457 | - sqlite3ReleaseTempReg(pParse, r1); | |
| 95745 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, | |
| 95746 | + db->aDb[iDb].pSchema->schema_cookie+1); | |
| 95458 | 95747 | } |
| 95459 | 95748 | |
| 95460 | 95749 | /* |
| 95461 | 95750 | ** Measure the number of characters needed to output the given |
| 95462 | 95751 | ** identifier. The number returned includes any quotes used |
| @@ -95534,11 +95823,11 @@ | ||
| 95534 | 95823 | zEnd = "\n)"; |
| 95535 | 95824 | } |
| 95536 | 95825 | n += 35 + 6*p->nCol; |
| 95537 | 95826 | zStmt = sqlite3DbMallocRaw(0, n); |
| 95538 | 95827 | if( zStmt==0 ){ |
| 95539 | - db->mallocFailed = 1; | |
| 95828 | + sqlite3OomFault(db); | |
| 95540 | 95829 | return 0; |
| 95541 | 95830 | } |
| 95542 | 95831 | sqlite3_snprintf(n, zStmt, "CREATE TABLE "); |
| 95543 | 95832 | k = sqlite3Strlen30(zStmt); |
| 95544 | 95833 | identPut(zStmt, &k, p->zName); |
| @@ -95683,12 +95972,11 @@ | ||
| 95683 | 95972 | ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. |
| 95684 | 95973 | */ |
| 95685 | 95974 | if( pTab->iPKey>=0 ){ |
| 95686 | 95975 | ExprList *pList; |
| 95687 | 95976 | Token ipkToken; |
| 95688 | - ipkToken.z = pTab->aCol[pTab->iPKey].zName; | |
| 95689 | - ipkToken.n = sqlite3Strlen30(ipkToken.z); | |
| 95977 | + sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName); | |
| 95690 | 95978 | pList = sqlite3ExprListAppend(pParse, 0, |
| 95691 | 95979 | sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); |
| 95692 | 95980 | if( pList==0 ) return; |
| 95693 | 95981 | pList->a[0].sortOrder = pParse->iPkSortOrder; |
| 95694 | 95982 | assert( pParse->pNewTable==pTab ); |
| @@ -95934,11 +96222,11 @@ | ||
| 95934 | 96222 | pParse->nTab = 2; |
| 95935 | 96223 | addrTop = sqlite3VdbeCurrentAddr(v) + 1; |
| 95936 | 96224 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); |
| 95937 | 96225 | sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); |
| 95938 | 96226 | sqlite3Select(pParse, pSelect, &dest); |
| 95939 | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); | |
| 96227 | + sqlite3VdbeEndCoroutine(v, regYield); | |
| 95940 | 96228 | sqlite3VdbeJumpHere(v, addrTop - 1); |
| 95941 | 96229 | if( pParse->nErr ) return; |
| 95942 | 96230 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); |
| 95943 | 96231 | if( pSelTab==0 ) return; |
| 95944 | 96232 | assert( p->aCol==0 ); |
| @@ -96018,11 +96306,11 @@ | ||
| 96018 | 96306 | Schema *pSchema = p->pSchema; |
| 96019 | 96307 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 96020 | 96308 | pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); |
| 96021 | 96309 | if( pOld ){ |
| 96022 | 96310 | assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 96023 | - db->mallocFailed = 1; | |
| 96311 | + sqlite3OomFault(db); | |
| 96024 | 96312 | return; |
| 96025 | 96313 | } |
| 96026 | 96314 | pParse->pNewTable = 0; |
| 96027 | 96315 | db->flags |= SQLITE_InternChanges; |
| 96028 | 96316 | |
| @@ -96122,11 +96410,10 @@ | ||
| 96122 | 96410 | Select *pSel; /* Copy of the SELECT that implements the view */ |
| 96123 | 96411 | int nErr = 0; /* Number of errors encountered */ |
| 96124 | 96412 | int n; /* Temporarily holds the number of cursors assigned */ |
| 96125 | 96413 | sqlite3 *db = pParse->db; /* Database connection for malloc errors */ |
| 96126 | 96414 | sqlite3_xauth xAuth; /* Saved xAuth pointer */ |
| 96127 | - u8 bEnabledLA; /* Saved db->lookaside.bEnabled state */ | |
| 96128 | 96415 | |
| 96129 | 96416 | assert( pTable ); |
| 96130 | 96417 | |
| 96131 | 96418 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 96132 | 96419 | if( sqlite3VtabCallConnect(pParse, pTable) ){ |
| @@ -96168,30 +96455,31 @@ | ||
| 96168 | 96455 | ** to the elements of the FROM clause. But we do not want these changes |
| 96169 | 96456 | ** to be permanent. So the computation is done on a copy of the SELECT |
| 96170 | 96457 | ** statement that defines the view. |
| 96171 | 96458 | */ |
| 96172 | 96459 | assert( pTable->pSelect ); |
| 96173 | - bEnabledLA = db->lookaside.bEnabled; | |
| 96174 | 96460 | if( pTable->pCheck ){ |
| 96175 | - db->lookaside.bEnabled = 0; | |
| 96461 | + db->lookaside.bDisable++; | |
| 96176 | 96462 | sqlite3ColumnsFromExprList(pParse, pTable->pCheck, |
| 96177 | 96463 | &pTable->nCol, &pTable->aCol); |
| 96464 | + db->lookaside.bDisable--; | |
| 96178 | 96465 | }else{ |
| 96179 | 96466 | pSel = sqlite3SelectDup(db, pTable->pSelect, 0); |
| 96180 | 96467 | if( pSel ){ |
| 96181 | 96468 | n = pParse->nTab; |
| 96182 | 96469 | sqlite3SrcListAssignCursors(pParse, pSel->pSrc); |
| 96183 | 96470 | pTable->nCol = -1; |
| 96184 | - db->lookaside.bEnabled = 0; | |
| 96471 | + db->lookaside.bDisable++; | |
| 96185 | 96472 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 96186 | 96473 | xAuth = db->xAuth; |
| 96187 | 96474 | db->xAuth = 0; |
| 96188 | 96475 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96189 | 96476 | db->xAuth = xAuth; |
| 96190 | 96477 | #else |
| 96191 | 96478 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96192 | 96479 | #endif |
| 96480 | + db->lookaside.bDisable--; | |
| 96193 | 96481 | pParse->nTab = n; |
| 96194 | 96482 | if( pSelTab ){ |
| 96195 | 96483 | assert( pTable->aCol==0 ); |
| 96196 | 96484 | pTable->nCol = pSelTab->nCol; |
| 96197 | 96485 | pTable->aCol = pSelTab->aCol; |
| @@ -96206,11 +96494,10 @@ | ||
| 96206 | 96494 | sqlite3SelectDelete(db, pSel); |
| 96207 | 96495 | } else { |
| 96208 | 96496 | nErr++; |
| 96209 | 96497 | } |
| 96210 | 96498 | } |
| 96211 | - db->lookaside.bEnabled = bEnabledLA; | |
| 96212 | 96499 | pTable->pSchema->schemaFlags |= DB_UnresetViews; |
| 96213 | 96500 | #endif /* SQLITE_OMIT_VIEW */ |
| 96214 | 96501 | return nErr; |
| 96215 | 96502 | } |
| 96216 | 96503 | #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ |
| @@ -96672,11 +96959,11 @@ | ||
| 96672 | 96959 | assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); |
| 96673 | 96960 | pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, |
| 96674 | 96961 | pFKey->zTo, (void *)pFKey |
| 96675 | 96962 | ); |
| 96676 | 96963 | if( pNextTo==pFKey ){ |
| 96677 | - db->mallocFailed = 1; | |
| 96964 | + sqlite3OomFault(db); | |
| 96678 | 96965 | goto fk_end; |
| 96679 | 96966 | } |
| 96680 | 96967 | if( pNextTo ){ |
| 96681 | 96968 | assert( pNextTo->pPrevTo==0 ); |
| 96682 | 96969 | pFKey->pNextTo = pNextTo; |
| @@ -97032,12 +97319,11 @@ | ||
| 97032 | 97319 | ** key out of the last column added to the table under construction. |
| 97033 | 97320 | ** So create a fake list to simulate this. |
| 97034 | 97321 | */ |
| 97035 | 97322 | if( pList==0 ){ |
| 97036 | 97323 | Token prevCol; |
| 97037 | - prevCol.z = pTab->aCol[pTab->nCol-1].zName; | |
| 97038 | - prevCol.n = sqlite3Strlen30(prevCol.z); | |
| 97324 | + sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName); | |
| 97039 | 97325 | pList = sqlite3ExprListAppend(pParse, 0, |
| 97040 | 97326 | sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); |
| 97041 | 97327 | if( pList==0 ) goto exit_create_index; |
| 97042 | 97328 | assert( pList->nExpr==1 ); |
| 97043 | 97329 | sqlite3ExprListSetSortOrder(pList, sortOrder); |
| @@ -97255,11 +97541,11 @@ | ||
| 97255 | 97541 | assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); |
| 97256 | 97542 | p = sqlite3HashInsert(&pIndex->pSchema->idxHash, |
| 97257 | 97543 | pIndex->zName, pIndex); |
| 97258 | 97544 | if( p ){ |
| 97259 | 97545 | assert( p==pIndex ); /* Malloc must have failed */ |
| 97260 | - db->mallocFailed = 1; | |
| 97546 | + sqlite3OomFault(db); | |
| 97261 | 97547 | goto exit_create_index; |
| 97262 | 97548 | } |
| 97263 | 97549 | db->flags |= SQLITE_InternChanges; |
| 97264 | 97550 | if( pTblName!=0 ){ |
| 97265 | 97551 | pIndex->tnum = db->init.newTnum; |
| @@ -97684,12 +97970,13 @@ | ||
| 97684 | 97970 | Token *pTable, /* Table to append */ |
| 97685 | 97971 | Token *pDatabase /* Database of the table */ |
| 97686 | 97972 | ){ |
| 97687 | 97973 | struct SrcList_item *pItem; |
| 97688 | 97974 | assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ |
| 97975 | + assert( db!=0 ); | |
| 97689 | 97976 | if( pList==0 ){ |
| 97690 | - pList = sqlite3DbMallocRaw(db, sizeof(SrcList) ); | |
| 97977 | + pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) ); | |
| 97691 | 97978 | if( pList==0 ) return 0; |
| 97692 | 97979 | pList->nAlloc = 1; |
| 97693 | 97980 | pList->nSrc = 0; |
| 97694 | 97981 | } |
| 97695 | 97982 | pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); |
| @@ -97869,21 +98156,20 @@ | ||
| 97869 | 98156 | p->a[0].fg.jointype = 0; |
| 97870 | 98157 | } |
| 97871 | 98158 | } |
| 97872 | 98159 | |
| 97873 | 98160 | /* |
| 97874 | -** Begin a transaction | |
| 98161 | +** Generate VDBE code for a BEGIN statement. | |
| 97875 | 98162 | */ |
| 97876 | 98163 | SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ |
| 97877 | 98164 | sqlite3 *db; |
| 97878 | 98165 | Vdbe *v; |
| 97879 | 98166 | int i; |
| 97880 | 98167 | |
| 97881 | 98168 | assert( pParse!=0 ); |
| 97882 | 98169 | db = pParse->db; |
| 97883 | 98170 | assert( db!=0 ); |
| 97884 | -/* if( db->aDb[0].pBt==0 ) return; */ | |
| 97885 | 98171 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ |
| 97886 | 98172 | return; |
| 97887 | 98173 | } |
| 97888 | 98174 | v = sqlite3GetVdbe(pParse); |
| 97889 | 98175 | if( !v ) return; |
| @@ -97891,15 +98177,15 @@ | ||
| 97891 | 98177 | for(i=0; i<db->nDb; i++){ |
| 97892 | 98178 | sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); |
| 97893 | 98179 | sqlite3VdbeUsesBtree(v, i); |
| 97894 | 98180 | } |
| 97895 | 98181 | } |
| 97896 | - sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0); | |
| 98182 | + sqlite3VdbeAddOp0(v, OP_AutoCommit); | |
| 97897 | 98183 | } |
| 97898 | 98184 | |
| 97899 | 98185 | /* |
| 97900 | -** Commit a transaction | |
| 98186 | +** Generate VDBE code for a COMMIT statement. | |
| 97901 | 98187 | */ |
| 97902 | 98188 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){ |
| 97903 | 98189 | Vdbe *v; |
| 97904 | 98190 | |
| 97905 | 98191 | assert( pParse!=0 ); |
| @@ -97907,16 +98193,16 @@ | ||
| 97907 | 98193 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ |
| 97908 | 98194 | return; |
| 97909 | 98195 | } |
| 97910 | 98196 | v = sqlite3GetVdbe(pParse); |
| 97911 | 98197 | if( v ){ |
| 97912 | - sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); | |
| 98198 | + sqlite3VdbeAddOp1(v, OP_AutoCommit, 1); | |
| 97913 | 98199 | } |
| 97914 | 98200 | } |
| 97915 | 98201 | |
| 97916 | 98202 | /* |
| 97917 | -** Rollback a transaction | |
| 98203 | +** Generate VDBE code for a ROLLBACK statement. | |
| 97918 | 98204 | */ |
| 97919 | 98205 | SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){ |
| 97920 | 98206 | Vdbe *v; |
| 97921 | 98207 | |
| 97922 | 98208 | assert( pParse!=0 ); |
| @@ -97974,11 +98260,11 @@ | ||
| 97974 | 98260 | return 1; |
| 97975 | 98261 | } |
| 97976 | 98262 | db->aDb[1].pBt = pBt; |
| 97977 | 98263 | assert( db->aDb[1].pSchema ); |
| 97978 | 98264 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 97979 | - db->mallocFailed = 1; | |
| 98265 | + sqlite3OomFault(db); | |
| 97980 | 98266 | return 1; |
| 97981 | 98267 | } |
| 97982 | 98268 | } |
| 97983 | 98269 | return 0; |
| 97984 | 98270 | } |
| @@ -98109,18 +98395,18 @@ | ||
| 98109 | 98395 | StrAccum errMsg; |
| 98110 | 98396 | Table *pTab = pIdx->pTable; |
| 98111 | 98397 | |
| 98112 | 98398 | sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); |
| 98113 | 98399 | if( pIdx->aColExpr ){ |
| 98114 | - sqlite3XPrintf(&errMsg, 0, "index '%q'", pIdx->zName); | |
| 98400 | + sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); | |
| 98115 | 98401 | }else{ |
| 98116 | 98402 | for(j=0; j<pIdx->nKeyCol; j++){ |
| 98117 | 98403 | char *zCol; |
| 98118 | 98404 | assert( pIdx->aiColumn[j]>=0 ); |
| 98119 | 98405 | zCol = pTab->aCol[pIdx->aiColumn[j]].zName; |
| 98120 | 98406 | if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); |
| 98121 | - sqlite3XPrintf(&errMsg, 0, "%s.%s", pTab->zName, zCol); | |
| 98407 | + sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol); | |
| 98122 | 98408 | } |
| 98123 | 98409 | } |
| 98124 | 98410 | zErr = sqlite3StrAccumFinish(&errMsg); |
| 98125 | 98411 | sqlite3HaltConstraint(pParse, |
| 98126 | 98412 | IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY |
| @@ -98349,14 +98635,13 @@ | ||
| 98349 | 98635 | int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); |
| 98350 | 98636 | pNew = sqlite3DbRealloc(db, pWith, nByte); |
| 98351 | 98637 | }else{ |
| 98352 | 98638 | pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); |
| 98353 | 98639 | } |
| 98354 | - assert( zName!=0 || pNew==0 ); | |
| 98355 | - assert( db->mallocFailed==0 || pNew==0 ); | |
| 98640 | + assert( (pNew!=0 && zName!=0) || db->mallocFailed ); | |
| 98356 | 98641 | |
| 98357 | - if( pNew==0 ){ | |
| 98642 | + if( db->mallocFailed ){ | |
| 98358 | 98643 | sqlite3ExprListDelete(db, pArglist); |
| 98359 | 98644 | sqlite3SelectDelete(db, pQuery); |
| 98360 | 98645 | sqlite3DbFree(db, zName); |
| 98361 | 98646 | pNew = pWith; |
| 98362 | 98647 | }else{ |
| @@ -98566,11 +98851,11 @@ | ||
| 98566 | 98851 | ** return the pColl pointer to be deleted (because it wasn't added |
| 98567 | 98852 | ** to the hash table). |
| 98568 | 98853 | */ |
| 98569 | 98854 | assert( pDel==0 || pDel==pColl ); |
| 98570 | 98855 | if( pDel!=0 ){ |
| 98571 | - db->mallocFailed = 1; | |
| 98856 | + sqlite3OomFault(db); | |
| 98572 | 98857 | sqlite3DbFree(db, pDel); |
| 98573 | 98858 | pColl = 0; |
| 98574 | 98859 | } |
| 98575 | 98860 | } |
| 98576 | 98861 | } |
| @@ -98854,11 +99139,11 @@ | ||
| 98854 | 99139 | p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); |
| 98855 | 99140 | }else{ |
| 98856 | 99141 | p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); |
| 98857 | 99142 | } |
| 98858 | 99143 | if( !p ){ |
| 98859 | - db->mallocFailed = 1; | |
| 99144 | + sqlite3OomFault(db); | |
| 98860 | 99145 | }else if ( 0==p->file_format ){ |
| 98861 | 99146 | sqlite3HashInit(&p->tblHash); |
| 98862 | 99147 | sqlite3HashInit(&p->idxHash); |
| 98863 | 99148 | sqlite3HashInit(&p->trigHash); |
| 98864 | 99149 | sqlite3HashInit(&p->fkeyHash); |
| @@ -99308,11 +99593,11 @@ | ||
| 99308 | 99593 | if( eOnePass!=ONEPASS_OFF ){ |
| 99309 | 99594 | /* For ONEPASS, no need to store the rowid/primary-key. There is only |
| 99310 | 99595 | ** one, so just keep it in its register(s) and fall through to the |
| 99311 | 99596 | ** delete code. */ |
| 99312 | 99597 | nKey = nPk; /* OP_Found will use an unpacked key */ |
| 99313 | - aToOpen = sqlite3DbMallocRaw(db, nIdx+2); | |
| 99598 | + aToOpen = sqlite3DbMallocRawNN(db, nIdx+2); | |
| 99314 | 99599 | if( aToOpen==0 ){ |
| 99315 | 99600 | sqlite3WhereEnd(pWInfo); |
| 99316 | 99601 | goto delete_from_cleanup; |
| 99317 | 99602 | } |
| 99318 | 99603 | memset(aToOpen, 1, nIdx+1); |
| @@ -99348,17 +99633,16 @@ | ||
| 99348 | 99633 | ** only effect this statement has is to fire the INSTEAD OF |
| 99349 | 99634 | ** triggers. |
| 99350 | 99635 | */ |
| 99351 | 99636 | if( !isView ){ |
| 99352 | 99637 | int iAddrOnce = 0; |
| 99353 | - u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE); | |
| 99354 | 99638 | if( eOnePass==ONEPASS_MULTI ){ |
| 99355 | 99639 | iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); |
| 99356 | 99640 | } |
| 99357 | 99641 | testcase( IsVirtual(pTab) ); |
| 99358 | - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, | |
| 99359 | - aToOpen, &iDataCur, &iIdxCur); | |
| 99642 | + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, | |
| 99643 | + iTabCur, aToOpen, &iDataCur, &iIdxCur); | |
| 99360 | 99644 | assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); |
| 99361 | 99645 | assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); |
| 99362 | 99646 | if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); |
| 99363 | 99647 | } |
| 99364 | 99648 | |
| @@ -99587,19 +99871,24 @@ | ||
| 99587 | 99871 | |
| 99588 | 99872 | /* Delete the index and table entries. Skip this step if pTab is really |
| 99589 | 99873 | ** a view (in which case the only effect of the DELETE statement is to |
| 99590 | 99874 | ** fire the INSTEAD OF triggers). */ |
| 99591 | 99875 | if( pTab->pSelect==0 ){ |
| 99876 | + u8 p5 = 0; | |
| 99592 | 99877 | sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); |
| 99593 | 99878 | sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); |
| 99594 | 99879 | if( count ){ |
| 99595 | 99880 | sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); |
| 99596 | 99881 | } |
| 99882 | + if( eMode!=ONEPASS_OFF ){ | |
| 99883 | + sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); | |
| 99884 | + } | |
| 99597 | 99885 | if( iIdxNoSeek>=0 ){ |
| 99598 | 99886 | sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); |
| 99599 | 99887 | } |
| 99600 | - sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI); | |
| 99888 | + if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; | |
| 99889 | + sqlite3VdbeChangeP5(v, p5); | |
| 99601 | 99890 | } |
| 99602 | 99891 | |
| 99603 | 99892 | /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
| 99604 | 99893 | ** handle rows (possibly in other tables) that refer via a foreign key |
| 99605 | 99894 | ** to the row just deleted. */ |
| @@ -100005,11 +100294,12 @@ | ||
| 100005 | 100294 | if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
| 100006 | 100295 | x.nArg = argc-1; |
| 100007 | 100296 | x.nUsed = 0; |
| 100008 | 100297 | x.apArg = argv+1; |
| 100009 | 100298 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 100010 | - sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); | |
| 100299 | + str.printfFlags = SQLITE_PRINTF_SQLFUNC; | |
| 100300 | + sqlite3XPrintf(&str, zFormat, &x); | |
| 100011 | 100301 | n = str.nChar; |
| 100012 | 100302 | sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, |
| 100013 | 100303 | SQLITE_DYNAMIC); |
| 100014 | 100304 | } |
| 100015 | 100305 | } |
| @@ -101380,11 +101670,11 @@ | ||
| 101380 | 101670 | */ |
| 101381 | 101671 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ |
| 101382 | 101672 | int rc = sqlite3_overload_function(db, "MATCH", 2); |
| 101383 | 101673 | assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); |
| 101384 | 101674 | if( rc==SQLITE_NOMEM ){ |
| 101385 | - db->mallocFailed = 1; | |
| 101675 | + sqlite3OomFault(db); | |
| 101386 | 101676 | } |
| 101387 | 101677 | } |
| 101388 | 101678 | |
| 101389 | 101679 | /* |
| 101390 | 101680 | ** Set the LIKEOPT flag on the 2-argument function with the given name. |
| @@ -101795,11 +102085,11 @@ | ||
| 101795 | 102085 | if( !zKey ) return 0; |
| 101796 | 102086 | if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; |
| 101797 | 102087 | } |
| 101798 | 102088 | }else if( paiCol ){ |
| 101799 | 102089 | assert( nCol>1 ); |
| 101800 | - aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int)); | |
| 102090 | + aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); | |
| 101801 | 102091 | if( !aiCol ) return 1; |
| 101802 | 102092 | *paiCol = aiCol; |
| 101803 | 102093 | } |
| 101804 | 102094 | |
| 101805 | 102095 | for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ |
| @@ -102741,11 +103031,10 @@ | ||
| 102741 | 103031 | |
| 102742 | 103032 | action = pFKey->aAction[iAction]; |
| 102743 | 103033 | pTrigger = pFKey->apTrigger[iAction]; |
| 102744 | 103034 | |
| 102745 | 103035 | if( action!=OE_None && !pTrigger ){ |
| 102746 | - u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ | |
| 102747 | 103036 | char const *zFrom; /* Name of child table */ |
| 102748 | 103037 | int nFrom; /* Length in bytes of zFrom */ |
| 102749 | 103038 | Index *pIdx = 0; /* Parent key index for this FK */ |
| 102750 | 103039 | int *aiCol = 0; /* child table cols -> parent key cols */ |
| 102751 | 103040 | TriggerStep *pStep = 0; /* First (only) step of trigger program */ |
| @@ -102768,15 +103057,13 @@ | ||
| 102768 | 103057 | |
| 102769 | 103058 | iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 102770 | 103059 | assert( iFromCol>=0 ); |
| 102771 | 103060 | assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 102772 | 103061 | assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
| 102773 | - tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; | |
| 102774 | - tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; | |
| 102775 | - | |
| 102776 | - tToCol.n = sqlite3Strlen30(tToCol.z); | |
| 102777 | - tFromCol.n = sqlite3Strlen30(tFromCol.z); | |
| 103062 | + sqlite3TokenInit(&tToCol, | |
| 103063 | + pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName); | |
| 103064 | + sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName); | |
| 102778 | 103065 | |
| 102779 | 103066 | /* Create the expression "OLD.zToCol = zFromCol". It is important |
| 102780 | 103067 | ** that the "OLD.zToCol" term is on the LHS of the = operator, so |
| 102781 | 103068 | ** that the affinity and collation sequence associated with the |
| 102782 | 103069 | ** parent table are used for the comparison. */ |
| @@ -102852,12 +103139,11 @@ | ||
| 102852 | 103139 | ); |
| 102853 | 103140 | pWhere = 0; |
| 102854 | 103141 | } |
| 102855 | 103142 | |
| 102856 | 103143 | /* Disable lookaside memory allocation */ |
| 102857 | - enableLookaside = db->lookaside.bEnabled; | |
| 102858 | - db->lookaside.bEnabled = 0; | |
| 103144 | + db->lookaside.bDisable++; | |
| 102859 | 103145 | |
| 102860 | 103146 | pTrigger = (Trigger *)sqlite3DbMallocZero(db, |
| 102861 | 103147 | sizeof(Trigger) + /* struct Trigger */ |
| 102862 | 103148 | sizeof(TriggerStep) + /* Single step in trigger program */ |
| 102863 | 103149 | nFrom + 1 /* Space for pStep->zTarget */ |
| @@ -102875,11 +103161,11 @@ | ||
| 102875 | 103161 | pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
| 102876 | 103162 | } |
| 102877 | 103163 | } |
| 102878 | 103164 | |
| 102879 | 103165 | /* Re-enable the lookaside buffer, if it was disabled earlier. */ |
| 102880 | - db->lookaside.bEnabled = enableLookaside; | |
| 103166 | + db->lookaside.bDisable--; | |
| 102881 | 103167 | |
| 102882 | 103168 | sqlite3ExprDelete(db, pWhere); |
| 102883 | 103169 | sqlite3ExprDelete(db, pWhen); |
| 102884 | 103170 | sqlite3ExprListDelete(db, pList); |
| 102885 | 103171 | sqlite3SelectDelete(db, pSelect); |
| @@ -103070,11 +103356,11 @@ | ||
| 103070 | 103356 | */ |
| 103071 | 103357 | int n; |
| 103072 | 103358 | Table *pTab = pIdx->pTable; |
| 103073 | 103359 | pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); |
| 103074 | 103360 | if( !pIdx->zColAff ){ |
| 103075 | - db->mallocFailed = 1; | |
| 103361 | + sqlite3OomFault(db); | |
| 103076 | 103362 | return 0; |
| 103077 | 103363 | } |
| 103078 | 103364 | for(n=0; n<pIdx->nColumn; n++){ |
| 103079 | 103365 | i16 x = pIdx->aiColumn[n]; |
| 103080 | 103366 | if( x>=0 ){ |
| @@ -103121,11 +103407,11 @@ | ||
| 103121 | 103407 | char *zColAff = pTab->zColAff; |
| 103122 | 103408 | if( zColAff==0 ){ |
| 103123 | 103409 | sqlite3 *db = sqlite3VdbeDb(v); |
| 103124 | 103410 | zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); |
| 103125 | 103411 | if( !zColAff ){ |
| 103126 | - db->mallocFailed = 1; | |
| 103412 | + sqlite3OomFault(db); | |
| 103127 | 103413 | return; |
| 103128 | 103414 | } |
| 103129 | 103415 | |
| 103130 | 103416 | for(i=0; i<pTab->nCol; i++){ |
| 103131 | 103417 | zColAff[i] = pTab->aCol[i].affinity; |
| @@ -103217,11 +103503,11 @@ | ||
| 103217 | 103503 | AutoincInfo *pInfo; |
| 103218 | 103504 | |
| 103219 | 103505 | pInfo = pToplevel->pAinc; |
| 103220 | 103506 | while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } |
| 103221 | 103507 | if( pInfo==0 ){ |
| 103222 | - pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo)); | |
| 103508 | + pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); | |
| 103223 | 103509 | if( pInfo==0 ) return 0; |
| 103224 | 103510 | pInfo->pNext = pToplevel->pAinc; |
| 103225 | 103511 | pToplevel->pAinc = pInfo; |
| 103226 | 103512 | pInfo->pTab = pTab; |
| 103227 | 103513 | pInfo->iDb = iDb; |
| @@ -103241,47 +103527,59 @@ | ||
| 103241 | 103527 | SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ |
| 103242 | 103528 | AutoincInfo *p; /* Information about an AUTOINCREMENT */ |
| 103243 | 103529 | sqlite3 *db = pParse->db; /* The database connection */ |
| 103244 | 103530 | Db *pDb; /* Database only autoinc table */ |
| 103245 | 103531 | int memId; /* Register holding max rowid */ |
| 103246 | - int addr; /* A VDBE address */ | |
| 103247 | 103532 | Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
| 103248 | 103533 | |
| 103249 | 103534 | /* This routine is never called during trigger-generation. It is |
| 103250 | 103535 | ** only called from the top-level */ |
| 103251 | 103536 | assert( pParse->pTriggerTab==0 ); |
| 103252 | 103537 | assert( sqlite3IsToplevel(pParse) ); |
| 103253 | 103538 | |
| 103254 | 103539 | assert( v ); /* We failed long ago if this is not so */ |
| 103255 | 103540 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103541 | + static const int iLn = VDBE_OFFSET_LINENO(2); | |
| 103542 | + static const VdbeOpList autoInc[] = { | |
| 103543 | + /* 0 */ {OP_Null, 0, 0, 0}, | |
| 103544 | + /* 1 */ {OP_Rewind, 0, 9, 0}, | |
| 103545 | + /* 2 */ {OP_Column, 0, 0, 0}, | |
| 103546 | + /* 3 */ {OP_Ne, 0, 7, 0}, | |
| 103547 | + /* 4 */ {OP_Rowid, 0, 0, 0}, | |
| 103548 | + /* 5 */ {OP_Column, 0, 1, 0}, | |
| 103549 | + /* 6 */ {OP_Goto, 0, 9, 0}, | |
| 103550 | + /* 7 */ {OP_Next, 0, 2, 0}, | |
| 103551 | + /* 8 */ {OP_Integer, 0, 0, 0}, | |
| 103552 | + /* 9 */ {OP_Close, 0, 0, 0} | |
| 103553 | + }; | |
| 103554 | + VdbeOp *aOp; | |
| 103256 | 103555 | pDb = &db->aDb[p->iDb]; |
| 103257 | 103556 | memId = p->regCtr; |
| 103258 | 103557 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103259 | 103558 | sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); |
| 103260 | - sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); | |
| 103261 | - addr = sqlite3VdbeCurrentAddr(v); | |
| 103262 | 103559 | sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); |
| 103263 | - sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v); | |
| 103264 | - sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); | |
| 103265 | - sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v); | |
| 103266 | - sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); | |
| 103267 | - sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); | |
| 103268 | - sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); | |
| 103269 | - sqlite3VdbeGoto(v, addr+9); | |
| 103270 | - sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v); | |
| 103271 | - sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); | |
| 103272 | - sqlite3VdbeAddOp0(v, OP_Close); | |
| 103560 | + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); | |
| 103561 | + if( aOp==0 ) break; | |
| 103562 | + aOp[0].p2 = memId; | |
| 103563 | + aOp[0].p3 = memId+1; | |
| 103564 | + aOp[2].p3 = memId; | |
| 103565 | + aOp[3].p1 = memId-1; | |
| 103566 | + aOp[3].p3 = memId; | |
| 103567 | + aOp[3].p5 = SQLITE_JUMPIFNULL; | |
| 103568 | + aOp[4].p2 = memId+1; | |
| 103569 | + aOp[5].p3 = memId; | |
| 103570 | + aOp[8].p2 = memId; | |
| 103273 | 103571 | } |
| 103274 | 103572 | } |
| 103275 | 103573 | |
| 103276 | 103574 | /* |
| 103277 | 103575 | ** Update the maximum rowid for an autoincrement calculation. |
| 103278 | 103576 | ** |
| 103279 | -** This routine should be called when the top of the stack holds a | |
| 103577 | +** This routine should be called when the regRowid register holds a | |
| 103280 | 103578 | ** new rowid that is about to be inserted. If that new rowid is |
| 103281 | 103579 | ** larger than the maximum rowid in the memId memory cell, then the |
| 103282 | -** memory cell is updated. The stack is unchanged. | |
| 103580 | +** memory cell is updated. | |
| 103283 | 103581 | */ |
| 103284 | 103582 | static void autoIncStep(Parse *pParse, int memId, int regRowid){ |
| 103285 | 103583 | if( memId>0 ){ |
| 103286 | 103584 | sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); |
| 103287 | 103585 | } |
| @@ -103292,34 +103590,47 @@ | ||
| 103292 | 103590 | ** maximum rowid values back into the sqlite_sequence register. |
| 103293 | 103591 | ** Every statement that might do an INSERT into an autoincrement |
| 103294 | 103592 | ** table (either directly or through triggers) needs to call this |
| 103295 | 103593 | ** routine just before the "exit" code. |
| 103296 | 103594 | */ |
| 103297 | -SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ | |
| 103595 | +static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ | |
| 103298 | 103596 | AutoincInfo *p; |
| 103299 | 103597 | Vdbe *v = pParse->pVdbe; |
| 103300 | 103598 | sqlite3 *db = pParse->db; |
| 103301 | 103599 | |
| 103302 | 103600 | assert( v ); |
| 103303 | 103601 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103602 | + static const int iLn = VDBE_OFFSET_LINENO(2); | |
| 103603 | + static const VdbeOpList autoIncEnd[] = { | |
| 103604 | + /* 0 */ {OP_NotNull, 0, 2, 0}, | |
| 103605 | + /* 1 */ {OP_NewRowid, 0, 0, 0}, | |
| 103606 | + /* 2 */ {OP_MakeRecord, 0, 2, 0}, | |
| 103607 | + /* 3 */ {OP_Insert, 0, 0, 0}, | |
| 103608 | + /* 4 */ {OP_Close, 0, 0, 0} | |
| 103609 | + }; | |
| 103610 | + VdbeOp *aOp; | |
| 103304 | 103611 | Db *pDb = &db->aDb[p->iDb]; |
| 103305 | - int addr1; | |
| 103306 | 103612 | int iRec; |
| 103307 | 103613 | int memId = p->regCtr; |
| 103308 | 103614 | |
| 103309 | 103615 | iRec = sqlite3GetTempReg(pParse); |
| 103310 | 103616 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103311 | 103617 | sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); |
| 103312 | - addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); | |
| 103313 | - sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); | |
| 103314 | - sqlite3VdbeJumpHere(v, addr1); | |
| 103315 | - sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); | |
| 103316 | - sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); | |
| 103317 | - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); | |
| 103318 | - sqlite3VdbeAddOp0(v, OP_Close); | |
| 103618 | + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); | |
| 103619 | + if( aOp==0 ) break; | |
| 103620 | + aOp[0].p1 = memId+1; | |
| 103621 | + aOp[1].p2 = memId+1; | |
| 103622 | + aOp[2].p1 = memId-1; | |
| 103623 | + aOp[2].p3 = iRec; | |
| 103624 | + aOp[3].p2 = iRec; | |
| 103625 | + aOp[3].p3 = memId+1; | |
| 103626 | + aOp[3].p5 = OPFLAG_APPEND; | |
| 103319 | 103627 | sqlite3ReleaseTempReg(pParse, iRec); |
| 103320 | 103628 | } |
| 103629 | +} | |
| 103630 | +SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ | |
| 103631 | + if( pParse->pAinc ) autoIncrementEnd(pParse); | |
| 103321 | 103632 | } |
| 103322 | 103633 | #else |
| 103323 | 103634 | /* |
| 103324 | 103635 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines |
| 103325 | 103636 | ** above are all no-ops |
| @@ -103647,11 +103958,11 @@ | ||
| 103647 | 103958 | dest.iSdst = bIdListInOrder ? regData : 0; |
| 103648 | 103959 | dest.nSdst = pTab->nCol; |
| 103649 | 103960 | rc = sqlite3Select(pParse, pSelect, &dest); |
| 103650 | 103961 | regFromSelect = dest.iSdst; |
| 103651 | 103962 | if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; |
| 103652 | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); | |
| 103963 | + sqlite3VdbeEndCoroutine(v, regYield); | |
| 103653 | 103964 | sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ |
| 103654 | 103965 | assert( pSelect->pEList ); |
| 103655 | 103966 | nColumn = pSelect->pEList->nExpr; |
| 103656 | 103967 | |
| 103657 | 103968 | /* Set useTempTable to TRUE if the result of the SELECT statement |
| @@ -103749,11 +104060,11 @@ | ||
| 103749 | 104060 | /* If this is not a view, open the table and and all indices */ |
| 103750 | 104061 | if( !isView ){ |
| 103751 | 104062 | int nIdx; |
| 103752 | 104063 | nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, |
| 103753 | 104064 | &iDataCur, &iIdxCur); |
| 103754 | - aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); | |
| 104065 | + aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); | |
| 103755 | 104066 | if( aRegIdx==0 ){ |
| 103756 | 104067 | goto insert_cleanup; |
| 103757 | 104068 | } |
| 103758 | 104069 | for(i=0; i<nIdx; i++){ |
| 103759 | 104070 | aRegIdx[i] = ++pParse->nMem; |
| @@ -104634,11 +104945,11 @@ | ||
| 104634 | 104945 | */ |
| 104635 | 104946 | SQLITE_PRIVATE int sqlite3OpenTableAndIndices( |
| 104636 | 104947 | Parse *pParse, /* Parsing context */ |
| 104637 | 104948 | Table *pTab, /* Table to be opened */ |
| 104638 | 104949 | int op, /* OP_OpenRead or OP_OpenWrite */ |
| 104639 | - u8 p5, /* P5 value for OP_Open* instructions */ | |
| 104950 | + u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ | |
| 104640 | 104951 | int iBase, /* Use this for the table cursor, if there is one */ |
| 104641 | 104952 | u8 *aToOpen, /* If not NULL: boolean for each table and index */ |
| 104642 | 104953 | int *piDataCur, /* Write the database source cursor number here */ |
| 104643 | 104954 | int *piIdxCur /* Write the first index cursor number here */ |
| 104644 | 104955 | ){ |
| @@ -104669,18 +104980,19 @@ | ||
| 104669 | 104980 | } |
| 104670 | 104981 | if( piIdxCur ) *piIdxCur = iBase; |
| 104671 | 104982 | for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ |
| 104672 | 104983 | int iIdxCur = iBase++; |
| 104673 | 104984 | assert( pIdx->pSchema==pTab->pSchema ); |
| 104674 | - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){ | |
| 104675 | - *piDataCur = iIdxCur; | |
| 104676 | - } | |
| 104677 | 104985 | if( aToOpen==0 || aToOpen[i+1] ){ |
| 104678 | 104986 | sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); |
| 104679 | 104987 | sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
| 104680 | - sqlite3VdbeChangeP5(v, p5); | |
| 104681 | 104988 | VdbeComment((v, "%s", pIdx->zName)); |
| 104989 | + } | |
| 104990 | + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ | |
| 104991 | + if( piDataCur ) *piDataCur = iIdxCur; | |
| 104992 | + }else{ | |
| 104993 | + sqlite3VdbeChangeP5(v, p5); | |
| 104682 | 104994 | } |
| 104683 | 104995 | } |
| 104684 | 104996 | if( iBase>pParse->nTab ) pParse->nTab = iBase; |
| 104685 | 104997 | return i; |
| 104686 | 104998 | } |
| @@ -105167,11 +105479,11 @@ | ||
| 105167 | 105479 | if( rc==SQLITE_ROW ){ |
| 105168 | 105480 | azVals = &azCols[nCol]; |
| 105169 | 105481 | for(i=0; i<nCol; i++){ |
| 105170 | 105482 | azVals[i] = (char *)sqlite3_column_text(pStmt, i); |
| 105171 | 105483 | if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 105172 | - db->mallocFailed = 1; | |
| 105484 | + sqlite3OomFault(db); | |
| 105173 | 105485 | goto exec_out; |
| 105174 | 105486 | } |
| 105175 | 105487 | } |
| 105176 | 105488 | } |
| 105177 | 105489 | if( xCallback(pArg, nCol, azVals, azCols) ){ |
| @@ -107055,32 +107367,35 @@ | ||
| 107055 | 107367 | /************** End of pragma.h **********************************************/ |
| 107056 | 107368 | /************** Continuing where we left off in pragma.c *********************/ |
| 107057 | 107369 | |
| 107058 | 107370 | /* |
| 107059 | 107371 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| 107060 | -** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or | |
| 107061 | -** unrecognized string argument. The FULL option is disallowed | |
| 107372 | +** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or | |
| 107373 | +** unrecognized string argument. The FULL and EXTRA option is disallowed | |
| 107062 | 107374 | ** if the omitFull parameter it 1. |
| 107063 | 107375 | ** |
| 107064 | 107376 | ** Note that the values returned are one less that the values that |
| 107065 | 107377 | ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done |
| 107066 | 107378 | ** to support legacy SQL code. The safety level used to be boolean |
| 107067 | 107379 | ** and older scripts may have used numbers 0 for OFF and 1 for ON. |
| 107068 | 107380 | */ |
| 107069 | 107381 | static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ |
| 107070 | - /* 123456789 123456789 */ | |
| 107071 | - static const char zText[] = "onoffalseyestruefull"; | |
| 107072 | - static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; | |
| 107073 | - static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; | |
| 107074 | - static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; | |
| 107382 | + /* 123456789 123456789 123 */ | |
| 107383 | + static const char zText[] = "onoffalseyestruextrafull"; | |
| 107384 | + static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 15, 20}; | |
| 107385 | + static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 5, 4}; | |
| 107386 | + static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 3, 2}; | |
| 107387 | + /* on no off false yes true extra full */ | |
| 107075 | 107388 | int i, n; |
| 107076 | 107389 | if( sqlite3Isdigit(*z) ){ |
| 107077 | 107390 | return (u8)sqlite3Atoi(z); |
| 107078 | 107391 | } |
| 107079 | 107392 | n = sqlite3Strlen30(z); |
| 107080 | - for(i=0; i<ArraySize(iLength)-omitFull; i++){ | |
| 107081 | - if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ | |
| 107393 | + for(i=0; i<ArraySize(iLength); i++){ | |
| 107394 | + if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 | |
| 107395 | + && (!omitFull || iValue[i]<=1) | |
| 107396 | + ){ | |
| 107082 | 107397 | return iValue[i]; |
| 107083 | 107398 | } |
| 107084 | 107399 | } |
| 107085 | 107400 | return dflt; |
| 107086 | 107401 | } |
| @@ -107467,12 +107782,11 @@ | ||
| 107467 | 107782 | aOp[1].p1 = iDb; |
| 107468 | 107783 | aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE; |
| 107469 | 107784 | }else{ |
| 107470 | 107785 | int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); |
| 107471 | 107786 | sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 107472 | - sqlite3VdbeAddOp2(v, OP_Integer, size, 1); | |
| 107473 | - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); | |
| 107787 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, size); | |
| 107474 | 107788 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 107475 | 107789 | pDb->pSchema->cache_size = size; |
| 107476 | 107790 | sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
| 107477 | 107791 | } |
| 107478 | 107792 | break; |
| @@ -107499,11 +107813,11 @@ | ||
| 107499 | 107813 | /* Malloc may fail when setting the page-size, as there is an internal |
| 107500 | 107814 | ** buffer that the pager module resizes using sqlite3_realloc(). |
| 107501 | 107815 | */ |
| 107502 | 107816 | db->nextPagesize = sqlite3Atoi(zRight); |
| 107503 | 107817 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ |
| 107504 | - db->mallocFailed = 1; | |
| 107818 | + sqlite3OomFault(db); | |
| 107505 | 107819 | } |
| 107506 | 107820 | } |
| 107507 | 107821 | break; |
| 107508 | 107822 | } |
| 107509 | 107823 | |
| @@ -107706,23 +108020,22 @@ | ||
| 107706 | 108020 | static const VdbeOpList setMeta6[] = { |
| 107707 | 108021 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 107708 | 108022 | { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, |
| 107709 | 108023 | { OP_If, 1, 0, 0}, /* 2 */ |
| 107710 | 108024 | { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ |
| 107711 | - { OP_Integer, 0, 1, 0}, /* 4 */ | |
| 107712 | - { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ | |
| 108025 | + { OP_SetCookie, 0, BTREE_INCR_VACUUM, 0}, /* 4 */ | |
| 107713 | 108026 | }; |
| 107714 | 108027 | VdbeOp *aOp; |
| 107715 | 108028 | int iAddr = sqlite3VdbeCurrentAddr(v); |
| 107716 | 108029 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setMeta6)); |
| 107717 | 108030 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); |
| 107718 | 108031 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 107719 | 108032 | aOp[0].p1 = iDb; |
| 107720 | 108033 | aOp[1].p1 = iDb; |
| 107721 | 108034 | aOp[2].p2 = iAddr+4; |
| 107722 | - aOp[4].p1 = eAuto - 1; | |
| 107723 | - aOp[5].p1 = iDb; | |
| 108035 | + aOp[4].p1 = iDb; | |
| 108036 | + aOp[4].p3 = eAuto - 1; | |
| 107724 | 108037 | sqlite3VdbeUsesBtree(v, iDb); |
| 107725 | 108038 | } |
| 107726 | 108039 | } |
| 107727 | 108040 | break; |
| 107728 | 108041 | } |
| @@ -107997,11 +108310,11 @@ | ||
| 107997 | 108310 | } |
| 107998 | 108311 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 107999 | 108312 | |
| 108000 | 108313 | /* |
| 108001 | 108314 | ** PRAGMA [schema.]synchronous |
| 108002 | - ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL | |
| 108315 | + ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA | |
| 108003 | 108316 | ** |
| 108004 | 108317 | ** Return or set the local value of the synchronous flag. Changing |
| 108005 | 108318 | ** the local value does not make changes to the disk file and the |
| 108006 | 108319 | ** default value will be restored the next time the database is |
| 108007 | 108320 | ** opened. |
| @@ -108624,20 +108937,19 @@ | ||
| 108624 | 108937 | } |
| 108625 | 108938 | { |
| 108626 | 108939 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 108627 | 108940 | static const VdbeOpList endCode[] = { |
| 108628 | 108941 | { OP_AddImm, 1, 0, 0}, /* 0 */ |
| 108629 | - { OP_If, 1, 0, 0}, /* 1 */ | |
| 108942 | + { OP_If, 1, 4, 0}, /* 1 */ | |
| 108630 | 108943 | { OP_String8, 0, 3, 0}, /* 2 */ |
| 108631 | - { OP_ResultRow, 3, 1, 0}, | |
| 108944 | + { OP_ResultRow, 3, 1, 0}, /* 3 */ | |
| 108632 | 108945 | }; |
| 108633 | 108946 | VdbeOp *aOp; |
| 108634 | 108947 | |
| 108635 | 108948 | aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
| 108636 | 108949 | if( aOp ){ |
| 108637 | 108950 | aOp[0].p2 = -mxErr; |
| 108638 | - aOp[1].p2 = sqlite3VdbeCurrentAddr(v); | |
| 108639 | 108951 | aOp[2].p4type = P4_STATIC; |
| 108640 | 108952 | aOp[2].p4.z = "ok"; |
| 108641 | 108953 | } |
| 108642 | 108954 | } |
| 108643 | 108955 | } |
| @@ -108751,21 +109063,20 @@ | ||
| 108751 | 109063 | sqlite3VdbeUsesBtree(v, iDb); |
| 108752 | 109064 | if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ |
| 108753 | 109065 | /* Write the specified cookie value */ |
| 108754 | 109066 | static const VdbeOpList setCookie[] = { |
| 108755 | 109067 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 108756 | - { OP_Integer, 0, 1, 0}, /* 1 */ | |
| 108757 | - { OP_SetCookie, 0, 0, 1}, /* 2 */ | |
| 109068 | + { OP_SetCookie, 0, 0, 0}, /* 1 */ | |
| 108758 | 109069 | }; |
| 108759 | 109070 | VdbeOp *aOp; |
| 108760 | 109071 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); |
| 108761 | 109072 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); |
| 108762 | 109073 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 108763 | 109074 | aOp[0].p1 = iDb; |
| 108764 | - aOp[1].p1 = sqlite3Atoi(zRight); | |
| 108765 | - aOp[2].p1 = iDb; | |
| 108766 | - aOp[2].p2 = iCookie; | |
| 109075 | + aOp[1].p1 = iDb; | |
| 109076 | + aOp[1].p2 = iCookie; | |
| 109077 | + aOp[1].p3 = sqlite3Atoi(zRight); | |
| 108767 | 109078 | }else{ |
| 108768 | 109079 | /* Read the specified cookie value */ |
| 108769 | 109080 | static const VdbeOpList readCookie[] = { |
| 108770 | 109081 | { OP_Transaction, 0, 0, 0}, /* 0 */ |
| 108771 | 109082 | { OP_ReadCookie, 0, 1, 0}, /* 1 */ |
| @@ -109033,15 +109344,14 @@ | ||
| 109033 | 109344 | ){ |
| 109034 | 109345 | sqlite3 *db = pData->db; |
| 109035 | 109346 | if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ |
| 109036 | 109347 | char *z; |
| 109037 | 109348 | if( zObj==0 ) zObj = "?"; |
| 109038 | - z = sqlite3_mprintf("malformed database schema (%s)", zObj); | |
| 109039 | - if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra); | |
| 109349 | + z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); | |
| 109350 | + if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); | |
| 109040 | 109351 | sqlite3DbFree(db, *pData->pzErrMsg); |
| 109041 | 109352 | *pData->pzErrMsg = z; |
| 109042 | - if( z==0 ) db->mallocFailed = 1; | |
| 109043 | 109353 | } |
| 109044 | 109354 | pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; |
| 109045 | 109355 | } |
| 109046 | 109356 | |
| 109047 | 109357 | /* |
| @@ -109096,11 +109406,11 @@ | ||
| 109096 | 109406 | if( db->init.orphanTrigger ){ |
| 109097 | 109407 | assert( iDb==1 ); |
| 109098 | 109408 | }else{ |
| 109099 | 109409 | pData->rc = rc; |
| 109100 | 109410 | if( rc==SQLITE_NOMEM ){ |
| 109101 | - db->mallocFailed = 1; | |
| 109411 | + sqlite3OomFault(db); | |
| 109102 | 109412 | }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ |
| 109103 | 109413 | corruptSchema(pData, argv[0], sqlite3_errmsg(db)); |
| 109104 | 109414 | } |
| 109105 | 109415 | } |
| 109106 | 109416 | } |
| @@ -109341,11 +109651,11 @@ | ||
| 109341 | 109651 | } |
| 109342 | 109652 | sqlite3BtreeLeave(pDb->pBt); |
| 109343 | 109653 | |
| 109344 | 109654 | error_out: |
| 109345 | 109655 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109346 | - db->mallocFailed = 1; | |
| 109656 | + sqlite3OomFault(db); | |
| 109347 | 109657 | } |
| 109348 | 109658 | return rc; |
| 109349 | 109659 | } |
| 109350 | 109660 | |
| 109351 | 109661 | /* |
| @@ -109439,11 +109749,11 @@ | ||
| 109439 | 109749 | ** on the b-tree database, open one now. If a transaction is opened, it |
| 109440 | 109750 | ** will be closed immediately after reading the meta-value. */ |
| 109441 | 109751 | if( !sqlite3BtreeIsInReadTrans(pBt) ){ |
| 109442 | 109752 | rc = sqlite3BtreeBeginTrans(pBt, 0); |
| 109443 | 109753 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109444 | - db->mallocFailed = 1; | |
| 109754 | + sqlite3OomFault(db); | |
| 109445 | 109755 | } |
| 109446 | 109756 | if( rc!=SQLITE_OK ) return; |
| 109447 | 109757 | openedTransaction = 1; |
| 109448 | 109758 | } |
| 109449 | 109759 | |
| @@ -109502,10 +109812,15 @@ | ||
| 109502 | 109812 | SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ |
| 109503 | 109813 | if( pParse ){ |
| 109504 | 109814 | sqlite3 *db = pParse->db; |
| 109505 | 109815 | sqlite3DbFree(db, pParse->aLabel); |
| 109506 | 109816 | sqlite3ExprListDelete(db, pParse->pConstExpr); |
| 109817 | + if( db ){ | |
| 109818 | + assert( db->lookaside.bDisable >= pParse->disableLookaside ); | |
| 109819 | + db->lookaside.bDisable -= pParse->disableLookaside; | |
| 109820 | + } | |
| 109821 | + pParse->disableLookaside = 0; | |
| 109507 | 109822 | } |
| 109508 | 109823 | } |
| 109509 | 109824 | |
| 109510 | 109825 | /* |
| 109511 | 109826 | ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. |
| @@ -109530,11 +109845,11 @@ | ||
| 109530 | 109845 | rc = SQLITE_NOMEM; |
| 109531 | 109846 | goto end_prepare; |
| 109532 | 109847 | } |
| 109533 | 109848 | pParse->pReprepare = pReprepare; |
| 109534 | 109849 | assert( ppStmt && *ppStmt==0 ); |
| 109535 | - assert( !db->mallocFailed ); | |
| 109850 | + /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ | |
| 109536 | 109851 | assert( sqlite3_mutex_held(db->mutex) ); |
| 109537 | 109852 | |
| 109538 | 109853 | /* Check to verify that it is possible to get a read lock on all |
| 109539 | 109854 | ** database schemas. The inability to get a read lock indicates that |
| 109540 | 109855 | ** some other database connection is holding a write-lock, which in |
| @@ -109587,23 +109902,20 @@ | ||
| 109587 | 109902 | goto end_prepare; |
| 109588 | 109903 | } |
| 109589 | 109904 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 109590 | 109905 | if( zSqlCopy ){ |
| 109591 | 109906 | sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); |
| 109592 | - sqlite3DbFree(db, zSqlCopy); | |
| 109593 | 109907 | pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; |
| 109908 | + sqlite3DbFree(db, zSqlCopy); | |
| 109594 | 109909 | }else{ |
| 109595 | 109910 | pParse->zTail = &zSql[nBytes]; |
| 109596 | 109911 | } |
| 109597 | 109912 | }else{ |
| 109598 | 109913 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 109599 | 109914 | } |
| 109600 | 109915 | assert( 0==pParse->nQueryLoop ); |
| 109601 | 109916 | |
| 109602 | - if( db->mallocFailed ){ | |
| 109603 | - pParse->rc = SQLITE_NOMEM; | |
| 109604 | - } | |
| 109605 | 109917 | if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; |
| 109606 | 109918 | if( pParse->checkSchema ){ |
| 109607 | 109919 | schemaIsValid(pParse); |
| 109608 | 109920 | } |
| 109609 | 109921 | if( db->mallocFailed ){ |
| @@ -109721,11 +110033,11 @@ | ||
| 109721 | 110033 | db = sqlite3VdbeDb(p); |
| 109722 | 110034 | assert( sqlite3_mutex_held(db->mutex) ); |
| 109723 | 110035 | rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0); |
| 109724 | 110036 | if( rc ){ |
| 109725 | 110037 | if( rc==SQLITE_NOMEM ){ |
| 109726 | - db->mallocFailed = 1; | |
| 110038 | + sqlite3OomFault(db); | |
| 109727 | 110039 | } |
| 109728 | 110040 | assert( pNew==0 ); |
| 109729 | 110041 | return rc; |
| 109730 | 110042 | }else{ |
| 109731 | 110043 | assert( pNew!=0 ); |
| @@ -109975,11 +110287,11 @@ | ||
| 109975 | 110287 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 109976 | 110288 | ){ |
| 109977 | 110289 | Select *pNew; |
| 109978 | 110290 | Select standin; |
| 109979 | 110291 | sqlite3 *db = pParse->db; |
| 109980 | - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); | |
| 110292 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); | |
| 109981 | 110293 | if( pNew==0 ){ |
| 109982 | 110294 | assert( db->mallocFailed ); |
| 109983 | 110295 | pNew = &standin; |
| 109984 | 110296 | } |
| 109985 | 110297 | if( pEList==0 ){ |
| @@ -110879,11 +111191,11 @@ | ||
| 110879 | 111191 | p->enc = ENC(db); |
| 110880 | 111192 | p->db = db; |
| 110881 | 111193 | p->nRef = 1; |
| 110882 | 111194 | memset(&p[1], 0, nExtra); |
| 110883 | 111195 | }else{ |
| 110884 | - db->mallocFailed = 1; | |
| 111196 | + sqlite3OomFault(db); | |
| 110885 | 111197 | } |
| 110886 | 111198 | return p; |
| 110887 | 111199 | } |
| 110888 | 111200 | |
| 110889 | 111201 | /* |
| @@ -111540,11 +111852,11 @@ | ||
| 111540 | 111852 | if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); |
| 111541 | 111853 | } |
| 111542 | 111854 | pCol->zName = zName; |
| 111543 | 111855 | sqlite3ColumnPropertiesFromName(0, pCol); |
| 111544 | 111856 | if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ |
| 111545 | - db->mallocFailed = 1; | |
| 111857 | + sqlite3OomFault(db); | |
| 111546 | 111858 | } |
| 111547 | 111859 | } |
| 111548 | 111860 | sqlite3HashClear(&ht); |
| 111549 | 111861 | if( db->mallocFailed ){ |
| 111550 | 111862 | for(j=0; j<i; j++){ |
| @@ -111627,11 +111939,11 @@ | ||
| 111627 | 111939 | if( pTab==0 ){ |
| 111628 | 111940 | return 0; |
| 111629 | 111941 | } |
| 111630 | 111942 | /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside |
| 111631 | 111943 | ** is disabled */ |
| 111632 | - assert( db->lookaside.bEnabled==0 ); | |
| 111944 | + assert( db->lookaside.bDisable ); | |
| 111633 | 111945 | pTab->nRef = 1; |
| 111634 | 111946 | pTab->zName = 0; |
| 111635 | 111947 | pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 111636 | 111948 | sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
| 111637 | 111949 | selectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
| @@ -111723,14 +112035,12 @@ | ||
| 111723 | 112035 | p->iOffset = iOffset = ++pParse->nMem; |
| 111724 | 112036 | pParse->nMem++; /* Allocate an extra register for limit+offset */ |
| 111725 | 112037 | sqlite3ExprCode(pParse, p->pOffset, iOffset); |
| 111726 | 112038 | sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); |
| 111727 | 112039 | VdbeComment((v, "OFFSET counter")); |
| 111728 | - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0); | |
| 111729 | - sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); | |
| 112040 | + sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); | |
| 111730 | 112041 | VdbeComment((v, "LIMIT+OFFSET")); |
| 111731 | - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1); | |
| 111732 | 112042 | } |
| 111733 | 112043 | } |
| 111734 | 112044 | } |
| 111735 | 112045 | |
| 111736 | 112046 | #ifndef SQLITE_OMIT_COMPOUND_SELECT |
| @@ -112143,13 +112453,12 @@ | ||
| 112143 | 112453 | p->iOffset = pPrior->iOffset; |
| 112144 | 112454 | if( p->iLimit ){ |
| 112145 | 112455 | addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); |
| 112146 | 112456 | VdbeComment((v, "Jump ahead if LIMIT reached")); |
| 112147 | 112457 | if( p->iOffset ){ |
| 112148 | - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0); | |
| 112149 | - sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1); | |
| 112150 | - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1); | |
| 112458 | + sqlite3VdbeAddOp3(v, OP_OffsetLimit, | |
| 112459 | + p->iLimit, p->iOffset+1, p->iOffset); | |
| 112151 | 112460 | } |
| 112152 | 112461 | } |
| 112153 | 112462 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 112154 | 112463 | rc = sqlite3Select(pParse, p, &dest); |
| 112155 | 112464 | testcase( rc!=SQLITE_OK ); |
| @@ -112736,14 +113045,15 @@ | ||
| 112736 | 113045 | ** row of results comes from selectA or selectB. Also add explicit |
| 112737 | 113046 | ** collations to the ORDER BY clause terms so that when the subqueries |
| 112738 | 113047 | ** to the right and the left are evaluated, they use the correct |
| 112739 | 113048 | ** collation. |
| 112740 | 113049 | */ |
| 112741 | - aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); | |
| 113050 | + aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1)); | |
| 112742 | 113051 | if( aPermute ){ |
| 112743 | 113052 | struct ExprList_item *pItem; |
| 112744 | - for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ | |
| 113053 | + aPermute[0] = nOrderBy; | |
| 113054 | + for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ | |
| 112745 | 113055 | assert( pItem->u.x.iOrderByCol>0 ); |
| 112746 | 113056 | assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
| 112747 | 113057 | aPermute[i] = pItem->u.x.iOrderByCol - 1; |
| 112748 | 113058 | } |
| 112749 | 113059 | pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); |
| @@ -112817,11 +113127,11 @@ | ||
| 112817 | 113127 | addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
| 112818 | 113128 | VdbeComment((v, "left SELECT")); |
| 112819 | 113129 | pPrior->iLimit = regLimitA; |
| 112820 | 113130 | explainSetInteger(iSub1, pParse->iNextSelectId); |
| 112821 | 113131 | sqlite3Select(pParse, pPrior, &destA); |
| 112822 | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA); | |
| 113132 | + sqlite3VdbeEndCoroutine(v, regAddrA); | |
| 112823 | 113133 | sqlite3VdbeJumpHere(v, addr1); |
| 112824 | 113134 | |
| 112825 | 113135 | /* Generate a coroutine to evaluate the SELECT statement on |
| 112826 | 113136 | ** the right - the "B" select |
| 112827 | 113137 | */ |
| @@ -112834,11 +113144,11 @@ | ||
| 112834 | 113144 | p->iOffset = 0; |
| 112835 | 113145 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 112836 | 113146 | sqlite3Select(pParse, p, &destB); |
| 112837 | 113147 | p->iLimit = savedLimit; |
| 112838 | 113148 | p->iOffset = savedOffset; |
| 112839 | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB); | |
| 113149 | + sqlite3VdbeEndCoroutine(v, regAddrB); | |
| 112840 | 113150 | |
| 112841 | 113151 | /* Generate a subroutine that outputs the current row of the A |
| 112842 | 113152 | ** select as the next output row of the compound select. |
| 112843 | 113153 | */ |
| 112844 | 113154 | VdbeNoopComment((v, "Output routine for A")); |
| @@ -114301,12 +114611,11 @@ | ||
| 114301 | 114611 | } |
| 114302 | 114612 | }else{ |
| 114303 | 114613 | pExpr = pRight; |
| 114304 | 114614 | } |
| 114305 | 114615 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 114306 | - sColname.z = zColname; | |
| 114307 | - sColname.n = sqlite3Strlen30(zColname); | |
| 114616 | + sqlite3TokenInit(&sColname, zColname); | |
| 114308 | 114617 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 114309 | 114618 | if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ |
| 114310 | 114619 | struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; |
| 114311 | 114620 | if( pSub ){ |
| 114312 | 114621 | pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); |
| @@ -114856,11 +115165,11 @@ | ||
| 114856 | 115165 | explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
| 114857 | 115166 | sqlite3Select(pParse, pSub, &dest); |
| 114858 | 115167 | pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); |
| 114859 | 115168 | pItem->fg.viaCoroutine = 1; |
| 114860 | 115169 | pItem->regResult = dest.iSdst; |
| 114861 | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); | |
| 115170 | + sqlite3VdbeEndCoroutine(v, pItem->regReturn); | |
| 114862 | 115171 | sqlite3VdbeJumpHere(v, addrTop-1); |
| 114863 | 115172 | sqlite3ClearTempRegCache(pParse); |
| 114864 | 115173 | }else{ |
| 114865 | 115174 | /* Generate a subroutine that will fill an ephemeral table with |
| 114866 | 115175 | ** the content of this subquery. pItem->addrFillSub will point |
| @@ -115428,11 +115737,12 @@ | ||
| 115428 | 115737 | assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); |
| 115429 | 115738 | |
| 115430 | 115739 | if( flag ){ |
| 115431 | 115740 | pMinMax = sqlite3ExprListDup(db, pMinMax, 0); |
| 115432 | 115741 | pDel = pMinMax; |
| 115433 | - if( pMinMax && !db->mallocFailed ){ | |
| 115742 | + assert( db->mallocFailed || pMinMax!=0 ); | |
| 115743 | + if( !db->mallocFailed ){ | |
| 115434 | 115744 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 115435 | 115745 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 115436 | 115746 | } |
| 115437 | 115747 | } |
| 115438 | 115748 | |
| @@ -116001,12 +116311,11 @@ | ||
| 116001 | 116311 | pTrig->step_list = pStepList; |
| 116002 | 116312 | while( pStepList ){ |
| 116003 | 116313 | pStepList->pTrig = pTrig; |
| 116004 | 116314 | pStepList = pStepList->pNext; |
| 116005 | 116315 | } |
| 116006 | - nameToken.z = pTrig->zName; | |
| 116007 | - nameToken.n = sqlite3Strlen30(nameToken.z); | |
| 116316 | + sqlite3TokenInit(&nameToken, pTrig->zName); | |
| 116008 | 116317 | sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
| 116009 | 116318 | if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) |
| 116010 | 116319 | || sqlite3FixExpr(&sFix, pTrig->pWhen) |
| 116011 | 116320 | ){ |
| 116012 | 116321 | goto triggerfinish_cleanup; |
| @@ -116038,11 +116347,11 @@ | ||
| 116038 | 116347 | Trigger *pLink = pTrig; |
| 116039 | 116348 | Hash *pHash = &db->aDb[iDb].pSchema->trigHash; |
| 116040 | 116349 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 116041 | 116350 | pTrig = sqlite3HashInsert(pHash, zName, pTrig); |
| 116042 | 116351 | if( pTrig ){ |
| 116043 | - db->mallocFailed = 1; | |
| 116352 | + sqlite3OomFault(db); | |
| 116044 | 116353 | }else if( pLink->pSchema==pLink->pTabSchema ){ |
| 116045 | 116354 | Table *pTab; |
| 116046 | 116355 | pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); |
| 116047 | 116356 | assert( pTab!=0 ); |
| 116048 | 116357 | pLink->pNext = pTab->pTrigger; |
| @@ -117014,11 +117323,11 @@ | ||
| 117014 | 117323 | } |
| 117015 | 117324 | |
| 117016 | 117325 | /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. |
| 117017 | 117326 | ** Initialize aXRef[] and aToOpen[] to their default values. |
| 117018 | 117327 | */ |
| 117019 | - aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); | |
| 117328 | + aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); | |
| 117020 | 117329 | if( aXRef==0 ) goto update_cleanup; |
| 117021 | 117330 | aRegIdx = aXRef+pTab->nCol; |
| 117022 | 117331 | aToOpen = (u8*)(aRegIdx+nIdx); |
| 117023 | 117332 | memset(aToOpen, 1, nIdx+1); |
| 117024 | 117333 | aToOpen[nIdx+1] = 0; |
| @@ -118054,11 +118363,11 @@ | ||
| 118054 | 118363 | nName = sqlite3Strlen30(zName); |
| 118055 | 118364 | if( sqlite3HashFind(&db->aModule, zName) ){ |
| 118056 | 118365 | rc = SQLITE_MISUSE_BKPT; |
| 118057 | 118366 | }else{ |
| 118058 | 118367 | Module *pMod; |
| 118059 | - pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); | |
| 118368 | + pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); | |
| 118060 | 118369 | if( pMod ){ |
| 118061 | 118370 | Module *pDel; |
| 118062 | 118371 | char *zCopy = (char *)(&pMod[1]); |
| 118063 | 118372 | memcpy(zCopy, zName, nName+1); |
| 118064 | 118373 | pMod->zName = zCopy; |
| @@ -118067,11 +118376,11 @@ | ||
| 118067 | 118376 | pMod->xDestroy = xDestroy; |
| 118068 | 118377 | pMod->pEpoTab = 0; |
| 118069 | 118378 | pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); |
| 118070 | 118379 | assert( pDel==0 || pDel==pMod ); |
| 118071 | 118380 | if( pDel ){ |
| 118072 | - db->mallocFailed = 1; | |
| 118381 | + sqlite3OomFault(db); | |
| 118073 | 118382 | sqlite3DbFree(db, pDel); |
| 118074 | 118383 | } |
| 118075 | 118384 | } |
| 118076 | 118385 | } |
| 118077 | 118386 | rc = sqlite3ApiExit(db, rc); |
| @@ -118444,11 +118753,11 @@ | ||
| 118444 | 118753 | Schema *pSchema = pTab->pSchema; |
| 118445 | 118754 | const char *zName = pTab->zName; |
| 118446 | 118755 | assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); |
| 118447 | 118756 | pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); |
| 118448 | 118757 | if( pOld ){ |
| 118449 | - db->mallocFailed = 1; | |
| 118758 | + sqlite3OomFault(db); | |
| 118450 | 118759 | assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 118451 | 118760 | return; |
| 118452 | 118761 | } |
| 118453 | 118762 | pParse->pNewTable = 0; |
| 118454 | 118763 | } |
| @@ -118535,11 +118844,11 @@ | ||
| 118535 | 118844 | sCtx.pPrior = db->pVtabCtx; |
| 118536 | 118845 | sCtx.bDeclared = 0; |
| 118537 | 118846 | db->pVtabCtx = &sCtx; |
| 118538 | 118847 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 118539 | 118848 | db->pVtabCtx = sCtx.pPrior; |
| 118540 | - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; | |
| 118849 | + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); | |
| 118541 | 118850 | assert( sCtx.pTab==pTab ); |
| 118542 | 118851 | |
| 118543 | 118852 | if( SQLITE_OK!=rc ){ |
| 118544 | 118853 | if( zErr==0 ){ |
| 118545 | 118854 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| @@ -119093,11 +119402,11 @@ | ||
| 119093 | 119402 | apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); |
| 119094 | 119403 | if( apVtabLock ){ |
| 119095 | 119404 | pToplevel->apVtabLock = apVtabLock; |
| 119096 | 119405 | pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; |
| 119097 | 119406 | }else{ |
| 119098 | - pToplevel->db->mallocFailed = 1; | |
| 119407 | + sqlite3OomFault(pToplevel->db); | |
| 119099 | 119408 | } |
| 119100 | 119409 | } |
| 119101 | 119410 | |
| 119102 | 119411 | /* |
| 119103 | 119412 | ** Check to see if virtual tale module pMod can be have an eponymous |
| @@ -119835,11 +120144,11 @@ | ||
| 119835 | 120144 | if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; |
| 119836 | 120145 | sqlite3StrAccumAppend(pStr, " (", 2); |
| 119837 | 120146 | for(i=0; i<nEq; i++){ |
| 119838 | 120147 | const char *z = explainIndexColumnName(pIndex, i); |
| 119839 | 120148 | if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5); |
| 119840 | - sqlite3XPrintf(pStr, 0, i>=nSkip ? "%s=?" : "ANY(%s)", z); | |
| 120149 | + sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); | |
| 119841 | 120150 | } |
| 119842 | 120151 | |
| 119843 | 120152 | j = i; |
| 119844 | 120153 | if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ |
| 119845 | 120154 | const char *z = explainIndexColumnName(pIndex, i); |
| @@ -119894,17 +120203,17 @@ | ||
| 119894 | 120203 | || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); |
| 119895 | 120204 | |
| 119896 | 120205 | sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); |
| 119897 | 120206 | sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); |
| 119898 | 120207 | if( pItem->pSelect ){ |
| 119899 | - sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); | |
| 120208 | + sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); | |
| 119900 | 120209 | }else{ |
| 119901 | - sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName); | |
| 120210 | + sqlite3XPrintf(&str, " TABLE %s", pItem->zName); | |
| 119902 | 120211 | } |
| 119903 | 120212 | |
| 119904 | 120213 | if( pItem->zAlias ){ |
| 119905 | - sqlite3XPrintf(&str, 0, " AS %s", pItem->zAlias); | |
| 120214 | + sqlite3XPrintf(&str, " AS %s", pItem->zAlias); | |
| 119906 | 120215 | } |
| 119907 | 120216 | if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ |
| 119908 | 120217 | const char *zFmt = 0; |
| 119909 | 120218 | Index *pIdx; |
| 119910 | 120219 | |
| @@ -119924,11 +120233,11 @@ | ||
| 119924 | 120233 | }else{ |
| 119925 | 120234 | zFmt = "INDEX %s"; |
| 119926 | 120235 | } |
| 119927 | 120236 | if( zFmt ){ |
| 119928 | 120237 | sqlite3StrAccumAppend(&str, " USING ", 7); |
| 119929 | - sqlite3XPrintf(&str, 0, zFmt, pIdx->zName); | |
| 120238 | + sqlite3XPrintf(&str, zFmt, pIdx->zName); | |
| 119930 | 120239 | explainIndexRange(&str, pLoop); |
| 119931 | 120240 | } |
| 119932 | 120241 | }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ |
| 119933 | 120242 | const char *zRangeOp; |
| 119934 | 120243 | if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ |
| @@ -119939,21 +120248,21 @@ | ||
| 119939 | 120248 | zRangeOp = ">"; |
| 119940 | 120249 | }else{ |
| 119941 | 120250 | assert( flags&WHERE_TOP_LIMIT); |
| 119942 | 120251 | zRangeOp = "<"; |
| 119943 | 120252 | } |
| 119944 | - sqlite3XPrintf(&str, 0, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); | |
| 120253 | + sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); | |
| 119945 | 120254 | } |
| 119946 | 120255 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 119947 | 120256 | else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ |
| 119948 | - sqlite3XPrintf(&str, 0, " VIRTUAL TABLE INDEX %d:%s", | |
| 120257 | + sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", | |
| 119949 | 120258 | pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); |
| 119950 | 120259 | } |
| 119951 | 120260 | #endif |
| 119952 | 120261 | #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS |
| 119953 | 120262 | if( pLoop->nOut>=10 ){ |
| 119954 | - sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); | |
| 120263 | + sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); | |
| 119955 | 120264 | }else{ |
| 119956 | 120265 | sqlite3StrAccumAppend(&str, " (~1 row)", 9); |
| 119957 | 120266 | } |
| 119958 | 120267 | #endif |
| 119959 | 120268 | zMsg = sqlite3StrAccumFinish(&str); |
| @@ -120254,13 +120563,11 @@ | ||
| 120254 | 120563 | regBase = pParse->nMem + 1; |
| 120255 | 120564 | nReg = pLoop->u.btree.nEq + nExtraReg; |
| 120256 | 120565 | pParse->nMem += nReg; |
| 120257 | 120566 | |
| 120258 | 120567 | zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); |
| 120259 | - if( !zAff ){ | |
| 120260 | - pParse->db->mallocFailed = 1; | |
| 120261 | - } | |
| 120568 | + assert( zAff!=0 || pParse->db->mallocFailed ); | |
| 120262 | 120569 | |
| 120263 | 120570 | if( nSkip ){ |
| 120264 | 120571 | int iIdxCur = pLevel->iIdxCur; |
| 120265 | 120572 | sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); |
| 120266 | 120573 | VdbeCoverageIf(v, bRev==0); |
| @@ -120504,10 +120811,58 @@ | ||
| 120504 | 120811 | } |
| 120505 | 120812 | } |
| 120506 | 120813 | #else |
| 120507 | 120814 | # define codeCursorHint(A,B,C) /* No-op */ |
| 120508 | 120815 | #endif /* SQLITE_ENABLE_CURSOR_HINTS */ |
| 120816 | + | |
| 120817 | +/* | |
| 120818 | +** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains | |
| 120819 | +** a rowid value just read from cursor iIdxCur, open on index pIdx. This | |
| 120820 | +** function generates code to do a deferred seek of cursor iCur to the | |
| 120821 | +** rowid stored in register iRowid. | |
| 120822 | +** | |
| 120823 | +** Normally, this is just: | |
| 120824 | +** | |
| 120825 | +** OP_Seek $iCur $iRowid | |
| 120826 | +** | |
| 120827 | +** However, if the scan currently being coded is a branch of an OR-loop and | |
| 120828 | +** the statement currently being coded is a SELECT, then P3 of the OP_Seek | |
| 120829 | +** is set to iIdxCur and P4 is set to point to an array of integers | |
| 120830 | +** containing one entry for each column of the table cursor iCur is open | |
| 120831 | +** on. For each table column, if the column is the i'th column of the | |
| 120832 | +** index, then the corresponding array entry is set to (i+1). If the column | |
| 120833 | +** does not appear in the index at all, the array entry is set to 0. | |
| 120834 | +*/ | |
| 120835 | +static void codeDeferredSeek( | |
| 120836 | + WhereInfo *pWInfo, /* Where clause context */ | |
| 120837 | + Index *pIdx, /* Index scan is using */ | |
| 120838 | + int iCur, /* Cursor for IPK b-tree */ | |
| 120839 | + int iIdxCur /* Index cursor */ | |
| 120840 | +){ | |
| 120841 | + Parse *pParse = pWInfo->pParse; /* Parse context */ | |
| 120842 | + Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ | |
| 120843 | + | |
| 120844 | + assert( iIdxCur>0 ); | |
| 120845 | + assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); | |
| 120846 | + | |
| 120847 | + sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur); | |
| 120848 | + if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE) | |
| 120849 | + && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) | |
| 120850 | + ){ | |
| 120851 | + int i; | |
| 120852 | + Table *pTab = pIdx->pTable; | |
| 120853 | + int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1)); | |
| 120854 | + if( ai ){ | |
| 120855 | + ai[0] = pTab->nCol; | |
| 120856 | + for(i=0; i<pIdx->nColumn-1; i++){ | |
| 120857 | + assert( pIdx->aiColumn[i]<pTab->nCol ); | |
| 120858 | + if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1; | |
| 120859 | + } | |
| 120860 | + sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); | |
| 120861 | + } | |
| 120862 | + } | |
| 120863 | +} | |
| 120509 | 120864 | |
| 120510 | 120865 | /* |
| 120511 | 120866 | ** Generate code for the start of the iLevel-th loop in the WHERE clause |
| 120512 | 120867 | ** implementation described by pWInfo. |
| 120513 | 120868 | */ |
| @@ -120984,18 +121339,18 @@ | ||
| 120984 | 121339 | disableTerm(pLevel, pRangeStart); |
| 120985 | 121340 | disableTerm(pLevel, pRangeEnd); |
| 120986 | 121341 | if( omitTable ){ |
| 120987 | 121342 | /* pIdx is a covering index. No need to access the main table. */ |
| 120988 | 121343 | }else if( HasRowid(pIdx->pTable) ){ |
| 120989 | - iRowidReg = ++pParse->nMem; | |
| 120990 | - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); | |
| 120991 | - sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); | |
| 120992 | 121344 | if( pWInfo->eOnePass!=ONEPASS_OFF ){ |
| 121345 | + iRowidReg = ++pParse->nMem; | |
| 121346 | + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); | |
| 121347 | + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); | |
| 120993 | 121348 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); |
| 120994 | 121349 | VdbeCoverage(v); |
| 120995 | 121350 | }else{ |
| 120996 | - sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ | |
| 121351 | + codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); | |
| 120997 | 121352 | } |
| 120998 | 121353 | }else if( iCur!=iIdxCur ){ |
| 120999 | 121354 | Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); |
| 121000 | 121355 | iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); |
| 121001 | 121356 | for(j=0; j<pPk->nKeyCol; j++){ |
| @@ -121160,11 +121515,13 @@ | ||
| 121160 | 121515 | int iTerm; |
| 121161 | 121516 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 121162 | 121517 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 121163 | 121518 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 121164 | 121519 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 121165 | - if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; | |
| 121520 | + testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); | |
| 121521 | + testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); | |
| 121522 | + if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; | |
| 121166 | 121523 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 121167 | 121524 | testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); |
| 121168 | 121525 | pExpr = sqlite3ExprDup(db, pExpr, 0); |
| 121169 | 121526 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
| 121170 | 121527 | } |
| @@ -121500,11 +121857,11 @@ | ||
| 121500 | 121857 | int idx; |
| 121501 | 121858 | testcase( wtFlags & TERM_VIRTUAL ); |
| 121502 | 121859 | if( pWC->nTerm>=pWC->nSlot ){ |
| 121503 | 121860 | WhereTerm *pOld = pWC->a; |
| 121504 | 121861 | sqlite3 *db = pWC->pWInfo->pParse->db; |
| 121505 | - pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); | |
| 121862 | + pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); | |
| 121506 | 121863 | if( pWC->a==0 ){ |
| 121507 | 121864 | if( wtFlags & TERM_DYNAMIC ){ |
| 121508 | 121865 | sqlite3ExprDelete(db, p); |
| 121509 | 121866 | } |
| 121510 | 121867 | pWC->a = pOld; |
| @@ -121985,11 +122342,11 @@ | ||
| 121985 | 122342 | for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ |
| 121986 | 122343 | if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ |
| 121987 | 122344 | WhereAndInfo *pAndInfo; |
| 121988 | 122345 | assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); |
| 121989 | 122346 | chngToIN = 0; |
| 121990 | - pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); | |
| 122347 | + pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo)); | |
| 121991 | 122348 | if( pAndInfo ){ |
| 121992 | 122349 | WhereClause *pAndWC; |
| 121993 | 122350 | WhereTerm *pAndTerm; |
| 121994 | 122351 | int j; |
| 121995 | 122352 | Bitmask b = 0; |
| @@ -121999,11 +122356,10 @@ | ||
| 121999 | 122356 | pAndWC = &pAndInfo->wc; |
| 122000 | 122357 | sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); |
| 122001 | 122358 | sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); |
| 122002 | 122359 | sqlite3WhereExprAnalyze(pSrc, pAndWC); |
| 122003 | 122360 | pAndWC->pOuter = pWC; |
| 122004 | - testcase( db->mallocFailed ); | |
| 122005 | 122361 | if( !db->mallocFailed ){ |
| 122006 | 122362 | for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ |
| 122007 | 122363 | assert( pAndTerm->pExpr ); |
| 122008 | 122364 | if( allowedOp(pAndTerm->pExpr->op) ){ |
| 122009 | 122365 | b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); |
| @@ -123742,11 +124098,11 @@ | ||
| 123742 | 124098 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 123743 | 124099 | TRACE_IDX_OUTPUTS(p); |
| 123744 | 124100 | |
| 123745 | 124101 | if( rc!=SQLITE_OK ){ |
| 123746 | 124102 | if( rc==SQLITE_NOMEM ){ |
| 123747 | - pParse->db->mallocFailed = 1; | |
| 124103 | + sqlite3OomFault(pParse->db); | |
| 123748 | 124104 | }else if( !pVtab->zErrMsg ){ |
| 123749 | 124105 | sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); |
| 123750 | 124106 | }else{ |
| 123751 | 124107 | sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); |
| 123752 | 124108 | } |
| @@ -124534,11 +124890,11 @@ | ||
| 124534 | 124890 | */ |
| 124535 | 124891 | static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ |
| 124536 | 124892 | WhereTerm **paNew; |
| 124537 | 124893 | if( p->nLSlot>=n ) return SQLITE_OK; |
| 124538 | 124894 | n = (n+7)&~7; |
| 124539 | - paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n); | |
| 124895 | + paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); | |
| 124540 | 124896 | if( paNew==0 ) return SQLITE_NOMEM; |
| 124541 | 124897 | memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); |
| 124542 | 124898 | if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm); |
| 124543 | 124899 | p->aLTerm = paNew; |
| 124544 | 124900 | p->nLSlot = n; |
| @@ -124831,11 +125187,11 @@ | ||
| 124831 | 125187 | whereLoopPrint(pTemplate, pBuilder->pWC); |
| 124832 | 125188 | } |
| 124833 | 125189 | #endif |
| 124834 | 125190 | if( p==0 ){ |
| 124835 | 125191 | /* Allocate a new WhereLoop to add to the end of the list */ |
| 124836 | - *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); | |
| 125192 | + *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); | |
| 124837 | 125193 | if( p==0 ) return SQLITE_NOMEM; |
| 124838 | 125194 | whereLoopInit(p); |
| 124839 | 125195 | p->pNextLoop = 0; |
| 124840 | 125196 | }else{ |
| 124841 | 125197 | /* We will be overwriting WhereLoop p[]. But before we do, first |
| @@ -126328,11 +126684,11 @@ | ||
| 126328 | 126684 | } |
| 126329 | 126685 | |
| 126330 | 126686 | /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ |
| 126331 | 126687 | nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; |
| 126332 | 126688 | nSpace += sizeof(LogEst) * nOrderBy; |
| 126333 | - pSpace = sqlite3DbMallocRaw(db, nSpace); | |
| 126689 | + pSpace = sqlite3DbMallocRawNN(db, nSpace); | |
| 126334 | 126690 | if( pSpace==0 ) return SQLITE_NOMEM; |
| 126335 | 126691 | aTo = (WherePath*)pSpace; |
| 126336 | 126692 | aFrom = aTo+mxChoice; |
| 126337 | 126693 | memset(aFrom, 0, sizeof(aFrom[0])); |
| 126338 | 126694 | pX = (WhereLoop**)(aFrom+mxChoice); |
| @@ -126813,11 +127169,11 @@ | ||
| 126813 | 127169 | WhereLevel *pLevel; /* A single level in pWInfo->a[] */ |
| 126814 | 127170 | WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ |
| 126815 | 127171 | int ii; /* Loop counter */ |
| 126816 | 127172 | sqlite3 *db; /* Database connection */ |
| 126817 | 127173 | int rc; /* Return code */ |
| 126818 | - u8 bFordelete = 0; | |
| 127174 | + u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */ | |
| 126819 | 127175 | |
| 126820 | 127176 | assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( |
| 126821 | 127177 | (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 |
| 126822 | 127178 | && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 |
| 126823 | 127179 | )); |
| @@ -127058,20 +127414,19 @@ | ||
| 127058 | 127414 | WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); |
| 127059 | 127415 | pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; |
| 127060 | 127416 | |
| 127061 | 127417 | /* If the caller is an UPDATE or DELETE statement that is requesting |
| 127062 | 127418 | ** to use a one-pass algorithm, determine if this is appropriate. |
| 127063 | - ** The one-pass algorithm only works if the WHERE clause constrains | |
| 127064 | - ** the statement to update or delete a single row. | |
| 127065 | 127419 | */ |
| 127066 | 127420 | assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); |
| 127067 | 127421 | if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ |
| 127068 | 127422 | int wsFlags = pWInfo->a[0].pWLoop->wsFlags; |
| 127069 | 127423 | int bOnerow = (wsFlags & WHERE_ONEROW)!=0; |
| 127070 | - if( bOnerow || ( (wctrlFlags & WHERE_ONEPASS_MULTIROW) | |
| 127071 | - && 0==(wsFlags & WHERE_VIRTUALTABLE) | |
| 127072 | - )){ | |
| 127424 | + if( bOnerow | |
| 127425 | + || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0 | |
| 127426 | + && 0==(wsFlags & WHERE_VIRTUALTABLE)) | |
| 127427 | + ){ | |
| 127073 | 127428 | pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; |
| 127074 | 127429 | if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ |
| 127075 | 127430 | if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ |
| 127076 | 127431 | bFordelete = OPFLAG_FORDELETE; |
| 127077 | 127432 | } |
| @@ -127511,10 +127866,19 @@ | ||
| 127511 | 127866 | /* |
| 127512 | 127867 | ** An instance of this structure holds the ATTACH key and the key type. |
| 127513 | 127868 | */ |
| 127514 | 127869 | struct AttachKey { int type; Token key; }; |
| 127515 | 127870 | |
| 127871 | +/* | |
| 127872 | +** Disable lookaside memory allocation for objects that might be | |
| 127873 | +** shared across database connections. | |
| 127874 | +*/ | |
| 127875 | +static void disableLookaside(Parse *pParse){ | |
| 127876 | + pParse->disableLookaside++; | |
| 127877 | + pParse->db->lookaside.bDisable++; | |
| 127878 | +} | |
| 127879 | + | |
| 127516 | 127880 | |
| 127517 | 127881 | /* |
| 127518 | 127882 | ** For a compound SELECT statement, make sure p->pPrior->pNext==p for |
| 127519 | 127883 | ** all elements in the list. And make sure list length does not exceed |
| 127520 | 127884 | ** SQLITE_LIMIT_COMPOUND_SELECT. |
| @@ -127593,11 +127957,11 @@ | ||
| 127593 | 127957 | |
| 127594 | 127958 | /* A routine to convert a binary TK_IS or TK_ISNOT expression into a |
| 127595 | 127959 | ** unary TK_ISNULL or TK_NOTNULL expression. */ |
| 127596 | 127960 | static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ |
| 127597 | 127961 | sqlite3 *db = pParse->db; |
| 127598 | - if( pY && pA && pY->op==TK_NULL ){ | |
| 127962 | + if( pA && pY && pY->op==TK_NULL ){ | |
| 127599 | 127963 | pA->op = (u8)op; |
| 127600 | 127964 | sqlite3ExprDelete(db, pA->pRight); |
| 127601 | 127965 | pA->pRight = 0; |
| 127602 | 127966 | } |
| 127603 | 127967 | } |
| @@ -129635,11 +129999,11 @@ | ||
| 129635 | 129999 | sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); |
| 129636 | 130000 | } |
| 129637 | 130001 | break; |
| 129638 | 130002 | case 27: /* createkw ::= CREATE */ |
| 129639 | 130003 | { |
| 129640 | - pParse->db->lookaside.bEnabled = 0; | |
| 130004 | + disableLookaside(pParse); | |
| 129641 | 130005 | yygotominor.yy0 = yymsp[0].minor.yy0; |
| 129642 | 130006 | } |
| 129643 | 130007 | break; |
| 129644 | 130008 | case 28: /* ifnotexists ::= */ |
| 129645 | 130009 | case 31: /* temp ::= */ yytestcase(yyruleno==31); |
| @@ -130717,11 +131081,11 @@ | ||
| 130717 | 131081 | sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); |
| 130718 | 131082 | } |
| 130719 | 131083 | break; |
| 130720 | 131084 | case 307: /* add_column_fullname ::= fullname */ |
| 130721 | 131085 | { |
| 130722 | - pParse->db->lookaside.bEnabled = 0; | |
| 131086 | + disableLookaside(pParse); | |
| 130723 | 131087 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); |
| 130724 | 131088 | } |
| 130725 | 131089 | break; |
| 130726 | 131090 | case 310: /* cmd ::= create_vtab */ |
| 130727 | 131091 | {sqlite3VtabFinishParse(pParse,0);} |
| @@ -131097,16 +131461,96 @@ | ||
| 131097 | 131461 | ** parser for analysis. |
| 131098 | 131462 | */ |
| 131099 | 131463 | /* #include "sqliteInt.h" */ |
| 131100 | 131464 | /* #include <stdlib.h> */ |
| 131101 | 131465 | |
| 131466 | +/* Character classes for tokenizing | |
| 131467 | +** | |
| 131468 | +** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented | |
| 131469 | +** using a lookup table, whereas a switch() directly on c uses a binary search. | |
| 131470 | +** The lookup table is much faster. To maximize speed, and to ensure that | |
| 131471 | +** a lookup table is used, all of the classes need to be small integers and | |
| 131472 | +** all of them need to be used within the switch. | |
| 131473 | +*/ | |
| 131474 | +#define CC_X 0 /* The letter 'x', or start of BLOB literal */ | |
| 131475 | +#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */ | |
| 131476 | +#define CC_ID 2 /* unicode characters usable in IDs */ | |
| 131477 | +#define CC_DIGIT 3 /* Digits */ | |
| 131478 | +#define CC_DOLLAR 4 /* '$' */ | |
| 131479 | +#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */ | |
| 131480 | +#define CC_VARNUM 6 /* '?'. Numeric SQL variables */ | |
| 131481 | +#define CC_SPACE 7 /* Space characters */ | |
| 131482 | +#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */ | |
| 131483 | +#define CC_QUOTE2 9 /* '['. [...] style quoted ids */ | |
| 131484 | +#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */ | |
| 131485 | +#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */ | |
| 131486 | +#define CC_LT 12 /* '<'. Part of < or <= or <> */ | |
| 131487 | +#define CC_GT 13 /* '>'. Part of > or >= */ | |
| 131488 | +#define CC_EQ 14 /* '='. Part of = or == */ | |
| 131489 | +#define CC_BANG 15 /* '!'. Part of != */ | |
| 131490 | +#define CC_SLASH 16 /* '/'. / or c-style comment */ | |
| 131491 | +#define CC_LP 17 /* '(' */ | |
| 131492 | +#define CC_RP 18 /* ')' */ | |
| 131493 | +#define CC_SEMI 19 /* ';' */ | |
| 131494 | +#define CC_PLUS 20 /* '+' */ | |
| 131495 | +#define CC_STAR 21 /* '*' */ | |
| 131496 | +#define CC_PERCENT 22 /* '%' */ | |
| 131497 | +#define CC_COMMA 23 /* ',' */ | |
| 131498 | +#define CC_AND 24 /* '&' */ | |
| 131499 | +#define CC_TILDA 25 /* '~' */ | |
| 131500 | +#define CC_DOT 26 /* '.' */ | |
| 131501 | +#define CC_ILLEGAL 27 /* Illegal character */ | |
| 131502 | + | |
| 131503 | +static const unsigned char aiClass[] = { | |
| 131504 | +#ifdef SQLITE_ASCII | |
| 131505 | +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ | |
| 131506 | +/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, | |
| 131507 | +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, | |
| 131508 | +/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, | |
| 131509 | +/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, | |
| 131510 | +/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
| 131511 | +/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1, | |
| 131512 | +/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
| 131513 | +/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27, | |
| 131514 | +/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
| 131515 | +/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
| 131516 | +/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
| 131517 | +/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
| 131518 | +/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
| 131519 | +/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
| 131520 | +/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
| 131521 | +/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | |
| 131522 | +#endif | |
| 131523 | +#ifdef SQLITE_EBCDIC | |
| 131524 | +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ | |
| 131525 | +/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27, | |
| 131526 | +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, | |
| 131527 | +/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, | |
| 131528 | +/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, | |
| 131529 | +/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 12, 17, 20, 10, | |
| 131530 | +/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27, | |
| 131531 | +/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 7, | |
| 131532 | +/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8, | |
| 131533 | +/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, | |
| 131534 | +/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, | |
| 131535 | +/* 9x */ 25, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, | |
| 131536 | +/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, | |
| 131537 | +/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, | |
| 131538 | +/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, | |
| 131539 | +/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, | |
| 131540 | +/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, | |
| 131541 | +#endif | |
| 131542 | +}; | |
| 131543 | + | |
| 131102 | 131544 | /* |
| 131103 | -** The charMap() macro maps alphabetic characters into their | |
| 131545 | +** The charMap() macro maps alphabetic characters (only) into their | |
| 131104 | 131546 | ** lower-case ASCII equivalent. On ASCII machines, this is just |
| 131105 | 131547 | ** an upper-to-lower case map. On EBCDIC machines we also need |
| 131106 | -** to adjust the encoding. Only alphabetic characters and underscores | |
| 131107 | -** need to be translated. | |
| 131548 | +** to adjust the encoding. The mapping is only valid for alphabetics | |
| 131549 | +** which are the only characters for which this feature is used. | |
| 131550 | +** | |
| 131551 | +** Used by keywordhash.h | |
| 131108 | 131552 | */ |
| 131109 | 131553 | #ifdef SQLITE_ASCII |
| 131110 | 131554 | # define charMap(X) sqlite3UpperToLower[(unsigned char)X] |
| 131111 | 131555 | #endif |
| 131112 | 131556 | #ifdef SQLITE_EBCDIC |
| @@ -131136,11 +131580,11 @@ | ||
| 131136 | 131580 | ** The sqlite3KeywordCode function looks up an identifier to determine if |
| 131137 | 131581 | ** it is a keyword. If it is a keyword, the token code of that keyword is |
| 131138 | 131582 | ** returned. If the input is not a keyword, TK_ID is returned. |
| 131139 | 131583 | ** |
| 131140 | 131584 | ** The implementation of this routine was generated by a program, |
| 131141 | -** mkkeywordhash.h, located in the tool subdirectory of the distribution. | |
| 131585 | +** mkkeywordhash.c, located in the tool subdirectory of the distribution. | |
| 131142 | 131586 | ** The output of the mkkeywordhash.c program is written into a file |
| 131143 | 131587 | ** named keywordhash.h and then included into this source file by |
| 131144 | 131588 | ** the #include below. |
| 131145 | 131589 | */ |
| 131146 | 131590 | /************** Include keywordhash.h in the middle of tokenize.c ************/ |
| @@ -131277,142 +131721,151 @@ | ||
| 131277 | 131721 | TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, |
| 131278 | 131722 | TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, |
| 131279 | 131723 | TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, |
| 131280 | 131724 | TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, |
| 131281 | 131725 | }; |
| 131282 | - int h, i; | |
| 131726 | + int i, j; | |
| 131727 | + const char *zKW; | |
| 131283 | 131728 | if( n>=2 ){ |
| 131284 | - h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; | |
| 131285 | - for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ | |
| 131286 | - if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ | |
| 131287 | - testcase( i==0 ); /* REINDEX */ | |
| 131288 | - testcase( i==1 ); /* INDEXED */ | |
| 131289 | - testcase( i==2 ); /* INDEX */ | |
| 131290 | - testcase( i==3 ); /* DESC */ | |
| 131291 | - testcase( i==4 ); /* ESCAPE */ | |
| 131292 | - testcase( i==5 ); /* EACH */ | |
| 131293 | - testcase( i==6 ); /* CHECK */ | |
| 131294 | - testcase( i==7 ); /* KEY */ | |
| 131295 | - testcase( i==8 ); /* BEFORE */ | |
| 131296 | - testcase( i==9 ); /* FOREIGN */ | |
| 131297 | - testcase( i==10 ); /* FOR */ | |
| 131298 | - testcase( i==11 ); /* IGNORE */ | |
| 131299 | - testcase( i==12 ); /* REGEXP */ | |
| 131300 | - testcase( i==13 ); /* EXPLAIN */ | |
| 131301 | - testcase( i==14 ); /* INSTEAD */ | |
| 131302 | - testcase( i==15 ); /* ADD */ | |
| 131303 | - testcase( i==16 ); /* DATABASE */ | |
| 131304 | - testcase( i==17 ); /* AS */ | |
| 131305 | - testcase( i==18 ); /* SELECT */ | |
| 131306 | - testcase( i==19 ); /* TABLE */ | |
| 131307 | - testcase( i==20 ); /* LEFT */ | |
| 131308 | - testcase( i==21 ); /* THEN */ | |
| 131309 | - testcase( i==22 ); /* END */ | |
| 131310 | - testcase( i==23 ); /* DEFERRABLE */ | |
| 131311 | - testcase( i==24 ); /* ELSE */ | |
| 131312 | - testcase( i==25 ); /* EXCEPT */ | |
| 131313 | - testcase( i==26 ); /* TRANSACTION */ | |
| 131314 | - testcase( i==27 ); /* ACTION */ | |
| 131315 | - testcase( i==28 ); /* ON */ | |
| 131316 | - testcase( i==29 ); /* NATURAL */ | |
| 131317 | - testcase( i==30 ); /* ALTER */ | |
| 131318 | - testcase( i==31 ); /* RAISE */ | |
| 131319 | - testcase( i==32 ); /* EXCLUSIVE */ | |
| 131320 | - testcase( i==33 ); /* EXISTS */ | |
| 131321 | - testcase( i==34 ); /* SAVEPOINT */ | |
| 131322 | - testcase( i==35 ); /* INTERSECT */ | |
| 131323 | - testcase( i==36 ); /* TRIGGER */ | |
| 131324 | - testcase( i==37 ); /* REFERENCES */ | |
| 131325 | - testcase( i==38 ); /* CONSTRAINT */ | |
| 131326 | - testcase( i==39 ); /* INTO */ | |
| 131327 | - testcase( i==40 ); /* OFFSET */ | |
| 131328 | - testcase( i==41 ); /* OF */ | |
| 131329 | - testcase( i==42 ); /* SET */ | |
| 131330 | - testcase( i==43 ); /* TEMPORARY */ | |
| 131331 | - testcase( i==44 ); /* TEMP */ | |
| 131332 | - testcase( i==45 ); /* OR */ | |
| 131333 | - testcase( i==46 ); /* UNIQUE */ | |
| 131334 | - testcase( i==47 ); /* QUERY */ | |
| 131335 | - testcase( i==48 ); /* WITHOUT */ | |
| 131336 | - testcase( i==49 ); /* WITH */ | |
| 131337 | - testcase( i==50 ); /* OUTER */ | |
| 131338 | - testcase( i==51 ); /* RELEASE */ | |
| 131339 | - testcase( i==52 ); /* ATTACH */ | |
| 131340 | - testcase( i==53 ); /* HAVING */ | |
| 131341 | - testcase( i==54 ); /* GROUP */ | |
| 131342 | - testcase( i==55 ); /* UPDATE */ | |
| 131343 | - testcase( i==56 ); /* BEGIN */ | |
| 131344 | - testcase( i==57 ); /* INNER */ | |
| 131345 | - testcase( i==58 ); /* RECURSIVE */ | |
| 131346 | - testcase( i==59 ); /* BETWEEN */ | |
| 131347 | - testcase( i==60 ); /* NOTNULL */ | |
| 131348 | - testcase( i==61 ); /* NOT */ | |
| 131349 | - testcase( i==62 ); /* NO */ | |
| 131350 | - testcase( i==63 ); /* NULL */ | |
| 131351 | - testcase( i==64 ); /* LIKE */ | |
| 131352 | - testcase( i==65 ); /* CASCADE */ | |
| 131353 | - testcase( i==66 ); /* ASC */ | |
| 131354 | - testcase( i==67 ); /* DELETE */ | |
| 131355 | - testcase( i==68 ); /* CASE */ | |
| 131356 | - testcase( i==69 ); /* COLLATE */ | |
| 131357 | - testcase( i==70 ); /* CREATE */ | |
| 131358 | - testcase( i==71 ); /* CURRENT_DATE */ | |
| 131359 | - testcase( i==72 ); /* DETACH */ | |
| 131360 | - testcase( i==73 ); /* IMMEDIATE */ | |
| 131361 | - testcase( i==74 ); /* JOIN */ | |
| 131362 | - testcase( i==75 ); /* INSERT */ | |
| 131363 | - testcase( i==76 ); /* MATCH */ | |
| 131364 | - testcase( i==77 ); /* PLAN */ | |
| 131365 | - testcase( i==78 ); /* ANALYZE */ | |
| 131366 | - testcase( i==79 ); /* PRAGMA */ | |
| 131367 | - testcase( i==80 ); /* ABORT */ | |
| 131368 | - testcase( i==81 ); /* VALUES */ | |
| 131369 | - testcase( i==82 ); /* VIRTUAL */ | |
| 131370 | - testcase( i==83 ); /* LIMIT */ | |
| 131371 | - testcase( i==84 ); /* WHEN */ | |
| 131372 | - testcase( i==85 ); /* WHERE */ | |
| 131373 | - testcase( i==86 ); /* RENAME */ | |
| 131374 | - testcase( i==87 ); /* AFTER */ | |
| 131375 | - testcase( i==88 ); /* REPLACE */ | |
| 131376 | - testcase( i==89 ); /* AND */ | |
| 131377 | - testcase( i==90 ); /* DEFAULT */ | |
| 131378 | - testcase( i==91 ); /* AUTOINCREMENT */ | |
| 131379 | - testcase( i==92 ); /* TO */ | |
| 131380 | - testcase( i==93 ); /* IN */ | |
| 131381 | - testcase( i==94 ); /* CAST */ | |
| 131382 | - testcase( i==95 ); /* COLUMN */ | |
| 131383 | - testcase( i==96 ); /* COMMIT */ | |
| 131384 | - testcase( i==97 ); /* CONFLICT */ | |
| 131385 | - testcase( i==98 ); /* CROSS */ | |
| 131386 | - testcase( i==99 ); /* CURRENT_TIMESTAMP */ | |
| 131387 | - testcase( i==100 ); /* CURRENT_TIME */ | |
| 131388 | - testcase( i==101 ); /* PRIMARY */ | |
| 131389 | - testcase( i==102 ); /* DEFERRED */ | |
| 131390 | - testcase( i==103 ); /* DISTINCT */ | |
| 131391 | - testcase( i==104 ); /* IS */ | |
| 131392 | - testcase( i==105 ); /* DROP */ | |
| 131393 | - testcase( i==106 ); /* FAIL */ | |
| 131394 | - testcase( i==107 ); /* FROM */ | |
| 131395 | - testcase( i==108 ); /* FULL */ | |
| 131396 | - testcase( i==109 ); /* GLOB */ | |
| 131397 | - testcase( i==110 ); /* BY */ | |
| 131398 | - testcase( i==111 ); /* IF */ | |
| 131399 | - testcase( i==112 ); /* ISNULL */ | |
| 131400 | - testcase( i==113 ); /* ORDER */ | |
| 131401 | - testcase( i==114 ); /* RESTRICT */ | |
| 131402 | - testcase( i==115 ); /* RIGHT */ | |
| 131403 | - testcase( i==116 ); /* ROLLBACK */ | |
| 131404 | - testcase( i==117 ); /* ROW */ | |
| 131405 | - testcase( i==118 ); /* UNION */ | |
| 131406 | - testcase( i==119 ); /* USING */ | |
| 131407 | - testcase( i==120 ); /* VACUUM */ | |
| 131408 | - testcase( i==121 ); /* VIEW */ | |
| 131409 | - testcase( i==122 ); /* INITIALLY */ | |
| 131410 | - testcase( i==123 ); /* ALL */ | |
| 131411 | - *pType = aCode[i]; | |
| 131412 | - break; | |
| 131413 | - } | |
| 131729 | + i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; | |
| 131730 | + for(i=((int)aHash[i])-1; i>=0; i=((int)aNext[i])-1){ | |
| 131731 | + if( aLen[i]!=n ) continue; | |
| 131732 | + j = 0; | |
| 131733 | + zKW = &zText[aOffset[i]]; | |
| 131734 | +#ifdef SQLITE_ASCII | |
| 131735 | + while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; } | |
| 131736 | +#endif | |
| 131737 | +#ifdef SQLITE_EBCDIC | |
| 131738 | + while( j<n && toupper(z[j])==zKW[j] ){ j++; } | |
| 131739 | +#endif | |
| 131740 | + if( j<n ) continue; | |
| 131741 | + testcase( i==0 ); /* REINDEX */ | |
| 131742 | + testcase( i==1 ); /* INDEXED */ | |
| 131743 | + testcase( i==2 ); /* INDEX */ | |
| 131744 | + testcase( i==3 ); /* DESC */ | |
| 131745 | + testcase( i==4 ); /* ESCAPE */ | |
| 131746 | + testcase( i==5 ); /* EACH */ | |
| 131747 | + testcase( i==6 ); /* CHECK */ | |
| 131748 | + testcase( i==7 ); /* KEY */ | |
| 131749 | + testcase( i==8 ); /* BEFORE */ | |
| 131750 | + testcase( i==9 ); /* FOREIGN */ | |
| 131751 | + testcase( i==10 ); /* FOR */ | |
| 131752 | + testcase( i==11 ); /* IGNORE */ | |
| 131753 | + testcase( i==12 ); /* REGEXP */ | |
| 131754 | + testcase( i==13 ); /* EXPLAIN */ | |
| 131755 | + testcase( i==14 ); /* INSTEAD */ | |
| 131756 | + testcase( i==15 ); /* ADD */ | |
| 131757 | + testcase( i==16 ); /* DATABASE */ | |
| 131758 | + testcase( i==17 ); /* AS */ | |
| 131759 | + testcase( i==18 ); /* SELECT */ | |
| 131760 | + testcase( i==19 ); /* TABLE */ | |
| 131761 | + testcase( i==20 ); /* LEFT */ | |
| 131762 | + testcase( i==21 ); /* THEN */ | |
| 131763 | + testcase( i==22 ); /* END */ | |
| 131764 | + testcase( i==23 ); /* DEFERRABLE */ | |
| 131765 | + testcase( i==24 ); /* ELSE */ | |
| 131766 | + testcase( i==25 ); /* EXCEPT */ | |
| 131767 | + testcase( i==26 ); /* TRANSACTION */ | |
| 131768 | + testcase( i==27 ); /* ACTION */ | |
| 131769 | + testcase( i==28 ); /* ON */ | |
| 131770 | + testcase( i==29 ); /* NATURAL */ | |
| 131771 | + testcase( i==30 ); /* ALTER */ | |
| 131772 | + testcase( i==31 ); /* RAISE */ | |
| 131773 | + testcase( i==32 ); /* EXCLUSIVE */ | |
| 131774 | + testcase( i==33 ); /* EXISTS */ | |
| 131775 | + testcase( i==34 ); /* SAVEPOINT */ | |
| 131776 | + testcase( i==35 ); /* INTERSECT */ | |
| 131777 | + testcase( i==36 ); /* TRIGGER */ | |
| 131778 | + testcase( i==37 ); /* REFERENCES */ | |
| 131779 | + testcase( i==38 ); /* CONSTRAINT */ | |
| 131780 | + testcase( i==39 ); /* INTO */ | |
| 131781 | + testcase( i==40 ); /* OFFSET */ | |
| 131782 | + testcase( i==41 ); /* OF */ | |
| 131783 | + testcase( i==42 ); /* SET */ | |
| 131784 | + testcase( i==43 ); /* TEMPORARY */ | |
| 131785 | + testcase( i==44 ); /* TEMP */ | |
| 131786 | + testcase( i==45 ); /* OR */ | |
| 131787 | + testcase( i==46 ); /* UNIQUE */ | |
| 131788 | + testcase( i==47 ); /* QUERY */ | |
| 131789 | + testcase( i==48 ); /* WITHOUT */ | |
| 131790 | + testcase( i==49 ); /* WITH */ | |
| 131791 | + testcase( i==50 ); /* OUTER */ | |
| 131792 | + testcase( i==51 ); /* RELEASE */ | |
| 131793 | + testcase( i==52 ); /* ATTACH */ | |
| 131794 | + testcase( i==53 ); /* HAVING */ | |
| 131795 | + testcase( i==54 ); /* GROUP */ | |
| 131796 | + testcase( i==55 ); /* UPDATE */ | |
| 131797 | + testcase( i==56 ); /* BEGIN */ | |
| 131798 | + testcase( i==57 ); /* INNER */ | |
| 131799 | + testcase( i==58 ); /* RECURSIVE */ | |
| 131800 | + testcase( i==59 ); /* BETWEEN */ | |
| 131801 | + testcase( i==60 ); /* NOTNULL */ | |
| 131802 | + testcase( i==61 ); /* NOT */ | |
| 131803 | + testcase( i==62 ); /* NO */ | |
| 131804 | + testcase( i==63 ); /* NULL */ | |
| 131805 | + testcase( i==64 ); /* LIKE */ | |
| 131806 | + testcase( i==65 ); /* CASCADE */ | |
| 131807 | + testcase( i==66 ); /* ASC */ | |
| 131808 | + testcase( i==67 ); /* DELETE */ | |
| 131809 | + testcase( i==68 ); /* CASE */ | |
| 131810 | + testcase( i==69 ); /* COLLATE */ | |
| 131811 | + testcase( i==70 ); /* CREATE */ | |
| 131812 | + testcase( i==71 ); /* CURRENT_DATE */ | |
| 131813 | + testcase( i==72 ); /* DETACH */ | |
| 131814 | + testcase( i==73 ); /* IMMEDIATE */ | |
| 131815 | + testcase( i==74 ); /* JOIN */ | |
| 131816 | + testcase( i==75 ); /* INSERT */ | |
| 131817 | + testcase( i==76 ); /* MATCH */ | |
| 131818 | + testcase( i==77 ); /* PLAN */ | |
| 131819 | + testcase( i==78 ); /* ANALYZE */ | |
| 131820 | + testcase( i==79 ); /* PRAGMA */ | |
| 131821 | + testcase( i==80 ); /* ABORT */ | |
| 131822 | + testcase( i==81 ); /* VALUES */ | |
| 131823 | + testcase( i==82 ); /* VIRTUAL */ | |
| 131824 | + testcase( i==83 ); /* LIMIT */ | |
| 131825 | + testcase( i==84 ); /* WHEN */ | |
| 131826 | + testcase( i==85 ); /* WHERE */ | |
| 131827 | + testcase( i==86 ); /* RENAME */ | |
| 131828 | + testcase( i==87 ); /* AFTER */ | |
| 131829 | + testcase( i==88 ); /* REPLACE */ | |
| 131830 | + testcase( i==89 ); /* AND */ | |
| 131831 | + testcase( i==90 ); /* DEFAULT */ | |
| 131832 | + testcase( i==91 ); /* AUTOINCREMENT */ | |
| 131833 | + testcase( i==92 ); /* TO */ | |
| 131834 | + testcase( i==93 ); /* IN */ | |
| 131835 | + testcase( i==94 ); /* CAST */ | |
| 131836 | + testcase( i==95 ); /* COLUMN */ | |
| 131837 | + testcase( i==96 ); /* COMMIT */ | |
| 131838 | + testcase( i==97 ); /* CONFLICT */ | |
| 131839 | + testcase( i==98 ); /* CROSS */ | |
| 131840 | + testcase( i==99 ); /* CURRENT_TIMESTAMP */ | |
| 131841 | + testcase( i==100 ); /* CURRENT_TIME */ | |
| 131842 | + testcase( i==101 ); /* PRIMARY */ | |
| 131843 | + testcase( i==102 ); /* DEFERRED */ | |
| 131844 | + testcase( i==103 ); /* DISTINCT */ | |
| 131845 | + testcase( i==104 ); /* IS */ | |
| 131846 | + testcase( i==105 ); /* DROP */ | |
| 131847 | + testcase( i==106 ); /* FAIL */ | |
| 131848 | + testcase( i==107 ); /* FROM */ | |
| 131849 | + testcase( i==108 ); /* FULL */ | |
| 131850 | + testcase( i==109 ); /* GLOB */ | |
| 131851 | + testcase( i==110 ); /* BY */ | |
| 131852 | + testcase( i==111 ); /* IF */ | |
| 131853 | + testcase( i==112 ); /* ISNULL */ | |
| 131854 | + testcase( i==113 ); /* ORDER */ | |
| 131855 | + testcase( i==114 ); /* RESTRICT */ | |
| 131856 | + testcase( i==115 ); /* RIGHT */ | |
| 131857 | + testcase( i==116 ); /* ROLLBACK */ | |
| 131858 | + testcase( i==117 ); /* ROW */ | |
| 131859 | + testcase( i==118 ); /* UNION */ | |
| 131860 | + testcase( i==119 ); /* USING */ | |
| 131861 | + testcase( i==120 ); /* VACUUM */ | |
| 131862 | + testcase( i==121 ); /* VIEW */ | |
| 131863 | + testcase( i==122 ); /* INITIALLY */ | |
| 131864 | + testcase( i==123 ); /* ALL */ | |
| 131865 | + *pType = aCode[i]; | |
| 131866 | + break; | |
| 131414 | 131867 | } |
| 131415 | 131868 | } |
| 131416 | 131869 | return n; |
| 131417 | 131870 | } |
| 131418 | 131871 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ |
| @@ -131469,74 +131922,76 @@ | ||
| 131469 | 131922 | SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } |
| 131470 | 131923 | #endif |
| 131471 | 131924 | |
| 131472 | 131925 | |
| 131473 | 131926 | /* |
| 131474 | -** Return the length of the token that begins at z[0]. | |
| 131927 | +** Return the length (in bytes) of the token that begins at z[0]. | |
| 131475 | 131928 | ** Store the token type in *tokenType before returning. |
| 131476 | 131929 | */ |
| 131477 | 131930 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ |
| 131478 | 131931 | int i, c; |
| 131479 | - switch( *z ){ | |
| 131480 | - case ' ': case '\t': case '\n': case '\f': case '\r': { | |
| 131932 | + switch( aiClass[*z] ){ /* Switch on the character-class of the first byte | |
| 131933 | + ** of the token. See the comment on the CC_ defines | |
| 131934 | + ** above. */ | |
| 131935 | + case CC_SPACE: { | |
| 131481 | 131936 | testcase( z[0]==' ' ); |
| 131482 | 131937 | testcase( z[0]=='\t' ); |
| 131483 | 131938 | testcase( z[0]=='\n' ); |
| 131484 | 131939 | testcase( z[0]=='\f' ); |
| 131485 | 131940 | testcase( z[0]=='\r' ); |
| 131486 | 131941 | for(i=1; sqlite3Isspace(z[i]); i++){} |
| 131487 | 131942 | *tokenType = TK_SPACE; |
| 131488 | 131943 | return i; |
| 131489 | 131944 | } |
| 131490 | - case '-': { | |
| 131945 | + case CC_MINUS: { | |
| 131491 | 131946 | if( z[1]=='-' ){ |
| 131492 | 131947 | for(i=2; (c=z[i])!=0 && c!='\n'; i++){} |
| 131493 | 131948 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131494 | 131949 | return i; |
| 131495 | 131950 | } |
| 131496 | 131951 | *tokenType = TK_MINUS; |
| 131497 | 131952 | return 1; |
| 131498 | 131953 | } |
| 131499 | - case '(': { | |
| 131954 | + case CC_LP: { | |
| 131500 | 131955 | *tokenType = TK_LP; |
| 131501 | 131956 | return 1; |
| 131502 | 131957 | } |
| 131503 | - case ')': { | |
| 131958 | + case CC_RP: { | |
| 131504 | 131959 | *tokenType = TK_RP; |
| 131505 | 131960 | return 1; |
| 131506 | 131961 | } |
| 131507 | - case ';': { | |
| 131962 | + case CC_SEMI: { | |
| 131508 | 131963 | *tokenType = TK_SEMI; |
| 131509 | 131964 | return 1; |
| 131510 | 131965 | } |
| 131511 | - case '+': { | |
| 131966 | + case CC_PLUS: { | |
| 131512 | 131967 | *tokenType = TK_PLUS; |
| 131513 | 131968 | return 1; |
| 131514 | 131969 | } |
| 131515 | - case '*': { | |
| 131970 | + case CC_STAR: { | |
| 131516 | 131971 | *tokenType = TK_STAR; |
| 131517 | 131972 | return 1; |
| 131518 | 131973 | } |
| 131519 | - case '/': { | |
| 131974 | + case CC_SLASH: { | |
| 131520 | 131975 | if( z[1]!='*' || z[2]==0 ){ |
| 131521 | 131976 | *tokenType = TK_SLASH; |
| 131522 | 131977 | return 1; |
| 131523 | 131978 | } |
| 131524 | 131979 | for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} |
| 131525 | 131980 | if( c ) i++; |
| 131526 | 131981 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131527 | 131982 | return i; |
| 131528 | 131983 | } |
| 131529 | - case '%': { | |
| 131984 | + case CC_PERCENT: { | |
| 131530 | 131985 | *tokenType = TK_REM; |
| 131531 | 131986 | return 1; |
| 131532 | 131987 | } |
| 131533 | - case '=': { | |
| 131988 | + case CC_EQ: { | |
| 131534 | 131989 | *tokenType = TK_EQ; |
| 131535 | 131990 | return 1 + (z[1]=='='); |
| 131536 | 131991 | } |
| 131537 | - case '<': { | |
| 131992 | + case CC_LT: { | |
| 131538 | 131993 | if( (c=z[1])=='=' ){ |
| 131539 | 131994 | *tokenType = TK_LE; |
| 131540 | 131995 | return 2; |
| 131541 | 131996 | }else if( c=='>' ){ |
| 131542 | 131997 | *tokenType = TK_NE; |
| @@ -131547,11 +132002,11 @@ | ||
| 131547 | 132002 | }else{ |
| 131548 | 132003 | *tokenType = TK_LT; |
| 131549 | 132004 | return 1; |
| 131550 | 132005 | } |
| 131551 | 132006 | } |
| 131552 | - case '>': { | |
| 132007 | + case CC_GT: { | |
| 131553 | 132008 | if( (c=z[1])=='=' ){ |
| 131554 | 132009 | *tokenType = TK_GE; |
| 131555 | 132010 | return 2; |
| 131556 | 132011 | }else if( c=='>' ){ |
| 131557 | 132012 | *tokenType = TK_RSHIFT; |
| @@ -131559,43 +132014,41 @@ | ||
| 131559 | 132014 | }else{ |
| 131560 | 132015 | *tokenType = TK_GT; |
| 131561 | 132016 | return 1; |
| 131562 | 132017 | } |
| 131563 | 132018 | } |
| 131564 | - case '!': { | |
| 132019 | + case CC_BANG: { | |
| 131565 | 132020 | if( z[1]!='=' ){ |
| 131566 | 132021 | *tokenType = TK_ILLEGAL; |
| 131567 | 132022 | return 2; |
| 131568 | 132023 | }else{ |
| 131569 | 132024 | *tokenType = TK_NE; |
| 131570 | 132025 | return 2; |
| 131571 | 132026 | } |
| 131572 | 132027 | } |
| 131573 | - case '|': { | |
| 132028 | + case CC_PIPE: { | |
| 131574 | 132029 | if( z[1]!='|' ){ |
| 131575 | 132030 | *tokenType = TK_BITOR; |
| 131576 | 132031 | return 1; |
| 131577 | 132032 | }else{ |
| 131578 | 132033 | *tokenType = TK_CONCAT; |
| 131579 | 132034 | return 2; |
| 131580 | 132035 | } |
| 131581 | 132036 | } |
| 131582 | - case ',': { | |
| 132037 | + case CC_COMMA: { | |
| 131583 | 132038 | *tokenType = TK_COMMA; |
| 131584 | 132039 | return 1; |
| 131585 | 132040 | } |
| 131586 | - case '&': { | |
| 132041 | + case CC_AND: { | |
| 131587 | 132042 | *tokenType = TK_BITAND; |
| 131588 | 132043 | return 1; |
| 131589 | 132044 | } |
| 131590 | - case '~': { | |
| 132045 | + case CC_TILDA: { | |
| 131591 | 132046 | *tokenType = TK_BITNOT; |
| 131592 | 132047 | return 1; |
| 131593 | 132048 | } |
| 131594 | - case '`': | |
| 131595 | - case '\'': | |
| 131596 | - case '"': { | |
| 132049 | + case CC_QUOTE: { | |
| 131597 | 132050 | int delim = z[0]; |
| 131598 | 132051 | testcase( delim=='`' ); |
| 131599 | 132052 | testcase( delim=='\'' ); |
| 131600 | 132053 | testcase( delim=='"' ); |
| 131601 | 132054 | for(i=1; (c=z[i])!=0; i++){ |
| @@ -131616,11 +132069,11 @@ | ||
| 131616 | 132069 | }else{ |
| 131617 | 132070 | *tokenType = TK_ILLEGAL; |
| 131618 | 132071 | return i; |
| 131619 | 132072 | } |
| 131620 | 132073 | } |
| 131621 | - case '.': { | |
| 132074 | + case CC_DOT: { | |
| 131622 | 132075 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 131623 | 132076 | if( !sqlite3Isdigit(z[1]) ) |
| 131624 | 132077 | #endif |
| 131625 | 132078 | { |
| 131626 | 132079 | *tokenType = TK_DOT; |
| @@ -131627,12 +132080,11 @@ | ||
| 131627 | 132080 | return 1; |
| 131628 | 132081 | } |
| 131629 | 132082 | /* If the next character is a digit, this is a floating point |
| 131630 | 132083 | ** number that begins with ".". Fall thru into the next case */ |
| 131631 | 132084 | } |
| 131632 | - case '0': case '1': case '2': case '3': case '4': | |
| 131633 | - case '5': case '6': case '7': case '8': case '9': { | |
| 132085 | + case CC_DIGIT: { | |
| 131634 | 132086 | testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); |
| 131635 | 132087 | testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); |
| 131636 | 132088 | testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); |
| 131637 | 132089 | testcase( z[0]=='9' ); |
| 131638 | 132090 | *tokenType = TK_INTEGER; |
| @@ -131663,26 +132115,22 @@ | ||
| 131663 | 132115 | *tokenType = TK_ILLEGAL; |
| 131664 | 132116 | i++; |
| 131665 | 132117 | } |
| 131666 | 132118 | return i; |
| 131667 | 132119 | } |
| 131668 | - case '[': { | |
| 132120 | + case CC_QUOTE2: { | |
| 131669 | 132121 | for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} |
| 131670 | 132122 | *tokenType = c==']' ? TK_ID : TK_ILLEGAL; |
| 131671 | 132123 | return i; |
| 131672 | 132124 | } |
| 131673 | - case '?': { | |
| 132125 | + case CC_VARNUM: { | |
| 131674 | 132126 | *tokenType = TK_VARIABLE; |
| 131675 | 132127 | for(i=1; sqlite3Isdigit(z[i]); i++){} |
| 131676 | 132128 | return i; |
| 131677 | 132129 | } |
| 131678 | -#ifndef SQLITE_OMIT_TCL_VARIABLE | |
| 131679 | - case '$': | |
| 131680 | -#endif | |
| 131681 | - case '@': /* For compatibility with MS SQL Server */ | |
| 131682 | - case '#': | |
| 131683 | - case ':': { | |
| 132130 | + case CC_DOLLAR: | |
| 132131 | + case CC_VARALPHA: { | |
| 131684 | 132132 | int n = 0; |
| 131685 | 132133 | testcase( z[0]=='$' ); testcase( z[0]=='@' ); |
| 131686 | 132134 | testcase( z[0]==':' ); testcase( z[0]=='#' ); |
| 131687 | 132135 | *tokenType = TK_VARIABLE; |
| 131688 | 132136 | for(i=1; (c=z[i])!=0; i++){ |
| @@ -131707,12 +132155,24 @@ | ||
| 131707 | 132155 | } |
| 131708 | 132156 | } |
| 131709 | 132157 | if( n==0 ) *tokenType = TK_ILLEGAL; |
| 131710 | 132158 | return i; |
| 131711 | 132159 | } |
| 132160 | + case CC_KYWD: { | |
| 132161 | + for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} | |
| 132162 | + if( IdChar(z[i]) ){ | |
| 132163 | + /* This token started out using characters that can appear in keywords, | |
| 132164 | + ** but z[i] is a character not allowed within keywords, so this must | |
| 132165 | + ** be an identifier instead */ | |
| 132166 | + i++; | |
| 132167 | + break; | |
| 132168 | + } | |
| 132169 | + *tokenType = TK_ID; | |
| 132170 | + return keywordCode((char*)z, i, tokenType); | |
| 132171 | + } | |
| 131712 | 132172 | #ifndef SQLITE_OMIT_BLOB_LITERAL |
| 131713 | - case 'x': case 'X': { | |
| 132173 | + case CC_X: { | |
| 131714 | 132174 | testcase( z[0]=='x' ); testcase( z[0]=='X' ); |
| 131715 | 132175 | if( z[1]=='\'' ){ |
| 131716 | 132176 | *tokenType = TK_BLOB; |
| 131717 | 132177 | for(i=2; sqlite3Isxdigit(z[i]); i++){} |
| 131718 | 132178 | if( z[i]!='\'' || i%2 ){ |
| @@ -131720,24 +132180,26 @@ | ||
| 131720 | 132180 | while( z[i] && z[i]!='\'' ){ i++; } |
| 131721 | 132181 | } |
| 131722 | 132182 | if( z[i] ) i++; |
| 131723 | 132183 | return i; |
| 131724 | 132184 | } |
| 131725 | - /* Otherwise fall through to the next case */ | |
| 132185 | + /* If it is not a BLOB literal, then it must be an ID, since no | |
| 132186 | + ** SQL keywords start with the letter 'x'. Fall through */ | |
| 131726 | 132187 | } |
| 131727 | 132188 | #endif |
| 132189 | + case CC_ID: { | |
| 132190 | + i = 1; | |
| 132191 | + break; | |
| 132192 | + } | |
| 131728 | 132193 | default: { |
| 131729 | - if( !IdChar(*z) ){ | |
| 131730 | - break; | |
| 131731 | - } | |
| 131732 | - for(i=1; IdChar(z[i]); i++){} | |
| 131733 | - *tokenType = TK_ID; | |
| 131734 | - return keywordCode((char*)z, i, tokenType); | |
| 132194 | + *tokenType = TK_ILLEGAL; | |
| 132195 | + return 1; | |
| 131735 | 132196 | } |
| 131736 | 132197 | } |
| 131737 | - *tokenType = TK_ILLEGAL; | |
| 131738 | - return 1; | |
| 132198 | + while( IdChar(z[i]) ){ i++; } | |
| 132199 | + *tokenType = TK_ID; | |
| 132200 | + return i; | |
| 131739 | 132201 | } |
| 131740 | 132202 | |
| 131741 | 132203 | /* |
| 131742 | 132204 | ** Run the parser on the given SQL string. The parser structure is |
| 131743 | 132205 | ** passed in. An SQLITE_ status code is returned. If an error occurs |
| @@ -131749,11 +132211,10 @@ | ||
| 131749 | 132211 | int nErr = 0; /* Number of errors encountered */ |
| 131750 | 132212 | int i; /* Loop counter */ |
| 131751 | 132213 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 131752 | 132214 | int tokenType; /* type of the next token */ |
| 131753 | 132215 | int lastTokenParsed = -1; /* type of the previous token */ |
| 131754 | - u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ | |
| 131755 | 132216 | sqlite3 *db = pParse->db; /* The database connection */ |
| 131756 | 132217 | int mxSqlLen; /* Max length of an SQL string */ |
| 131757 | 132218 | |
| 131758 | 132219 | assert( zSql!=0 ); |
| 131759 | 132220 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| @@ -131765,20 +132226,18 @@ | ||
| 131765 | 132226 | i = 0; |
| 131766 | 132227 | assert( pzErrMsg!=0 ); |
| 131767 | 132228 | /* sqlite3ParserTrace(stdout, "parser: "); */ |
| 131768 | 132229 | pEngine = sqlite3ParserAlloc(sqlite3Malloc); |
| 131769 | 132230 | if( pEngine==0 ){ |
| 131770 | - db->mallocFailed = 1; | |
| 132231 | + sqlite3OomFault(db); | |
| 131771 | 132232 | return SQLITE_NOMEM; |
| 131772 | 132233 | } |
| 131773 | 132234 | assert( pParse->pNewTable==0 ); |
| 131774 | 132235 | assert( pParse->pNewTrigger==0 ); |
| 131775 | 132236 | assert( pParse->nVar==0 ); |
| 131776 | 132237 | assert( pParse->nzVar==0 ); |
| 131777 | 132238 | assert( pParse->azVar==0 ); |
| 131778 | - enableLookaside = db->lookaside.bEnabled; | |
| 131779 | - if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; | |
| 131780 | 132239 | while( zSql[i]!=0 ){ |
| 131781 | 132240 | assert( i>=0 ); |
| 131782 | 132241 | pParse->sLastToken.z = &zSql[i]; |
| 131783 | 132242 | pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); |
| 131784 | 132243 | i += pParse->sLastToken.n; |
| @@ -131787,11 +132246,10 @@ | ||
| 131787 | 132246 | break; |
| 131788 | 132247 | } |
| 131789 | 132248 | if( tokenType>=TK_SPACE ){ |
| 131790 | 132249 | assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); |
| 131791 | 132250 | if( db->u1.isInterrupted ){ |
| 131792 | - sqlite3ErrorMsg(pParse, "interrupt"); | |
| 131793 | 132251 | pParse->rc = SQLITE_INTERRUPT; |
| 131794 | 132252 | break; |
| 131795 | 132253 | } |
| 131796 | 132254 | if( tokenType==TK_ILLEGAL ){ |
| 131797 | 132255 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", |
| @@ -131822,11 +132280,10 @@ | ||
| 131822 | 132280 | sqlite3ParserStackPeak(pEngine) |
| 131823 | 132281 | ); |
| 131824 | 132282 | sqlite3_mutex_leave(sqlite3MallocMutex()); |
| 131825 | 132283 | #endif /* YYDEBUG */ |
| 131826 | 132284 | sqlite3ParserFree(pEngine, sqlite3_free); |
| 131827 | - db->lookaside.bEnabled = enableLookaside; | |
| 131828 | 132285 | if( db->mallocFailed ){ |
| 131829 | 132286 | pParse->rc = SQLITE_NOMEM; |
| 131830 | 132287 | } |
| 131831 | 132288 | if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ |
| 131832 | 132289 | pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); |
| @@ -132963,16 +133420,16 @@ | ||
| 132963 | 133420 | p->pNext = db->lookaside.pFree; |
| 132964 | 133421 | db->lookaside.pFree = p; |
| 132965 | 133422 | p = (LookasideSlot*)&((u8*)p)[sz]; |
| 132966 | 133423 | } |
| 132967 | 133424 | db->lookaside.pEnd = p; |
| 132968 | - db->lookaside.bEnabled = 1; | |
| 133425 | + db->lookaside.bDisable = 0; | |
| 132969 | 133426 | db->lookaside.bMalloced = pBuf==0 ?1:0; |
| 132970 | 133427 | }else{ |
| 132971 | 133428 | db->lookaside.pStart = db; |
| 132972 | 133429 | db->lookaside.pEnd = db; |
| 132973 | - db->lookaside.bEnabled = 0; | |
| 133430 | + db->lookaside.bDisable = 1; | |
| 132974 | 133431 | db->lookaside.bMalloced = 0; |
| 132975 | 133432 | } |
| 132976 | 133433 | #endif /* SQLITE_OMIT_LOOKASIDE */ |
| 132977 | 133434 | return SQLITE_OK; |
| 132978 | 133435 | } |
| @@ -134473,11 +134930,11 @@ | ||
| 134473 | 134930 | /* A malloc() may have failed within the call to sqlite3_value_text16() |
| 134474 | 134931 | ** above. If this is the case, then the db->mallocFailed flag needs to |
| 134475 | 134932 | ** be cleared before returning. Do this directly, instead of via |
| 134476 | 134933 | ** sqlite3ApiExit(), to avoid setting the database handle error message. |
| 134477 | 134934 | */ |
| 134478 | - db->mallocFailed = 0; | |
| 134935 | + sqlite3OomClear(db); | |
| 134479 | 134936 | } |
| 134480 | 134937 | sqlite3_mutex_leave(db->mutex); |
| 134481 | 134938 | return z; |
| 134482 | 134939 | } |
| 134483 | 134940 | #endif /* SQLITE_OMIT_UTF16 */ |
| @@ -135111,11 +135568,11 @@ | ||
| 135111 | 135568 | |
| 135112 | 135569 | /* Parse the filename/URI argument. */ |
| 135113 | 135570 | db->openFlags = flags; |
| 135114 | 135571 | rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); |
| 135115 | 135572 | if( rc!=SQLITE_OK ){ |
| 135116 | - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; | |
| 135573 | + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); | |
| 135117 | 135574 | sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); |
| 135118 | 135575 | sqlite3_free(zErrMsg); |
| 135119 | 135576 | goto opendb_out; |
| 135120 | 135577 | } |
| 135121 | 135578 | |
| @@ -135831,11 +136288,11 @@ | ||
| 135831 | 136288 | ** process aborts. If X is false and assert() is disabled, then the |
| 135832 | 136289 | ** return value is zero. |
| 135833 | 136290 | */ |
| 135834 | 136291 | case SQLITE_TESTCTRL_ASSERT: { |
| 135835 | 136292 | volatile int x = 0; |
| 135836 | - assert( (x = va_arg(ap,int))!=0 ); | |
| 136293 | + assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 ); | |
| 135837 | 136294 | rc = x; |
| 135838 | 136295 | break; |
| 135839 | 136296 | } |
| 135840 | 136297 | |
| 135841 | 136298 | |
| @@ -146361,10 +146818,11 @@ | ||
| 146361 | 146818 | |
| 146362 | 146819 | zName = sqlite3_value_text(argv[0]); |
| 146363 | 146820 | nName = sqlite3_value_bytes(argv[0])+1; |
| 146364 | 146821 | |
| 146365 | 146822 | if( argc==2 ){ |
| 146823 | +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER | |
| 146366 | 146824 | void *pOld; |
| 146367 | 146825 | int n = sqlite3_value_bytes(argv[1]); |
| 146368 | 146826 | if( zName==0 || n!=sizeof(pPtr) ){ |
| 146369 | 146827 | sqlite3_result_error(context, "argument type mismatch", -1); |
| 146370 | 146828 | return; |
| @@ -146373,11 +146831,18 @@ | ||
| 146373 | 146831 | pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); |
| 146374 | 146832 | if( pOld==pPtr ){ |
| 146375 | 146833 | sqlite3_result_error(context, "out of memory", -1); |
| 146376 | 146834 | return; |
| 146377 | 146835 | } |
| 146378 | - }else{ | |
| 146836 | +#else | |
| 146837 | + sqlite3_result_error(context, "fts3tokenize: " | |
| 146838 | + "disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER", -1 | |
| 146839 | + ); | |
| 146840 | + return; | |
| 146841 | +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ | |
| 146842 | + }else | |
| 146843 | + { | |
| 146379 | 146844 | if( zName ){ |
| 146380 | 146845 | pPtr = sqlite3Fts3HashFind(pHash, zName, nName); |
| 146381 | 146846 | } |
| 146382 | 146847 | if( !pPtr ){ |
| 146383 | 146848 | char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); |
| @@ -146622,10 +147087,11 @@ | ||
| 146622 | 147087 | sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); |
| 146623 | 147088 | } |
| 146624 | 147089 | Tcl_DecrRefCount(pRet); |
| 146625 | 147090 | } |
| 146626 | 147091 | |
| 147092 | +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER | |
| 146627 | 147093 | static |
| 146628 | 147094 | int registerTokenizer( |
| 146629 | 147095 | sqlite3 *db, |
| 146630 | 147096 | char *zName, |
| 146631 | 147097 | const sqlite3_tokenizer_module *p |
| @@ -146643,10 +147109,12 @@ | ||
| 146643 | 147109 | sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); |
| 146644 | 147110 | sqlite3_step(pStmt); |
| 146645 | 147111 | |
| 146646 | 147112 | return sqlite3_finalize(pStmt); |
| 146647 | 147113 | } |
| 147114 | +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ | |
| 147115 | + | |
| 146648 | 147116 | |
| 146649 | 147117 | static |
| 146650 | 147118 | int queryTokenizer( |
| 146651 | 147119 | sqlite3 *db, |
| 146652 | 147120 | char *zName, |
| @@ -146714,15 +147182,17 @@ | ||
| 146714 | 147182 | assert( rc==SQLITE_ERROR ); |
| 146715 | 147183 | assert( p2==0 ); |
| 146716 | 147184 | assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); |
| 146717 | 147185 | |
| 146718 | 147186 | /* Test the storage function */ |
| 147187 | +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER | |
| 146719 | 147188 | rc = registerTokenizer(db, "nosuchtokenizer", p1); |
| 146720 | 147189 | assert( rc==SQLITE_OK ); |
| 146721 | 147190 | rc = queryTokenizer(db, "nosuchtokenizer", &p2); |
| 146722 | 147191 | assert( rc==SQLITE_OK ); |
| 146723 | 147192 | assert( p2==p1 ); |
| 147193 | +#endif | |
| 146724 | 147194 | |
| 146725 | 147195 | sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); |
| 146726 | 147196 | } |
| 146727 | 147197 | |
| 146728 | 147198 | #endif |
| @@ -164601,11 +165071,13 @@ | ||
| 164601 | 165071 | StatTable *pTab = 0; |
| 164602 | 165072 | int rc = SQLITE_OK; |
| 164603 | 165073 | int iDb; |
| 164604 | 165074 | |
| 164605 | 165075 | if( argc>=4 ){ |
| 164606 | - iDb = sqlite3FindDbName(db, argv[3]); | |
| 165076 | + Token nm; | |
| 165077 | + sqlite3TokenInit(&nm, (char*)argv[3]); | |
| 165078 | + iDb = sqlite3FindDb(db, &nm); | |
| 164607 | 165079 | if( iDb<0 ){ |
| 164608 | 165080 | *pzErr = sqlite3_mprintf("no such database: %s", argv[3]); |
| 164609 | 165081 | return SQLITE_ERROR; |
| 164610 | 165082 | } |
| 164611 | 165083 | }else{ |
| @@ -165431,14 +165903,37 @@ | ||
| 165431 | 165903 | static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ |
| 165432 | 165904 | u32 i; |
| 165433 | 165905 | if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; |
| 165434 | 165906 | p->zBuf[p->nUsed++] = '"'; |
| 165435 | 165907 | for(i=0; i<N; i++){ |
| 165436 | - char c = zIn[i]; | |
| 165908 | + unsigned char c = ((unsigned const char*)zIn)[i]; | |
| 165437 | 165909 | if( c=='"' || c=='\\' ){ |
| 165910 | + json_simple_escape: | |
| 165438 | 165911 | if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; |
| 165439 | 165912 | p->zBuf[p->nUsed++] = '\\'; |
| 165913 | + }else if( c<=0x1f ){ | |
| 165914 | + static const char aSpecial[] = { | |
| 165915 | + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, | |
| 165916 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| 165917 | + }; | |
| 165918 | + assert( sizeof(aSpecial)==32 ); | |
| 165919 | + assert( aSpecial['\b']=='b' ); | |
| 165920 | + assert( aSpecial['\f']=='f' ); | |
| 165921 | + assert( aSpecial['\n']=='n' ); | |
| 165922 | + assert( aSpecial['\r']=='r' ); | |
| 165923 | + assert( aSpecial['\t']=='t' ); | |
| 165924 | + if( aSpecial[c] ){ | |
| 165925 | + c = aSpecial[c]; | |
| 165926 | + goto json_simple_escape; | |
| 165927 | + } | |
| 165928 | + if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; | |
| 165929 | + p->zBuf[p->nUsed++] = '\\'; | |
| 165930 | + p->zBuf[p->nUsed++] = 'u'; | |
| 165931 | + p->zBuf[p->nUsed++] = '0'; | |
| 165932 | + p->zBuf[p->nUsed++] = '0'; | |
| 165933 | + p->zBuf[p->nUsed++] = '0' + (c>>4); | |
| 165934 | + c = "0123456789abcdef"[c&0xf]; | |
| 165440 | 165935 | } |
| 165441 | 165936 | p->zBuf[p->nUsed++] = c; |
| 165442 | 165937 | } |
| 165443 | 165938 | p->zBuf[p->nUsed++] = '"'; |
| 165444 | 165939 | assert( p->nUsed<p->nAlloc ); |
| @@ -165475,11 +165970,11 @@ | ||
| 165475 | 165970 | break; |
| 165476 | 165971 | } |
| 165477 | 165972 | default: { |
| 165478 | 165973 | if( p->bErr==0 ){ |
| 165479 | 165974 | sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); |
| 165480 | - p->bErr = 1; | |
| 165975 | + p->bErr = 2; | |
| 165481 | 165976 | jsonReset(p); |
| 165482 | 165977 | } |
| 165483 | 165978 | break; |
| 165484 | 165979 | } |
| 165485 | 165980 | } |
| @@ -166703,11 +167198,11 @@ | ||
| 166703 | 167198 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 166704 | 167199 | if( pStr ){ |
| 166705 | 167200 | pStr->pCtx = ctx; |
| 166706 | 167201 | jsonAppendChar(pStr, ']'); |
| 166707 | 167202 | if( pStr->bErr ){ |
| 166708 | - sqlite3_result_error_nomem(ctx); | |
| 167203 | + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); | |
| 166709 | 167204 | assert( pStr->bStatic ); |
| 166710 | 167205 | }else{ |
| 166711 | 167206 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 166712 | 167207 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 166713 | 167208 | pStr->bStatic = 1; |
| @@ -166751,11 +167246,11 @@ | ||
| 166751 | 167246 | JsonString *pStr; |
| 166752 | 167247 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 166753 | 167248 | if( pStr ){ |
| 166754 | 167249 | jsonAppendChar(pStr, '}'); |
| 166755 | 167250 | if( pStr->bErr ){ |
| 166756 | - sqlite3_result_error_nomem(ctx); | |
| 167251 | + if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); | |
| 166757 | 167252 | assert( pStr->bStatic ); |
| 166758 | 167253 | }else{ |
| 166759 | 167254 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 166760 | 167255 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 166761 | 167256 | pStr->bStatic = 1; |
| @@ -167940,11 +168435,11 @@ | ||
| 167940 | 168435 | typedef unsigned int u32; |
| 167941 | 168436 | typedef unsigned short u16; |
| 167942 | 168437 | typedef sqlite3_int64 i64; |
| 167943 | 168438 | typedef sqlite3_uint64 u64; |
| 167944 | 168439 | |
| 167945 | -#define ArraySize(x) (sizeof(x) / sizeof(x[0])) | |
| 168440 | +#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) | |
| 167946 | 168441 | |
| 167947 | 168442 | #define testcase(x) |
| 167948 | 168443 | #define ALWAYS(x) 1 |
| 167949 | 168444 | #define NEVER(x) 0 |
| 167950 | 168445 | |
| @@ -168136,12 +168631,12 @@ | ||
| 168136 | 168631 | ** Buffer object for the incremental building of string data. |
| 168137 | 168632 | */ |
| 168138 | 168633 | typedef struct Fts5Buffer Fts5Buffer; |
| 168139 | 168634 | struct Fts5Buffer { |
| 168140 | 168635 | u8 *p; |
| 168141 | - u32 n; | |
| 168142 | - u32 nSpace; | |
| 168636 | + int n; | |
| 168637 | + int nSpace; | |
| 168143 | 168638 | }; |
| 168144 | 168639 | |
| 168145 | 168640 | static int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32); |
| 168146 | 168641 | static void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64); |
| 168147 | 168642 | static void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, u32, const u8*); |
| @@ -168158,11 +168653,11 @@ | ||
| 168158 | 168653 | #define fts5BufferFree(a) sqlite3Fts5BufferFree(a) |
| 168159 | 168654 | #define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d) |
| 168160 | 168655 | #define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) |
| 168161 | 168656 | |
| 168162 | 168657 | #define fts5BufferGrow(pRc,pBuf,nn) ( \ |
| 168163 | - (pBuf)->n + (nn) <= (pBuf)->nSpace ? 0 : \ | |
| 168658 | + (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \ | |
| 168164 | 168659 | sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \ |
| 168165 | 168660 | ) |
| 168166 | 168661 | |
| 168167 | 168662 | /* Write and decode big-endian 32-bit integer values */ |
| 168168 | 168663 | static void sqlite3Fts5Put32(u8*, int); |
| @@ -168193,10 +168688,11 @@ | ||
| 168193 | 168688 | typedef struct Fts5PoslistWriter Fts5PoslistWriter; |
| 168194 | 168689 | struct Fts5PoslistWriter { |
| 168195 | 168690 | i64 iPrev; |
| 168196 | 168691 | }; |
| 168197 | 168692 | static int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); |
| 168693 | +static void sqlite3Fts5PoslistSafeAppend(Fts5Buffer*, i64*, i64); | |
| 168198 | 168694 | |
| 168199 | 168695 | static int sqlite3Fts5PoslistNext64( |
| 168200 | 168696 | const u8 *a, int n, /* Buffer containing poslist */ |
| 168201 | 168697 | int *pi, /* IN/OUT: Offset within a[] */ |
| 168202 | 168698 | i64 *piOff /* IN/OUT: Current offset */ |
| @@ -168226,17 +168722,32 @@ | ||
| 168226 | 168722 | */ |
| 168227 | 168723 | |
| 168228 | 168724 | typedef struct Fts5Index Fts5Index; |
| 168229 | 168725 | typedef struct Fts5IndexIter Fts5IndexIter; |
| 168230 | 168726 | |
| 168727 | +struct Fts5IndexIter { | |
| 168728 | + i64 iRowid; | |
| 168729 | + const u8 *pData; | |
| 168730 | + int nData; | |
| 168731 | + u8 bEof; | |
| 168732 | +}; | |
| 168733 | + | |
| 168734 | +#define sqlite3Fts5IterEof(x) ((x)->bEof) | |
| 168735 | + | |
| 168231 | 168736 | /* |
| 168232 | 168737 | ** Values used as part of the flags argument passed to IndexQuery(). |
| 168233 | 168738 | */ |
| 168234 | 168739 | #define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ |
| 168235 | 168740 | #define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ |
| 168236 | 168741 | #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ |
| 168237 | 168742 | #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ |
| 168743 | + | |
| 168744 | +/* The following are used internally by the fts5_index.c module. They are | |
| 168745 | +** defined here only to make it easier to avoid clashes with the flags | |
| 168746 | +** above. */ | |
| 168747 | +#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 | |
| 168748 | +#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 | |
| 168238 | 168749 | |
| 168239 | 168750 | /* |
| 168240 | 168751 | ** Create/destroy an Fts5Index object. |
| 168241 | 168752 | */ |
| 168242 | 168753 | static int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); |
| @@ -168289,16 +168800,13 @@ | ||
| 168289 | 168800 | |
| 168290 | 168801 | /* |
| 168291 | 168802 | ** The various operations on open token or token prefix iterators opened |
| 168292 | 168803 | ** using sqlite3Fts5IndexQuery(). |
| 168293 | 168804 | */ |
| 168294 | -static int sqlite3Fts5IterEof(Fts5IndexIter*); | |
| 168295 | 168805 | static int sqlite3Fts5IterNext(Fts5IndexIter*); |
| 168296 | 168806 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); |
| 168297 | 168807 | static i64 sqlite3Fts5IterRowid(Fts5IndexIter*); |
| 168298 | -static int sqlite3Fts5IterPoslist(Fts5IndexIter*,Fts5Colset*, const u8**, int*, i64*); | |
| 168299 | -static int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf); | |
| 168300 | 168808 | |
| 168301 | 168809 | /* |
| 168302 | 168810 | ** Close an iterator opened by sqlite3Fts5IndexQuery(). |
| 168303 | 168811 | */ |
| 168304 | 168812 | static void sqlite3Fts5IterClose(Fts5IndexIter*); |
| @@ -168380,12 +168888,10 @@ | ||
| 168380 | 168888 | static int sqlite3Fts5IndexOptimize(Fts5Index *p); |
| 168381 | 168889 | static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); |
| 168382 | 168890 | |
| 168383 | 168891 | static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); |
| 168384 | 168892 | |
| 168385 | -static int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*); | |
| 168386 | - | |
| 168387 | 168893 | /* |
| 168388 | 168894 | ** End of interface to code in fts5_index.c. |
| 168389 | 168895 | **************************************************************************/ |
| 168390 | 168896 | |
| 168391 | 168897 | /************************************************************************** |
| @@ -170432,11 +170938,11 @@ | ||
| 170432 | 170938 | { "bm25", 0, fts5Bm25Function, 0 }, |
| 170433 | 170939 | }; |
| 170434 | 170940 | int rc = SQLITE_OK; /* Return code */ |
| 170435 | 170941 | int i; /* To iterate through builtin functions */ |
| 170436 | 170942 | |
| 170437 | - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ | |
| 170943 | + for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){ | |
| 170438 | 170944 | rc = pApi->xCreateFunction(pApi, |
| 170439 | 170945 | aBuiltin[i].zFunc, |
| 170440 | 170946 | aBuiltin[i].pUserData, |
| 170441 | 170947 | aBuiltin[i].xFunc, |
| 170442 | 170948 | aBuiltin[i].xDestroy |
| @@ -170464,22 +170970,24 @@ | ||
| 170464 | 170970 | |
| 170465 | 170971 | |
| 170466 | 170972 | /* #include "fts5Int.h" */ |
| 170467 | 170973 | |
| 170468 | 170974 | static int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){ |
| 170469 | - u32 nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64; | |
| 170470 | - u8 *pNew; | |
| 170471 | - while( nNew<nByte ){ | |
| 170472 | - nNew = nNew * 2; | |
| 170473 | - } | |
| 170474 | - pNew = sqlite3_realloc(pBuf->p, nNew); | |
| 170475 | - if( pNew==0 ){ | |
| 170476 | - *pRc = SQLITE_NOMEM; | |
| 170477 | - return 1; | |
| 170478 | - }else{ | |
| 170479 | - pBuf->nSpace = nNew; | |
| 170480 | - pBuf->p = pNew; | |
| 170975 | + if( (u32)pBuf->nSpace<nByte ){ | |
| 170976 | + u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64; | |
| 170977 | + u8 *pNew; | |
| 170978 | + while( nNew<nByte ){ | |
| 170979 | + nNew = nNew * 2; | |
| 170980 | + } | |
| 170981 | + pNew = sqlite3_realloc(pBuf->p, nNew); | |
| 170982 | + if( pNew==0 ){ | |
| 170983 | + *pRc = SQLITE_NOMEM; | |
| 170984 | + return 1; | |
| 170985 | + }else{ | |
| 170986 | + pBuf->nSpace = nNew; | |
| 170987 | + pBuf->p = pNew; | |
| 170988 | + } | |
| 170481 | 170989 | } |
| 170482 | 170990 | return 0; |
| 170483 | 170991 | } |
| 170484 | 170992 | |
| 170485 | 170993 | |
| @@ -170655,28 +171163,41 @@ | ||
| 170655 | 171163 | pIter->a = a; |
| 170656 | 171164 | pIter->n = n; |
| 170657 | 171165 | sqlite3Fts5PoslistReaderNext(pIter); |
| 170658 | 171166 | return pIter->bEof; |
| 170659 | 171167 | } |
| 171168 | + | |
| 171169 | +/* | |
| 171170 | +** Append position iPos to the position list being accumulated in buffer | |
| 171171 | +** pBuf, which must be already be large enough to hold the new data. | |
| 171172 | +** The previous position written to this list is *piPrev. *piPrev is set | |
| 171173 | +** to iPos before returning. | |
| 171174 | +*/ | |
| 171175 | +static void sqlite3Fts5PoslistSafeAppend( | |
| 171176 | + Fts5Buffer *pBuf, | |
| 171177 | + i64 *piPrev, | |
| 171178 | + i64 iPos | |
| 171179 | +){ | |
| 171180 | + static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; | |
| 171181 | + if( (iPos & colmask) != (*piPrev & colmask) ){ | |
| 171182 | + pBuf->p[pBuf->n++] = 1; | |
| 171183 | + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); | |
| 171184 | + *piPrev = (iPos & colmask); | |
| 171185 | + } | |
| 171186 | + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); | |
| 171187 | + *piPrev = iPos; | |
| 171188 | +} | |
| 170660 | 171189 | |
| 170661 | 171190 | static int sqlite3Fts5PoslistWriterAppend( |
| 170662 | 171191 | Fts5Buffer *pBuf, |
| 170663 | 171192 | Fts5PoslistWriter *pWriter, |
| 170664 | 171193 | i64 iPos |
| 170665 | 171194 | ){ |
| 170666 | - static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; | |
| 170667 | - int rc = SQLITE_OK; | |
| 170668 | - if( 0==fts5BufferGrow(&rc, pBuf, 5+5+5) ){ | |
| 170669 | - if( (iPos & colmask) != (pWriter->iPrev & colmask) ){ | |
| 170670 | - pBuf->p[pBuf->n++] = 1; | |
| 170671 | - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); | |
| 170672 | - pWriter->iPrev = (iPos & colmask); | |
| 170673 | - } | |
| 170674 | - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-pWriter->iPrev)+2); | |
| 170675 | - pWriter->iPrev = iPos; | |
| 170676 | - } | |
| 170677 | - return rc; | |
| 171195 | + int rc; | |
| 171196 | + if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; | |
| 171197 | + sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); | |
| 171198 | + return SQLITE_OK; | |
| 170678 | 171199 | } |
| 170679 | 171200 | |
| 170680 | 171201 | static void *sqlite3Fts5MallocZero(int *pRc, int nByte){ |
| 170681 | 171202 | void *pRet = 0; |
| 170682 | 171203 | if( *pRc==SQLITE_OK ){ |
| @@ -170770,11 +171291,11 @@ | ||
| 170770 | 171291 | ){ |
| 170771 | 171292 | int rc = SQLITE_OK; |
| 170772 | 171293 | *pbPresent = 0; |
| 170773 | 171294 | if( p ){ |
| 170774 | 171295 | int i; |
| 170775 | - int hash = 13; | |
| 171296 | + u32 hash = 13; | |
| 170776 | 171297 | Fts5TermsetEntry *pEntry; |
| 170777 | 171298 | |
| 170778 | 171299 | /* Calculate a hash value for this term. This is the same hash checksum |
| 170779 | 171300 | ** used by the fts5_hash.c module. This is not important for correct |
| 170780 | 171301 | ** operation of the module, but is necessary to ensure that some tests |
| @@ -170787,11 +171308,11 @@ | ||
| 170787 | 171308 | |
| 170788 | 171309 | for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){ |
| 170789 | 171310 | if( pEntry->iIdx==iIdx |
| 170790 | 171311 | && pEntry->nTerm==nTerm |
| 170791 | 171312 | && memcmp(pEntry->pTerm, pTerm, nTerm)==0 |
| 170792 | - ){ | |
| 171313 | + ){ | |
| 170793 | 171314 | *pbPresent = 1; |
| 170794 | 171315 | break; |
| 170795 | 171316 | } |
| 170796 | 171317 | } |
| 170797 | 171318 | |
| @@ -170811,11 +171332,11 @@ | ||
| 170811 | 171332 | return rc; |
| 170812 | 171333 | } |
| 170813 | 171334 | |
| 170814 | 171335 | static void sqlite3Fts5TermsetFree(Fts5Termset *p){ |
| 170815 | 171336 | if( p ){ |
| 170816 | - int i; | |
| 171337 | + u32 i; | |
| 170817 | 171338 | for(i=0; i<ArraySize(p->apHash); i++){ |
| 170818 | 171339 | Fts5TermsetEntry *pEntry = p->apHash[i]; |
| 170819 | 171340 | while( pEntry ){ |
| 170820 | 171341 | Fts5TermsetEntry *pDel = pEntry; |
| 170821 | 171342 | pEntry = pEntry->pNext; |
| @@ -171838,10 +172359,13 @@ | ||
| 171838 | 172359 | struct Fts5ExprNode { |
| 171839 | 172360 | int eType; /* Node type */ |
| 171840 | 172361 | int bEof; /* True at EOF */ |
| 171841 | 172362 | int bNomatch; /* True if entry is not a match */ |
| 171842 | 172363 | |
| 172364 | + /* Next method for this node. */ | |
| 172365 | + int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64); | |
| 172366 | + | |
| 171843 | 172367 | i64 iRowid; /* Current rowid */ |
| 171844 | 172368 | Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ |
| 171845 | 172369 | |
| 171846 | 172370 | /* Child nodes. For a NOT node, this array always contains 2 entries. For |
| 171847 | 172371 | ** AND or OR nodes, it contains 2 or more entries. */ |
| @@ -171849,10 +172373,16 @@ | ||
| 171849 | 172373 | Fts5ExprNode *apChild[1]; /* Array of child nodes */ |
| 171850 | 172374 | }; |
| 171851 | 172375 | |
| 171852 | 172376 | #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) |
| 171853 | 172377 | |
| 172378 | +/* | |
| 172379 | +** Invoke the xNext method of an Fts5ExprNode object. This macro should be | |
| 172380 | +** used as if it has the same signature as the xNext() methods themselves. | |
| 172381 | +*/ | |
| 172382 | +#define fts5ExprNodeNext(a,b,c,d) (b)->xNext((a), (b), (c), (d)) | |
| 172383 | + | |
| 171854 | 172384 | /* |
| 171855 | 172385 | ** An instance of the following structure represents a single search term |
| 171856 | 172386 | ** or term prefix. |
| 171857 | 172387 | */ |
| 171858 | 172388 | struct Fts5ExprTerm { |
| @@ -172010,11 +172540,19 @@ | ||
| 172010 | 172540 | *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); |
| 172011 | 172541 | if( pNew==0 ){ |
| 172012 | 172542 | sParse.rc = SQLITE_NOMEM; |
| 172013 | 172543 | sqlite3Fts5ParseNodeFree(sParse.pExpr); |
| 172014 | 172544 | }else{ |
| 172015 | - pNew->pRoot = sParse.pExpr; | |
| 172545 | + if( !sParse.pExpr ){ | |
| 172546 | + const int nByte = sizeof(Fts5ExprNode); | |
| 172547 | + pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte); | |
| 172548 | + if( pNew->pRoot ){ | |
| 172549 | + pNew->pRoot->bEof = 1; | |
| 172550 | + } | |
| 172551 | + }else{ | |
| 172552 | + pNew->pRoot = sParse.pExpr; | |
| 172553 | + } | |
| 172016 | 172554 | pNew->pIndex = 0; |
| 172017 | 172555 | pNew->pConfig = pConfig; |
| 172018 | 172556 | pNew->apExprPhrase = sParse.apPhrase; |
| 172019 | 172557 | pNew->nPhrase = sParse.nPhrase; |
| 172020 | 172558 | sParse.apPhrase = 0; |
| @@ -172062,11 +172600,11 @@ | ||
| 172062 | 172600 | |
| 172063 | 172601 | assert( pTerm->pSynonym ); |
| 172064 | 172602 | assert( bDesc==0 || bDesc==1 ); |
| 172065 | 172603 | for(p=pTerm; p; p=p->pSynonym){ |
| 172066 | 172604 | if( 0==sqlite3Fts5IterEof(p->pIter) ){ |
| 172067 | - i64 iRowid = sqlite3Fts5IterRowid(p->pIter); | |
| 172605 | + i64 iRowid = p->pIter->iRowid; | |
| 172068 | 172606 | if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){ |
| 172069 | 172607 | iRet = iRowid; |
| 172070 | 172608 | bRetValid = 1; |
| 172071 | 172609 | } |
| 172072 | 172610 | } |
| @@ -172082,11 +172620,11 @@ | ||
| 172082 | 172620 | static int fts5ExprSynonymList( |
| 172083 | 172621 | Fts5ExprTerm *pTerm, |
| 172084 | 172622 | int bCollist, |
| 172085 | 172623 | Fts5Colset *pColset, |
| 172086 | 172624 | i64 iRowid, |
| 172087 | - int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ | |
| 172625 | + Fts5Buffer *pBuf, /* Use this buffer for space if required */ | |
| 172088 | 172626 | u8 **pa, int *pn |
| 172089 | 172627 | ){ |
| 172090 | 172628 | Fts5PoslistReader aStatic[4]; |
| 172091 | 172629 | Fts5PoslistReader *aIter = aStatic; |
| 172092 | 172630 | int nIter = 0; |
| @@ -172095,23 +172633,12 @@ | ||
| 172095 | 172633 | Fts5ExprTerm *p; |
| 172096 | 172634 | |
| 172097 | 172635 | assert( pTerm->pSynonym ); |
| 172098 | 172636 | for(p=pTerm; p; p=p->pSynonym){ |
| 172099 | 172637 | Fts5IndexIter *pIter = p->pIter; |
| 172100 | - if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ | |
| 172101 | - const u8 *a; | |
| 172102 | - int n; | |
| 172103 | - | |
| 172104 | - if( bCollist ){ | |
| 172105 | - rc = sqlite3Fts5IterCollist(pIter, &a, &n); | |
| 172106 | - }else{ | |
| 172107 | - i64 dummy; | |
| 172108 | - rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy); | |
| 172109 | - } | |
| 172110 | - | |
| 172111 | - if( rc!=SQLITE_OK ) goto synonym_poslist_out; | |
| 172112 | - if( n==0 ) continue; | |
| 172638 | + if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){ | |
| 172639 | + if( pIter->nData==0 ) continue; | |
| 172113 | 172640 | if( nIter==nAlloc ){ |
| 172114 | 172641 | int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; |
| 172115 | 172642 | Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172116 | 172643 | if( aNew==0 ){ |
| 172117 | 172644 | rc = SQLITE_NOMEM; |
| @@ -172120,24 +172647,23 @@ | ||
| 172120 | 172647 | memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); |
| 172121 | 172648 | nAlloc = nAlloc*2; |
| 172122 | 172649 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| 172123 | 172650 | aIter = aNew; |
| 172124 | 172651 | } |
| 172125 | - sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]); | |
| 172652 | + sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &aIter[nIter]); | |
| 172126 | 172653 | assert( aIter[nIter].bEof==0 ); |
| 172127 | 172654 | nIter++; |
| 172128 | 172655 | } |
| 172129 | 172656 | } |
| 172130 | 172657 | |
| 172131 | - assert( *pbDel==0 ); | |
| 172132 | 172658 | if( nIter==1 ){ |
| 172133 | 172659 | *pa = (u8*)aIter[0].a; |
| 172134 | 172660 | *pn = aIter[0].n; |
| 172135 | 172661 | }else{ |
| 172136 | 172662 | Fts5PoslistWriter writer = {0}; |
| 172137 | - Fts5Buffer buf = {0,0,0}; | |
| 172138 | 172663 | i64 iPrev = -1; |
| 172664 | + fts5BufferZero(pBuf); | |
| 172139 | 172665 | while( 1 ){ |
| 172140 | 172666 | int i; |
| 172141 | 172667 | i64 iMin = FTS5_LARGEST_INT64; |
| 172142 | 172668 | for(i=0; i<nIter; i++){ |
| 172143 | 172669 | if( aIter[i].bEof==0 ){ |
| @@ -172148,19 +172674,16 @@ | ||
| 172148 | 172674 | iMin = aIter[i].iPos; |
| 172149 | 172675 | } |
| 172150 | 172676 | } |
| 172151 | 172677 | } |
| 172152 | 172678 | if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break; |
| 172153 | - rc = sqlite3Fts5PoslistWriterAppend(&buf, &writer, iMin); | |
| 172679 | + rc = sqlite3Fts5PoslistWriterAppend(pBuf, &writer, iMin); | |
| 172154 | 172680 | iPrev = iMin; |
| 172155 | 172681 | } |
| 172156 | - if( rc ){ | |
| 172157 | - sqlite3_free(buf.p); | |
| 172158 | - }else{ | |
| 172159 | - *pa = buf.p; | |
| 172160 | - *pn = buf.n; | |
| 172161 | - *pbDel = 1; | |
| 172682 | + if( rc==SQLITE_OK ){ | |
| 172683 | + *pa = pBuf->p; | |
| 172684 | + *pn = pBuf->n; | |
| 172162 | 172685 | } |
| 172163 | 172686 | } |
| 172164 | 172687 | |
| 172165 | 172688 | synonym_poslist_out: |
| 172166 | 172689 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| @@ -172193,32 +172716,37 @@ | ||
| 172193 | 172716 | |
| 172194 | 172717 | fts5BufferZero(&pPhrase->poslist); |
| 172195 | 172718 | |
| 172196 | 172719 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172197 | 172720 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172198 | - if( pPhrase->nTerm>(int)ArraySize(aStatic) ){ | |
| 172721 | + if( pPhrase->nTerm>ArraySize(aStatic) ){ | |
| 172199 | 172722 | int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; |
| 172200 | 172723 | aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172201 | 172724 | if( !aIter ) return SQLITE_NOMEM; |
| 172202 | 172725 | } |
| 172203 | 172726 | memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm); |
| 172204 | 172727 | |
| 172205 | 172728 | /* Initialize a term iterator for each term in the phrase */ |
| 172206 | 172729 | for(i=0; i<pPhrase->nTerm; i++){ |
| 172207 | 172730 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 172208 | - i64 dummy; | |
| 172209 | 172731 | int n = 0; |
| 172210 | 172732 | int bFlag = 0; |
| 172211 | - const u8 *a = 0; | |
| 172733 | + u8 *a = 0; | |
| 172212 | 172734 | if( pTerm->pSynonym ){ |
| 172735 | + Fts5Buffer buf = {0, 0, 0}; | |
| 172213 | 172736 | rc = fts5ExprSynonymList( |
| 172214 | - pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n | |
| 172737 | + pTerm, 0, pColset, pNode->iRowid, &buf, &a, &n | |
| 172215 | 172738 | ); |
| 172739 | + if( rc ){ | |
| 172740 | + sqlite3_free(a); | |
| 172741 | + goto ismatch_out; | |
| 172742 | + } | |
| 172743 | + if( a==buf.p ) bFlag = 1; | |
| 172216 | 172744 | }else{ |
| 172217 | - rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); | |
| 172745 | + a = (u8*)pTerm->pIter->pData; | |
| 172746 | + n = pTerm->pIter->nData; | |
| 172218 | 172747 | } |
| 172219 | - if( rc!=SQLITE_OK ) goto ismatch_out; | |
| 172220 | 172748 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); |
| 172221 | 172749 | aIter[i].bFlag = (u8)bFlag; |
| 172222 | 172750 | if( aIter[i].bEof ) goto ismatch_out; |
| 172223 | 172751 | } |
| 172224 | 172752 | |
| @@ -172286,16 +172814,10 @@ | ||
| 172286 | 172814 | p->n = n; |
| 172287 | 172815 | fts5LookaheadReaderNext(p); |
| 172288 | 172816 | return fts5LookaheadReaderNext(p); |
| 172289 | 172817 | } |
| 172290 | 172818 | |
| 172291 | -#if 0 | |
| 172292 | -static int fts5LookaheadReaderEof(Fts5LookaheadReader *p){ | |
| 172293 | - return (p->iPos==FTS5_LOOKAHEAD_EOF); | |
| 172294 | -} | |
| 172295 | -#endif | |
| 172296 | - | |
| 172297 | 172819 | typedef struct Fts5NearTrimmer Fts5NearTrimmer; |
| 172298 | 172820 | struct Fts5NearTrimmer { |
| 172299 | 172821 | Fts5LookaheadReader reader; /* Input iterator */ |
| 172300 | 172822 | Fts5PoslistWriter writer; /* Writer context */ |
| 172301 | 172823 | Fts5Buffer *pOut; /* Output poslist */ |
| @@ -172329,11 +172851,11 @@ | ||
| 172329 | 172851 | |
| 172330 | 172852 | assert( pNear->nPhrase>1 ); |
| 172331 | 172853 | |
| 172332 | 172854 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172333 | 172855 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172334 | - if( pNear->nPhrase>(int)ArraySize(aStatic) ){ | |
| 172856 | + if( pNear->nPhrase>ArraySize(aStatic) ){ | |
| 172335 | 172857 | int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; |
| 172336 | 172858 | a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); |
| 172337 | 172859 | }else{ |
| 172338 | 172860 | memset(aStatic, 0, sizeof(aStatic)); |
| 172339 | 172861 | } |
| @@ -172406,75 +172928,10 @@ | ||
| 172406 | 172928 | if( a!=aStatic ) sqlite3_free(a); |
| 172407 | 172929 | return bRet; |
| 172408 | 172930 | } |
| 172409 | 172931 | } |
| 172410 | 172932 | |
| 172411 | -/* | |
| 172412 | -** Advance the first term iterator in the first phrase of pNear. Set output | |
| 172413 | -** variable *pbEof to true if it reaches EOF or if an error occurs. | |
| 172414 | -** | |
| 172415 | -** Return SQLITE_OK if successful, or an SQLite error code if an error | |
| 172416 | -** occurs. | |
| 172417 | -*/ | |
| 172418 | -static int fts5ExprNearAdvanceFirst( | |
| 172419 | - Fts5Expr *pExpr, /* Expression pPhrase belongs to */ | |
| 172420 | - Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ | |
| 172421 | - int bFromValid, | |
| 172422 | - i64 iFrom | |
| 172423 | -){ | |
| 172424 | - Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; | |
| 172425 | - int rc = SQLITE_OK; | |
| 172426 | - | |
| 172427 | - if( pTerm->pSynonym ){ | |
| 172428 | - int bEof = 1; | |
| 172429 | - Fts5ExprTerm *p; | |
| 172430 | - | |
| 172431 | - /* Find the firstest rowid any synonym points to. */ | |
| 172432 | - i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); | |
| 172433 | - | |
| 172434 | - /* Advance each iterator that currently points to iRowid. Or, if iFrom | |
| 172435 | - ** is valid - each iterator that points to a rowid before iFrom. */ | |
| 172436 | - for(p=pTerm; p; p=p->pSynonym){ | |
| 172437 | - if( sqlite3Fts5IterEof(p->pIter)==0 ){ | |
| 172438 | - i64 ii = sqlite3Fts5IterRowid(p->pIter); | |
| 172439 | - if( ii==iRowid | |
| 172440 | - || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) | |
| 172441 | - ){ | |
| 172442 | - if( bFromValid ){ | |
| 172443 | - rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); | |
| 172444 | - }else{ | |
| 172445 | - rc = sqlite3Fts5IterNext(p->pIter); | |
| 172446 | - } | |
| 172447 | - if( rc!=SQLITE_OK ) break; | |
| 172448 | - if( sqlite3Fts5IterEof(p->pIter)==0 ){ | |
| 172449 | - bEof = 0; | |
| 172450 | - } | |
| 172451 | - }else{ | |
| 172452 | - bEof = 0; | |
| 172453 | - } | |
| 172454 | - } | |
| 172455 | - } | |
| 172456 | - | |
| 172457 | - /* Set the EOF flag if either all synonym iterators are at EOF or an | |
| 172458 | - ** error has occurred. */ | |
| 172459 | - pNode->bEof = (rc || bEof); | |
| 172460 | - }else{ | |
| 172461 | - Fts5IndexIter *pIter = pTerm->pIter; | |
| 172462 | - | |
| 172463 | - assert( Fts5NodeIsString(pNode) ); | |
| 172464 | - if( bFromValid ){ | |
| 172465 | - rc = sqlite3Fts5IterNextFrom(pIter, iFrom); | |
| 172466 | - }else{ | |
| 172467 | - rc = sqlite3Fts5IterNext(pIter); | |
| 172468 | - } | |
| 172469 | - | |
| 172470 | - pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); | |
| 172471 | - } | |
| 172472 | - | |
| 172473 | - return rc; | |
| 172474 | -} | |
| 172475 | - | |
| 172476 | 172933 | /* |
| 172477 | 172934 | ** Advance iterator pIter until it points to a value equal to or laster |
| 172478 | 172935 | ** than the initial value of *piLast. If this means the iterator points |
| 172479 | 172936 | ** to a value laster than *piLast, update *piLast to the new lastest value. |
| 172480 | 172937 | ** |
| @@ -172490,19 +172947,19 @@ | ||
| 172490 | 172947 | int *pbEof /* OUT: Set to true if EOF */ |
| 172491 | 172948 | ){ |
| 172492 | 172949 | i64 iLast = *piLast; |
| 172493 | 172950 | i64 iRowid; |
| 172494 | 172951 | |
| 172495 | - iRowid = sqlite3Fts5IterRowid(pIter); | |
| 172952 | + iRowid = pIter->iRowid; | |
| 172496 | 172953 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172497 | 172954 | int rc = sqlite3Fts5IterNextFrom(pIter, iLast); |
| 172498 | 172955 | if( rc || sqlite3Fts5IterEof(pIter) ){ |
| 172499 | 172956 | *pRc = rc; |
| 172500 | 172957 | *pbEof = 1; |
| 172501 | 172958 | return 1; |
| 172502 | 172959 | } |
| 172503 | - iRowid = sqlite3Fts5IterRowid(pIter); | |
| 172960 | + iRowid = pIter->iRowid; | |
| 172504 | 172961 | assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) ); |
| 172505 | 172962 | } |
| 172506 | 172963 | *piLast = iRowid; |
| 172507 | 172964 | |
| 172508 | 172965 | return 0; |
| @@ -172519,11 +172976,11 @@ | ||
| 172519 | 172976 | Fts5ExprTerm *p; |
| 172520 | 172977 | int bEof = 0; |
| 172521 | 172978 | |
| 172522 | 172979 | for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){ |
| 172523 | 172980 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 172524 | - i64 iRowid = sqlite3Fts5IterRowid(p->pIter); | |
| 172981 | + i64 iRowid = p->pIter->iRowid; | |
| 172525 | 172982 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172526 | 172983 | rc = sqlite3Fts5IterNextFrom(p->pIter, iLast); |
| 172527 | 172984 | } |
| 172528 | 172985 | } |
| 172529 | 172986 | } |
| @@ -172551,17 +173008,11 @@ | ||
| 172551 | 173008 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 172552 | 173009 | pPhrase->poslist.n = 0; |
| 172553 | 173010 | for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ |
| 172554 | 173011 | Fts5IndexIter *pIter = pTerm->pIter; |
| 172555 | 173012 | if( sqlite3Fts5IterEof(pIter)==0 ){ |
| 172556 | - int n; | |
| 172557 | - i64 iRowid; | |
| 172558 | - rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid); | |
| 172559 | - if( rc!=SQLITE_OK ){ | |
| 172560 | - *pRc = rc; | |
| 172561 | - return 0; | |
| 172562 | - }else if( iRowid==pNode->iRowid && n>0 ){ | |
| 173013 | + if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){ | |
| 172563 | 173014 | pPhrase->poslist.n = 1; |
| 172564 | 173015 | } |
| 172565 | 173016 | } |
| 172566 | 173017 | } |
| 172567 | 173018 | return pPhrase->poslist.n; |
| @@ -172576,13 +173027,12 @@ | ||
| 172576 | 173027 | if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ |
| 172577 | 173028 | int bMatch = 0; |
| 172578 | 173029 | rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch); |
| 172579 | 173030 | if( bMatch==0 ) break; |
| 172580 | 173031 | }else{ |
| 172581 | - rc = sqlite3Fts5IterPoslistBuffer( | |
| 172582 | - pPhrase->aTerm[0].pIter, &pPhrase->poslist | |
| 172583 | - ); | |
| 173032 | + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; | |
| 173033 | + fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData); | |
| 172584 | 173034 | } |
| 172585 | 173035 | } |
| 172586 | 173036 | |
| 172587 | 173037 | *pRc = rc; |
| 172588 | 173038 | if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){ |
| @@ -172590,107 +173040,10 @@ | ||
| 172590 | 173040 | } |
| 172591 | 173041 | return 0; |
| 172592 | 173042 | } |
| 172593 | 173043 | } |
| 172594 | 173044 | |
| 172595 | -static int fts5ExprTokenTest( | |
| 172596 | - Fts5Expr *pExpr, /* Expression that pNear is a part of */ | |
| 172597 | - Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ | |
| 172598 | -){ | |
| 172599 | - /* As this "NEAR" object is actually a single phrase that consists | |
| 172600 | - ** of a single term only, grab pointers into the poslist managed by the | |
| 172601 | - ** fts5_index.c iterator object. This is much faster than synthesizing | |
| 172602 | - ** a new poslist the way we have to for more complicated phrase or NEAR | |
| 172603 | - ** expressions. */ | |
| 172604 | - Fts5ExprNearset *pNear = pNode->pNear; | |
| 172605 | - Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; | |
| 172606 | - Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; | |
| 172607 | - Fts5Colset *pColset = pNear->pColset; | |
| 172608 | - int rc; | |
| 172609 | - | |
| 172610 | - assert( pNode->eType==FTS5_TERM ); | |
| 172611 | - assert( pNear->nPhrase==1 && pPhrase->nTerm==1 ); | |
| 172612 | - assert( pPhrase->aTerm[0].pSynonym==0 ); | |
| 172613 | - | |
| 172614 | - rc = sqlite3Fts5IterPoslist(pIter, pColset, | |
| 172615 | - (const u8**)&pPhrase->poslist.p, (int*)&pPhrase->poslist.n, &pNode->iRowid | |
| 172616 | - ); | |
| 172617 | - pNode->bNomatch = (pPhrase->poslist.n==0); | |
| 172618 | - return rc; | |
| 172619 | -} | |
| 172620 | - | |
| 172621 | -/* | |
| 172622 | -** All individual term iterators in pNear are guaranteed to be valid when | |
| 172623 | -** this function is called. This function checks if all term iterators | |
| 172624 | -** point to the same rowid, and if not, advances them until they do. | |
| 172625 | -** If an EOF is reached before this happens, *pbEof is set to true before | |
| 172626 | -** returning. | |
| 172627 | -** | |
| 172628 | -** SQLITE_OK is returned if an error occurs, or an SQLite error code | |
| 172629 | -** otherwise. It is not considered an error code if an iterator reaches | |
| 172630 | -** EOF. | |
| 172631 | -*/ | |
| 172632 | -static int fts5ExprNearNextMatch( | |
| 172633 | - Fts5Expr *pExpr, /* Expression pPhrase belongs to */ | |
| 172634 | - Fts5ExprNode *pNode | |
| 172635 | -){ | |
| 172636 | - Fts5ExprNearset *pNear = pNode->pNear; | |
| 172637 | - Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; | |
| 172638 | - int rc = SQLITE_OK; | |
| 172639 | - i64 iLast; /* Lastest rowid any iterator points to */ | |
| 172640 | - int i, j; /* Phrase and token index, respectively */ | |
| 172641 | - int bMatch; /* True if all terms are at the same rowid */ | |
| 172642 | - const int bDesc = pExpr->bDesc; | |
| 172643 | - | |
| 172644 | - /* Check that this node should not be FTS5_TERM */ | |
| 172645 | - assert( pNear->nPhrase>1 | |
| 172646 | - || pNear->apPhrase[0]->nTerm>1 | |
| 172647 | - || pNear->apPhrase[0]->aTerm[0].pSynonym | |
| 172648 | - ); | |
| 172649 | - | |
| 172650 | - /* Initialize iLast, the "lastest" rowid any iterator points to. If the | |
| 172651 | - ** iterator skips through rowids in the default ascending order, this means | |
| 172652 | - ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it | |
| 172653 | - ** means the minimum rowid. */ | |
| 172654 | - if( pLeft->aTerm[0].pSynonym ){ | |
| 172655 | - iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); | |
| 172656 | - }else{ | |
| 172657 | - iLast = sqlite3Fts5IterRowid(pLeft->aTerm[0].pIter); | |
| 172658 | - } | |
| 172659 | - | |
| 172660 | - do { | |
| 172661 | - bMatch = 1; | |
| 172662 | - for(i=0; i<pNear->nPhrase; i++){ | |
| 172663 | - Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; | |
| 172664 | - for(j=0; j<pPhrase->nTerm; j++){ | |
| 172665 | - Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; | |
| 172666 | - if( pTerm->pSynonym ){ | |
| 172667 | - i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); | |
| 172668 | - if( iRowid==iLast ) continue; | |
| 172669 | - bMatch = 0; | |
| 172670 | - if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ | |
| 172671 | - pNode->bEof = 1; | |
| 172672 | - return rc; | |
| 172673 | - } | |
| 172674 | - }else{ | |
| 172675 | - Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; | |
| 172676 | - i64 iRowid = sqlite3Fts5IterRowid(pIter); | |
| 172677 | - if( iRowid==iLast ) continue; | |
| 172678 | - bMatch = 0; | |
| 172679 | - if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ | |
| 172680 | - return rc; | |
| 172681 | - } | |
| 172682 | - } | |
| 172683 | - } | |
| 172684 | - } | |
| 172685 | - }while( bMatch==0 ); | |
| 172686 | - | |
| 172687 | - pNode->iRowid = iLast; | |
| 172688 | - pNode->bNomatch = (0==fts5ExprNearTest(&rc, pExpr, pNode)); | |
| 172689 | - | |
| 172690 | - return rc; | |
| 172691 | -} | |
| 172692 | 173045 | |
| 172693 | 173046 | /* |
| 172694 | 173047 | ** Initialize all term iterators in the pNear object. If any term is found |
| 172695 | 173048 | ** to match no documents at all, return immediately without initializing any |
| 172696 | 173049 | ** further iterators. |
| @@ -172701,10 +173054,11 @@ | ||
| 172701 | 173054 | ){ |
| 172702 | 173055 | Fts5ExprNearset *pNear = pNode->pNear; |
| 172703 | 173056 | int i, j; |
| 172704 | 173057 | int rc = SQLITE_OK; |
| 172705 | 173058 | |
| 173059 | + assert( pNode->bNomatch==0 ); | |
| 172706 | 173060 | for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){ |
| 172707 | 173061 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 172708 | 173062 | for(j=0; j<pPhrase->nTerm; j++){ |
| 172709 | 173063 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; |
| 172710 | 173064 | Fts5ExprTerm *p; |
| @@ -172735,14 +173089,10 @@ | ||
| 172735 | 173089 | } |
| 172736 | 173090 | } |
| 172737 | 173091 | |
| 172738 | 173092 | return rc; |
| 172739 | 173093 | } |
| 172740 | - | |
| 172741 | -/* fts5ExprNodeNext() calls fts5ExprNodeNextMatch(). And vice-versa. */ | |
| 172742 | -static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*); | |
| 172743 | - | |
| 172744 | 173094 | |
| 172745 | 173095 | /* |
| 172746 | 173096 | ** If pExpr is an ASC iterator, this function returns a value with the |
| 172747 | 173097 | ** same sign as: |
| 172748 | 173098 | ** |
| @@ -172768,10 +173118,11 @@ | ||
| 172768 | 173118 | } |
| 172769 | 173119 | |
| 172770 | 173120 | static void fts5ExprSetEof(Fts5ExprNode *pNode){ |
| 172771 | 173121 | int i; |
| 172772 | 173122 | pNode->bEof = 1; |
| 173123 | + pNode->bNomatch = 0; | |
| 172773 | 173124 | for(i=0; i<pNode->nChild; i++){ |
| 172774 | 173125 | fts5ExprSetEof(pNode->apChild[i]); |
| 172775 | 173126 | } |
| 172776 | 173127 | } |
| 172777 | 173128 | |
| @@ -172790,16 +173141,279 @@ | ||
| 172790 | 173141 | } |
| 172791 | 173142 | } |
| 172792 | 173143 | } |
| 172793 | 173144 | |
| 172794 | 173145 | |
| 172795 | -static int fts5ExprNodeNext(Fts5Expr*, Fts5ExprNode*, int, i64); | |
| 173146 | + | |
| 173147 | +/* | |
| 173148 | +** Compare the values currently indicated by the two nodes as follows: | |
| 173149 | +** | |
| 173150 | +** res = (*p1) - (*p2) | |
| 173151 | +** | |
| 173152 | +** Nodes that point to values that come later in the iteration order are | |
| 173153 | +** considered to be larger. Nodes at EOF are the largest of all. | |
| 173154 | +** | |
| 173155 | +** This means that if the iteration order is ASC, then numerically larger | |
| 173156 | +** rowids are considered larger. Or if it is the default DESC, numerically | |
| 173157 | +** smaller rowids are larger. | |
| 173158 | +*/ | |
| 173159 | +static int fts5NodeCompare( | |
| 173160 | + Fts5Expr *pExpr, | |
| 173161 | + Fts5ExprNode *p1, | |
| 173162 | + Fts5ExprNode *p2 | |
| 173163 | +){ | |
| 173164 | + if( p2->bEof ) return -1; | |
| 173165 | + if( p1->bEof ) return +1; | |
| 173166 | + return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); | |
| 173167 | +} | |
| 173168 | + | |
| 173169 | +/* | |
| 173170 | +** All individual term iterators in pNear are guaranteed to be valid when | |
| 173171 | +** this function is called. This function checks if all term iterators | |
| 173172 | +** point to the same rowid, and if not, advances them until they do. | |
| 173173 | +** If an EOF is reached before this happens, *pbEof is set to true before | |
| 173174 | +** returning. | |
| 173175 | +** | |
| 173176 | +** SQLITE_OK is returned if an error occurs, or an SQLite error code | |
| 173177 | +** otherwise. It is not considered an error code if an iterator reaches | |
| 173178 | +** EOF. | |
| 173179 | +*/ | |
| 173180 | +static int fts5ExprNodeTest_STRING( | |
| 173181 | + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ | |
| 173182 | + Fts5ExprNode *pNode | |
| 173183 | +){ | |
| 173184 | + Fts5ExprNearset *pNear = pNode->pNear; | |
| 173185 | + Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; | |
| 173186 | + int rc = SQLITE_OK; | |
| 173187 | + i64 iLast; /* Lastest rowid any iterator points to */ | |
| 173188 | + int i, j; /* Phrase and token index, respectively */ | |
| 173189 | + int bMatch; /* True if all terms are at the same rowid */ | |
| 173190 | + const int bDesc = pExpr->bDesc; | |
| 173191 | + | |
| 173192 | + /* Check that this node should not be FTS5_TERM */ | |
| 173193 | + assert( pNear->nPhrase>1 | |
| 173194 | + || pNear->apPhrase[0]->nTerm>1 | |
| 173195 | + || pNear->apPhrase[0]->aTerm[0].pSynonym | |
| 173196 | + ); | |
| 173197 | + | |
| 173198 | + /* Initialize iLast, the "lastest" rowid any iterator points to. If the | |
| 173199 | + ** iterator skips through rowids in the default ascending order, this means | |
| 173200 | + ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it | |
| 173201 | + ** means the minimum rowid. */ | |
| 173202 | + if( pLeft->aTerm[0].pSynonym ){ | |
| 173203 | + iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); | |
| 173204 | + }else{ | |
| 173205 | + iLast = pLeft->aTerm[0].pIter->iRowid; | |
| 173206 | + } | |
| 173207 | + | |
| 173208 | + do { | |
| 173209 | + bMatch = 1; | |
| 173210 | + for(i=0; i<pNear->nPhrase; i++){ | |
| 173211 | + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; | |
| 173212 | + for(j=0; j<pPhrase->nTerm; j++){ | |
| 173213 | + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; | |
| 173214 | + if( pTerm->pSynonym ){ | |
| 173215 | + i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); | |
| 173216 | + if( iRowid==iLast ) continue; | |
| 173217 | + bMatch = 0; | |
| 173218 | + if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ | |
| 173219 | + pNode->bNomatch = 0; | |
| 173220 | + pNode->bEof = 1; | |
| 173221 | + return rc; | |
| 173222 | + } | |
| 173223 | + }else{ | |
| 173224 | + Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; | |
| 173225 | + if( pIter->iRowid==iLast ) continue; | |
| 173226 | + bMatch = 0; | |
| 173227 | + if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ | |
| 173228 | + return rc; | |
| 173229 | + } | |
| 173230 | + } | |
| 173231 | + } | |
| 173232 | + } | |
| 173233 | + }while( bMatch==0 ); | |
| 173234 | + | |
| 173235 | + pNode->iRowid = iLast; | |
| 173236 | + pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK); | |
| 173237 | + assert( pNode->bEof==0 || pNode->bNomatch==0 ); | |
| 173238 | + | |
| 173239 | + return rc; | |
| 173240 | +} | |
| 173241 | + | |
| 173242 | +/* | |
| 173243 | +** Advance the first term iterator in the first phrase of pNear. Set output | |
| 173244 | +** variable *pbEof to true if it reaches EOF or if an error occurs. | |
| 173245 | +** | |
| 173246 | +** Return SQLITE_OK if successful, or an SQLite error code if an error | |
| 173247 | +** occurs. | |
| 173248 | +*/ | |
| 173249 | +static int fts5ExprNodeNext_STRING( | |
| 173250 | + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ | |
| 173251 | + Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ | |
| 173252 | + int bFromValid, | |
| 173253 | + i64 iFrom | |
| 173254 | +){ | |
| 173255 | + Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; | |
| 173256 | + int rc = SQLITE_OK; | |
| 173257 | + | |
| 173258 | + pNode->bNomatch = 0; | |
| 173259 | + if( pTerm->pSynonym ){ | |
| 173260 | + int bEof = 1; | |
| 173261 | + Fts5ExprTerm *p; | |
| 173262 | + | |
| 173263 | + /* Find the firstest rowid any synonym points to. */ | |
| 173264 | + i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); | |
| 173265 | + | |
| 173266 | + /* Advance each iterator that currently points to iRowid. Or, if iFrom | |
| 173267 | + ** is valid - each iterator that points to a rowid before iFrom. */ | |
| 173268 | + for(p=pTerm; p; p=p->pSynonym){ | |
| 173269 | + if( sqlite3Fts5IterEof(p->pIter)==0 ){ | |
| 173270 | + i64 ii = p->pIter->iRowid; | |
| 173271 | + if( ii==iRowid | |
| 173272 | + || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) | |
| 173273 | + ){ | |
| 173274 | + if( bFromValid ){ | |
| 173275 | + rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); | |
| 173276 | + }else{ | |
| 173277 | + rc = sqlite3Fts5IterNext(p->pIter); | |
| 173278 | + } | |
| 173279 | + if( rc!=SQLITE_OK ) break; | |
| 173280 | + if( sqlite3Fts5IterEof(p->pIter)==0 ){ | |
| 173281 | + bEof = 0; | |
| 173282 | + } | |
| 173283 | + }else{ | |
| 173284 | + bEof = 0; | |
| 173285 | + } | |
| 173286 | + } | |
| 173287 | + } | |
| 173288 | + | |
| 173289 | + /* Set the EOF flag if either all synonym iterators are at EOF or an | |
| 173290 | + ** error has occurred. */ | |
| 173291 | + pNode->bEof = (rc || bEof); | |
| 173292 | + }else{ | |
| 173293 | + Fts5IndexIter *pIter = pTerm->pIter; | |
| 173294 | + | |
| 173295 | + assert( Fts5NodeIsString(pNode) ); | |
| 173296 | + if( bFromValid ){ | |
| 173297 | + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); | |
| 173298 | + }else{ | |
| 173299 | + rc = sqlite3Fts5IterNext(pIter); | |
| 173300 | + } | |
| 173301 | + | |
| 173302 | + pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); | |
| 173303 | + } | |
| 173304 | + | |
| 173305 | + if( pNode->bEof==0 ){ | |
| 173306 | + assert( rc==SQLITE_OK ); | |
| 173307 | + rc = fts5ExprNodeTest_STRING(pExpr, pNode); | |
| 173308 | + } | |
| 173309 | + | |
| 173310 | + return rc; | |
| 173311 | +} | |
| 173312 | + | |
| 173313 | + | |
| 173314 | +static int fts5ExprNodeTest_TERM( | |
| 173315 | + Fts5Expr *pExpr, /* Expression that pNear is a part of */ | |
| 173316 | + Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ | |
| 173317 | +){ | |
| 173318 | + /* As this "NEAR" object is actually a single phrase that consists | |
| 173319 | + ** of a single term only, grab pointers into the poslist managed by the | |
| 173320 | + ** fts5_index.c iterator object. This is much faster than synthesizing | |
| 173321 | + ** a new poslist the way we have to for more complicated phrase or NEAR | |
| 173322 | + ** expressions. */ | |
| 173323 | + Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; | |
| 173324 | + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; | |
| 173325 | + | |
| 173326 | + assert( pNode->eType==FTS5_TERM ); | |
| 173327 | + assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 ); | |
| 173328 | + assert( pPhrase->aTerm[0].pSynonym==0 ); | |
| 173329 | + | |
| 173330 | + pPhrase->poslist.n = pIter->nData; | |
| 173331 | + if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){ | |
| 173332 | + pPhrase->poslist.p = (u8*)pIter->pData; | |
| 173333 | + } | |
| 173334 | + pNode->iRowid = pIter->iRowid; | |
| 173335 | + pNode->bNomatch = (pPhrase->poslist.n==0); | |
| 173336 | + return SQLITE_OK; | |
| 173337 | +} | |
| 173338 | + | |
| 173339 | +/* | |
| 173340 | +** xNext() method for a node of type FTS5_TERM. | |
| 173341 | +*/ | |
| 173342 | +static int fts5ExprNodeNext_TERM( | |
| 173343 | + Fts5Expr *pExpr, | |
| 173344 | + Fts5ExprNode *pNode, | |
| 173345 | + int bFromValid, | |
| 173346 | + i64 iFrom | |
| 173347 | +){ | |
| 173348 | + int rc; | |
| 173349 | + Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; | |
| 173350 | + | |
| 173351 | + assert( pNode->bEof==0 ); | |
| 173352 | + if( bFromValid ){ | |
| 173353 | + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); | |
| 173354 | + }else{ | |
| 173355 | + rc = sqlite3Fts5IterNext(pIter); | |
| 173356 | + } | |
| 173357 | + if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ | |
| 173358 | + rc = fts5ExprNodeTest_TERM(pExpr, pNode); | |
| 173359 | + }else{ | |
| 173360 | + pNode->bEof = 1; | |
| 173361 | + pNode->bNomatch = 0; | |
| 173362 | + } | |
| 173363 | + return rc; | |
| 173364 | +} | |
| 173365 | + | |
| 173366 | +static void fts5ExprNodeTest_OR( | |
| 173367 | + Fts5Expr *pExpr, /* Expression of which pNode is a part */ | |
| 173368 | + Fts5ExprNode *pNode /* Expression node to test */ | |
| 173369 | +){ | |
| 173370 | + Fts5ExprNode *pNext = pNode->apChild[0]; | |
| 173371 | + int i; | |
| 173372 | + | |
| 173373 | + for(i=1; i<pNode->nChild; i++){ | |
| 173374 | + Fts5ExprNode *pChild = pNode->apChild[i]; | |
| 173375 | + int cmp = fts5NodeCompare(pExpr, pNext, pChild); | |
| 173376 | + if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ | |
| 173377 | + pNext = pChild; | |
| 173378 | + } | |
| 173379 | + } | |
| 173380 | + pNode->iRowid = pNext->iRowid; | |
| 173381 | + pNode->bEof = pNext->bEof; | |
| 173382 | + pNode->bNomatch = pNext->bNomatch; | |
| 173383 | +} | |
| 173384 | + | |
| 173385 | +static int fts5ExprNodeNext_OR( | |
| 173386 | + Fts5Expr *pExpr, | |
| 173387 | + Fts5ExprNode *pNode, | |
| 173388 | + int bFromValid, | |
| 173389 | + i64 iFrom | |
| 173390 | +){ | |
| 173391 | + int i; | |
| 173392 | + i64 iLast = pNode->iRowid; | |
| 173393 | + | |
| 173394 | + for(i=0; i<pNode->nChild; i++){ | |
| 173395 | + Fts5ExprNode *p1 = pNode->apChild[i]; | |
| 173396 | + assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); | |
| 173397 | + if( p1->bEof==0 ){ | |
| 173398 | + if( (p1->iRowid==iLast) | |
| 173399 | + || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) | |
| 173400 | + ){ | |
| 173401 | + int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); | |
| 173402 | + if( rc!=SQLITE_OK ) return rc; | |
| 173403 | + } | |
| 173404 | + } | |
| 173405 | + } | |
| 173406 | + | |
| 173407 | + fts5ExprNodeTest_OR(pExpr, pNode); | |
| 173408 | + return SQLITE_OK; | |
| 173409 | +} | |
| 172796 | 173410 | |
| 172797 | 173411 | /* |
| 172798 | 173412 | ** Argument pNode is an FTS5_AND node. |
| 172799 | 173413 | */ |
| 172800 | -static int fts5ExprAndNextRowid( | |
| 173414 | +static int fts5ExprNodeTest_AND( | |
| 172801 | 173415 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 172802 | 173416 | Fts5ExprNode *pAnd /* FTS5_AND node to advance */ |
| 172803 | 173417 | ){ |
| 172804 | 173418 | int iChild; |
| 172805 | 173419 | i64 iLast = pAnd->iRowid; |
| @@ -172810,19 +173424,15 @@ | ||
| 172810 | 173424 | do { |
| 172811 | 173425 | pAnd->bNomatch = 0; |
| 172812 | 173426 | bMatch = 1; |
| 172813 | 173427 | for(iChild=0; iChild<pAnd->nChild; iChild++){ |
| 172814 | 173428 | Fts5ExprNode *pChild = pAnd->apChild[iChild]; |
| 172815 | - if( 0 && pChild->eType==FTS5_STRING ){ | |
| 172816 | - /* TODO */ | |
| 172817 | - }else{ | |
| 172818 | - int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); | |
| 172819 | - if( cmp>0 ){ | |
| 172820 | - /* Advance pChild until it points to iLast or laster */ | |
| 172821 | - rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); | |
| 172822 | - if( rc!=SQLITE_OK ) return rc; | |
| 172823 | - } | |
| 173429 | + int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); | |
| 173430 | + if( cmp>0 ){ | |
| 173431 | + /* Advance pChild until it points to iLast or laster */ | |
| 173432 | + rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); | |
| 173433 | + if( rc!=SQLITE_OK ) return rc; | |
| 172824 | 173434 | } |
| 172825 | 173435 | |
| 172826 | 173436 | /* If the child node is now at EOF, so is the parent AND node. Otherwise, |
| 172827 | 173437 | ** the child node is guaranteed to have advanced at least as far as |
| 172828 | 173438 | ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the |
| @@ -172848,190 +173458,99 @@ | ||
| 172848 | 173458 | } |
| 172849 | 173459 | pAnd->iRowid = iLast; |
| 172850 | 173460 | return SQLITE_OK; |
| 172851 | 173461 | } |
| 172852 | 173462 | |
| 172853 | - | |
| 172854 | -/* | |
| 172855 | -** Compare the values currently indicated by the two nodes as follows: | |
| 172856 | -** | |
| 172857 | -** res = (*p1) - (*p2) | |
| 172858 | -** | |
| 172859 | -** Nodes that point to values that come later in the iteration order are | |
| 172860 | -** considered to be larger. Nodes at EOF are the largest of all. | |
| 172861 | -** | |
| 172862 | -** This means that if the iteration order is ASC, then numerically larger | |
| 172863 | -** rowids are considered larger. Or if it is the default DESC, numerically | |
| 172864 | -** smaller rowids are larger. | |
| 172865 | -*/ | |
| 172866 | -static int fts5NodeCompare( | |
| 172867 | - Fts5Expr *pExpr, | |
| 172868 | - Fts5ExprNode *p1, | |
| 172869 | - Fts5ExprNode *p2 | |
| 172870 | -){ | |
| 172871 | - if( p2->bEof ) return -1; | |
| 172872 | - if( p1->bEof ) return +1; | |
| 172873 | - return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); | |
| 172874 | -} | |
| 172875 | - | |
| 172876 | -/* | |
| 172877 | -** Advance node iterator pNode, part of expression pExpr. If argument | |
| 172878 | -** bFromValid is zero, then pNode is advanced exactly once. Or, if argument | |
| 172879 | -** bFromValid is non-zero, then pNode is advanced until it is at or past | |
| 172880 | -** rowid value iFrom. Whether "past" means "less than" or "greater than" | |
| 172881 | -** depends on whether this is an ASC or DESC iterator. | |
| 172882 | -*/ | |
| 172883 | -static int fts5ExprNodeNext( | |
| 173463 | +static int fts5ExprNodeNext_AND( | |
| 173464 | + Fts5Expr *pExpr, | |
| 173465 | + Fts5ExprNode *pNode, | |
| 173466 | + int bFromValid, | |
| 173467 | + i64 iFrom | |
| 173468 | +){ | |
| 173469 | + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); | |
| 173470 | + if( rc==SQLITE_OK ){ | |
| 173471 | + rc = fts5ExprNodeTest_AND(pExpr, pNode); | |
| 173472 | + } | |
| 173473 | + return rc; | |
| 173474 | +} | |
| 173475 | + | |
| 173476 | +static int fts5ExprNodeTest_NOT( | |
| 173477 | + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ | |
| 173478 | + Fts5ExprNode *pNode /* FTS5_NOT node to advance */ | |
| 173479 | +){ | |
| 173480 | + int rc = SQLITE_OK; | |
| 173481 | + Fts5ExprNode *p1 = pNode->apChild[0]; | |
| 173482 | + Fts5ExprNode *p2 = pNode->apChild[1]; | |
| 173483 | + assert( pNode->nChild==2 ); | |
| 173484 | + | |
| 173485 | + while( rc==SQLITE_OK && p1->bEof==0 ){ | |
| 173486 | + int cmp = fts5NodeCompare(pExpr, p1, p2); | |
| 173487 | + if( cmp>0 ){ | |
| 173488 | + rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); | |
| 173489 | + cmp = fts5NodeCompare(pExpr, p1, p2); | |
| 173490 | + } | |
| 173491 | + assert( rc!=SQLITE_OK || cmp<=0 ); | |
| 173492 | + if( cmp || p2->bNomatch ) break; | |
| 173493 | + rc = fts5ExprNodeNext(pExpr, p1, 0, 0); | |
| 173494 | + } | |
| 173495 | + pNode->bEof = p1->bEof; | |
| 173496 | + pNode->bNomatch = p1->bNomatch; | |
| 173497 | + pNode->iRowid = p1->iRowid; | |
| 173498 | + if( p1->bEof ){ | |
| 173499 | + fts5ExprNodeZeroPoslist(p2); | |
| 173500 | + } | |
| 173501 | + return rc; | |
| 173502 | +} | |
| 173503 | + | |
| 173504 | +static int fts5ExprNodeNext_NOT( | |
| 172884 | 173505 | Fts5Expr *pExpr, |
| 172885 | 173506 | Fts5ExprNode *pNode, |
| 172886 | 173507 | int bFromValid, |
| 172887 | 173508 | i64 iFrom |
| 172888 | 173509 | ){ |
| 172889 | - int rc = SQLITE_OK; | |
| 172890 | - | |
| 172891 | - if( pNode->bEof==0 ){ | |
| 172892 | - switch( pNode->eType ){ | |
| 172893 | - case FTS5_STRING: { | |
| 172894 | - rc = fts5ExprNearAdvanceFirst(pExpr, pNode, bFromValid, iFrom); | |
| 172895 | - break; | |
| 172896 | - }; | |
| 172897 | - | |
| 172898 | - case FTS5_TERM: { | |
| 172899 | - Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; | |
| 172900 | - if( bFromValid ){ | |
| 172901 | - rc = sqlite3Fts5IterNextFrom(pIter, iFrom); | |
| 172902 | - }else{ | |
| 172903 | - rc = sqlite3Fts5IterNext(pIter); | |
| 172904 | - } | |
| 172905 | - if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ | |
| 172906 | - assert( rc==SQLITE_OK ); | |
| 172907 | - rc = fts5ExprTokenTest(pExpr, pNode); | |
| 172908 | - }else{ | |
| 172909 | - pNode->bEof = 1; | |
| 172910 | - } | |
| 172911 | - return rc; | |
| 172912 | - }; | |
| 172913 | - | |
| 172914 | - case FTS5_AND: { | |
| 172915 | - Fts5ExprNode *pLeft = pNode->apChild[0]; | |
| 172916 | - rc = fts5ExprNodeNext(pExpr, pLeft, bFromValid, iFrom); | |
| 172917 | - break; | |
| 172918 | - } | |
| 172919 | - | |
| 172920 | - case FTS5_OR: { | |
| 172921 | - int i; | |
| 172922 | - i64 iLast = pNode->iRowid; | |
| 172923 | - | |
| 172924 | - for(i=0; rc==SQLITE_OK && i<pNode->nChild; i++){ | |
| 172925 | - Fts5ExprNode *p1 = pNode->apChild[i]; | |
| 172926 | - assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); | |
| 172927 | - if( p1->bEof==0 ){ | |
| 172928 | - if( (p1->iRowid==iLast) | |
| 172929 | - || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) | |
| 172930 | - ){ | |
| 172931 | - rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); | |
| 172932 | - } | |
| 172933 | - } | |
| 172934 | - } | |
| 172935 | - | |
| 172936 | - break; | |
| 172937 | - } | |
| 172938 | - | |
| 172939 | - default: assert( pNode->eType==FTS5_NOT ); { | |
| 172940 | - assert( pNode->nChild==2 ); | |
| 172941 | - rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); | |
| 172942 | - break; | |
| 172943 | - } | |
| 172944 | - } | |
| 172945 | - | |
| 172946 | - if( rc==SQLITE_OK ){ | |
| 172947 | - rc = fts5ExprNodeNextMatch(pExpr, pNode); | |
| 172948 | - } | |
| 172949 | - } | |
| 172950 | - | |
| 172951 | - /* Assert that if bFromValid was true, either: | |
| 172952 | - ** | |
| 172953 | - ** a) an error occurred, or | |
| 172954 | - ** b) the node is now at EOF, or | |
| 172955 | - ** c) the node is now at or past rowid iFrom. | |
| 172956 | - */ | |
| 172957 | - assert( bFromValid==0 | |
| 172958 | - || rc!=SQLITE_OK /* a */ | |
| 172959 | - || pNode->bEof /* b */ | |
| 172960 | - || pNode->iRowid==iFrom || pExpr->bDesc==(pNode->iRowid<iFrom) /* c */ | |
| 172961 | - ); | |
| 172962 | - | |
| 172963 | - return rc; | |
| 172964 | -} | |
| 172965 | - | |
| 173510 | + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); | |
| 173511 | + if( rc==SQLITE_OK ){ | |
| 173512 | + rc = fts5ExprNodeTest_NOT(pExpr, pNode); | |
| 173513 | + } | |
| 173514 | + return rc; | |
| 173515 | +} | |
| 172966 | 173516 | |
| 172967 | 173517 | /* |
| 172968 | 173518 | ** If pNode currently points to a match, this function returns SQLITE_OK |
| 172969 | 173519 | ** without modifying it. Otherwise, pNode is advanced until it does point |
| 172970 | 173520 | ** to a match or EOF is reached. |
| 172971 | 173521 | */ |
| 172972 | -static int fts5ExprNodeNextMatch( | |
| 173522 | +static int fts5ExprNodeTest( | |
| 172973 | 173523 | Fts5Expr *pExpr, /* Expression of which pNode is a part */ |
| 172974 | 173524 | Fts5ExprNode *pNode /* Expression node to test */ |
| 172975 | 173525 | ){ |
| 172976 | 173526 | int rc = SQLITE_OK; |
| 172977 | 173527 | if( pNode->bEof==0 ){ |
| 172978 | 173528 | switch( pNode->eType ){ |
| 172979 | 173529 | |
| 172980 | 173530 | case FTS5_STRING: { |
| 172981 | - /* Advance the iterators until they all point to the same rowid */ | |
| 172982 | - rc = fts5ExprNearNextMatch(pExpr, pNode); | |
| 173531 | + rc = fts5ExprNodeTest_STRING(pExpr, pNode); | |
| 172983 | 173532 | break; |
| 172984 | 173533 | } |
| 172985 | 173534 | |
| 172986 | 173535 | case FTS5_TERM: { |
| 172987 | - rc = fts5ExprTokenTest(pExpr, pNode); | |
| 173536 | + rc = fts5ExprNodeTest_TERM(pExpr, pNode); | |
| 172988 | 173537 | break; |
| 172989 | 173538 | } |
| 172990 | 173539 | |
| 172991 | 173540 | case FTS5_AND: { |
| 172992 | - rc = fts5ExprAndNextRowid(pExpr, pNode); | |
| 173541 | + rc = fts5ExprNodeTest_AND(pExpr, pNode); | |
| 172993 | 173542 | break; |
| 172994 | 173543 | } |
| 172995 | 173544 | |
| 172996 | 173545 | case FTS5_OR: { |
| 172997 | - Fts5ExprNode *pNext = pNode->apChild[0]; | |
| 172998 | - int i; | |
| 172999 | - | |
| 173000 | - for(i=1; i<pNode->nChild; i++){ | |
| 173001 | - Fts5ExprNode *pChild = pNode->apChild[i]; | |
| 173002 | - int cmp = fts5NodeCompare(pExpr, pNext, pChild); | |
| 173003 | - if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ | |
| 173004 | - pNext = pChild; | |
| 173005 | - } | |
| 173006 | - } | |
| 173007 | - pNode->iRowid = pNext->iRowid; | |
| 173008 | - pNode->bEof = pNext->bEof; | |
| 173009 | - pNode->bNomatch = pNext->bNomatch; | |
| 173546 | + fts5ExprNodeTest_OR(pExpr, pNode); | |
| 173010 | 173547 | break; |
| 173011 | 173548 | } |
| 173012 | 173549 | |
| 173013 | 173550 | default: assert( pNode->eType==FTS5_NOT ); { |
| 173014 | - Fts5ExprNode *p1 = pNode->apChild[0]; | |
| 173015 | - Fts5ExprNode *p2 = pNode->apChild[1]; | |
| 173016 | - assert( pNode->nChild==2 ); | |
| 173017 | - | |
| 173018 | - while( rc==SQLITE_OK && p1->bEof==0 ){ | |
| 173019 | - int cmp = fts5NodeCompare(pExpr, p1, p2); | |
| 173020 | - if( cmp>0 ){ | |
| 173021 | - rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); | |
| 173022 | - cmp = fts5NodeCompare(pExpr, p1, p2); | |
| 173023 | - } | |
| 173024 | - assert( rc!=SQLITE_OK || cmp<=0 ); | |
| 173025 | - if( cmp || p2->bNomatch ) break; | |
| 173026 | - rc = fts5ExprNodeNext(pExpr, p1, 0, 0); | |
| 173027 | - } | |
| 173028 | - pNode->bEof = p1->bEof; | |
| 173029 | - pNode->iRowid = p1->iRowid; | |
| 173030 | - if( p1->bEof ){ | |
| 173031 | - fts5ExprNodeZeroPoslist(p2); | |
| 173032 | - } | |
| 173551 | + rc = fts5ExprNodeTest_NOT(pExpr, pNode); | |
| 173033 | 173552 | break; |
| 173034 | 173553 | } |
| 173035 | 173554 | } |
| 173036 | 173555 | } |
| 173037 | 173556 | return rc; |
| @@ -173046,24 +173565,44 @@ | ||
| 173046 | 173565 | ** It is not an error if there are no matches. |
| 173047 | 173566 | */ |
| 173048 | 173567 | static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ |
| 173049 | 173568 | int rc = SQLITE_OK; |
| 173050 | 173569 | pNode->bEof = 0; |
| 173570 | + pNode->bNomatch = 0; | |
| 173051 | 173571 | |
| 173052 | 173572 | if( Fts5NodeIsString(pNode) ){ |
| 173053 | 173573 | /* Initialize all term iterators in the NEAR object. */ |
| 173054 | 173574 | rc = fts5ExprNearInitAll(pExpr, pNode); |
| 173055 | 173575 | }else{ |
| 173056 | 173576 | int i; |
| 173577 | + int nEof = 0; | |
| 173057 | 173578 | for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){ |
| 173579 | + Fts5ExprNode *pChild = pNode->apChild[i]; | |
| 173058 | 173580 | rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]); |
| 173581 | + assert( pChild->bEof==0 || pChild->bEof==1 ); | |
| 173582 | + nEof += pChild->bEof; | |
| 173059 | 173583 | } |
| 173060 | 173584 | pNode->iRowid = pNode->apChild[0]->iRowid; |
| 173585 | + | |
| 173586 | + switch( pNode->eType ){ | |
| 173587 | + case FTS5_AND: | |
| 173588 | + if( nEof>0 ) fts5ExprSetEof(pNode); | |
| 173589 | + break; | |
| 173590 | + | |
| 173591 | + case FTS5_OR: | |
| 173592 | + if( pNode->nChild==nEof ) fts5ExprSetEof(pNode); | |
| 173593 | + break; | |
| 173594 | + | |
| 173595 | + default: | |
| 173596 | + assert( pNode->eType==FTS5_NOT ); | |
| 173597 | + pNode->bEof = pNode->apChild[0]->bEof; | |
| 173598 | + break; | |
| 173599 | + } | |
| 173061 | 173600 | } |
| 173062 | 173601 | |
| 173063 | 173602 | if( rc==SQLITE_OK ){ |
| 173064 | - rc = fts5ExprNodeNextMatch(pExpr, pNode); | |
| 173603 | + rc = fts5ExprNodeTest(pExpr, pNode); | |
| 173065 | 173604 | } |
| 173066 | 173605 | return rc; |
| 173067 | 173606 | } |
| 173068 | 173607 | |
| 173069 | 173608 | |
| @@ -173083,11 +173622,11 @@ | ||
| 173083 | 173622 | ** is not considered an error if the query does not match any documents. |
| 173084 | 173623 | */ |
| 173085 | 173624 | static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ |
| 173086 | 173625 | Fts5ExprNode *pRoot = p->pRoot; |
| 173087 | 173626 | int rc = SQLITE_OK; |
| 173088 | - if( pRoot ){ | |
| 173627 | + if( pRoot->xNext ){ | |
| 173089 | 173628 | p->pIndex = pIdx; |
| 173090 | 173629 | p->bDesc = bDesc; |
| 173091 | 173630 | rc = fts5ExprNodeFirst(p, pRoot); |
| 173092 | 173631 | |
| 173093 | 173632 | /* If not at EOF but the current rowid occurs earlier than iFirst in |
| @@ -173095,11 +173634,12 @@ | ||
| 173095 | 173634 | if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ |
| 173096 | 173635 | rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); |
| 173097 | 173636 | } |
| 173098 | 173637 | |
| 173099 | 173638 | /* If the iterator is not at a real match, skip forward until it is. */ |
| 173100 | - while( pRoot->bNomatch && rc==SQLITE_OK && pRoot->bEof==0 ){ | |
| 173639 | + while( pRoot->bNomatch ){ | |
| 173640 | + assert( pRoot->bEof==0 && rc==SQLITE_OK ); | |
| 173101 | 173641 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173102 | 173642 | } |
| 173103 | 173643 | } |
| 173104 | 173644 | return rc; |
| 173105 | 173645 | } |
| @@ -173111,21 +173651,23 @@ | ||
| 173111 | 173651 | ** is not considered an error if the query does not match any documents. |
| 173112 | 173652 | */ |
| 173113 | 173653 | static int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ |
| 173114 | 173654 | int rc; |
| 173115 | 173655 | Fts5ExprNode *pRoot = p->pRoot; |
| 173656 | + assert( pRoot->bEof==0 && pRoot->bNomatch==0 ); | |
| 173116 | 173657 | do { |
| 173117 | 173658 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173118 | - }while( pRoot->bNomatch && pRoot->bEof==0 && rc==SQLITE_OK ); | |
| 173659 | + assert( pRoot->bNomatch==0 || (rc==SQLITE_OK && pRoot->bEof==0) ); | |
| 173660 | + }while( pRoot->bNomatch ); | |
| 173119 | 173661 | if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ |
| 173120 | 173662 | pRoot->bEof = 1; |
| 173121 | 173663 | } |
| 173122 | 173664 | return rc; |
| 173123 | 173665 | } |
| 173124 | 173666 | |
| 173125 | 173667 | static int sqlite3Fts5ExprEof(Fts5Expr *p){ |
| 173126 | - return (p->pRoot==0 || p->pRoot->bEof); | |
| 173668 | + return p->pRoot->bEof; | |
| 173127 | 173669 | } |
| 173128 | 173670 | |
| 173129 | 173671 | static i64 sqlite3Fts5ExprRowid(Fts5Expr *p){ |
| 173130 | 173672 | return p->pRoot->iRowid; |
| 173131 | 173673 | } |
| @@ -173146,14 +173688,14 @@ | ||
| 173146 | 173688 | Fts5ExprTerm *pSyn; |
| 173147 | 173689 | Fts5ExprTerm *pNext; |
| 173148 | 173690 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 173149 | 173691 | sqlite3_free(pTerm->zTerm); |
| 173150 | 173692 | sqlite3Fts5IterClose(pTerm->pIter); |
| 173151 | - | |
| 173152 | 173693 | for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ |
| 173153 | 173694 | pNext = pSyn->pSynonym; |
| 173154 | 173695 | sqlite3Fts5IterClose(pSyn->pIter); |
| 173696 | + fts5BufferFree((Fts5Buffer*)&pSyn[1]); | |
| 173155 | 173697 | sqlite3_free(pSyn); |
| 173156 | 173698 | } |
| 173157 | 173699 | } |
| 173158 | 173700 | if( pPhrase->poslist.nSpace>0 ) fts5BufferFree(&pPhrase->poslist); |
| 173159 | 173701 | sqlite3_free(pPhrase); |
| @@ -173237,17 +173779,17 @@ | ||
| 173237 | 173779 | if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; |
| 173238 | 173780 | |
| 173239 | 173781 | assert( pPhrase==0 || pPhrase->nTerm>0 ); |
| 173240 | 173782 | if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ |
| 173241 | 173783 | Fts5ExprTerm *pSyn; |
| 173242 | - int nByte = sizeof(Fts5ExprTerm) + nToken+1; | |
| 173784 | + int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; | |
| 173243 | 173785 | pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); |
| 173244 | 173786 | if( pSyn==0 ){ |
| 173245 | 173787 | rc = SQLITE_NOMEM; |
| 173246 | 173788 | }else{ |
| 173247 | 173789 | memset(pSyn, 0, nByte); |
| 173248 | - pSyn->zTerm = (char*)&pSyn[1]; | |
| 173790 | + pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); | |
| 173249 | 173791 | memcpy(pSyn->zTerm, pToken, nToken); |
| 173250 | 173792 | pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; |
| 173251 | 173793 | pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; |
| 173252 | 173794 | } |
| 173253 | 173795 | }else{ |
| @@ -173422,12 +173964,14 @@ | ||
| 173422 | 173964 | pNew->pRoot->pNear->nPhrase = 1; |
| 173423 | 173965 | sCtx.pPhrase->pNode = pNew->pRoot; |
| 173424 | 173966 | |
| 173425 | 173967 | if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ |
| 173426 | 173968 | pNew->pRoot->eType = FTS5_TERM; |
| 173969 | + pNew->pRoot->xNext = fts5ExprNodeNext_TERM; | |
| 173427 | 173970 | }else{ |
| 173428 | 173971 | pNew->pRoot->eType = FTS5_STRING; |
| 173972 | + pNew->pRoot->xNext = fts5ExprNodeNext_STRING; | |
| 173429 | 173973 | } |
| 173430 | 173974 | }else{ |
| 173431 | 173975 | sqlite3Fts5ExprFree(pNew); |
| 173432 | 173976 | fts5ExprPhraseFree(sCtx.pPhrase); |
| 173433 | 173977 | pNew = 0; |
| @@ -173570,10 +174114,42 @@ | ||
| 173570 | 174114 | pNear->pColset = pColset; |
| 173571 | 174115 | }else{ |
| 173572 | 174116 | sqlite3_free(pColset); |
| 173573 | 174117 | } |
| 173574 | 174118 | } |
| 174119 | + | |
| 174120 | +static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ | |
| 174121 | + switch( pNode->eType ){ | |
| 174122 | + case FTS5_STRING: { | |
| 174123 | + Fts5ExprNearset *pNear = pNode->pNear; | |
| 174124 | + if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 | |
| 174125 | + && pNear->apPhrase[0]->aTerm[0].pSynonym==0 | |
| 174126 | + ){ | |
| 174127 | + pNode->eType = FTS5_TERM; | |
| 174128 | + pNode->xNext = fts5ExprNodeNext_TERM; | |
| 174129 | + }else{ | |
| 174130 | + pNode->xNext = fts5ExprNodeNext_STRING; | |
| 174131 | + } | |
| 174132 | + break; | |
| 174133 | + }; | |
| 174134 | + | |
| 174135 | + case FTS5_OR: { | |
| 174136 | + pNode->xNext = fts5ExprNodeNext_OR; | |
| 174137 | + break; | |
| 174138 | + }; | |
| 174139 | + | |
| 174140 | + case FTS5_AND: { | |
| 174141 | + pNode->xNext = fts5ExprNodeNext_AND; | |
| 174142 | + break; | |
| 174143 | + }; | |
| 174144 | + | |
| 174145 | + default: assert( pNode->eType==FTS5_NOT ); { | |
| 174146 | + pNode->xNext = fts5ExprNodeNext_NOT; | |
| 174147 | + break; | |
| 174148 | + }; | |
| 174149 | + } | |
| 174150 | +} | |
| 173575 | 174151 | |
| 173576 | 174152 | static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ |
| 173577 | 174153 | if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){ |
| 173578 | 174154 | int nByte = sizeof(Fts5ExprNode*) * pSub->nChild; |
| 173579 | 174155 | memcpy(&p->apChild[p->nChild], pSub->apChild, nByte); |
| @@ -173620,20 +174196,20 @@ | ||
| 173620 | 174196 | pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); |
| 173621 | 174197 | |
| 173622 | 174198 | if( pRet ){ |
| 173623 | 174199 | pRet->eType = eType; |
| 173624 | 174200 | pRet->pNear = pNear; |
| 174201 | + fts5ExprAssignXNext(pRet); | |
| 173625 | 174202 | if( eType==FTS5_STRING ){ |
| 173626 | 174203 | int iPhrase; |
| 173627 | 174204 | for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){ |
| 173628 | 174205 | pNear->apPhrase[iPhrase]->pNode = pRet; |
| 173629 | 174206 | } |
| 173630 | - if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){ | |
| 173631 | - if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){ | |
| 173632 | - pRet->eType = FTS5_TERM; | |
| 173633 | - } | |
| 173634 | - }else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ | |
| 174207 | + | |
| 174208 | + if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL | |
| 174209 | + && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1) | |
| 174210 | + ){ | |
| 173635 | 174211 | assert( pParse->rc==SQLITE_OK ); |
| 173636 | 174212 | pParse->rc = SQLITE_ERROR; |
| 173637 | 174213 | assert( pParse->zErr==0 ); |
| 173638 | 174214 | pParse->zErr = sqlite3_mprintf( |
| 173639 | 174215 | "fts5: %s queries are not supported (detail!=full)", |
| @@ -173640,10 +174216,11 @@ | ||
| 173640 | 174216 | pNear->nPhrase==1 ? "phrase": "NEAR" |
| 173641 | 174217 | ); |
| 173642 | 174218 | sqlite3_free(pRet); |
| 173643 | 174219 | pRet = 0; |
| 173644 | 174220 | } |
| 174221 | + | |
| 173645 | 174222 | }else{ |
| 173646 | 174223 | fts5ExprAddChildren(pRet, pLeft); |
| 173647 | 174224 | fts5ExprAddChildren(pRet, pRight); |
| 173648 | 174225 | } |
| 173649 | 174226 | } |
| @@ -173922,11 +174499,11 @@ | ||
| 173922 | 174499 | if( rc==SQLITE_OK ){ |
| 173923 | 174500 | rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr); |
| 173924 | 174501 | } |
| 173925 | 174502 | if( rc==SQLITE_OK ){ |
| 173926 | 174503 | char *zText; |
| 173927 | - if( pExpr->pRoot==0 ){ | |
| 174504 | + if( pExpr->pRoot->xNext==0 ){ | |
| 173928 | 174505 | zText = sqlite3_mprintf(""); |
| 173929 | 174506 | }else if( bTcl ){ |
| 173930 | 174507 | zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot); |
| 173931 | 174508 | }else{ |
| 173932 | 174509 | zText = fts5ExprPrint(pConfig, pExpr->pRoot); |
| @@ -174022,11 +174599,11 @@ | ||
| 174022 | 174599 | }; |
| 174023 | 174600 | int i; |
| 174024 | 174601 | int rc = SQLITE_OK; |
| 174025 | 174602 | void *pCtx = (void*)pGlobal; |
| 174026 | 174603 | |
| 174027 | - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){ | |
| 174604 | + for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){ | |
| 174028 | 174605 | struct Fts5ExprFunc *p = &aFunc[i]; |
| 174029 | 174606 | rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); |
| 174030 | 174607 | } |
| 174031 | 174608 | |
| 174032 | 174609 | /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ |
| @@ -174260,30 +174837,25 @@ | ||
| 174260 | 174837 | Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase]; |
| 174261 | 174838 | Fts5ExprNode *pNode = pPhrase->pNode; |
| 174262 | 174839 | int rc = SQLITE_OK; |
| 174263 | 174840 | |
| 174264 | 174841 | assert( iPhrase>=0 && iPhrase<pExpr->nPhrase ); |
| 174842 | + assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); | |
| 174843 | + | |
| 174265 | 174844 | if( pNode->bEof==0 |
| 174266 | 174845 | && pNode->iRowid==pExpr->pRoot->iRowid |
| 174267 | 174846 | && pPhrase->poslist.n>0 |
| 174268 | 174847 | ){ |
| 174269 | 174848 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; |
| 174270 | 174849 | if( pTerm->pSynonym ){ |
| 174271 | - int bDel = 0; | |
| 174272 | - u8 *a; | |
| 174850 | + Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1]; | |
| 174273 | 174851 | rc = fts5ExprSynonymList( |
| 174274 | - pTerm, 1, 0, pNode->iRowid, &bDel, &a, pnCollist | |
| 174852 | + pTerm, 1, 0, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist | |
| 174275 | 174853 | ); |
| 174276 | - if( bDel ){ | |
| 174277 | - sqlite3Fts5BufferSet(&rc, &pPhrase->poslist, *pnCollist, a); | |
| 174278 | - *ppCollist = pPhrase->poslist.p; | |
| 174279 | - sqlite3_free(a); | |
| 174280 | - }else{ | |
| 174281 | - *ppCollist = a; | |
| 174282 | - } | |
| 174283 | - }else{ | |
| 174284 | - sqlite3Fts5IterCollist(pPhrase->aTerm[0].pIter, ppCollist, pnCollist); | |
| 174854 | + }else{ | |
| 174855 | + *ppCollist = pPhrase->aTerm[0].pIter->pData; | |
| 174856 | + *pnCollist = pPhrase->aTerm[0].pIter->nData; | |
| 174285 | 174857 | } |
| 174286 | 174858 | }else{ |
| 174287 | 174859 | *ppCollist = 0; |
| 174288 | 174860 | *pnCollist = 0; |
| 174289 | 174861 | } |
| @@ -175080,10 +175652,11 @@ | ||
| 175080 | 175652 | |
| 175081 | 175653 | typedef struct Fts5Data Fts5Data; |
| 175082 | 175654 | typedef struct Fts5DlidxIter Fts5DlidxIter; |
| 175083 | 175655 | typedef struct Fts5DlidxLvl Fts5DlidxLvl; |
| 175084 | 175656 | typedef struct Fts5DlidxWriter Fts5DlidxWriter; |
| 175657 | +typedef struct Fts5Iter Fts5Iter; | |
| 175085 | 175658 | typedef struct Fts5PageWriter Fts5PageWriter; |
| 175086 | 175659 | typedef struct Fts5SegIter Fts5SegIter; |
| 175087 | 175660 | typedef struct Fts5DoclistIter Fts5DoclistIter; |
| 175088 | 175661 | typedef struct Fts5SegWriter Fts5SegWriter; |
| 175089 | 175662 | typedef struct Fts5Structure Fts5Structure; |
| @@ -175322,20 +175895,24 @@ | ||
| 175322 | 175895 | ** |
| 175323 | 175896 | ** poslist: |
| 175324 | 175897 | ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. |
| 175325 | 175898 | ** There is no way to tell if this is populated or not. |
| 175326 | 175899 | */ |
| 175327 | -struct Fts5IndexIter { | |
| 175900 | +struct Fts5Iter { | |
| 175901 | + Fts5IndexIter base; /* Base class containing output vars */ | |
| 175902 | + | |
| 175328 | 175903 | Fts5Index *pIndex; /* Index that owns this iterator */ |
| 175329 | 175904 | Fts5Structure *pStruct; /* Database structure for this iterator */ |
| 175330 | 175905 | Fts5Buffer poslist; /* Buffer containing current poslist */ |
| 175906 | + Fts5Colset *pColset; /* Restrict matches to these columns */ | |
| 175907 | + | |
| 175908 | + /* Invoked to set output variables. */ | |
| 175909 | + void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*); | |
| 175331 | 175910 | |
| 175332 | 175911 | int nSeg; /* Size of aSeg[] array */ |
| 175333 | 175912 | int bRev; /* True to iterate in reverse order */ |
| 175334 | 175913 | u8 bSkipEmpty; /* True to skip deleted entries */ |
| 175335 | - u8 bEof; /* True at EOF */ | |
| 175336 | - u8 bFiltered; /* True if column-filter already applied */ | |
| 175337 | 175914 | |
| 175338 | 175915 | i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ |
| 175339 | 175916 | Fts5CResult *aFirst; /* Current merge state (see above) */ |
| 175340 | 175917 | Fts5SegIter aSeg[1]; /* Array of segment iterators */ |
| 175341 | 175918 | }; |
| @@ -176571,11 +177148,11 @@ | ||
| 176571 | 177148 | /* |
| 176572 | 177149 | ** Return true if the iterator passed as the second argument currently |
| 176573 | 177150 | ** points to a delete marker. A delete marker is an entry with a 0 byte |
| 176574 | 177151 | ** position-list. |
| 176575 | 177152 | */ |
| 176576 | -static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){ | |
| 177153 | +static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){ | |
| 176577 | 177154 | Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; |
| 176578 | 177155 | return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0); |
| 176579 | 177156 | } |
| 176580 | 177157 | |
| 176581 | 177158 | /* |
| @@ -176843,13 +177420,10 @@ | ||
| 176843 | 177420 | iPoslist = pIter->iTermLeafOffset; |
| 176844 | 177421 | }else{ |
| 176845 | 177422 | iPoslist = 4; |
| 176846 | 177423 | } |
| 176847 | 177424 | fts5IndexSkipVarint(pLeaf->p, iPoslist); |
| 176848 | - assert( p->pConfig->eDetail==FTS5_DETAIL_NONE || iPoslist==( | |
| 176849 | - pIter->iLeafOffset - sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel) | |
| 176850 | - )); | |
| 176851 | 177425 | pIter->iLeafOffset = iPoslist; |
| 176852 | 177426 | |
| 176853 | 177427 | /* If this condition is true then the largest rowid for the current |
| 176854 | 177428 | ** term may not be stored on the current page. So search forward to |
| 176855 | 177429 | ** see where said rowid really is. */ |
| @@ -177077,13 +177651,10 @@ | ||
| 177077 | 177651 | ){ |
| 177078 | 177652 | int iPg = 1; |
| 177079 | 177653 | int bGe = (flags & FTS5INDEX_QUERY_SCAN); |
| 177080 | 177654 | int bDlidx = 0; /* True if there is a doclist-index */ |
| 177081 | 177655 | |
| 177082 | - static int nCall = 0; | |
| 177083 | - nCall++; | |
| 177084 | - | |
| 177085 | 177656 | assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); |
| 177086 | 177657 | assert( pTerm && nTerm ); |
| 177087 | 177658 | memset(pIter, 0, sizeof(*pIter)); |
| 177088 | 177659 | pIter->pSeg = pSeg; |
| 177089 | 177660 | |
| @@ -177225,11 +177796,11 @@ | ||
| 177225 | 177796 | ** fts5AssertMultiIterSetup(). It ensures that the result currently stored |
| 177226 | 177797 | ** in *pRes is the correct result of comparing the current positions of the |
| 177227 | 177798 | ** two iterators. |
| 177228 | 177799 | */ |
| 177229 | 177800 | static void fts5AssertComparisonResult( |
| 177230 | - Fts5IndexIter *pIter, | |
| 177801 | + Fts5Iter *pIter, | |
| 177231 | 177802 | Fts5SegIter *p1, |
| 177232 | 177803 | Fts5SegIter *p2, |
| 177233 | 177804 | Fts5CResult *pRes |
| 177234 | 177805 | ){ |
| 177235 | 177806 | int i1 = p1 - pIter->aSeg; |
| @@ -177266,16 +177837,16 @@ | ||
| 177266 | 177837 | ** This function is a no-op unless SQLITE_DEBUG is defined when this module |
| 177267 | 177838 | ** is compiled. In that case, this function is essentially an assert() |
| 177268 | 177839 | ** statement used to verify that the contents of the pIter->aFirst[] array |
| 177269 | 177840 | ** are correct. |
| 177270 | 177841 | */ |
| 177271 | -static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5IndexIter *pIter){ | |
| 177842 | +static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){ | |
| 177272 | 177843 | if( p->rc==SQLITE_OK ){ |
| 177273 | 177844 | Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177274 | 177845 | int i; |
| 177275 | 177846 | |
| 177276 | - assert( (pFirst->pLeaf==0)==pIter->bEof ); | |
| 177847 | + assert( (pFirst->pLeaf==0)==pIter->base.bEof ); | |
| 177277 | 177848 | |
| 177278 | 177849 | /* Check that pIter->iSwitchRowid is set correctly. */ |
| 177279 | 177850 | for(i=0; i<pIter->nSeg; i++){ |
| 177280 | 177851 | Fts5SegIter *p1 = &pIter->aSeg[i]; |
| 177281 | 177852 | assert( p1==pFirst |
| @@ -177311,11 +177882,11 @@ | ||
| 177311 | 177882 | ** If the returned value is non-zero, then it is the index of an entry |
| 177312 | 177883 | ** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing |
| 177313 | 177884 | ** to a key that is a duplicate of another, higher priority, |
| 177314 | 177885 | ** segment-iterator in the pSeg->aSeg[] array. |
| 177315 | 177886 | */ |
| 177316 | -static int fts5MultiIterDoCompare(Fts5IndexIter *pIter, int iOut){ | |
| 177887 | +static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ | |
| 177317 | 177888 | int i1; /* Index of left-hand Fts5SegIter */ |
| 177318 | 177889 | int i2; /* Index of right-hand Fts5SegIter */ |
| 177319 | 177890 | int iRes; |
| 177320 | 177891 | Fts5SegIter *p1; /* Left-hand Fts5SegIter */ |
| 177321 | 177892 | Fts5SegIter *p2; /* Right-hand Fts5SegIter */ |
| @@ -177457,11 +178028,11 @@ | ||
| 177457 | 178028 | |
| 177458 | 178029 | |
| 177459 | 178030 | /* |
| 177460 | 178031 | ** Free the iterator object passed as the second argument. |
| 177461 | 178032 | */ |
| 177462 | -static void fts5MultiIterFree(Fts5Index *p, Fts5IndexIter *pIter){ | |
| 178033 | +static void fts5MultiIterFree(Fts5Index *p, Fts5Iter *pIter){ | |
| 177463 | 178034 | if( pIter ){ |
| 177464 | 178035 | int i; |
| 177465 | 178036 | for(i=0; i<pIter->nSeg; i++){ |
| 177466 | 178037 | fts5SegIterClear(&pIter->aSeg[i]); |
| 177467 | 178038 | } |
| @@ -177471,11 +178042,11 @@ | ||
| 177471 | 178042 | } |
| 177472 | 178043 | } |
| 177473 | 178044 | |
| 177474 | 178045 | static void fts5MultiIterAdvanced( |
| 177475 | 178046 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177476 | - Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ | |
| 178047 | + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ | |
| 177477 | 178048 | int iChanged, /* Index of sub-iterator just advanced */ |
| 177478 | 178049 | int iMinset /* Minimum entry in aFirst[] to set */ |
| 177479 | 178050 | ){ |
| 177480 | 178051 | int i; |
| 177481 | 178052 | for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){ |
| @@ -177499,12 +178070,13 @@ | ||
| 177499 | 178070 | ** on the iterator instead. That function does the same as this one, except |
| 177500 | 178071 | ** that it deals with more complicated cases as well. |
| 177501 | 178072 | */ |
| 177502 | 178073 | static int fts5MultiIterAdvanceRowid( |
| 177503 | 178074 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177504 | - Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ | |
| 177505 | - int iChanged /* Index of sub-iterator just advanced */ | |
| 178075 | + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ | |
| 178076 | + int iChanged, /* Index of sub-iterator just advanced */ | |
| 178077 | + Fts5SegIter **ppFirst | |
| 177506 | 178078 | ){ |
| 177507 | 178079 | Fts5SegIter *pNew = &pIter->aSeg[iChanged]; |
| 177508 | 178080 | |
| 177509 | 178081 | if( pNew->iRowid==pIter->iSwitchRowid |
| 177510 | 178082 | || (pNew->iRowid<pIter->iSwitchRowid)==pIter->bRev |
| @@ -177533,19 +178105,20 @@ | ||
| 177533 | 178105 | |
| 177534 | 178106 | pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ]; |
| 177535 | 178107 | } |
| 177536 | 178108 | } |
| 177537 | 178109 | |
| 178110 | + *ppFirst = pNew; | |
| 177538 | 178111 | return 0; |
| 177539 | 178112 | } |
| 177540 | 178113 | |
| 177541 | 178114 | /* |
| 177542 | 178115 | ** Set the pIter->bEof variable based on the state of the sub-iterators. |
| 177543 | 178116 | */ |
| 177544 | -static void fts5MultiIterSetEof(Fts5IndexIter *pIter){ | |
| 178117 | +static void fts5MultiIterSetEof(Fts5Iter *pIter){ | |
| 177545 | 178118 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177546 | - pIter->bEof = pSeg->pLeaf==0; | |
| 178119 | + pIter->base.bEof = pSeg->pLeaf==0; | |
| 177547 | 178120 | pIter->iSwitchRowid = pSeg->iRowid; |
| 177548 | 178121 | } |
| 177549 | 178122 | |
| 177550 | 178123 | /* |
| 177551 | 178124 | ** Move the iterator to the next entry. |
| @@ -177554,43 +178127,48 @@ | ||
| 177554 | 178127 | ** considered an error if the iterator reaches EOF, or if it is already at |
| 177555 | 178128 | ** EOF when this function is called. |
| 177556 | 178129 | */ |
| 177557 | 178130 | static void fts5MultiIterNext( |
| 177558 | 178131 | Fts5Index *p, |
| 177559 | - Fts5IndexIter *pIter, | |
| 178132 | + Fts5Iter *pIter, | |
| 177560 | 178133 | int bFrom, /* True if argument iFrom is valid */ |
| 177561 | 178134 | i64 iFrom /* Advance at least as far as this */ |
| 177562 | 178135 | ){ |
| 177563 | - if( p->rc==SQLITE_OK ){ | |
| 177564 | - int bUseFrom = bFrom; | |
| 177565 | - do { | |
| 177566 | - int iFirst = pIter->aFirst[1].iFirst; | |
| 177567 | - int bNewTerm = 0; | |
| 177568 | - Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; | |
| 177569 | - assert( p->rc==SQLITE_OK ); | |
| 177570 | - if( bUseFrom && pSeg->pDlidx ){ | |
| 177571 | - fts5SegIterNextFrom(p, pSeg, iFrom); | |
| 177572 | - }else{ | |
| 177573 | - pSeg->xNext(p, pSeg, &bNewTerm); | |
| 177574 | - } | |
| 177575 | - | |
| 177576 | - if( pSeg->pLeaf==0 || bNewTerm | |
| 177577 | - || fts5MultiIterAdvanceRowid(p, pIter, iFirst) | |
| 177578 | - ){ | |
| 177579 | - fts5MultiIterAdvanced(p, pIter, iFirst, 1); | |
| 177580 | - fts5MultiIterSetEof(pIter); | |
| 177581 | - } | |
| 177582 | - fts5AssertMultiIterSetup(p, pIter); | |
| 177583 | - | |
| 177584 | - bUseFrom = 0; | |
| 177585 | - }while( pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter) ); | |
| 178136 | + int bUseFrom = bFrom; | |
| 178137 | + while( p->rc==SQLITE_OK ){ | |
| 178138 | + int iFirst = pIter->aFirst[1].iFirst; | |
| 178139 | + int bNewTerm = 0; | |
| 178140 | + Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; | |
| 178141 | + assert( p->rc==SQLITE_OK ); | |
| 178142 | + if( bUseFrom && pSeg->pDlidx ){ | |
| 178143 | + fts5SegIterNextFrom(p, pSeg, iFrom); | |
| 178144 | + }else{ | |
| 178145 | + pSeg->xNext(p, pSeg, &bNewTerm); | |
| 178146 | + } | |
| 178147 | + | |
| 178148 | + if( pSeg->pLeaf==0 || bNewTerm | |
| 178149 | + || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) | |
| 178150 | + ){ | |
| 178151 | + fts5MultiIterAdvanced(p, pIter, iFirst, 1); | |
| 178152 | + fts5MultiIterSetEof(pIter); | |
| 178153 | + pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; | |
| 178154 | + if( pSeg->pLeaf==0 ) return; | |
| 178155 | + } | |
| 178156 | + | |
| 178157 | + fts5AssertMultiIterSetup(p, pIter); | |
| 178158 | + assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); | |
| 178159 | + if( pIter->bSkipEmpty==0 || pSeg->nPos ){ | |
| 178160 | + pIter->xSetOutputs(pIter, pSeg); | |
| 178161 | + return; | |
| 178162 | + } | |
| 178163 | + bUseFrom = 0; | |
| 177586 | 178164 | } |
| 177587 | 178165 | } |
| 177588 | 178166 | |
| 177589 | 178167 | static void fts5MultiIterNext2( |
| 177590 | 178168 | Fts5Index *p, |
| 177591 | - Fts5IndexIter *pIter, | |
| 178169 | + Fts5Iter *pIter, | |
| 177592 | 178170 | int *pbNewTerm /* OUT: True if *might* be new term */ |
| 177593 | 178171 | ){ |
| 177594 | 178172 | assert( pIter->bSkipEmpty ); |
| 177595 | 178173 | if( p->rc==SQLITE_OK ){ |
| 177596 | 178174 | do { |
| @@ -177599,11 +178177,11 @@ | ||
| 177599 | 178177 | int bNewTerm = 0; |
| 177600 | 178178 | |
| 177601 | 178179 | assert( p->rc==SQLITE_OK ); |
| 177602 | 178180 | pSeg->xNext(p, pSeg, &bNewTerm); |
| 177603 | 178181 | if( pSeg->pLeaf==0 || bNewTerm |
| 177604 | - || fts5MultiIterAdvanceRowid(p, pIter, iFirst) | |
| 178182 | + || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) | |
| 177605 | 178183 | ){ |
| 177606 | 178184 | fts5MultiIterAdvanced(p, pIter, iFirst, 1); |
| 177607 | 178185 | fts5MultiIterSetEof(pIter); |
| 177608 | 178186 | *pbNewTerm = 1; |
| 177609 | 178187 | }else{ |
| @@ -177613,220 +178191,143 @@ | ||
| 177613 | 178191 | |
| 177614 | 178192 | }while( fts5MultiIterIsEmpty(p, pIter) ); |
| 177615 | 178193 | } |
| 177616 | 178194 | } |
| 177617 | 178195 | |
| 178196 | +static void fts5IterSetOutputs_Noop(Fts5Iter *pIter, Fts5SegIter *pSeg){ | |
| 178197 | +} | |
| 177618 | 178198 | |
| 177619 | -static Fts5IndexIter *fts5MultiIterAlloc( | |
| 178199 | +static Fts5Iter *fts5MultiIterAlloc( | |
| 177620 | 178200 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177621 | 178201 | int nSeg |
| 177622 | 178202 | ){ |
| 177623 | - Fts5IndexIter *pNew; | |
| 178203 | + Fts5Iter *pNew; | |
| 177624 | 178204 | int nSlot; /* Power of two >= nSeg */ |
| 177625 | 178205 | |
| 177626 | 178206 | for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2); |
| 177627 | 178207 | pNew = fts5IdxMalloc(p, |
| 177628 | - sizeof(Fts5IndexIter) + /* pNew */ | |
| 178208 | + sizeof(Fts5Iter) + /* pNew */ | |
| 177629 | 178209 | sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */ |
| 177630 | 178210 | sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ |
| 177631 | 178211 | ); |
| 177632 | 178212 | if( pNew ){ |
| 177633 | 178213 | pNew->nSeg = nSlot; |
| 177634 | 178214 | pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; |
| 177635 | 178215 | pNew->pIndex = p; |
| 178216 | + pNew->xSetOutputs = fts5IterSetOutputs_Noop; | |
| 177636 | 178217 | } |
| 177637 | 178218 | return pNew; |
| 177638 | 178219 | } |
| 177639 | 178220 | |
| 177640 | -/* | |
| 177641 | -** Allocate a new Fts5IndexIter object. | |
| 177642 | -** | |
| 177643 | -** The new object will be used to iterate through data in structure pStruct. | |
| 177644 | -** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel | |
| 177645 | -** is zero or greater, data from the first nSegment segments on level iLevel | |
| 177646 | -** is merged. | |
| 177647 | -** | |
| 177648 | -** The iterator initially points to the first term/rowid entry in the | |
| 177649 | -** iterated data. | |
| 177650 | -*/ | |
| 177651 | -static void fts5MultiIterNew( | |
| 177652 | - Fts5Index *p, /* FTS5 backend to iterate within */ | |
| 177653 | - Fts5Structure *pStruct, /* Structure of specific index */ | |
| 177654 | - int bSkipEmpty, /* True to ignore delete-keys */ | |
| 177655 | - int flags, /* FTS5INDEX_QUERY_XXX flags */ | |
| 177656 | - const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ | |
| 177657 | - int iLevel, /* Level to iterate (-1 for all) */ | |
| 177658 | - int nSegment, /* Number of segments to merge (iLevel>=0) */ | |
| 177659 | - Fts5IndexIter **ppOut /* New object */ | |
| 177660 | -){ | |
| 177661 | - int nSeg = 0; /* Number of segment-iters in use */ | |
| 177662 | - int iIter = 0; /* */ | |
| 177663 | - int iSeg; /* Used to iterate through segments */ | |
| 177664 | - Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */ | |
| 177665 | - Fts5StructureLevel *pLvl; | |
| 177666 | - Fts5IndexIter *pNew; | |
| 177667 | - | |
| 177668 | - assert( (pTerm==0 && nTerm==0) || iLevel<0 ); | |
| 177669 | - | |
| 177670 | - /* Allocate space for the new multi-seg-iterator. */ | |
| 177671 | - if( p->rc==SQLITE_OK ){ | |
| 177672 | - if( iLevel<0 ){ | |
| 177673 | - assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); | |
| 177674 | - nSeg = pStruct->nSegment; | |
| 177675 | - nSeg += (p->pHash ? 1 : 0); | |
| 177676 | - }else{ | |
| 177677 | - nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); | |
| 177678 | - } | |
| 177679 | - } | |
| 177680 | - *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); | |
| 177681 | - if( pNew==0 ) return; | |
| 177682 | - pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); | |
| 177683 | - pNew->bSkipEmpty = (u8)bSkipEmpty; | |
| 177684 | - pNew->pStruct = pStruct; | |
| 177685 | - fts5StructureRef(pStruct); | |
| 177686 | - | |
| 177687 | - /* Initialize each of the component segment iterators. */ | |
| 177688 | - if( iLevel<0 ){ | |
| 177689 | - Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; | |
| 177690 | - if( p->pHash ){ | |
| 177691 | - /* Add a segment iterator for the current contents of the hash table. */ | |
| 177692 | - Fts5SegIter *pIter = &pNew->aSeg[iIter++]; | |
| 177693 | - fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); | |
| 177694 | - } | |
| 177695 | - for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){ | |
| 177696 | - for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){ | |
| 177697 | - Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; | |
| 177698 | - Fts5SegIter *pIter = &pNew->aSeg[iIter++]; | |
| 177699 | - if( pTerm==0 ){ | |
| 177700 | - fts5SegIterInit(p, pSeg, pIter); | |
| 177701 | - }else{ | |
| 177702 | - fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter); | |
| 177703 | - } | |
| 177704 | - } | |
| 177705 | - } | |
| 177706 | - }else{ | |
| 177707 | - pLvl = &pStruct->aLevel[iLevel]; | |
| 177708 | - for(iSeg=nSeg-1; iSeg>=0; iSeg--){ | |
| 177709 | - fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); | |
| 177710 | - } | |
| 177711 | - } | |
| 177712 | - assert( iIter==nSeg ); | |
| 177713 | - | |
| 177714 | - /* If the above was successful, each component iterators now points | |
| 177715 | - ** to the first entry in its segment. In this case initialize the | |
| 177716 | - ** aFirst[] array. Or, if an error has occurred, free the iterator | |
| 177717 | - ** object and set the output variable to NULL. */ | |
| 177718 | - if( p->rc==SQLITE_OK ){ | |
| 177719 | - for(iIter=pNew->nSeg-1; iIter>0; iIter--){ | |
| 177720 | - int iEq; | |
| 177721 | - if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ | |
| 177722 | - Fts5SegIter *pSeg = &pNew->aSeg[iEq]; | |
| 177723 | - if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); | |
| 177724 | - fts5MultiIterAdvanced(p, pNew, iEq, iIter); | |
| 177725 | - } | |
| 177726 | - } | |
| 177727 | - fts5MultiIterSetEof(pNew); | |
| 177728 | - fts5AssertMultiIterSetup(p, pNew); | |
| 177729 | - | |
| 177730 | - if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ | |
| 177731 | - fts5MultiIterNext(p, pNew, 0, 0); | |
| 177732 | - } | |
| 177733 | - }else{ | |
| 177734 | - fts5MultiIterFree(p, pNew); | |
| 177735 | - *ppOut = 0; | |
| 177736 | - } | |
| 177737 | - fts5BufferFree(&buf); | |
| 177738 | -} | |
| 177739 | - | |
| 177740 | -/* | |
| 177741 | -** Create an Fts5IndexIter that iterates through the doclist provided | |
| 177742 | -** as the second argument. | |
| 177743 | -*/ | |
| 177744 | -static void fts5MultiIterNew2( | |
| 177745 | - Fts5Index *p, /* FTS5 backend to iterate within */ | |
| 177746 | - Fts5Data *pData, /* Doclist to iterate through */ | |
| 177747 | - int bDesc, /* True for descending rowid order */ | |
| 177748 | - Fts5IndexIter **ppOut /* New object */ | |
| 177749 | -){ | |
| 177750 | - Fts5IndexIter *pNew; | |
| 177751 | - pNew = fts5MultiIterAlloc(p, 2); | |
| 177752 | - if( pNew ){ | |
| 177753 | - Fts5SegIter *pIter = &pNew->aSeg[1]; | |
| 177754 | - | |
| 177755 | - pNew->bFiltered = 1; | |
| 177756 | - pIter->flags = FTS5_SEGITER_ONETERM; | |
| 177757 | - if( pData->szLeaf>0 ){ | |
| 177758 | - pIter->pLeaf = pData; | |
| 177759 | - pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); | |
| 177760 | - pIter->iEndofDoclist = pData->nn; | |
| 177761 | - pNew->aFirst[1].iFirst = 1; | |
| 177762 | - if( bDesc ){ | |
| 177763 | - pNew->bRev = 1; | |
| 177764 | - pIter->flags |= FTS5_SEGITER_REVERSE; | |
| 177765 | - fts5SegIterReverseInitPage(p, pIter); | |
| 177766 | - }else{ | |
| 177767 | - fts5SegIterLoadNPos(p, pIter); | |
| 177768 | - } | |
| 177769 | - pData = 0; | |
| 177770 | - }else{ | |
| 177771 | - pNew->bEof = 1; | |
| 177772 | - } | |
| 177773 | - fts5SegIterSetNext(p, pIter); | |
| 177774 | - | |
| 177775 | - *ppOut = pNew; | |
| 177776 | - } | |
| 177777 | - | |
| 177778 | - fts5DataRelease(pData); | |
| 177779 | -} | |
| 177780 | - | |
| 177781 | -/* | |
| 177782 | -** Return true if the iterator is at EOF or if an error has occurred. | |
| 177783 | -** False otherwise. | |
| 177784 | -*/ | |
| 177785 | -static int fts5MultiIterEof(Fts5Index *p, Fts5IndexIter *pIter){ | |
| 177786 | - assert( p->rc | |
| 177787 | - || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->bEof | |
| 177788 | - ); | |
| 177789 | - return (p->rc || pIter->bEof); | |
| 177790 | -} | |
| 177791 | - | |
| 177792 | -/* | |
| 177793 | -** Return the rowid of the entry that the iterator currently points | |
| 177794 | -** to. If the iterator points to EOF when this function is called the | |
| 177795 | -** results are undefined. | |
| 177796 | -*/ | |
| 177797 | -static i64 fts5MultiIterRowid(Fts5IndexIter *pIter){ | |
| 177798 | - assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); | |
| 177799 | - return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; | |
| 177800 | -} | |
| 177801 | - | |
| 177802 | -/* | |
| 177803 | -** Move the iterator to the next entry at or following iMatch. | |
| 177804 | -*/ | |
| 177805 | -static void fts5MultiIterNextFrom( | |
| 177806 | - Fts5Index *p, | |
| 177807 | - Fts5IndexIter *pIter, | |
| 177808 | - i64 iMatch | |
| 177809 | -){ | |
| 177810 | - while( 1 ){ | |
| 177811 | - i64 iRowid; | |
| 177812 | - fts5MultiIterNext(p, pIter, 1, iMatch); | |
| 177813 | - if( fts5MultiIterEof(p, pIter) ) break; | |
| 177814 | - iRowid = fts5MultiIterRowid(pIter); | |
| 177815 | - if( pIter->bRev==0 && iRowid>=iMatch ) break; | |
| 177816 | - if( pIter->bRev!=0 && iRowid<=iMatch ) break; | |
| 177817 | - } | |
| 177818 | -} | |
| 177819 | - | |
| 177820 | -/* | |
| 177821 | -** Return a pointer to a buffer containing the term associated with the | |
| 177822 | -** entry that the iterator currently points to. | |
| 177823 | -*/ | |
| 177824 | -static const u8 *fts5MultiIterTerm(Fts5IndexIter *pIter, int *pn){ | |
| 177825 | - Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; | |
| 177826 | - *pn = p->term.n; | |
| 177827 | - return p->term.p; | |
| 178221 | +static void fts5PoslistCallback( | |
| 178222 | + Fts5Index *p, | |
| 178223 | + void *pContext, | |
| 178224 | + const u8 *pChunk, int nChunk | |
| 178225 | +){ | |
| 178226 | + assert_nc( nChunk>=0 ); | |
| 178227 | + if( nChunk>0 ){ | |
| 178228 | + fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); | |
| 178229 | + } | |
| 178230 | +} | |
| 178231 | + | |
| 178232 | +typedef struct PoslistCallbackCtx PoslistCallbackCtx; | |
| 178233 | +struct PoslistCallbackCtx { | |
| 178234 | + Fts5Buffer *pBuf; /* Append to this buffer */ | |
| 178235 | + Fts5Colset *pColset; /* Restrict matches to this column */ | |
| 178236 | + int eState; /* See above */ | |
| 178237 | +}; | |
| 178238 | + | |
| 178239 | +typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; | |
| 178240 | +struct PoslistOffsetsCtx { | |
| 178241 | + Fts5Buffer *pBuf; /* Append to this buffer */ | |
| 178242 | + Fts5Colset *pColset; /* Restrict matches to this column */ | |
| 178243 | + int iRead; | |
| 178244 | + int iWrite; | |
| 178245 | +}; | |
| 178246 | + | |
| 178247 | +/* | |
| 178248 | +** TODO: Make this more efficient! | |
| 178249 | +*/ | |
| 178250 | +static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ | |
| 178251 | + int i; | |
| 178252 | + for(i=0; i<pColset->nCol; i++){ | |
| 178253 | + if( pColset->aiCol[i]==iCol ) return 1; | |
| 178254 | + } | |
| 178255 | + return 0; | |
| 178256 | +} | |
| 178257 | + | |
| 178258 | +static void fts5PoslistOffsetsCallback( | |
| 178259 | + Fts5Index *p, | |
| 178260 | + void *pContext, | |
| 178261 | + const u8 *pChunk, int nChunk | |
| 178262 | +){ | |
| 178263 | + PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; | |
| 178264 | + assert_nc( nChunk>=0 ); | |
| 178265 | + if( nChunk>0 ){ | |
| 178266 | + int i = 0; | |
| 178267 | + while( i<nChunk ){ | |
| 178268 | + int iVal; | |
| 178269 | + i += fts5GetVarint32(&pChunk[i], iVal); | |
| 178270 | + iVal += pCtx->iRead - 2; | |
| 178271 | + pCtx->iRead = iVal; | |
| 178272 | + if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ | |
| 178273 | + fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); | |
| 178274 | + pCtx->iWrite = iVal; | |
| 178275 | + } | |
| 178276 | + } | |
| 178277 | + } | |
| 178278 | +} | |
| 178279 | + | |
| 178280 | +static void fts5PoslistFilterCallback( | |
| 178281 | + Fts5Index *p, | |
| 178282 | + void *pContext, | |
| 178283 | + const u8 *pChunk, int nChunk | |
| 178284 | +){ | |
| 178285 | + PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; | |
| 178286 | + assert_nc( nChunk>=0 ); | |
| 178287 | + if( nChunk>0 ){ | |
| 178288 | + /* Search through to find the first varint with value 1. This is the | |
| 178289 | + ** start of the next columns hits. */ | |
| 178290 | + int i = 0; | |
| 178291 | + int iStart = 0; | |
| 178292 | + | |
| 178293 | + if( pCtx->eState==2 ){ | |
| 178294 | + int iCol; | |
| 178295 | + fts5FastGetVarint32(pChunk, i, iCol); | |
| 178296 | + if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ | |
| 178297 | + pCtx->eState = 1; | |
| 178298 | + fts5BufferSafeAppendVarint(pCtx->pBuf, 1); | |
| 178299 | + }else{ | |
| 178300 | + pCtx->eState = 0; | |
| 178301 | + } | |
| 178302 | + } | |
| 178303 | + | |
| 178304 | + do { | |
| 178305 | + while( i<nChunk && pChunk[i]!=0x01 ){ | |
| 178306 | + while( pChunk[i] & 0x80 ) i++; | |
| 178307 | + i++; | |
| 178308 | + } | |
| 178309 | + if( pCtx->eState ){ | |
| 178310 | + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); | |
| 178311 | + } | |
| 178312 | + if( i<nChunk ){ | |
| 178313 | + int iCol; | |
| 178314 | + iStart = i; | |
| 178315 | + i++; | |
| 178316 | + if( i>=nChunk ){ | |
| 178317 | + pCtx->eState = 2; | |
| 178318 | + }else{ | |
| 178319 | + fts5FastGetVarint32(pChunk, i, iCol); | |
| 178320 | + pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); | |
| 178321 | + if( pCtx->eState ){ | |
| 178322 | + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); | |
| 178323 | + iStart = i; | |
| 178324 | + } | |
| 178325 | + } | |
| 178326 | + } | |
| 178327 | + }while( i<nChunk ); | |
| 178328 | + } | |
| 177828 | 178329 | } |
| 177829 | 178330 | |
| 177830 | 178331 | static void fts5ChunkIterate( |
| 177831 | 178332 | Fts5Index *p, /* Index object */ |
| 177832 | 178333 | Fts5SegIter *pSeg, /* Poslist of this iterator */ |
| @@ -177866,11 +178367,462 @@ | ||
| 177866 | 178367 | } |
| 177867 | 178368 | } |
| 177868 | 178369 | } |
| 177869 | 178370 | } |
| 177870 | 178371 | |
| 178372 | +/* | |
| 178373 | +** Iterator pIter currently points to a valid entry (not EOF). This | |
| 178374 | +** function appends the position list data for the current entry to | |
| 178375 | +** buffer pBuf. It does not make a copy of the position-list size | |
| 178376 | +** field. | |
| 178377 | +*/ | |
| 178378 | +static void fts5SegiterPoslist( | |
| 178379 | + Fts5Index *p, | |
| 178380 | + Fts5SegIter *pSeg, | |
| 178381 | + Fts5Colset *pColset, | |
| 178382 | + Fts5Buffer *pBuf | |
| 178383 | +){ | |
| 178384 | + if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ | |
| 178385 | + if( pColset==0 ){ | |
| 178386 | + fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); | |
| 178387 | + }else{ | |
| 178388 | + if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ | |
| 178389 | + PoslistCallbackCtx sCtx; | |
| 178390 | + sCtx.pBuf = pBuf; | |
| 178391 | + sCtx.pColset = pColset; | |
| 178392 | + sCtx.eState = fts5IndexColsetTest(pColset, 0); | |
| 178393 | + assert( sCtx.eState==0 || sCtx.eState==1 ); | |
| 178394 | + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); | |
| 178395 | + }else{ | |
| 178396 | + PoslistOffsetsCtx sCtx; | |
| 178397 | + memset(&sCtx, 0, sizeof(sCtx)); | |
| 178398 | + sCtx.pBuf = pBuf; | |
| 178399 | + sCtx.pColset = pColset; | |
| 178400 | + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); | |
| 178401 | + } | |
| 178402 | + } | |
| 178403 | + } | |
| 178404 | +} | |
| 177871 | 178405 | |
| 178406 | +/* | |
| 178407 | +** IN/OUT parameter (*pa) points to a position list n bytes in size. If | |
| 178408 | +** the position list contains entries for column iCol, then (*pa) is set | |
| 178409 | +** to point to the sub-position-list for that column and the number of | |
| 178410 | +** bytes in it returned. Or, if the argument position list does not | |
| 178411 | +** contain any entries for column iCol, return 0. | |
| 178412 | +*/ | |
| 178413 | +static int fts5IndexExtractCol( | |
| 178414 | + const u8 **pa, /* IN/OUT: Pointer to poslist */ | |
| 178415 | + int n, /* IN: Size of poslist in bytes */ | |
| 178416 | + int iCol /* Column to extract from poslist */ | |
| 178417 | +){ | |
| 178418 | + int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ | |
| 178419 | + const u8 *p = *pa; | |
| 178420 | + const u8 *pEnd = &p[n]; /* One byte past end of position list */ | |
| 178421 | + | |
| 178422 | + while( iCol>iCurrent ){ | |
| 178423 | + /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 178424 | + ** not part of a varint. Note that it is not possible for a negative | |
| 178425 | + ** or extremely large varint to occur within an uncorrupted position | |
| 178426 | + ** list. So the last byte of each varint may be assumed to have a clear | |
| 178427 | + ** 0x80 bit. */ | |
| 178428 | + while( *p!=0x01 ){ | |
| 178429 | + while( *p++ & 0x80 ); | |
| 178430 | + if( p>=pEnd ) return 0; | |
| 178431 | + } | |
| 178432 | + *pa = p++; | |
| 178433 | + iCurrent = *p++; | |
| 178434 | + if( iCurrent & 0x80 ){ | |
| 178435 | + p--; | |
| 178436 | + p += fts5GetVarint32(p, iCurrent); | |
| 178437 | + } | |
| 178438 | + } | |
| 178439 | + if( iCol!=iCurrent ) return 0; | |
| 178440 | + | |
| 178441 | + /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 178442 | + ** not part of a varint */ | |
| 178443 | + while( p<pEnd && *p!=0x01 ){ | |
| 178444 | + while( *p++ & 0x80 ); | |
| 178445 | + } | |
| 178446 | + | |
| 178447 | + return p - (*pa); | |
| 178448 | +} | |
| 178449 | + | |
| 178450 | +static int fts5IndexExtractColset ( | |
| 178451 | + Fts5Colset *pColset, /* Colset to filter on */ | |
| 178452 | + const u8 *pPos, int nPos, /* Position list */ | |
| 178453 | + Fts5Buffer *pBuf /* Output buffer */ | |
| 178454 | +){ | |
| 178455 | + int rc = SQLITE_OK; | |
| 178456 | + int i; | |
| 178457 | + | |
| 178458 | + fts5BufferZero(pBuf); | |
| 178459 | + for(i=0; i<pColset->nCol; i++){ | |
| 178460 | + const u8 *pSub = pPos; | |
| 178461 | + int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); | |
| 178462 | + if( nSub ){ | |
| 178463 | + fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); | |
| 178464 | + } | |
| 178465 | + } | |
| 178466 | + return rc; | |
| 178467 | +} | |
| 178468 | + | |
| 178469 | +/* | |
| 178470 | +** xSetOutputs callback used by detail=none tables. | |
| 178471 | +*/ | |
| 178472 | +static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){ | |
| 178473 | + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE ); | |
| 178474 | + pIter->base.iRowid = pSeg->iRowid; | |
| 178475 | + pIter->base.nData = pSeg->nPos; | |
| 178476 | +} | |
| 178477 | + | |
| 178478 | +/* | |
| 178479 | +** xSetOutputs callback used by detail=full and detail=col tables when no | |
| 178480 | +** column filters are specified. | |
| 178481 | +*/ | |
| 178482 | +static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ | |
| 178483 | + pIter->base.iRowid = pSeg->iRowid; | |
| 178484 | + pIter->base.nData = pSeg->nPos; | |
| 178485 | + | |
| 178486 | + assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); | |
| 178487 | + assert( pIter->pColset==0 ); | |
| 178488 | + | |
| 178489 | + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ | |
| 178490 | + /* All data is stored on the current page. Populate the output | |
| 178491 | + ** variables to point into the body of the page object. */ | |
| 178492 | + pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 178493 | + }else{ | |
| 178494 | + /* The data is distributed over two or more pages. Copy it into the | |
| 178495 | + ** Fts5Iter.poslist buffer and then set the output pointer to point | |
| 178496 | + ** to this buffer. */ | |
| 178497 | + fts5BufferZero(&pIter->poslist); | |
| 178498 | + fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); | |
| 178499 | + pIter->base.pData = pIter->poslist.p; | |
| 178500 | + } | |
| 178501 | +} | |
| 178502 | + | |
| 178503 | +/* | |
| 178504 | +** xSetOutputs callback used by detail=col when there is a column filter | |
| 178505 | +** and there are 100 or more columns. Also called as a fallback from | |
| 178506 | +** fts5IterSetOutputs_Col100 if the column-list spans more than one page. | |
| 178507 | +*/ | |
| 178508 | +static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ | |
| 178509 | + fts5BufferZero(&pIter->poslist); | |
| 178510 | + fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist); | |
| 178511 | + pIter->base.iRowid = pSeg->iRowid; | |
| 178512 | + pIter->base.pData = pIter->poslist.p; | |
| 178513 | + pIter->base.nData = pIter->poslist.n; | |
| 178514 | +} | |
| 178515 | + | |
| 178516 | +/* | |
| 178517 | +** xSetOutputs callback used when: | |
| 178518 | +** | |
| 178519 | +** * detail=col, | |
| 178520 | +** * there is a column filter, and | |
| 178521 | +** * the table contains 100 or fewer columns. | |
| 178522 | +** | |
| 178523 | +** The last point is to ensure all column numbers are stored as | |
| 178524 | +** single-byte varints. | |
| 178525 | +*/ | |
| 178526 | +static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ | |
| 178527 | + | |
| 178528 | + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); | |
| 178529 | + assert( pIter->pColset ); | |
| 178530 | + | |
| 178531 | + if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ | |
| 178532 | + fts5IterSetOutputs_Col(pIter, pSeg); | |
| 178533 | + }else{ | |
| 178534 | + u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 178535 | + u8 *pEnd = (u8*)&a[pSeg->nPos]; | |
| 178536 | + int iPrev = 0; | |
| 178537 | + int *aiCol = pIter->pColset->aiCol; | |
| 178538 | + int *aiColEnd = &aiCol[pIter->pColset->nCol]; | |
| 178539 | + | |
| 178540 | + u8 *aOut = pIter->poslist.p; | |
| 178541 | + int iPrevOut = 0; | |
| 178542 | + | |
| 178543 | + pIter->base.iRowid = pSeg->iRowid; | |
| 178544 | + | |
| 178545 | + while( a<pEnd ){ | |
| 178546 | + iPrev += (int)a++[0] - 2; | |
| 178547 | + while( *aiCol<iPrev ){ | |
| 178548 | + aiCol++; | |
| 178549 | + if( aiCol==aiColEnd ) goto setoutputs_col_out; | |
| 178550 | + } | |
| 178551 | + if( *aiCol==iPrev ){ | |
| 178552 | + *aOut++ = (iPrev - iPrevOut) + 2; | |
| 178553 | + iPrevOut = iPrev; | |
| 178554 | + } | |
| 178555 | + } | |
| 178556 | + | |
| 178557 | +setoutputs_col_out: | |
| 178558 | + pIter->base.pData = pIter->poslist.p; | |
| 178559 | + pIter->base.nData = aOut - pIter->poslist.p; | |
| 178560 | + } | |
| 178561 | +} | |
| 178562 | + | |
| 178563 | +/* | |
| 178564 | +** xSetOutputs callback used by detail=full when there is a column filter. | |
| 178565 | +*/ | |
| 178566 | +static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ | |
| 178567 | + Fts5Colset *pColset = pIter->pColset; | |
| 178568 | + pIter->base.iRowid = pSeg->iRowid; | |
| 178569 | + | |
| 178570 | + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); | |
| 178571 | + assert( pColset ); | |
| 178572 | + | |
| 178573 | + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ | |
| 178574 | + /* All data is stored on the current page. Populate the output | |
| 178575 | + ** variables to point into the body of the page object. */ | |
| 178576 | + const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 178577 | + if( pColset->nCol==1 ){ | |
| 178578 | + pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); | |
| 178579 | + pIter->base.pData = a; | |
| 178580 | + }else{ | |
| 178581 | + fts5BufferZero(&pIter->poslist); | |
| 178582 | + fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist); | |
| 178583 | + pIter->base.pData = pIter->poslist.p; | |
| 178584 | + pIter->base.nData = pIter->poslist.n; | |
| 178585 | + } | |
| 178586 | + }else{ | |
| 178587 | + /* The data is distributed over two or more pages. Copy it into the | |
| 178588 | + ** Fts5Iter.poslist buffer and then set the output pointer to point | |
| 178589 | + ** to this buffer. */ | |
| 178590 | + fts5BufferZero(&pIter->poslist); | |
| 178591 | + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); | |
| 178592 | + pIter->base.pData = pIter->poslist.p; | |
| 178593 | + pIter->base.nData = pIter->poslist.n; | |
| 178594 | + } | |
| 178595 | +} | |
| 178596 | + | |
| 178597 | +static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ | |
| 178598 | + if( *pRc==SQLITE_OK ){ | |
| 178599 | + Fts5Config *pConfig = pIter->pIndex->pConfig; | |
| 178600 | + if( pConfig->eDetail==FTS5_DETAIL_NONE ){ | |
| 178601 | + pIter->xSetOutputs = fts5IterSetOutputs_None; | |
| 178602 | + } | |
| 178603 | + | |
| 178604 | + else if( pIter->pColset==0 ){ | |
| 178605 | + pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; | |
| 178606 | + } | |
| 178607 | + | |
| 178608 | + else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ | |
| 178609 | + pIter->xSetOutputs = fts5IterSetOutputs_Full; | |
| 178610 | + } | |
| 178611 | + | |
| 178612 | + else{ | |
| 178613 | + assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); | |
| 178614 | + if( pConfig->nCol<=100 ){ | |
| 178615 | + pIter->xSetOutputs = fts5IterSetOutputs_Col100; | |
| 178616 | + sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); | |
| 178617 | + }else{ | |
| 178618 | + pIter->xSetOutputs = fts5IterSetOutputs_Col; | |
| 178619 | + } | |
| 178620 | + } | |
| 178621 | + } | |
| 178622 | +} | |
| 178623 | + | |
| 178624 | + | |
| 178625 | +/* | |
| 178626 | +** Allocate a new Fts5Iter object. | |
| 178627 | +** | |
| 178628 | +** The new object will be used to iterate through data in structure pStruct. | |
| 178629 | +** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel | |
| 178630 | +** is zero or greater, data from the first nSegment segments on level iLevel | |
| 178631 | +** is merged. | |
| 178632 | +** | |
| 178633 | +** The iterator initially points to the first term/rowid entry in the | |
| 178634 | +** iterated data. | |
| 178635 | +*/ | |
| 178636 | +static void fts5MultiIterNew( | |
| 178637 | + Fts5Index *p, /* FTS5 backend to iterate within */ | |
| 178638 | + Fts5Structure *pStruct, /* Structure of specific index */ | |
| 178639 | + int flags, /* FTS5INDEX_QUERY_XXX flags */ | |
| 178640 | + Fts5Colset *pColset, /* Colset to filter on (or NULL) */ | |
| 178641 | + const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ | |
| 178642 | + int iLevel, /* Level to iterate (-1 for all) */ | |
| 178643 | + int nSegment, /* Number of segments to merge (iLevel>=0) */ | |
| 178644 | + Fts5Iter **ppOut /* New object */ | |
| 178645 | +){ | |
| 178646 | + int nSeg = 0; /* Number of segment-iters in use */ | |
| 178647 | + int iIter = 0; /* */ | |
| 178648 | + int iSeg; /* Used to iterate through segments */ | |
| 178649 | + Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */ | |
| 178650 | + Fts5StructureLevel *pLvl; | |
| 178651 | + Fts5Iter *pNew; | |
| 178652 | + | |
| 178653 | + assert( (pTerm==0 && nTerm==0) || iLevel<0 ); | |
| 178654 | + | |
| 178655 | + /* Allocate space for the new multi-seg-iterator. */ | |
| 178656 | + if( p->rc==SQLITE_OK ){ | |
| 178657 | + if( iLevel<0 ){ | |
| 178658 | + assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); | |
| 178659 | + nSeg = pStruct->nSegment; | |
| 178660 | + nSeg += (p->pHash ? 1 : 0); | |
| 178661 | + }else{ | |
| 178662 | + nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); | |
| 178663 | + } | |
| 178664 | + } | |
| 178665 | + *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); | |
| 178666 | + if( pNew==0 ) return; | |
| 178667 | + pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); | |
| 178668 | + pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY)); | |
| 178669 | + pNew->pStruct = pStruct; | |
| 178670 | + pNew->pColset = pColset; | |
| 178671 | + fts5StructureRef(pStruct); | |
| 178672 | + if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){ | |
| 178673 | + fts5IterSetOutputCb(&p->rc, pNew); | |
| 178674 | + } | |
| 178675 | + | |
| 178676 | + /* Initialize each of the component segment iterators. */ | |
| 178677 | + if( p->rc==SQLITE_OK ){ | |
| 178678 | + if( iLevel<0 ){ | |
| 178679 | + Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; | |
| 178680 | + if( p->pHash ){ | |
| 178681 | + /* Add a segment iterator for the current contents of the hash table. */ | |
| 178682 | + Fts5SegIter *pIter = &pNew->aSeg[iIter++]; | |
| 178683 | + fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); | |
| 178684 | + } | |
| 178685 | + for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){ | |
| 178686 | + for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){ | |
| 178687 | + Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; | |
| 178688 | + Fts5SegIter *pIter = &pNew->aSeg[iIter++]; | |
| 178689 | + if( pTerm==0 ){ | |
| 178690 | + fts5SegIterInit(p, pSeg, pIter); | |
| 178691 | + }else{ | |
| 178692 | + fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter); | |
| 178693 | + } | |
| 178694 | + } | |
| 178695 | + } | |
| 178696 | + }else{ | |
| 178697 | + pLvl = &pStruct->aLevel[iLevel]; | |
| 178698 | + for(iSeg=nSeg-1; iSeg>=0; iSeg--){ | |
| 178699 | + fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); | |
| 178700 | + } | |
| 178701 | + } | |
| 178702 | + assert( iIter==nSeg ); | |
| 178703 | + } | |
| 178704 | + | |
| 178705 | + /* If the above was successful, each component iterators now points | |
| 178706 | + ** to the first entry in its segment. In this case initialize the | |
| 178707 | + ** aFirst[] array. Or, if an error has occurred, free the iterator | |
| 178708 | + ** object and set the output variable to NULL. */ | |
| 178709 | + if( p->rc==SQLITE_OK ){ | |
| 178710 | + for(iIter=pNew->nSeg-1; iIter>0; iIter--){ | |
| 178711 | + int iEq; | |
| 178712 | + if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ | |
| 178713 | + Fts5SegIter *pSeg = &pNew->aSeg[iEq]; | |
| 178714 | + if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); | |
| 178715 | + fts5MultiIterAdvanced(p, pNew, iEq, iIter); | |
| 178716 | + } | |
| 178717 | + } | |
| 178718 | + fts5MultiIterSetEof(pNew); | |
| 178719 | + fts5AssertMultiIterSetup(p, pNew); | |
| 178720 | + | |
| 178721 | + if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ | |
| 178722 | + fts5MultiIterNext(p, pNew, 0, 0); | |
| 178723 | + }else if( pNew->base.bEof==0 ){ | |
| 178724 | + Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; | |
| 178725 | + pNew->xSetOutputs(pNew, pSeg); | |
| 178726 | + } | |
| 178727 | + | |
| 178728 | + }else{ | |
| 178729 | + fts5MultiIterFree(p, pNew); | |
| 178730 | + *ppOut = 0; | |
| 178731 | + } | |
| 178732 | + fts5BufferFree(&buf); | |
| 178733 | + | |
| 178734 | +} | |
| 178735 | + | |
| 178736 | +/* | |
| 178737 | +** Create an Fts5Iter that iterates through the doclist provided | |
| 178738 | +** as the second argument. | |
| 178739 | +*/ | |
| 178740 | +static void fts5MultiIterNew2( | |
| 178741 | + Fts5Index *p, /* FTS5 backend to iterate within */ | |
| 178742 | + Fts5Data *pData, /* Doclist to iterate through */ | |
| 178743 | + int bDesc, /* True for descending rowid order */ | |
| 178744 | + Fts5Iter **ppOut /* New object */ | |
| 178745 | +){ | |
| 178746 | + Fts5Iter *pNew; | |
| 178747 | + pNew = fts5MultiIterAlloc(p, 2); | |
| 178748 | + if( pNew ){ | |
| 178749 | + Fts5SegIter *pIter = &pNew->aSeg[1]; | |
| 178750 | + | |
| 178751 | + pIter->flags = FTS5_SEGITER_ONETERM; | |
| 178752 | + if( pData->szLeaf>0 ){ | |
| 178753 | + pIter->pLeaf = pData; | |
| 178754 | + pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); | |
| 178755 | + pIter->iEndofDoclist = pData->nn; | |
| 178756 | + pNew->aFirst[1].iFirst = 1; | |
| 178757 | + if( bDesc ){ | |
| 178758 | + pNew->bRev = 1; | |
| 178759 | + pIter->flags |= FTS5_SEGITER_REVERSE; | |
| 178760 | + fts5SegIterReverseInitPage(p, pIter); | |
| 178761 | + }else{ | |
| 178762 | + fts5SegIterLoadNPos(p, pIter); | |
| 178763 | + } | |
| 178764 | + pData = 0; | |
| 178765 | + }else{ | |
| 178766 | + pNew->base.bEof = 1; | |
| 178767 | + } | |
| 178768 | + fts5SegIterSetNext(p, pIter); | |
| 178769 | + | |
| 178770 | + *ppOut = pNew; | |
| 178771 | + } | |
| 178772 | + | |
| 178773 | + fts5DataRelease(pData); | |
| 178774 | +} | |
| 178775 | + | |
| 178776 | +/* | |
| 178777 | +** Return true if the iterator is at EOF or if an error has occurred. | |
| 178778 | +** False otherwise. | |
| 178779 | +*/ | |
| 178780 | +static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){ | |
| 178781 | + assert( p->rc | |
| 178782 | + || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof | |
| 178783 | + ); | |
| 178784 | + return (p->rc || pIter->base.bEof); | |
| 178785 | +} | |
| 178786 | + | |
| 178787 | +/* | |
| 178788 | +** Return the rowid of the entry that the iterator currently points | |
| 178789 | +** to. If the iterator points to EOF when this function is called the | |
| 178790 | +** results are undefined. | |
| 178791 | +*/ | |
| 178792 | +static i64 fts5MultiIterRowid(Fts5Iter *pIter){ | |
| 178793 | + assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); | |
| 178794 | + return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; | |
| 178795 | +} | |
| 178796 | + | |
| 178797 | +/* | |
| 178798 | +** Move the iterator to the next entry at or following iMatch. | |
| 178799 | +*/ | |
| 178800 | +static void fts5MultiIterNextFrom( | |
| 178801 | + Fts5Index *p, | |
| 178802 | + Fts5Iter *pIter, | |
| 178803 | + i64 iMatch | |
| 178804 | +){ | |
| 178805 | + while( 1 ){ | |
| 178806 | + i64 iRowid; | |
| 178807 | + fts5MultiIterNext(p, pIter, 1, iMatch); | |
| 178808 | + if( fts5MultiIterEof(p, pIter) ) break; | |
| 178809 | + iRowid = fts5MultiIterRowid(pIter); | |
| 178810 | + if( pIter->bRev==0 && iRowid>=iMatch ) break; | |
| 178811 | + if( pIter->bRev!=0 && iRowid<=iMatch ) break; | |
| 178812 | + } | |
| 178813 | +} | |
| 178814 | + | |
| 178815 | +/* | |
| 178816 | +** Return a pointer to a buffer containing the term associated with the | |
| 178817 | +** entry that the iterator currently points to. | |
| 178818 | +*/ | |
| 178819 | +static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){ | |
| 178820 | + Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; | |
| 178821 | + *pn = p->term.n; | |
| 178822 | + return p->term.p; | |
| 178823 | +} | |
| 177872 | 178824 | |
| 177873 | 178825 | /* |
| 177874 | 178826 | ** Allocate a new segment-id for the structure pStruct. The new segment |
| 177875 | 178827 | ** id must be between 1 and 65335 inclusive, and must not be used by |
| 177876 | 178828 | ** any currently existing segment. If a free segment id cannot be found, |
| @@ -178401,11 +179353,11 @@ | ||
| 178401 | 179353 | /* |
| 178402 | 179354 | ** Iterator pIter was used to iterate through the input segments of on an |
| 178403 | 179355 | ** incremental merge operation. This function is called if the incremental |
| 178404 | 179356 | ** merge step has finished but the input has not been completely exhausted. |
| 178405 | 179357 | */ |
| 178406 | -static void fts5TrimSegments(Fts5Index *p, Fts5IndexIter *pIter){ | |
| 179358 | +static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ | |
| 178407 | 179359 | int i; |
| 178408 | 179360 | Fts5Buffer buf; |
| 178409 | 179361 | memset(&buf, 0, sizeof(Fts5Buffer)); |
| 178410 | 179362 | for(i=0; i<pIter->nSeg; i++){ |
| 178411 | 179363 | Fts5SegIter *pSeg = &pIter->aSeg[i]; |
| @@ -178479,18 +179431,19 @@ | ||
| 178479 | 179431 | int *pnRem /* Write up to this many output leaves */ |
| 178480 | 179432 | ){ |
| 178481 | 179433 | Fts5Structure *pStruct = *ppStruct; |
| 178482 | 179434 | Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; |
| 178483 | 179435 | Fts5StructureLevel *pLvlOut; |
| 178484 | - Fts5IndexIter *pIter = 0; /* Iterator to read input data */ | |
| 179436 | + Fts5Iter *pIter = 0; /* Iterator to read input data */ | |
| 178485 | 179437 | int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */ |
| 178486 | 179438 | int nInput; /* Number of input segments */ |
| 178487 | 179439 | Fts5SegWriter writer; /* Writer object */ |
| 178488 | 179440 | Fts5StructureSegment *pSeg; /* Output segment */ |
| 178489 | 179441 | Fts5Buffer term; |
| 178490 | 179442 | int bOldest; /* True if the output segment is the oldest */ |
| 178491 | 179443 | int eDetail = p->pConfig->eDetail; |
| 179444 | + const int flags = FTS5INDEX_QUERY_NOOUTPUT; | |
| 178492 | 179445 | |
| 178493 | 179446 | assert( iLvl<pStruct->nLevel ); |
| 178494 | 179447 | assert( pLvl->nMerge<=pLvl->nSeg ); |
| 178495 | 179448 | |
| 178496 | 179449 | memset(&writer, 0, sizeof(Fts5SegWriter)); |
| @@ -178531,11 +179484,11 @@ | ||
| 178531 | 179484 | nInput = pLvl->nSeg; |
| 178532 | 179485 | } |
| 178533 | 179486 | bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); |
| 178534 | 179487 | |
| 178535 | 179488 | assert( iLvl>=0 ); |
| 178536 | - for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, iLvl, nInput, &pIter); | |
| 179489 | + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter); | |
| 178537 | 179490 | fts5MultiIterEof(p, pIter)==0; |
| 178538 | 179491 | fts5MultiIterNext(p, pIter, 0, 0) |
| 178539 | 179492 | ){ |
| 178540 | 179493 | Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 178541 | 179494 | int nPos; /* position-list size field value */ |
| @@ -178976,279 +179929,32 @@ | ||
| 178976 | 179929 | fts5StructureRelease(pStruct); |
| 178977 | 179930 | |
| 178978 | 179931 | return fts5IndexReturn(p); |
| 178979 | 179932 | } |
| 178980 | 179933 | |
| 178981 | -static void fts5PoslistCallback( | |
| 178982 | - Fts5Index *p, | |
| 178983 | - void *pContext, | |
| 178984 | - const u8 *pChunk, int nChunk | |
| 178985 | -){ | |
| 178986 | - assert_nc( nChunk>=0 ); | |
| 178987 | - if( nChunk>0 ){ | |
| 178988 | - fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); | |
| 178989 | - } | |
| 178990 | -} | |
| 178991 | - | |
| 178992 | -typedef struct PoslistCallbackCtx PoslistCallbackCtx; | |
| 178993 | -struct PoslistCallbackCtx { | |
| 178994 | - Fts5Buffer *pBuf; /* Append to this buffer */ | |
| 178995 | - Fts5Colset *pColset; /* Restrict matches to this column */ | |
| 178996 | - int eState; /* See above */ | |
| 178997 | -}; | |
| 178998 | - | |
| 178999 | -typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; | |
| 179000 | -struct PoslistOffsetsCtx { | |
| 179001 | - Fts5Buffer *pBuf; /* Append to this buffer */ | |
| 179002 | - Fts5Colset *pColset; /* Restrict matches to this column */ | |
| 179003 | - int iRead; | |
| 179004 | - int iWrite; | |
| 179005 | -}; | |
| 179006 | - | |
| 179007 | -/* | |
| 179008 | -** TODO: Make this more efficient! | |
| 179009 | -*/ | |
| 179010 | -static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ | |
| 179011 | - int i; | |
| 179012 | - for(i=0; i<pColset->nCol; i++){ | |
| 179013 | - if( pColset->aiCol[i]==iCol ) return 1; | |
| 179014 | - } | |
| 179015 | - return 0; | |
| 179016 | -} | |
| 179017 | - | |
| 179018 | -static void fts5PoslistOffsetsCallback( | |
| 179019 | - Fts5Index *p, | |
| 179020 | - void *pContext, | |
| 179021 | - const u8 *pChunk, int nChunk | |
| 179022 | -){ | |
| 179023 | - PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; | |
| 179024 | - assert_nc( nChunk>=0 ); | |
| 179025 | - if( nChunk>0 ){ | |
| 179026 | - int i = 0; | |
| 179027 | - while( i<nChunk ){ | |
| 179028 | - int iVal; | |
| 179029 | - i += fts5GetVarint32(&pChunk[i], iVal); | |
| 179030 | - iVal += pCtx->iRead - 2; | |
| 179031 | - pCtx->iRead = iVal; | |
| 179032 | - if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ | |
| 179033 | - fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); | |
| 179034 | - pCtx->iWrite = iVal; | |
| 179035 | - } | |
| 179036 | - } | |
| 179037 | - } | |
| 179038 | -} | |
| 179039 | - | |
| 179040 | -static void fts5PoslistFilterCallback( | |
| 179041 | - Fts5Index *p, | |
| 179042 | - void *pContext, | |
| 179043 | - const u8 *pChunk, int nChunk | |
| 179044 | -){ | |
| 179045 | - PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; | |
| 179046 | - assert_nc( nChunk>=0 ); | |
| 179047 | - if( nChunk>0 ){ | |
| 179048 | - /* Search through to find the first varint with value 1. This is the | |
| 179049 | - ** start of the next columns hits. */ | |
| 179050 | - int i = 0; | |
| 179051 | - int iStart = 0; | |
| 179052 | - | |
| 179053 | - if( pCtx->eState==2 ){ | |
| 179054 | - int iCol; | |
| 179055 | - fts5FastGetVarint32(pChunk, i, iCol); | |
| 179056 | - if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ | |
| 179057 | - pCtx->eState = 1; | |
| 179058 | - fts5BufferSafeAppendVarint(pCtx->pBuf, 1); | |
| 179059 | - }else{ | |
| 179060 | - pCtx->eState = 0; | |
| 179061 | - } | |
| 179062 | - } | |
| 179063 | - | |
| 179064 | - do { | |
| 179065 | - while( i<nChunk && pChunk[i]!=0x01 ){ | |
| 179066 | - while( pChunk[i] & 0x80 ) i++; | |
| 179067 | - i++; | |
| 179068 | - } | |
| 179069 | - if( pCtx->eState ){ | |
| 179070 | - fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); | |
| 179071 | - } | |
| 179072 | - if( i<nChunk ){ | |
| 179073 | - int iCol; | |
| 179074 | - iStart = i; | |
| 179075 | - i++; | |
| 179076 | - if( i>=nChunk ){ | |
| 179077 | - pCtx->eState = 2; | |
| 179078 | - }else{ | |
| 179079 | - fts5FastGetVarint32(pChunk, i, iCol); | |
| 179080 | - pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); | |
| 179081 | - if( pCtx->eState ){ | |
| 179082 | - fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); | |
| 179083 | - iStart = i; | |
| 179084 | - } | |
| 179085 | - } | |
| 179086 | - } | |
| 179087 | - }while( i<nChunk ); | |
| 179088 | - } | |
| 179089 | -} | |
| 179090 | - | |
| 179091 | -/* | |
| 179092 | -** Iterator pIter currently points to a valid entry (not EOF). This | |
| 179093 | -** function appends the position list data for the current entry to | |
| 179094 | -** buffer pBuf. It does not make a copy of the position-list size | |
| 179095 | -** field. | |
| 179096 | -*/ | |
| 179097 | -static void fts5SegiterPoslist( | |
| 179098 | - Fts5Index *p, | |
| 179099 | - Fts5SegIter *pSeg, | |
| 179100 | - Fts5Colset *pColset, | |
| 179101 | - Fts5Buffer *pBuf | |
| 179102 | -){ | |
| 179103 | - if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ | |
| 179104 | - if( pColset==0 ){ | |
| 179105 | - fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); | |
| 179106 | - }else{ | |
| 179107 | - if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ | |
| 179108 | - PoslistCallbackCtx sCtx; | |
| 179109 | - sCtx.pBuf = pBuf; | |
| 179110 | - sCtx.pColset = pColset; | |
| 179111 | - sCtx.eState = fts5IndexColsetTest(pColset, 0); | |
| 179112 | - assert( sCtx.eState==0 || sCtx.eState==1 ); | |
| 179113 | - fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); | |
| 179114 | - }else{ | |
| 179115 | - PoslistOffsetsCtx sCtx; | |
| 179116 | - memset(&sCtx, 0, sizeof(sCtx)); | |
| 179117 | - sCtx.pBuf = pBuf; | |
| 179118 | - sCtx.pColset = pColset; | |
| 179119 | - fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); | |
| 179120 | - } | |
| 179121 | - } | |
| 179122 | - } | |
| 179123 | -} | |
| 179124 | - | |
| 179125 | -/* | |
| 179126 | -** IN/OUT parameter (*pa) points to a position list n bytes in size. If | |
| 179127 | -** the position list contains entries for column iCol, then (*pa) is set | |
| 179128 | -** to point to the sub-position-list for that column and the number of | |
| 179129 | -** bytes in it returned. Or, if the argument position list does not | |
| 179130 | -** contain any entries for column iCol, return 0. | |
| 179131 | -*/ | |
| 179132 | -static int fts5IndexExtractCol( | |
| 179133 | - const u8 **pa, /* IN/OUT: Pointer to poslist */ | |
| 179134 | - int n, /* IN: Size of poslist in bytes */ | |
| 179135 | - int iCol /* Column to extract from poslist */ | |
| 179136 | -){ | |
| 179137 | - int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ | |
| 179138 | - const u8 *p = *pa; | |
| 179139 | - const u8 *pEnd = &p[n]; /* One byte past end of position list */ | |
| 179140 | - u8 prev = 0; | |
| 179141 | - | |
| 179142 | - while( iCol>iCurrent ){ | |
| 179143 | - /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 179144 | - ** not part of a varint */ | |
| 179145 | - while( (prev & 0x80) || *p!=0x01 ){ | |
| 179146 | - prev = *p++; | |
| 179147 | - if( p==pEnd ) return 0; | |
| 179148 | - } | |
| 179149 | - *pa = p++; | |
| 179150 | - p += fts5GetVarint32(p, iCurrent); | |
| 179151 | - } | |
| 179152 | - if( iCol!=iCurrent ) return 0; | |
| 179153 | - | |
| 179154 | - /* Advance pointer p until it points to pEnd or an 0x01 byte that is | |
| 179155 | - ** not part of a varint */ | |
| 179156 | - assert( (prev & 0x80)==0 ); | |
| 179157 | - while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){ | |
| 179158 | - prev = *p++; | |
| 179159 | - } | |
| 179160 | - return p - (*pa); | |
| 179161 | -} | |
| 179162 | - | |
| 179163 | -static int fts5AppendRowid( | |
| 179934 | +static void fts5AppendRowid( | |
| 179164 | 179935 | Fts5Index *p, |
| 179165 | 179936 | i64 iDelta, |
| 179166 | - Fts5IndexIter *pMulti, | |
| 179167 | - Fts5Colset *pColset, | |
| 179937 | + Fts5Iter *pMulti, | |
| 179168 | 179938 | Fts5Buffer *pBuf |
| 179169 | 179939 | ){ |
| 179170 | 179940 | fts5BufferAppendVarint(&p->rc, pBuf, iDelta); |
| 179171 | - return 0; | |
| 179172 | -} | |
| 179173 | - | |
| 179174 | -/* | |
| 179175 | -** Iterator pMulti currently points to a valid entry (not EOF). This | |
| 179176 | -** function appends the following to buffer pBuf: | |
| 179177 | -** | |
| 179178 | -** * The varint iDelta, and | |
| 179179 | -** * the position list that currently points to, including the size field. | |
| 179180 | -** | |
| 179181 | -** If argument pColset is NULL, then the position list is filtered according | |
| 179182 | -** to pColset before being appended to the buffer. If this means there are | |
| 179183 | -** no entries in the position list, nothing is appended to the buffer (not | |
| 179184 | -** even iDelta). | |
| 179185 | -** | |
| 179186 | -** If an error occurs, an error code is left in p->rc. | |
| 179187 | -*/ | |
| 179188 | -static int fts5AppendPoslist( | |
| 179941 | +} | |
| 179942 | + | |
| 179943 | +static void fts5AppendPoslist( | |
| 179189 | 179944 | Fts5Index *p, |
| 179190 | 179945 | i64 iDelta, |
| 179191 | - Fts5IndexIter *pMulti, | |
| 179192 | - Fts5Colset *pColset, | |
| 179946 | + Fts5Iter *pMulti, | |
| 179193 | 179947 | Fts5Buffer *pBuf |
| 179194 | 179948 | ){ |
| 179195 | - if( p->rc==SQLITE_OK ){ | |
| 179196 | - Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ]; | |
| 179197 | - assert( fts5MultiIterEof(p, pMulti)==0 ); | |
| 179198 | - assert( pSeg->nPos>0 ); | |
| 179199 | - if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){ | |
| 179200 | - if( p->pConfig->eDetail==FTS5_DETAIL_FULL | |
| 179201 | - && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf | |
| 179202 | - && (pColset==0 || pColset->nCol==1) | |
| 179203 | - ){ | |
| 179204 | - const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 179205 | - int nPos; | |
| 179206 | - if( pColset ){ | |
| 179207 | - nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]); | |
| 179208 | - if( nPos==0 ) return 1; | |
| 179209 | - }else{ | |
| 179210 | - nPos = pSeg->nPos; | |
| 179211 | - } | |
| 179212 | - assert( nPos>0 ); | |
| 179213 | - fts5BufferSafeAppendVarint(pBuf, iDelta); | |
| 179214 | - fts5BufferSafeAppendVarint(pBuf, nPos*2); | |
| 179215 | - fts5BufferSafeAppendBlob(pBuf, pPos, nPos); | |
| 179216 | - }else{ | |
| 179217 | - int iSv1; | |
| 179218 | - int iSv2; | |
| 179219 | - int iData; | |
| 179220 | - | |
| 179221 | - /* Append iDelta */ | |
| 179222 | - iSv1 = pBuf->n; | |
| 179223 | - fts5BufferSafeAppendVarint(pBuf, iDelta); | |
| 179224 | - | |
| 179225 | - /* WRITEPOSLISTSIZE */ | |
| 179226 | - iSv2 = pBuf->n; | |
| 179227 | - fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2); | |
| 179228 | - iData = pBuf->n; | |
| 179229 | - | |
| 179230 | - fts5SegiterPoslist(p, pSeg, pColset, pBuf); | |
| 179231 | - | |
| 179232 | - if( pColset ){ | |
| 179233 | - int nActual = pBuf->n - iData; | |
| 179234 | - if( nActual!=pSeg->nPos ){ | |
| 179235 | - if( nActual==0 ){ | |
| 179236 | - pBuf->n = iSv1; | |
| 179237 | - return 1; | |
| 179238 | - }else{ | |
| 179239 | - int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2)); | |
| 179240 | - while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; } | |
| 179241 | - sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2); | |
| 179242 | - } | |
| 179243 | - } | |
| 179244 | - } | |
| 179245 | - } | |
| 179246 | - } | |
| 179247 | - } | |
| 179248 | - | |
| 179249 | - return 0; | |
| 179949 | + int nData = pMulti->base.nData; | |
| 179950 | + assert( nData>0 ); | |
| 179951 | + if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){ | |
| 179952 | + fts5BufferSafeAppendVarint(pBuf, iDelta); | |
| 179953 | + fts5BufferSafeAppendVarint(pBuf, nData*2); | |
| 179954 | + fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData); | |
| 179955 | + } | |
| 179250 | 179956 | } |
| 179251 | 179957 | |
| 179252 | 179958 | |
| 179253 | 179959 | static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ |
| 179254 | 179960 | u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist; |
| @@ -179388,73 +180094,107 @@ | ||
| 179388 | 180094 | ){ |
| 179389 | 180095 | if( p2->n ){ |
| 179390 | 180096 | i64 iLastRowid = 0; |
| 179391 | 180097 | Fts5DoclistIter i1; |
| 179392 | 180098 | Fts5DoclistIter i2; |
| 179393 | - Fts5Buffer out; | |
| 179394 | - Fts5Buffer tmp; | |
| 179395 | - memset(&out, 0, sizeof(out)); | |
| 179396 | - memset(&tmp, 0, sizeof(tmp)); | |
| 180099 | + Fts5Buffer out = {0, 0, 0}; | |
| 180100 | + Fts5Buffer tmp = {0, 0, 0}; | |
| 179397 | 180101 | |
| 179398 | - sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n); | |
| 180102 | + if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; | |
| 179399 | 180103 | fts5DoclistIterInit(p1, &i1); |
| 179400 | 180104 | fts5DoclistIterInit(p2, &i2); |
| 179401 | - while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){ | |
| 179402 | - if( i2.aPoslist==0 || (i1.aPoslist && i1.iRowid<i2.iRowid) ){ | |
| 180105 | + | |
| 180106 | + while( 1 ){ | |
| 180107 | + if( i1.iRowid<i2.iRowid ){ | |
| 179403 | 180108 | /* Copy entry from i1 */ |
| 179404 | 180109 | fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); |
| 179405 | 180110 | fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize); |
| 179406 | 180111 | fts5DoclistIterNext(&i1); |
| 180112 | + if( i1.aPoslist==0 ) break; | |
| 179407 | 180113 | } |
| 179408 | - else if( i1.aPoslist==0 || i2.iRowid!=i1.iRowid ){ | |
| 180114 | + else if( i2.iRowid!=i1.iRowid ){ | |
| 179409 | 180115 | /* Copy entry from i2 */ |
| 179410 | 180116 | fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 179411 | 180117 | fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize); |
| 179412 | 180118 | fts5DoclistIterNext(&i2); |
| 180119 | + if( i2.aPoslist==0 ) break; | |
| 179413 | 180120 | } |
| 179414 | 180121 | else{ |
| 180122 | + /* Merge the two position lists. */ | |
| 179415 | 180123 | i64 iPos1 = 0; |
| 179416 | 180124 | i64 iPos2 = 0; |
| 179417 | 180125 | int iOff1 = 0; |
| 179418 | 180126 | int iOff2 = 0; |
| 179419 | 180127 | u8 *a1 = &i1.aPoslist[i1.nSize]; |
| 179420 | 180128 | u8 *a2 = &i2.aPoslist[i2.nSize]; |
| 179421 | 180129 | |
| 179422 | - Fts5PoslistWriter writer; | |
| 179423 | - memset(&writer, 0, sizeof(writer)); | |
| 179424 | - | |
| 179425 | - /* Merge the two position lists. */ | |
| 179426 | - fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); | |
| 179427 | - fts5BufferZero(&tmp); | |
| 179428 | - | |
| 179429 | - sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); | |
| 179430 | - sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); | |
| 179431 | - | |
| 179432 | - while( p->rc==SQLITE_OK && (iPos1>=0 || iPos2>=0) ){ | |
| 179433 | - i64 iNew; | |
| 179434 | - if( iPos2<0 || (iPos1>=0 && iPos1<iPos2) ){ | |
| 179435 | - iNew = iPos1; | |
| 179436 | - sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); | |
| 179437 | - }else{ | |
| 179438 | - iNew = iPos2; | |
| 179439 | - sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); | |
| 179440 | - if( iPos1==iPos2 ){ | |
| 179441 | - sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1); | |
| 179442 | - } | |
| 179443 | - } | |
| 179444 | - if( iNew!=writer.iPrev || tmp.n==0 ){ | |
| 179445 | - p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew); | |
| 179446 | - } | |
| 180130 | + i64 iPrev = 0; | |
| 180131 | + Fts5PoslistWriter writer; | |
| 180132 | + memset(&writer, 0, sizeof(writer)); | |
| 180133 | + | |
| 180134 | + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); | |
| 180135 | + fts5BufferZero(&tmp); | |
| 180136 | + sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist); | |
| 180137 | + if( p->rc ) break; | |
| 180138 | + | |
| 180139 | + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); | |
| 180140 | + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); | |
| 180141 | + assert( iPos1>=0 && iPos2>=0 ); | |
| 180142 | + | |
| 180143 | + if( iPos1<iPos2 ){ | |
| 180144 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); | |
| 180145 | + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); | |
| 180146 | + }else{ | |
| 180147 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); | |
| 180148 | + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); | |
| 180149 | + } | |
| 180150 | + | |
| 180151 | + if( iPos1>=0 && iPos2>=0 ){ | |
| 180152 | + while( 1 ){ | |
| 180153 | + if( iPos1<iPos2 ){ | |
| 180154 | + if( iPos1!=iPrev ){ | |
| 180155 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); | |
| 180156 | + } | |
| 180157 | + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); | |
| 180158 | + if( iPos1<0 ) break; | |
| 180159 | + }else{ | |
| 180160 | + assert( iPos2!=iPrev ); | |
| 180161 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); | |
| 180162 | + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); | |
| 180163 | + if( iPos2<0 ) break; | |
| 180164 | + } | |
| 180165 | + } | |
| 180166 | + } | |
| 180167 | + | |
| 180168 | + if( iPos1>=0 ){ | |
| 180169 | + if( iPos1!=iPrev ){ | |
| 180170 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); | |
| 180171 | + } | |
| 180172 | + fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); | |
| 180173 | + }else{ | |
| 180174 | + assert( iPos2>=0 && iPos2!=iPrev ); | |
| 180175 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); | |
| 180176 | + fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); | |
| 179447 | 180177 | } |
| 179448 | 180178 | |
| 179449 | 180179 | /* WRITEPOSLISTSIZE */ |
| 179450 | 180180 | fts5BufferSafeAppendVarint(&out, tmp.n * 2); |
| 179451 | 180181 | fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); |
| 179452 | 180182 | fts5DoclistIterNext(&i1); |
| 179453 | 180183 | fts5DoclistIterNext(&i2); |
| 180184 | + if( i1.aPoslist==0 || i2.aPoslist==0 ) break; | |
| 179454 | 180185 | } |
| 179455 | 180186 | } |
| 180187 | + | |
| 180188 | + if( i1.aPoslist ){ | |
| 180189 | + fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); | |
| 180190 | + fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist); | |
| 180191 | + } | |
| 180192 | + else if( i2.aPoslist ){ | |
| 180193 | + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); | |
| 180194 | + fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); | |
| 180195 | + } | |
| 179456 | 180196 | |
| 179457 | 180197 | fts5BufferSet(&p->rc, p1, out.n, out.p); |
| 179458 | 180198 | fts5BufferFree(&tmp); |
| 179459 | 180199 | fts5BufferFree(&out); |
| 179460 | 180200 | } |
| @@ -179464,18 +180204,18 @@ | ||
| 179464 | 180204 | Fts5Index *p, /* Index to read from */ |
| 179465 | 180205 | int bDesc, /* True for "ORDER BY rowid DESC" */ |
| 179466 | 180206 | const u8 *pToken, /* Buffer containing prefix to match */ |
| 179467 | 180207 | int nToken, /* Size of buffer pToken in bytes */ |
| 179468 | 180208 | Fts5Colset *pColset, /* Restrict matches to these columns */ |
| 179469 | - Fts5IndexIter **ppIter /* OUT: New iterator */ | |
| 180209 | + Fts5Iter **ppIter /* OUT: New iterator */ | |
| 179470 | 180210 | ){ |
| 179471 | 180211 | Fts5Structure *pStruct; |
| 179472 | 180212 | Fts5Buffer *aBuf; |
| 179473 | 180213 | const int nBuf = 32; |
| 179474 | 180214 | |
| 179475 | 180215 | void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); |
| 179476 | - int (*xAppend)(Fts5Index*, i64, Fts5IndexIter*, Fts5Colset*, Fts5Buffer*); | |
| 180216 | + void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*); | |
| 179477 | 180217 | if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 179478 | 180218 | xMerge = fts5MergeRowidLists; |
| 179479 | 180219 | xAppend = fts5AppendRowid; |
| 179480 | 180220 | }else{ |
| 179481 | 180221 | xMerge = fts5MergePrefixLists; |
| @@ -179484,32 +180224,40 @@ | ||
| 179484 | 180224 | |
| 179485 | 180225 | aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf); |
| 179486 | 180226 | pStruct = fts5StructureRead(p); |
| 179487 | 180227 | |
| 179488 | 180228 | if( aBuf && pStruct ){ |
| 179489 | - const int flags = FTS5INDEX_QUERY_SCAN; | |
| 180229 | + const int flags = FTS5INDEX_QUERY_SCAN | |
| 180230 | + | FTS5INDEX_QUERY_SKIPEMPTY | |
| 180231 | + | FTS5INDEX_QUERY_NOOUTPUT; | |
| 179490 | 180232 | int i; |
| 179491 | 180233 | i64 iLastRowid = 0; |
| 179492 | - Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */ | |
| 180234 | + Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ | |
| 179493 | 180235 | Fts5Data *pData; |
| 179494 | 180236 | Fts5Buffer doclist; |
| 179495 | 180237 | int bNewTerm = 1; |
| 179496 | 180238 | |
| 179497 | 180239 | memset(&doclist, 0, sizeof(doclist)); |
| 179498 | - for(fts5MultiIterNew(p, pStruct, 1, flags, pToken, nToken, -1, 0, &p1); | |
| 180240 | + fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1); | |
| 180241 | + fts5IterSetOutputCb(&p->rc, p1); | |
| 180242 | + for( /* no-op */ ; | |
| 179499 | 180243 | fts5MultiIterEof(p, p1)==0; |
| 179500 | 180244 | fts5MultiIterNext2(p, p1, &bNewTerm) |
| 179501 | 180245 | ){ |
| 179502 | - i64 iRowid = fts5MultiIterRowid(p1); | |
| 179503 | - int nTerm; | |
| 179504 | - const u8 *pTerm = fts5MultiIterTerm(p1, &nTerm); | |
| 180246 | + Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ]; | |
| 180247 | + int nTerm = pSeg->term.n; | |
| 180248 | + const u8 *pTerm = pSeg->term.p; | |
| 180249 | + p1->xSetOutputs(p1, pSeg); | |
| 180250 | + | |
| 179505 | 180251 | assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 ); |
| 179506 | 180252 | if( bNewTerm ){ |
| 179507 | 180253 | if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break; |
| 179508 | 180254 | } |
| 179509 | 180255 | |
| 179510 | - if( doclist.n>0 && iRowid<=iLastRowid ){ | |
| 180256 | + if( p1->base.nData==0 ) continue; | |
| 180257 | + | |
| 180258 | + if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){ | |
| 179511 | 180259 | for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ |
| 179512 | 180260 | assert( i<nBuf ); |
| 179513 | 180261 | if( aBuf[i].n==0 ){ |
| 179514 | 180262 | fts5BufferSwap(&doclist, &aBuf[i]); |
| 179515 | 180263 | fts5BufferZero(&doclist); |
| @@ -179519,13 +180267,12 @@ | ||
| 179519 | 180267 | } |
| 179520 | 180268 | } |
| 179521 | 180269 | iLastRowid = 0; |
| 179522 | 180270 | } |
| 179523 | 180271 | |
| 179524 | - if( !xAppend(p, iRowid-iLastRowid, p1, pColset, &doclist) ){ | |
| 179525 | - iLastRowid = iRowid; | |
| 179526 | - } | |
| 180272 | + xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist); | |
| 180273 | + iLastRowid = p1->base.iRowid; | |
| 179527 | 180274 | } |
| 179528 | 180275 | |
| 179529 | 180276 | for(i=0; i<nBuf; i++){ |
| 179530 | 180277 | if( p->rc==SQLITE_OK ){ |
| 179531 | 180278 | xMerge(p, &doclist, &aBuf[i]); |
| @@ -179591,11 +180338,11 @@ | ||
| 179591 | 180338 | ** records must be invalidated. |
| 179592 | 180339 | */ |
| 179593 | 180340 | static int sqlite3Fts5IndexRollback(Fts5Index *p){ |
| 179594 | 180341 | fts5CloseReader(p); |
| 179595 | 180342 | fts5IndexDiscardData(p); |
| 179596 | - assert( p->rc==SQLITE_OK ); | |
| 180343 | + /* assert( p->rc==SQLITE_OK ); */ | |
| 179597 | 180344 | return SQLITE_OK; |
| 179598 | 180345 | } |
| 179599 | 180346 | |
| 179600 | 180347 | /* |
| 179601 | 180348 | ** The %_data table is completely empty when this function is called. This |
| @@ -179763,26 +180510,31 @@ | ||
| 179763 | 180510 | int flags, /* Mask of FTS5INDEX_QUERY_X flags */ |
| 179764 | 180511 | Fts5Colset *pColset, /* Match these columns only */ |
| 179765 | 180512 | Fts5IndexIter **ppIter /* OUT: New iterator object */ |
| 179766 | 180513 | ){ |
| 179767 | 180514 | Fts5Config *pConfig = p->pConfig; |
| 179768 | - Fts5IndexIter *pRet = 0; | |
| 179769 | - int iIdx = 0; | |
| 180515 | + Fts5Iter *pRet = 0; | |
| 179770 | 180516 | Fts5Buffer buf = {0, 0, 0}; |
| 179771 | 180517 | |
| 179772 | 180518 | /* If the QUERY_SCAN flag is set, all other flags must be clear. */ |
| 179773 | 180519 | assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); |
| 179774 | 180520 | |
| 179775 | 180521 | if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ |
| 180522 | + int iIdx = 0; /* Index to search */ | |
| 179776 | 180523 | memcpy(&buf.p[1], pToken, nToken); |
| 179777 | 180524 | |
| 179778 | -#ifdef SQLITE_DEBUG | |
| 179779 | - /* If the QUERY_TEST_NOIDX flag was specified, then this must be a | |
| 180525 | + /* Figure out which index to search and set iIdx accordingly. If this | |
| 180526 | + ** is a prefix query for which there is no prefix index, set iIdx to | |
| 180527 | + ** greater than pConfig->nPrefix to indicate that the query will be | |
| 180528 | + ** satisfied by scanning multiple terms in the main index. | |
| 180529 | + ** | |
| 180530 | + ** If the QUERY_TEST_NOIDX flag was specified, then this must be a | |
| 179780 | 180531 | ** prefix-query. Instead of using a prefix-index (if one exists), |
| 179781 | 180532 | ** evaluate the prefix query using the main FTS index. This is used |
| 179782 | 180533 | ** for internal sanity checking by the integrity-check in debug |
| 179783 | 180534 | ** mode only. */ |
| 180535 | +#ifdef SQLITE_DEBUG | |
| 179784 | 180536 | if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ |
| 179785 | 180537 | assert( flags & FTS5INDEX_QUERY_PREFIX ); |
| 179786 | 180538 | iIdx = 1+pConfig->nPrefix; |
| 179787 | 180539 | }else |
| 179788 | 180540 | #endif |
| @@ -179792,54 +180544,62 @@ | ||
| 179792 | 180544 | if( pConfig->aPrefix[iIdx-1]==nChar ) break; |
| 179793 | 180545 | } |
| 179794 | 180546 | } |
| 179795 | 180547 | |
| 179796 | 180548 | if( iIdx<=pConfig->nPrefix ){ |
| 180549 | + /* Straight index lookup */ | |
| 179797 | 180550 | Fts5Structure *pStruct = fts5StructureRead(p); |
| 179798 | 180551 | buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); |
| 179799 | 180552 | if( pStruct ){ |
| 179800 | - fts5MultiIterNew(p, pStruct, 1, flags, buf.p, nToken+1, -1, 0, &pRet); | |
| 180553 | + fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, | |
| 180554 | + pColset, buf.p, nToken+1, -1, 0, &pRet | |
| 180555 | + ); | |
| 179801 | 180556 | fts5StructureRelease(pStruct); |
| 179802 | 180557 | } |
| 179803 | 180558 | }else{ |
| 180559 | + /* Scan multiple terms in the main index */ | |
| 179804 | 180560 | int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; |
| 179805 | 180561 | buf.p[0] = FTS5_MAIN_PREFIX; |
| 179806 | 180562 | fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); |
| 180563 | + assert( pRet->pColset==0 ); | |
| 180564 | + fts5IterSetOutputCb(&p->rc, pRet); | |
| 180565 | + if( p->rc==SQLITE_OK ){ | |
| 180566 | + Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; | |
| 180567 | + if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); | |
| 180568 | + } | |
| 179807 | 180569 | } |
| 179808 | 180570 | |
| 179809 | 180571 | if( p->rc ){ |
| 179810 | - sqlite3Fts5IterClose(pRet); | |
| 180572 | + sqlite3Fts5IterClose(&pRet->base); | |
| 179811 | 180573 | pRet = 0; |
| 179812 | 180574 | fts5CloseReader(p); |
| 179813 | 180575 | } |
| 179814 | - *ppIter = pRet; | |
| 180576 | + | |
| 180577 | + *ppIter = &pRet->base; | |
| 179815 | 180578 | sqlite3Fts5BufferFree(&buf); |
| 179816 | 180579 | } |
| 179817 | 180580 | return fts5IndexReturn(p); |
| 179818 | 180581 | } |
| 179819 | 180582 | |
| 179820 | 180583 | /* |
| 179821 | 180584 | ** Return true if the iterator passed as the only argument is at EOF. |
| 179822 | 180585 | */ |
| 179823 | -static int sqlite3Fts5IterEof(Fts5IndexIter *pIter){ | |
| 179824 | - assert( pIter->pIndex->rc==SQLITE_OK ); | |
| 179825 | - return pIter->bEof; | |
| 179826 | -} | |
| 179827 | - | |
| 179828 | 180586 | /* |
| 179829 | 180587 | ** Move to the next matching rowid. |
| 179830 | 180588 | */ |
| 179831 | -static int sqlite3Fts5IterNext(Fts5IndexIter *pIter){ | |
| 180589 | +static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){ | |
| 180590 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; | |
| 179832 | 180591 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179833 | 180592 | fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); |
| 179834 | 180593 | return fts5IndexReturn(pIter->pIndex); |
| 179835 | 180594 | } |
| 179836 | 180595 | |
| 179837 | 180596 | /* |
| 179838 | 180597 | ** Move to the next matching term/rowid. Used by the fts5vocab module. |
| 179839 | 180598 | */ |
| 179840 | -static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIter){ | |
| 180599 | +static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){ | |
| 180600 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; | |
| 179841 | 180601 | Fts5Index *p = pIter->pIndex; |
| 179842 | 180602 | |
| 179843 | 180603 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179844 | 180604 | |
| 179845 | 180605 | fts5MultiIterNext(p, pIter, 0, 0); |
| @@ -179846,11 +180606,11 @@ | ||
| 179846 | 180606 | if( p->rc==SQLITE_OK ){ |
| 179847 | 180607 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 179848 | 180608 | if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){ |
| 179849 | 180609 | fts5DataRelease(pSeg->pLeaf); |
| 179850 | 180610 | pSeg->pLeaf = 0; |
| 179851 | - pIter->bEof = 1; | |
| 180611 | + pIter->base.bEof = 1; | |
| 179852 | 180612 | } |
| 179853 | 180613 | } |
| 179854 | 180614 | |
| 179855 | 180615 | return fts5IndexReturn(pIter->pIndex); |
| 179856 | 180616 | } |
| @@ -179858,133 +180618,32 @@ | ||
| 179858 | 180618 | /* |
| 179859 | 180619 | ** Move to the next matching rowid that occurs at or after iMatch. The |
| 179860 | 180620 | ** definition of "at or after" depends on whether this iterator iterates |
| 179861 | 180621 | ** in ascending or descending rowid order. |
| 179862 | 180622 | */ |
| 179863 | -static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIter, i64 iMatch){ | |
| 180623 | +static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ | |
| 180624 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; | |
| 179864 | 180625 | fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); |
| 179865 | 180626 | return fts5IndexReturn(pIter->pIndex); |
| 179866 | 180627 | } |
| 179867 | 180628 | |
| 179868 | -/* | |
| 179869 | -** Return the current rowid. | |
| 179870 | -*/ | |
| 179871 | -static i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIter){ | |
| 179872 | - return fts5MultiIterRowid(pIter); | |
| 179873 | -} | |
| 179874 | - | |
| 179875 | 180629 | /* |
| 179876 | 180630 | ** Return the current term. |
| 179877 | 180631 | */ |
| 179878 | -static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIter, int *pn){ | |
| 180632 | +static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ | |
| 179879 | 180633 | int n; |
| 179880 | - const char *z = (const char*)fts5MultiIterTerm(pIter, &n); | |
| 180634 | + const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n); | |
| 179881 | 180635 | *pn = n-1; |
| 179882 | 180636 | return &z[1]; |
| 179883 | 180637 | } |
| 179884 | 180638 | |
| 179885 | - | |
| 179886 | -static int fts5IndexExtractColset ( | |
| 179887 | - Fts5Colset *pColset, /* Colset to filter on */ | |
| 179888 | - const u8 *pPos, int nPos, /* Position list */ | |
| 179889 | - Fts5Buffer *pBuf /* Output buffer */ | |
| 179890 | -){ | |
| 179891 | - int rc = SQLITE_OK; | |
| 179892 | - int i; | |
| 179893 | - | |
| 179894 | - fts5BufferZero(pBuf); | |
| 179895 | - for(i=0; i<pColset->nCol; i++){ | |
| 179896 | - const u8 *pSub = pPos; | |
| 179897 | - int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); | |
| 179898 | - if( nSub ){ | |
| 179899 | - fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); | |
| 179900 | - } | |
| 179901 | - } | |
| 179902 | - return rc; | |
| 179903 | -} | |
| 179904 | - | |
| 179905 | - | |
| 179906 | -/* | |
| 179907 | -** Return a pointer to a buffer containing a copy of the position list for | |
| 179908 | -** the current entry. Output variable *pn is set to the size of the buffer | |
| 179909 | -** in bytes before returning. | |
| 179910 | -** | |
| 179911 | -** The returned position list does not include the "number of bytes" varint | |
| 179912 | -** field that starts the position list on disk. | |
| 179913 | -*/ | |
| 179914 | -static int sqlite3Fts5IterPoslist( | |
| 179915 | - Fts5IndexIter *pIter, | |
| 179916 | - Fts5Colset *pColset, /* Column filter (or NULL) */ | |
| 179917 | - const u8 **pp, /* OUT: Pointer to position-list data */ | |
| 179918 | - int *pn, /* OUT: Size of position-list in bytes */ | |
| 179919 | - i64 *piRowid /* OUT: Current rowid */ | |
| 179920 | -){ | |
| 179921 | - Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; | |
| 179922 | - int eDetail = pIter->pIndex->pConfig->eDetail; | |
| 179923 | - | |
| 179924 | - assert( pIter->pIndex->rc==SQLITE_OK ); | |
| 179925 | - *piRowid = pSeg->iRowid; | |
| 179926 | - if( eDetail==FTS5_DETAIL_NONE ){ | |
| 179927 | - *pn = pSeg->nPos; | |
| 179928 | - }else | |
| 179929 | - if( eDetail==FTS5_DETAIL_FULL | |
| 179930 | - && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf | |
| 179931 | - ){ | |
| 179932 | - u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; | |
| 179933 | - if( pColset==0 || pIter->bFiltered ){ | |
| 179934 | - *pn = pSeg->nPos; | |
| 179935 | - *pp = pPos; | |
| 179936 | - }else if( pColset->nCol==1 ){ | |
| 179937 | - *pp = pPos; | |
| 179938 | - *pn = fts5IndexExtractCol(pp, pSeg->nPos, pColset->aiCol[0]); | |
| 179939 | - }else{ | |
| 179940 | - fts5BufferZero(&pIter->poslist); | |
| 179941 | - fts5IndexExtractColset(pColset, pPos, pSeg->nPos, &pIter->poslist); | |
| 179942 | - *pp = pIter->poslist.p; | |
| 179943 | - *pn = pIter->poslist.n; | |
| 179944 | - } | |
| 179945 | - }else{ | |
| 179946 | - fts5BufferZero(&pIter->poslist); | |
| 179947 | - fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); | |
| 179948 | - if( eDetail==FTS5_DETAIL_FULL ){ | |
| 179949 | - *pp = pIter->poslist.p; | |
| 179950 | - } | |
| 179951 | - *pn = pIter->poslist.n; | |
| 179952 | - } | |
| 179953 | - return fts5IndexReturn(pIter->pIndex); | |
| 179954 | -} | |
| 179955 | - | |
| 179956 | -static int sqlite3Fts5IterCollist( | |
| 179957 | - Fts5IndexIter *pIter, | |
| 179958 | - const u8 **pp, /* OUT: Pointer to position-list data */ | |
| 179959 | - int *pn /* OUT: Size of position-list in bytes */ | |
| 179960 | -){ | |
| 179961 | - assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); | |
| 179962 | - *pp = pIter->poslist.p; | |
| 179963 | - *pn = pIter->poslist.n; | |
| 179964 | - return SQLITE_OK; | |
| 179965 | -} | |
| 179966 | - | |
| 179967 | -/* | |
| 179968 | -** This function is similar to sqlite3Fts5IterPoslist(), except that it | |
| 179969 | -** copies the position list into the buffer supplied as the second | |
| 179970 | -** argument. | |
| 179971 | -*/ | |
| 179972 | -static int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf){ | |
| 179973 | - Fts5Index *p = pIter->pIndex; | |
| 179974 | - Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; | |
| 179975 | - assert( p->rc==SQLITE_OK ); | |
| 179976 | - fts5BufferZero(pBuf); | |
| 179977 | - fts5SegiterPoslist(p, pSeg, 0, pBuf); | |
| 179978 | - return fts5IndexReturn(p); | |
| 179979 | -} | |
| 179980 | - | |
| 179981 | 180639 | /* |
| 179982 | 180640 | ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). |
| 179983 | 180641 | */ |
| 179984 | -static void sqlite3Fts5IterClose(Fts5IndexIter *pIter){ | |
| 179985 | - if( pIter ){ | |
| 180642 | +static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ | |
| 180643 | + if( pIndexIter ){ | |
| 180644 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; | |
| 179986 | 180645 | Fts5Index *pIndex = pIter->pIndex; |
| 179987 | 180646 | fts5MultiIterFree(pIter->pIndex, pIter); |
| 179988 | 180647 | fts5CloseReader(pIndex); |
| 179989 | 180648 | } |
| 179990 | 180649 | } |
| @@ -180147,39 +180806,34 @@ | ||
| 180147 | 180806 | int flags, /* Flags for Fts5IndexQuery */ |
| 180148 | 180807 | u64 *pCksum /* IN/OUT: Checksum value */ |
| 180149 | 180808 | ){ |
| 180150 | 180809 | int eDetail = p->pConfig->eDetail; |
| 180151 | 180810 | u64 cksum = *pCksum; |
| 180152 | - Fts5IndexIter *pIdxIter = 0; | |
| 180153 | - Fts5Buffer buf = {0, 0, 0}; | |
| 180154 | - int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter); | |
| 180811 | + Fts5IndexIter *pIter = 0; | |
| 180812 | + int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); | |
| 180155 | 180813 | |
| 180156 | - while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ | |
| 180157 | - i64 rowid = sqlite3Fts5IterRowid(pIdxIter); | |
| 180814 | + while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){ | |
| 180815 | + i64 rowid = pIter->iRowid; | |
| 180158 | 180816 | |
| 180159 | 180817 | if( eDetail==FTS5_DETAIL_NONE ){ |
| 180160 | 180818 | cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); |
| 180161 | 180819 | }else{ |
| 180162 | - rc = sqlite3Fts5IterPoslistBuffer(pIdxIter, &buf); | |
| 180163 | - if( rc==SQLITE_OK ){ | |
| 180164 | - Fts5PoslistReader sReader; | |
| 180165 | - for(sqlite3Fts5PoslistReaderInit(buf.p, buf.n, &sReader); | |
| 180166 | - sReader.bEof==0; | |
| 180167 | - sqlite3Fts5PoslistReaderNext(&sReader) | |
| 180168 | - ){ | |
| 180169 | - int iCol = FTS5_POS2COLUMN(sReader.iPos); | |
| 180170 | - int iOff = FTS5_POS2OFFSET(sReader.iPos); | |
| 180171 | - cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); | |
| 180172 | - } | |
| 180820 | + Fts5PoslistReader sReader; | |
| 180821 | + for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader); | |
| 180822 | + sReader.bEof==0; | |
| 180823 | + sqlite3Fts5PoslistReaderNext(&sReader) | |
| 180824 | + ){ | |
| 180825 | + int iCol = FTS5_POS2COLUMN(sReader.iPos); | |
| 180826 | + int iOff = FTS5_POS2OFFSET(sReader.iPos); | |
| 180827 | + cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); | |
| 180173 | 180828 | } |
| 180174 | 180829 | } |
| 180175 | 180830 | if( rc==SQLITE_OK ){ |
| 180176 | - rc = sqlite3Fts5IterNext(pIdxIter); | |
| 180831 | + rc = sqlite3Fts5IterNext(pIter); | |
| 180177 | 180832 | } |
| 180178 | 180833 | } |
| 180179 | - sqlite3Fts5IterClose(pIdxIter); | |
| 180180 | - fts5BufferFree(&buf); | |
| 180834 | + sqlite3Fts5IterClose(pIter); | |
| 180181 | 180835 | |
| 180182 | 180836 | *pCksum = cksum; |
| 180183 | 180837 | return rc; |
| 180184 | 180838 | } |
| 180185 | 180839 | |
| @@ -180480,18 +181134,19 @@ | ||
| 180480 | 181134 | */ |
| 180481 | 181135 | static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ |
| 180482 | 181136 | int eDetail = p->pConfig->eDetail; |
| 180483 | 181137 | u64 cksum2 = 0; /* Checksum based on contents of indexes */ |
| 180484 | 181138 | Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ |
| 180485 | - Fts5IndexIter *pIter; /* Used to iterate through entire index */ | |
| 181139 | + Fts5Iter *pIter; /* Used to iterate through entire index */ | |
| 180486 | 181140 | Fts5Structure *pStruct; /* Index structure */ |
| 180487 | 181141 | |
| 180488 | 181142 | #ifdef SQLITE_DEBUG |
| 180489 | 181143 | /* Used by extra internal tests only run if NDEBUG is not defined */ |
| 180490 | 181144 | u64 cksum3 = 0; /* Checksum based on contents of indexes */ |
| 180491 | 181145 | Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ |
| 180492 | 181146 | #endif |
| 181147 | + const int flags = FTS5INDEX_QUERY_NOOUTPUT; | |
| 180493 | 181148 | |
| 180494 | 181149 | /* Load the FTS index structure */ |
| 180495 | 181150 | pStruct = fts5StructureRead(p); |
| 180496 | 181151 | |
| 180497 | 181152 | /* Check that the internal nodes of each segment match the leaves */ |
| @@ -180516,11 +181171,11 @@ | ||
| 180516 | 181171 | ** |
| 180517 | 181172 | ** As each term visited by the linear scans, a separate query for the |
| 180518 | 181173 | ** same term is performed. cksum3 is calculated based on the entries |
| 180519 | 181174 | ** extracted by these queries. |
| 180520 | 181175 | */ |
| 180521 | - for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, -1, 0, &pIter); | |
| 181176 | + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter); | |
| 180522 | 181177 | fts5MultiIterEof(p, pIter)==0; |
| 180523 | 181178 | fts5MultiIterNext(p, pIter, 0, 0) |
| 180524 | 181179 | ){ |
| 180525 | 181180 | int n; /* Size of term in bytes */ |
| 180526 | 181181 | i64 iPos = 0; /* Position read from poslist */ |
| @@ -181234,14 +181889,14 @@ | ||
| 181234 | 181889 | #define FTS5_BI_ORDER_DESC 0x0080 |
| 181235 | 181890 | |
| 181236 | 181891 | /* |
| 181237 | 181892 | ** Values for Fts5Cursor.csrflags |
| 181238 | 181893 | */ |
| 181239 | -#define FTS5CSR_REQUIRE_CONTENT 0x01 | |
| 181240 | -#define FTS5CSR_REQUIRE_DOCSIZE 0x02 | |
| 181241 | -#define FTS5CSR_REQUIRE_INST 0x04 | |
| 181242 | -#define FTS5CSR_EOF 0x08 | |
| 181894 | +#define FTS5CSR_EOF 0x01 | |
| 181895 | +#define FTS5CSR_REQUIRE_CONTENT 0x02 | |
| 181896 | +#define FTS5CSR_REQUIRE_DOCSIZE 0x04 | |
| 181897 | +#define FTS5CSR_REQUIRE_INST 0x08 | |
| 181243 | 181898 | #define FTS5CSR_FREE_ZRANK 0x10 |
| 181244 | 181899 | #define FTS5CSR_REQUIRE_RESEEK 0x20 |
| 181245 | 181900 | #define FTS5CSR_REQUIRE_POSLIST 0x40 |
| 181246 | 181901 | |
| 181247 | 181902 | #define BitFlagAllTest(x,y) (((x) & (y))==(y)) |
| @@ -181552,11 +182207,11 @@ | ||
| 181552 | 182207 | |
| 181553 | 182208 | /* Set idxFlags flags for all WHERE clause terms that will be used. */ |
| 181554 | 182209 | for(i=0; i<pInfo->nConstraint; i++){ |
| 181555 | 182210 | struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; |
| 181556 | 182211 | int j; |
| 181557 | - for(j=0; j<(int)ArraySize(aConstraint); j++){ | |
| 182212 | + for(j=0; j<ArraySize(aConstraint); j++){ | |
| 181558 | 182213 | struct Constraint *pC = &aConstraint[j]; |
| 181559 | 182214 | if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){ |
| 181560 | 182215 | if( p->usable ){ |
| 181561 | 182216 | pC->iConsIndex = i; |
| 181562 | 182217 | idxFlags |= pC->fts5op; |
| @@ -181599,11 +182254,11 @@ | ||
| 181599 | 182254 | pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; |
| 181600 | 182255 | } |
| 181601 | 182256 | |
| 181602 | 182257 | /* Assign argvIndex values to each constraint in use. */ |
| 181603 | 182258 | iNext = 1; |
| 181604 | - for(i=0; i<(int)ArraySize(aConstraint); i++){ | |
| 182259 | + for(i=0; i<ArraySize(aConstraint); i++){ | |
| 181605 | 182260 | struct Constraint *pC = &aConstraint[i]; |
| 181606 | 182261 | if( pC->iConsIndex>=0 ){ |
| 181607 | 182262 | pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; |
| 181608 | 182263 | pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; |
| 181609 | 182264 | } |
| @@ -181792,18 +182447,19 @@ | ||
| 181792 | 182447 | Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); |
| 181793 | 182448 | int bDesc = pCsr->bDesc; |
| 181794 | 182449 | i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); |
| 181795 | 182450 | |
| 181796 | 182451 | rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); |
| 181797 | - if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ | |
| 182452 | + if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ | |
| 181798 | 182453 | *pbSkip = 1; |
| 181799 | 182454 | } |
| 181800 | 182455 | |
| 181801 | 182456 | CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); |
| 181802 | 182457 | fts5CsrNewrow(pCsr); |
| 181803 | 182458 | if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ |
| 181804 | 182459 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 182460 | + *pbSkip = 1; | |
| 181805 | 182461 | } |
| 181806 | 182462 | } |
| 181807 | 182463 | return rc; |
| 181808 | 182464 | } |
| 181809 | 182465 | |
| @@ -181816,28 +182472,28 @@ | ||
| 181816 | 182472 | ** even if we reach end-of-file. The fts5EofMethod() will be called |
| 181817 | 182473 | ** subsequently to determine whether or not an EOF was hit. |
| 181818 | 182474 | */ |
| 181819 | 182475 | static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ |
| 181820 | 182476 | Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; |
| 181821 | - int rc = SQLITE_OK; | |
| 182477 | + int rc; | |
| 181822 | 182478 | |
| 181823 | 182479 | assert( (pCsr->ePlan<3)== |
| 181824 | 182480 | (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) |
| 181825 | 182481 | ); |
| 182482 | + assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) ); | |
| 181826 | 182483 | |
| 181827 | 182484 | if( pCsr->ePlan<3 ){ |
| 181828 | 182485 | int bSkip = 0; |
| 181829 | 182486 | if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; |
| 181830 | 182487 | rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); |
| 181831 | - if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ | |
| 181832 | - CsrFlagSet(pCsr, FTS5CSR_EOF); | |
| 181833 | - } | |
| 182488 | + CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr)); | |
| 181834 | 182489 | fts5CsrNewrow(pCsr); |
| 181835 | 182490 | }else{ |
| 181836 | 182491 | switch( pCsr->ePlan ){ |
| 181837 | 182492 | case FTS5_PLAN_SPECIAL: { |
| 181838 | 182493 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 182494 | + rc = SQLITE_OK; | |
| 181839 | 182495 | break; |
| 181840 | 182496 | } |
| 181841 | 182497 | |
| 181842 | 182498 | case FTS5_PLAN_SORTED_MATCH: { |
| 181843 | 182499 | rc = fts5SorterNext(pCsr); |
| @@ -183605,11 +184261,11 @@ | ||
| 183605 | 184261 | sqlite3_context *pCtx, /* Function call context */ |
| 183606 | 184262 | int nArg, /* Number of args */ |
| 183607 | 184263 | sqlite3_value **apVal /* Function arguments */ |
| 183608 | 184264 | ){ |
| 183609 | 184265 | assert( nArg==0 ); |
| 183610 | - sqlite3_result_text(pCtx, "fts5: 2016-01-20 14:22:41 204432ee72fda8e82d244c4aa18de7ec4811b8e1", -1, SQLITE_TRANSIENT); | |
| 184266 | + sqlite3_result_text(pCtx, "fts5: 2016-02-08 20:45:37 6eab74c9ae57676044b5bc82fa14e92fd2448008", -1, SQLITE_TRANSIENT); | |
| 183611 | 184267 | } |
| 183612 | 184268 | |
| 183613 | 184269 | static int fts5Init(sqlite3 *db){ |
| 183614 | 184270 | static const sqlite3_module fts5Mod = { |
| 183615 | 184271 | /* iVersion */ 2, |
| @@ -184050,11 +184706,11 @@ | ||
| 184050 | 184706 | int rc = SQLITE_OK; |
| 184051 | 184707 | if( p ){ |
| 184052 | 184708 | int i; |
| 184053 | 184709 | |
| 184054 | 184710 | /* Finalize all SQL statements */ |
| 184055 | - for(i=0; i<(int)ArraySize(p->aStmt); i++){ | |
| 184711 | + for(i=0; i<ArraySize(p->aStmt); i++){ | |
| 184056 | 184712 | sqlite3_finalize(p->aStmt[i]); |
| 184057 | 184713 | } |
| 184058 | 184714 | |
| 184059 | 184715 | sqlite3_free(p); |
| 184060 | 184716 | } |
| @@ -186055,11 +186711,11 @@ | ||
| 186055 | 186711 | }; |
| 186056 | 186712 | |
| 186057 | 186713 | int rc = SQLITE_OK; /* Return code */ |
| 186058 | 186714 | int i; /* To iterate through builtin functions */ |
| 186059 | 186715 | |
| 186060 | - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ | |
| 186716 | + for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){ | |
| 186061 | 186717 | rc = pApi->xCreateTokenizer(pApi, |
| 186062 | 186718 | aBuiltin[i].zName, |
| 186063 | 186719 | (void*)pApi, |
| 186064 | 186720 | &aBuiltin[i].x, |
| 186065 | 186721 | 0 |
| @@ -186765,11 +187421,14 @@ | ||
| 186765 | 187421 | return fts5PutVarint64(p,v); |
| 186766 | 187422 | } |
| 186767 | 187423 | |
| 186768 | 187424 | |
| 186769 | 187425 | static int sqlite3Fts5GetVarintLen(u32 iVal){ |
| 187426 | +#if 0 | |
| 186770 | 187427 | if( iVal<(1 << 7 ) ) return 1; |
| 187428 | +#endif | |
| 187429 | + assert( iVal>=(1 << 7) ); | |
| 186771 | 187430 | if( iVal<(1 << 14) ) return 2; |
| 186772 | 187431 | if( iVal<(1 << 21) ) return 3; |
| 186773 | 187432 | if( iVal<(1 << 28) ) return 4; |
| 186774 | 187433 | return 5; |
| 186775 | 187434 | } |
| @@ -186959,11 +187618,11 @@ | ||
| 186959 | 187618 | int nTab = (int)strlen(zTab)+1; |
| 186960 | 187619 | int eType = 0; |
| 186961 | 187620 | |
| 186962 | 187621 | rc = fts5VocabTableType(zType, pzErr, &eType); |
| 186963 | 187622 | if( rc==SQLITE_OK ){ |
| 186964 | - assert( eType>=0 && eType<sizeof(azSchema)/sizeof(azSchema[0]) ); | |
| 187623 | + assert( eType>=0 && eType<ArraySize(azSchema) ); | |
| 186965 | 187624 | rc = sqlite3_declare_vtab(db, azSchema[eType]); |
| 186966 | 187625 | } |
| 186967 | 187626 | |
| 186968 | 187627 | nByte = sizeof(Fts5VocabTable) + nDb + nTab; |
| 186969 | 187628 | pRet = sqlite3Fts5MallocZero(&rc, nByte); |
| @@ -187182,59 +187841,54 @@ | ||
| 187182 | 187841 | memset(pCsr->aDoc, 0, nCol * sizeof(i64)); |
| 187183 | 187842 | pCsr->iCol = 0; |
| 187184 | 187843 | |
| 187185 | 187844 | assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); |
| 187186 | 187845 | while( rc==SQLITE_OK ){ |
| 187187 | - i64 dummy; | |
| 187188 | 187846 | const u8 *pPos; int nPos; /* Position list */ |
| 187189 | 187847 | i64 iPos = 0; /* 64-bit position read from poslist */ |
| 187190 | 187848 | int iOff = 0; /* Current offset within position list */ |
| 187191 | 187849 | |
| 187850 | + pPos = pCsr->pIter->pData; | |
| 187851 | + nPos = pCsr->pIter->nData; | |
| 187192 | 187852 | switch( pCsr->pConfig->eDetail ){ |
| 187193 | 187853 | case FTS5_DETAIL_FULL: |
| 187194 | - rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); | |
| 187195 | - if( rc==SQLITE_OK ){ | |
| 187196 | - if( pTab->eType==FTS5_VOCAB_ROW ){ | |
| 187197 | - while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ | |
| 187198 | - pCsr->aCnt[0]++; | |
| 187199 | - } | |
| 187200 | - pCsr->aDoc[0]++; | |
| 187201 | - }else{ | |
| 187202 | - int iCol = -1; | |
| 187203 | - while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ | |
| 187204 | - int ii = FTS5_POS2COLUMN(iPos); | |
| 187205 | - pCsr->aCnt[ii]++; | |
| 187206 | - if( iCol!=ii ){ | |
| 187207 | - if( ii>=nCol ){ | |
| 187208 | - rc = FTS5_CORRUPT; | |
| 187209 | - break; | |
| 187210 | - } | |
| 187211 | - pCsr->aDoc[ii]++; | |
| 187212 | - iCol = ii; | |
| 187213 | - } | |
| 187854 | + pPos = pCsr->pIter->pData; | |
| 187855 | + nPos = pCsr->pIter->nData; | |
| 187856 | + if( pTab->eType==FTS5_VOCAB_ROW ){ | |
| 187857 | + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ | |
| 187858 | + pCsr->aCnt[0]++; | |
| 187859 | + } | |
| 187860 | + pCsr->aDoc[0]++; | |
| 187861 | + }else{ | |
| 187862 | + int iCol = -1; | |
| 187863 | + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ | |
| 187864 | + int ii = FTS5_POS2COLUMN(iPos); | |
| 187865 | + pCsr->aCnt[ii]++; | |
| 187866 | + if( iCol!=ii ){ | |
| 187867 | + if( ii>=nCol ){ | |
| 187868 | + rc = FTS5_CORRUPT; | |
| 187869 | + break; | |
| 187870 | + } | |
| 187871 | + pCsr->aDoc[ii]++; | |
| 187872 | + iCol = ii; | |
| 187214 | 187873 | } |
| 187215 | 187874 | } |
| 187216 | 187875 | } |
| 187217 | 187876 | break; |
| 187218 | 187877 | |
| 187219 | 187878 | case FTS5_DETAIL_COLUMNS: |
| 187220 | 187879 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 187221 | 187880 | pCsr->aDoc[0]++; |
| 187222 | 187881 | }else{ |
| 187223 | - Fts5Buffer buf = {0, 0, 0}; | |
| 187224 | - rc = sqlite3Fts5IterPoslistBuffer(pCsr->pIter, &buf); | |
| 187225 | - if( rc==SQLITE_OK ){ | |
| 187226 | - while( 0==sqlite3Fts5PoslistNext64(buf.p, buf.n, &iOff,&iPos) ){ | |
| 187227 | - assert_nc( iPos>=0 && iPos<nCol ); | |
| 187228 | - if( iPos>=nCol ){ | |
| 187229 | - rc = FTS5_CORRUPT; | |
| 187230 | - break; | |
| 187231 | - } | |
| 187232 | - pCsr->aDoc[iPos]++; | |
| 187233 | - } | |
| 187234 | - } | |
| 187235 | - sqlite3Fts5BufferFree(&buf); | |
| 187882 | + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ | |
| 187883 | + assert_nc( iPos>=0 && iPos<nCol ); | |
| 187884 | + if( iPos>=nCol ){ | |
| 187885 | + rc = FTS5_CORRUPT; | |
| 187886 | + break; | |
| 187887 | + } | |
| 187888 | + pCsr->aDoc[iPos]++; | |
| 187889 | + } | |
| 187236 | 187890 | } |
| 187237 | 187891 | break; |
| 187238 | 187892 | |
| 187239 | 187893 | default: |
| 187240 | 187894 | assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); |
| 187241 | 187895 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -121,10 +121,11 @@ | |
| 121 | #else |
| 122 | /* This is not VxWorks. */ |
| 123 | #define OS_VXWORKS 0 |
| 124 | #define HAVE_FCHOWN 1 |
| 125 | #define HAVE_READLINK 1 |
| 126 | #endif /* defined(_WRS_KERNEL) */ |
| 127 | |
| 128 | /************** End of vxworks.h *********************************************/ |
| 129 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| 130 | |
| @@ -327,11 +328,11 @@ | |
| 327 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 328 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 329 | */ |
| 330 | #define SQLITE_VERSION "3.11.0" |
| 331 | #define SQLITE_VERSION_NUMBER 3011000 |
| 332 | #define SQLITE_SOURCE_ID "2016-01-20 14:22:41 204432ee72fda8e82d244c4aa18de7ec4811b8e1" |
| 333 | |
| 334 | /* |
| 335 | ** CAPI3REF: Run-Time Library Version Numbers |
| 336 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 337 | ** |
| @@ -5911,11 +5912,11 @@ | |
| 5911 | */ |
| 5912 | struct sqlite3_index_info { |
| 5913 | /* Inputs */ |
| 5914 | int nConstraint; /* Number of entries in aConstraint */ |
| 5915 | struct sqlite3_index_constraint { |
| 5916 | int iColumn; /* Column on left-hand side of constraint */ |
| 5917 | unsigned char op; /* Constraint operator */ |
| 5918 | unsigned char usable; /* True if this constraint is usable */ |
| 5919 | int iTermOffset; /* Used internally - xBestIndex should ignore */ |
| 5920 | } *aConstraint; /* Table of WHERE clause constraints */ |
| 5921 | int nOrderBy; /* Number of terms in the ORDER BY clause */ |
| @@ -10468,18 +10469,28 @@ | |
| 10468 | |
| 10469 | /* |
| 10470 | ** Flags passed as the third argument to sqlite3BtreeCursor(). |
| 10471 | ** |
| 10472 | ** For read-only cursors the wrFlag argument is always zero. For read-write |
| 10473 | ** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or |
| 10474 | ** (BTREE_WRCSR). If the BTREE_FORDELETE flag is set, then the cursor will |
| 10475 | ** only be used by SQLite for the following: |
| 10476 | ** |
| 10477 | ** * to seek to and delete specific entries, and/or |
| 10478 | ** |
| 10479 | ** * to read values that will be used to create keys that other |
| 10480 | ** BTREE_FORDELETE cursors will seek to and delete. |
| 10481 | */ |
| 10482 | #define BTREE_WRCSR 0x00000004 /* read-write cursor */ |
| 10483 | #define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */ |
| 10484 | |
| 10485 | SQLITE_PRIVATE int sqlite3BtreeCursor( |
| @@ -10504,11 +10515,16 @@ | |
| 10504 | int bias, |
| 10505 | int *pRes |
| 10506 | ); |
| 10507 | SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); |
| 10508 | SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); |
| 10509 | SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, int); |
| 10510 | SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, |
| 10511 | const void *pData, int nData, |
| 10512 | int nZero, int bias, int seekResult); |
| 10513 | SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); |
| 10514 | SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); |
| @@ -10762,94 +10778,95 @@ | |
| 10762 | */ |
| 10763 | /************** Include opcodes.h in the middle of vdbe.h ********************/ |
| 10764 | /************** Begin file opcodes.h *****************************************/ |
| 10765 | /* Automatically generated. Do not edit */ |
| 10766 | /* See the tool/mkopcodeh.tcl script for details */ |
| 10767 | #define OP_Savepoint 1 |
| 10768 | #define OP_AutoCommit 2 |
| 10769 | #define OP_Transaction 3 |
| 10770 | #define OP_SorterNext 4 |
| 10771 | #define OP_PrevIfOpen 5 |
| 10772 | #define OP_NextIfOpen 6 |
| 10773 | #define OP_Prev 7 |
| 10774 | #define OP_Next 8 |
| 10775 | #define OP_Checkpoint 9 |
| 10776 | #define OP_JournalMode 10 |
| 10777 | #define OP_Vacuum 11 |
| 10778 | #define OP_VFilter 12 /* synopsis: iplan=r[P3] zplan='P4' */ |
| 10779 | #define OP_VUpdate 13 /* synopsis: data=r[P3@P2] */ |
| 10780 | #define OP_Goto 14 |
| 10781 | #define OP_Gosub 15 |
| 10782 | #define OP_Return 16 |
| 10783 | #define OP_InitCoroutine 17 |
| 10784 | #define OP_EndCoroutine 18 |
| 10785 | #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ |
| 10786 | #define OP_Yield 20 |
| 10787 | #define OP_HaltIfNull 21 /* synopsis: if r[P3]=null halt */ |
| 10788 | #define OP_Halt 22 |
| 10789 | #define OP_Integer 23 /* synopsis: r[P2]=P1 */ |
| 10790 | #define OP_Int64 24 /* synopsis: r[P2]=P4 */ |
| 10791 | #define OP_String 25 /* synopsis: r[P2]='P4' (len=P1) */ |
| 10792 | #define OP_Null 26 /* synopsis: r[P2..P3]=NULL */ |
| 10793 | #define OP_SoftNull 27 /* synopsis: r[P1]=NULL */ |
| 10794 | #define OP_Blob 28 /* synopsis: r[P2]=P4 (len=P1) */ |
| 10795 | #define OP_Variable 29 /* synopsis: r[P2]=parameter(P1,P4) */ |
| 10796 | #define OP_Move 30 /* synopsis: r[P2@P3]=r[P1@P3] */ |
| 10797 | #define OP_Copy 31 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ |
| 10798 | #define OP_SCopy 32 /* synopsis: r[P2]=r[P1] */ |
| 10799 | #define OP_IntCopy 33 /* synopsis: r[P2]=r[P1] */ |
| 10800 | #define OP_ResultRow 34 /* synopsis: output=r[P1@P2] */ |
| 10801 | #define OP_CollSeq 35 |
| 10802 | #define OP_Function0 36 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 10803 | #define OP_Function 37 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 10804 | #define OP_AddImm 38 /* synopsis: r[P1]=r[P1]+P2 */ |
| 10805 | #define OP_MustBeInt 39 |
| 10806 | #define OP_RealAffinity 40 |
| 10807 | #define OP_Cast 41 /* synopsis: affinity(r[P1]) */ |
| 10808 | #define OP_Permutation 42 |
| 10809 | #define OP_Compare 43 /* synopsis: r[P1@P3] <-> r[P2@P3] */ |
| 10810 | #define OP_Jump 44 |
| 10811 | #define OP_Once 45 |
| 10812 | #define OP_If 46 |
| 10813 | #define OP_IfNot 47 |
| 10814 | #define OP_Column 48 /* synopsis: r[P3]=PX */ |
| 10815 | #define OP_Affinity 49 /* synopsis: affinity(r[P1@P2]) */ |
| 10816 | #define OP_MakeRecord 50 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ |
| 10817 | #define OP_Count 51 /* synopsis: r[P2]=count() */ |
| 10818 | #define OP_ReadCookie 52 |
| 10819 | #define OP_SetCookie 53 |
| 10820 | #define OP_ReopenIdx 54 /* synopsis: root=P2 iDb=P3 */ |
| 10821 | #define OP_OpenRead 55 /* synopsis: root=P2 iDb=P3 */ |
| 10822 | #define OP_OpenWrite 56 /* synopsis: root=P2 iDb=P3 */ |
| 10823 | #define OP_OpenAutoindex 57 /* synopsis: nColumn=P2 */ |
| 10824 | #define OP_OpenEphemeral 58 /* synopsis: nColumn=P2 */ |
| 10825 | #define OP_SorterOpen 59 |
| 10826 | #define OP_SequenceTest 60 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ |
| 10827 | #define OP_OpenPseudo 61 /* synopsis: P3 columns in r[P2] */ |
| 10828 | #define OP_Close 62 |
| 10829 | #define OP_ColumnsUsed 63 |
| 10830 | #define OP_SeekLT 64 /* synopsis: key=r[P3@P4] */ |
| 10831 | #define OP_SeekLE 65 /* synopsis: key=r[P3@P4] */ |
| 10832 | #define OP_SeekGE 66 /* synopsis: key=r[P3@P4] */ |
| 10833 | #define OP_SeekGT 67 /* synopsis: key=r[P3@P4] */ |
| 10834 | #define OP_Seek 68 /* synopsis: intkey=r[P2] */ |
| 10835 | #define OP_NoConflict 69 /* synopsis: key=r[P3@P4] */ |
| 10836 | #define OP_NotFound 70 /* synopsis: key=r[P3@P4] */ |
| 10837 | #define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ |
| 10838 | #define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ |
| 10839 | #define OP_Found 73 /* synopsis: key=r[P3@P4] */ |
| 10840 | #define OP_NotExists 74 /* synopsis: intkey=r[P3] */ |
| 10841 | #define OP_Sequence 75 /* synopsis: r[P2]=cursor[P1].ctr++ */ |
| 10842 | #define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ |
| 10843 | #define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ |
| 10844 | #define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ |
| 10845 | #define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ |
| 10846 | #define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ |
| 10847 | #define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ |
| 10848 | #define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */ |
| 10849 | #define OP_Ge 83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */ |
| 10850 | #define OP_NewRowid 84 /* synopsis: r[P2]=rowid */ |
| 10851 | #define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ |
| 10852 | #define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ |
| 10853 | #define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ |
| 10854 | #define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */ |
| 10855 | #define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ |
| @@ -10856,111 +10873,110 @@ | |
| 10856 | #define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ |
| 10857 | #define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ |
| 10858 | #define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ |
| 10859 | #define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ |
| 10860 | #define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ |
| 10861 | #define OP_Insert 95 /* synopsis: intkey=r[P3] data=r[P2] */ |
| 10862 | #define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ |
| 10863 | #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ |
| 10864 | #define OP_InsertInt 98 /* synopsis: intkey=P3 data=r[P2] */ |
| 10865 | #define OP_Delete 99 |
| 10866 | #define OP_ResetCount 100 |
| 10867 | #define OP_SorterCompare 101 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ |
| 10868 | #define OP_SorterData 102 /* synopsis: r[P2]=data */ |
| 10869 | #define OP_RowKey 103 /* synopsis: r[P2]=key */ |
| 10870 | #define OP_RowData 104 /* synopsis: r[P2]=data */ |
| 10871 | #define OP_Rowid 105 /* synopsis: r[P2]=rowid */ |
| 10872 | #define OP_NullRow 106 |
| 10873 | #define OP_Last 107 |
| 10874 | #define OP_SorterSort 108 |
| 10875 | #define OP_Sort 109 |
| 10876 | #define OP_Rewind 110 |
| 10877 | #define OP_SorterInsert 111 |
| 10878 | #define OP_IdxInsert 112 /* synopsis: key=r[P2] */ |
| 10879 | #define OP_IdxDelete 113 /* synopsis: key=r[P2@P3] */ |
| 10880 | #define OP_IdxRowid 114 /* synopsis: r[P2]=rowid */ |
| 10881 | #define OP_IdxLE 115 /* synopsis: key=r[P3@P4] */ |
| 10882 | #define OP_IdxGT 116 /* synopsis: key=r[P3@P4] */ |
| 10883 | #define OP_IdxLT 117 /* synopsis: key=r[P3@P4] */ |
| 10884 | #define OP_IdxGE 118 /* synopsis: key=r[P3@P4] */ |
| 10885 | #define OP_Destroy 119 |
| 10886 | #define OP_Clear 120 |
| 10887 | #define OP_ResetSorter 121 |
| 10888 | #define OP_CreateIndex 122 /* synopsis: r[P2]=root iDb=P1 */ |
| 10889 | #define OP_CreateTable 123 /* synopsis: r[P2]=root iDb=P1 */ |
| 10890 | #define OP_ParseSchema 124 |
| 10891 | #define OP_LoadAnalysis 125 |
| 10892 | #define OP_DropTable 126 |
| 10893 | #define OP_DropIndex 127 |
| 10894 | #define OP_DropTrigger 128 |
| 10895 | #define OP_IntegrityCk 129 |
| 10896 | #define OP_RowSetAdd 130 /* synopsis: rowset(P1)=r[P2] */ |
| 10897 | #define OP_RowSetRead 131 /* synopsis: r[P3]=rowset(P1) */ |
| 10898 | #define OP_RowSetTest 132 /* synopsis: if r[P3] in rowset(P1) goto P2 */ |
| 10899 | #define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 10900 | #define OP_Program 134 |
| 10901 | #define OP_Param 135 |
| 10902 | #define OP_FkCounter 136 /* synopsis: fkctr[P1]+=P2 */ |
| 10903 | #define OP_FkIfZero 137 /* synopsis: if fkctr[P1]==0 goto P2 */ |
| 10904 | #define OP_MemMax 138 /* synopsis: r[P1]=max(r[P1],r[P2]) */ |
| 10905 | #define OP_IfPos 139 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ |
| 10906 | #define OP_SetIfNotPos 140 /* synopsis: if r[P1]<=0 then r[P2]=P3 */ |
| 10907 | #define OP_IfNotZero 141 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ |
| 10908 | #define OP_DecrJumpZero 142 /* synopsis: if (--r[P1])==0 goto P2 */ |
| 10909 | #define OP_JumpZeroIncr 143 /* synopsis: if (r[P1]++)==0 ) goto P2 */ |
| 10910 | #define OP_AggStep0 144 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 10911 | #define OP_AggStep 145 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 10912 | #define OP_AggFinal 146 /* synopsis: accum=r[P1] N=P2 */ |
| 10913 | #define OP_IncrVacuum 147 |
| 10914 | #define OP_Expire 148 |
| 10915 | #define OP_TableLock 149 /* synopsis: iDb=P1 root=P2 write=P3 */ |
| 10916 | #define OP_VBegin 150 |
| 10917 | #define OP_VCreate 151 |
| 10918 | #define OP_VDestroy 152 |
| 10919 | #define OP_VOpen 153 |
| 10920 | #define OP_VColumn 154 /* synopsis: r[P3]=vcolumn(P2) */ |
| 10921 | #define OP_VNext 155 |
| 10922 | #define OP_VRename 156 |
| 10923 | #define OP_Pagecount 157 |
| 10924 | #define OP_MaxPgcnt 158 |
| 10925 | #define OP_Init 159 /* synopsis: Start at P2 */ |
| 10926 | #define OP_CursorHint 160 |
| 10927 | #define OP_Noop 161 |
| 10928 | #define OP_Explain 162 |
| 10929 | |
| 10930 | /* Properties such as "out2" or "jump" that are specified in |
| 10931 | ** comments following the "case" for each opcode in the vdbe.c |
| 10932 | ** are encoded into bitvectors as follows: |
| 10933 | */ |
| 10934 | #define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ |
| 10935 | #define OPFLG_IN1 0x0002 /* in1: P1 is an input */ |
| 10936 | #define OPFLG_IN2 0x0004 /* in2: P2 is an input */ |
| 10937 | #define OPFLG_IN3 0x0008 /* in3: P3 is an input */ |
| 10938 | #define OPFLG_OUT2 0x0010 /* out2: P2 is an output */ |
| 10939 | #define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ |
| 10940 | #define OPFLG_INITIALIZER {\ |
| 10941 | /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,\ |
| 10942 | /* 8 */ 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01,\ |
| 10943 | /* 16 */ 0x02, 0x01, 0x02, 0x12, 0x03, 0x08, 0x00, 0x10,\ |
| 10944 | /* 24 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00,\ |
| 10945 | /* 32 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,\ |
| 10946 | /* 40 */ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03,\ |
| 10947 | /* 48 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00,\ |
| 10948 | /* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 10949 | /* 64 */ 0x09, 0x09, 0x09, 0x09, 0x04, 0x09, 0x09, 0x26,\ |
| 10950 | /* 72 */ 0x26, 0x09, 0x09, 0x10, 0x03, 0x03, 0x0b, 0x0b,\ |
| 10951 | /* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x10, 0x26, 0x26, 0x26,\ |
| 10952 | /* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ |
| 10953 | /* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 10954 | /* 104 */ 0x00, 0x10, 0x00, 0x01, 0x01, 0x01, 0x01, 0x04,\ |
| 10955 | /* 112 */ 0x04, 0x00, 0x10, 0x01, 0x01, 0x01, 0x01, 0x10,\ |
| 10956 | /* 120 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ |
| 10957 | /* 128 */ 0x00, 0x00, 0x06, 0x23, 0x0b, 0x10, 0x01, 0x10,\ |
| 10958 | /* 136 */ 0x00, 0x01, 0x04, 0x03, 0x06, 0x03, 0x03, 0x03,\ |
| 10959 | /* 144 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\ |
| 10960 | /* 152 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x01,\ |
| 10961 | /* 160 */ 0x00, 0x00, 0x00,} |
| 10962 | |
| 10963 | /************** End of opcodes.h *********************************************/ |
| 10964 | /************** Continuing where we left off in vdbe.h ***********************/ |
| 10965 | |
| 10966 | /* |
| @@ -10976,10 +10992,11 @@ | |
| 10976 | SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...); |
| 10977 | SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); |
| 10978 | SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); |
| 10979 | SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); |
| 10980 | SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); |
| 10981 | #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) |
| 10982 | SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); |
| 10983 | #else |
| 10984 | # define sqlite3VdbeVerifyNoMallocRequired(A,B) |
| 10985 | #endif |
| @@ -11199,15 +11216,16 @@ | |
| 11199 | ** Flags for sqlite3PagerSetFlags() |
| 11200 | */ |
| 11201 | #define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ |
| 11202 | #define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ |
| 11203 | #define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ |
| 11204 | #define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */ |
| 11205 | #define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */ |
| 11206 | #define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */ |
| 11207 | #define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */ |
| 11208 | #define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */ |
| 11209 | |
| 11210 | /* |
| 11211 | ** The remainder of this file contains the declarations of the functions |
| 11212 | ** that make up the Pager sub-system API. See source code comments for |
| 11213 | ** a detailed description of each routine. |
| @@ -11963,12 +11981,12 @@ | |
| 11963 | ** is shared by multiple database connections. Therefore, while parsing |
| 11964 | ** schema information, the Lookaside.bEnabled flag is cleared so that |
| 11965 | ** lookaside allocations are not used to construct the schema objects. |
| 11966 | */ |
| 11967 | struct Lookaside { |
| 11968 | u16 sz; /* Size of each buffer in bytes */ |
| 11969 | u8 bEnabled; /* False to disable new lookaside allocations */ |
| 11970 | u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ |
| 11971 | int nOut; /* Number of buffers currently checked out */ |
| 11972 | int mxOut; /* Highwater mark for nOut */ |
| 11973 | int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ |
| 11974 | LookasideSlot *pFree; /* List of available buffers */ |
| @@ -12047,10 +12065,11 @@ | |
| 12047 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 12048 | u8 enc; /* Text encoding */ |
| 12049 | u8 autoCommit; /* The auto-commit flag. */ |
| 12050 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 12051 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 12052 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 12053 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| 12054 | u8 suppressErr; /* Do not issue error messages if true */ |
| 12055 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
| 12056 | u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ |
| @@ -12155,14 +12174,14 @@ | |
| 12155 | /* |
| 12156 | ** Possible values for the sqlite3.flags. |
| 12157 | */ |
| 12158 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| 12159 | #define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ |
| 12160 | #define SQLITE_FullFSync 0x00000004 /* Use full fsync on the backend */ |
| 12161 | #define SQLITE_CkptFullFSync 0x00000008 /* Use full fsync for checkpoint */ |
| 12162 | #define SQLITE_CacheSpill 0x00000010 /* OK to spill pager cache */ |
| 12163 | #define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ |
| 12164 | #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ |
| 12165 | #define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ |
| 12166 | /* DELETE, or UPDATE and return */ |
| 12167 | /* the count using a callback. */ |
| 12168 | #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ |
| @@ -13510,11 +13529,11 @@ | |
| 13510 | /* |
| 13511 | ** During code generation of statements that do inserts into AUTOINCREMENT |
| 13512 | ** tables, the following information is attached to the Table.u.autoInc.p |
| 13513 | ** pointer of each autoincrement table to record some side information that |
| 13514 | ** the code generator needs. We have to keep per-table autoincrement |
| 13515 | ** information in case inserts are down within triggers. Triggers do not |
| 13516 | ** normally coordinate their activities, but we do need to coordinate the |
| 13517 | ** loading and saving of autoincrement information. |
| 13518 | */ |
| 13519 | struct AutoincInfo { |
| 13520 | AutoincInfo *pNext; /* Next info block in a list of them all */ |
| @@ -13602,10 +13621,11 @@ | |
| 13602 | u8 nTempReg; /* Number of temporary registers in aTempReg[] */ |
| 13603 | u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ |
| 13604 | u8 mayAbort; /* True if statement may throw an ABORT exception */ |
| 13605 | u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ |
| 13606 | u8 okConstFactor; /* OK to factor out constants */ |
| 13607 | int aTempReg[8]; /* Holding area for temporary registers */ |
| 13608 | int nRangeReg; /* Size of the temporary register block */ |
| 13609 | int iRangeReg; /* First register in temporary register block */ |
| 13610 | int nErr; /* Number of errors seen */ |
| 13611 | int nTab; /* Number of previously allocated VDBE cursors */ |
| @@ -13716,23 +13736,26 @@ | |
| 13716 | }; |
| 13717 | |
| 13718 | /* |
| 13719 | ** Bitfield flags for P5 value in various opcodes. |
| 13720 | */ |
| 13721 | #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ |
| 13722 | #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ |
| 13723 | #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ |
| 13724 | #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ |
| 13725 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ |
| 13726 | #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ |
| 13727 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 13728 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 13729 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 13730 | #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ |
| 13731 | #define OPFLAG_FORDELETE 0x08 /* OP_Open is opening for-delete csr */ |
| 13732 | #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ |
| 13733 | #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ |
| 13734 | |
| 13735 | /* |
| 13736 | * Each trigger present in the database schema is stored as an instance of |
| 13737 | * struct Trigger. |
| 13738 | * |
| @@ -13847,14 +13870,20 @@ | |
| 13847 | char *zText; /* The string collected so far */ |
| 13848 | u32 nChar; /* Length of the string so far */ |
| 13849 | u32 nAlloc; /* Amount of space allocated in zText */ |
| 13850 | u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ |
| 13851 | u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ |
| 13852 | u8 bMalloced; /* zText points to allocated space */ |
| 13853 | }; |
| 13854 | #define STRACCUM_NOMEM 1 |
| 13855 | #define STRACCUM_TOOBIG 2 |
| 13856 | |
| 13857 | /* |
| 13858 | ** A pointer to this structure is used to communicate information |
| 13859 | ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. |
| 13860 | */ |
| @@ -14085,10 +14114,11 @@ | |
| 14085 | SQLITE_PRIVATE void sqlite3MallocEnd(void); |
| 14086 | SQLITE_PRIVATE void *sqlite3Malloc(u64); |
| 14087 | SQLITE_PRIVATE void *sqlite3MallocZero(u64); |
| 14088 | SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); |
| 14089 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); |
| 14090 | SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); |
| 14091 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); |
| 14092 | SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); |
| 14093 | SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); |
| 14094 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); |
| @@ -14167,14 +14197,12 @@ | |
| 14167 | int nArg; /* Total number of arguments */ |
| 14168 | int nUsed; /* Number of arguments used so far */ |
| 14169 | sqlite3_value **apArg; /* The argument values */ |
| 14170 | }; |
| 14171 | |
| 14172 | #define SQLITE_PRINTF_INTERNAL 0x01 |
| 14173 | #define SQLITE_PRINTF_SQLFUNC 0x02 |
| 14174 | SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list); |
| 14175 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...); |
| 14176 | SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); |
| 14177 | SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); |
| 14178 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 14179 | SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); |
| 14180 | #endif |
| @@ -14191,10 +14219,11 @@ | |
| 14191 | |
| 14192 | |
| 14193 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); |
| 14194 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 14195 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 14196 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 14197 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 14198 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 14199 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| 14200 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); |
| @@ -14638,10 +14667,12 @@ | |
| 14638 | SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, |
| 14639 | void (*)(sqlite3_context*,int,sqlite3_value **), |
| 14640 | void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), |
| 14641 | FuncDestructor *pDestructor |
| 14642 | ); |
| 14643 | SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); |
| 14644 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); |
| 14645 | |
| 14646 | SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); |
| 14647 | SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); |
| @@ -15734,18 +15765,20 @@ | |
| 15734 | ** - On either an index or a table |
| 15735 | ** * A sorter |
| 15736 | ** * A virtual table |
| 15737 | ** * A one-row "pseudotable" stored in a single register |
| 15738 | */ |
| 15739 | struct VdbeCursor { |
| 15740 | u8 eCurType; /* One of the CURTYPE_* values above */ |
| 15741 | i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ |
| 15742 | u8 nullRow; /* True if pointing to a row with no data */ |
| 15743 | u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ |
| 15744 | u8 isTable; /* True for rowid tables. False for indexes */ |
| 15745 | #ifdef SQLITE_DEBUG |
| 15746 | u8 seekOp; /* Most recent seek operation on this cursor */ |
| 15747 | #endif |
| 15748 | Bool isEphemeral:1; /* True for an ephemeral table */ |
| 15749 | Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ |
| 15750 | Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ |
| 15751 | Pgno pgnoRoot; /* Root page of the open btree cursor */ |
| @@ -15760,10 +15793,12 @@ | |
| 15760 | Btree *pBt; /* Separate file holding temporary table */ |
| 15761 | KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ |
| 15762 | int seekResult; /* Result of previous sqlite3BtreeMoveto() */ |
| 15763 | i64 seqCount; /* Sequence counter */ |
| 15764 | i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ |
| 15765 | #ifdef SQLITE_ENABLE_COLUMN_USED_MASK |
| 15766 | u64 maskUsed; /* Mask of columns used by this cursor */ |
| 15767 | #endif |
| 15768 | |
| 15769 | /* Cached information about the header for the data record that the |
| @@ -15784,11 +15819,10 @@ | |
| 15784 | u32 aType[1]; /* Type values for all entries in the record */ |
| 15785 | /* 2*nField extra array elements allocated for aType[], beyond the one |
| 15786 | ** static element declared in the structure. nField total array slots for |
| 15787 | ** aType[] and nField+1 array slots for aOffset[] */ |
| 15788 | }; |
| 15789 | typedef struct VdbeCursor VdbeCursor; |
| 15790 | |
| 15791 | /* |
| 15792 | ** When a sub-program is executed (OP_Program), a structure of this type |
| 15793 | ** is allocated to store the current value of the program counter, as |
| 15794 | ** well as the current memory cell array and various other frame specific |
| @@ -15895,11 +15929,11 @@ | |
| 15895 | #define MEM_AffMask 0x001f /* Mask of affinity bits */ |
| 15896 | #define MEM_RowSet 0x0020 /* Value is a RowSet object */ |
| 15897 | #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ |
| 15898 | #define MEM_Undefined 0x0080 /* Value is undefined */ |
| 15899 | #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ |
| 15900 | #define MEM_TypeMask 0x01ff /* Mask of type bits */ |
| 15901 | |
| 15902 | |
| 15903 | /* Whenever Mem contains a valid string or blob representation, one of |
| 15904 | ** the following flags must be set to determine the memory management |
| 15905 | ** policy for Mem.z. The MEM_Term flag tells us whether or not the |
| @@ -15909,14 +15943,21 @@ | |
| 15909 | #define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ |
| 15910 | #define MEM_Static 0x0800 /* Mem.z points to a static string */ |
| 15911 | #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ |
| 15912 | #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ |
| 15913 | #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ |
| 15914 | #ifdef SQLITE_OMIT_INCRBLOB |
| 15915 | #undef MEM_Zero |
| 15916 | #define MEM_Zero 0x0000 |
| 15917 | #endif |
| 15918 | |
| 15919 | /* |
| 15920 | ** Clear any existing type flags from a Mem and replace them with f |
| 15921 | */ |
| 15922 | #define MemSetTypeFlag(p, f) \ |
| @@ -16083,11 +16124,11 @@ | |
| 16083 | ** Function prototypes |
| 16084 | */ |
| 16085 | SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); |
| 16086 | SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); |
| 16087 | void sqliteVdbePopStack(Vdbe*,int); |
| 16088 | SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); |
| 16089 | SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); |
| 16090 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 16091 | SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); |
| 16092 | #endif |
| 16093 | SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); |
| @@ -16129,12 +16170,10 @@ | |
| 16129 | SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); |
| 16130 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); |
| 16131 | SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); |
| 16132 | SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); |
| 16133 | SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); |
| 16134 | #define VdbeMemDynamic(X) \ |
| 16135 | (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) |
| 16136 | SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); |
| 16137 | SQLITE_PRIVATE const char *sqlite3OpcodeName(int); |
| 16138 | SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); |
| 16139 | SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); |
| 16140 | SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); |
| @@ -17492,11 +17531,11 @@ | |
| 17492 | z = zBuf; |
| 17493 | }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 17494 | sqlite3_result_error_toobig(context); |
| 17495 | return; |
| 17496 | }else{ |
| 17497 | z = sqlite3DbMallocRaw(db, (int)n); |
| 17498 | if( z==0 ){ |
| 17499 | sqlite3_result_error_nomem(context); |
| 17500 | return; |
| 17501 | } |
| 17502 | } |
| @@ -20081,15 +20120,15 @@ | |
| 20081 | mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; |
| 20082 | while( ALWAYS(iLogsize<LOGMAX) ){ |
| 20083 | int iBuddy; |
| 20084 | if( (iBlock>>iLogsize) & 1 ){ |
| 20085 | iBuddy = iBlock - size; |
| 20086 | }else{ |
| 20087 | iBuddy = iBlock + size; |
| 20088 | } |
| 20089 | assert( iBuddy>=0 ); |
| 20090 | if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break; |
| 20091 | if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; |
| 20092 | memsys5Unlink(iBuddy, iLogsize); |
| 20093 | iLogsize++; |
| 20094 | if( iBuddy<iBlock ){ |
| 20095 | mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize; |
| @@ -22386,14 +22425,28 @@ | |
| 22386 | /* |
| 22387 | ** Allocate and zero memory. If the allocation fails, make |
| 22388 | ** the mallocFailed flag in the connection pointer. |
| 22389 | */ |
| 22390 | SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ |
| 22391 | void *p = sqlite3DbMallocRaw(db, n); |
| 22392 | if( p ){ |
| 22393 | memset(p, 0, (size_t)n); |
| 22394 | } |
| 22395 | return p; |
| 22396 | } |
| 22397 | |
| 22398 | /* |
| 22399 | ** Allocate memory, either lookaside (if possible) or heap. |
| @@ -22411,71 +22464,77 @@ | |
| 22411 | ** int *b = (int*)sqlite3DbMallocRaw(db, 200); |
| 22412 | ** if( b ) a[10] = 9; |
| 22413 | ** |
| 22414 | ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed |
| 22415 | ** that all prior mallocs (ex: "a") worked too. |
| 22416 | */ |
| 22417 | static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n); |
| 22418 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ |
| 22419 | assert( db==0 || sqlite3_mutex_held(db->mutex) ); |
| 22420 | assert( db==0 || db->pnBytesFreed==0 ); |
| 22421 | #ifndef SQLITE_OMIT_LOOKASIDE |
| 22422 | if( db ){ |
| 22423 | LookasideSlot *pBuf; |
| 22424 | if( db->mallocFailed ){ |
| 22425 | return 0; |
| 22426 | } |
| 22427 | if( db->lookaside.bEnabled ){ |
| 22428 | if( n>db->lookaside.sz ){ |
| 22429 | db->lookaside.anStat[1]++; |
| 22430 | }else if( (pBuf = db->lookaside.pFree)==0 ){ |
| 22431 | db->lookaside.anStat[2]++; |
| 22432 | }else{ |
| 22433 | db->lookaside.pFree = pBuf->pNext; |
| 22434 | db->lookaside.nOut++; |
| 22435 | db->lookaside.anStat[0]++; |
| 22436 | if( db->lookaside.nOut>db->lookaside.mxOut ){ |
| 22437 | db->lookaside.mxOut = db->lookaside.nOut; |
| 22438 | } |
| 22439 | return (void*)pBuf; |
| 22440 | } |
| 22441 | } |
| 22442 | } |
| 22443 | #else |
| 22444 | if( db && db->mallocFailed ){ |
| 22445 | return 0; |
| 22446 | } |
| 22447 | #endif |
| 22448 | return dbMallocRawFinish(db, n); |
| 22449 | } |
| 22450 | static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ |
| 22451 | void *p = sqlite3Malloc(n); |
| 22452 | if( !p && db ){ |
| 22453 | db->mallocFailed = 1; |
| 22454 | } |
| 22455 | sqlite3MemdebugSetType(p, |
| 22456 | (db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); |
| 22457 | return p; |
| 22458 | } |
| 22459 | |
| 22460 | /* |
| 22461 | ** Resize the block of memory pointed to by p to n bytes. If the |
| 22462 | ** resize fails, set the mallocFailed flag in the connection object. |
| 22463 | */ |
| 22464 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ |
| 22465 | void *pNew = 0; |
| 22466 | assert( db!=0 ); |
| 22467 | assert( sqlite3_mutex_held(db->mutex) ); |
| 22468 | if( db->mallocFailed==0 ){ |
| 22469 | if( p==0 ){ |
| 22470 | return sqlite3DbMallocRaw(db, n); |
| 22471 | } |
| 22472 | if( isLookaside(db, p) ){ |
| 22473 | if( n<=db->lookaside.sz ){ |
| 22474 | return p; |
| 22475 | } |
| 22476 | pNew = sqlite3DbMallocRaw(db, n); |
| 22477 | if( pNew ){ |
| 22478 | memcpy(pNew, p, db->lookaside.sz); |
| 22479 | sqlite3DbFree(db, p); |
| 22480 | } |
| 22481 | }else{ |
| @@ -22482,14 +22541,14 @@ | |
| 22482 | assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22483 | assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22484 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 22485 | pNew = sqlite3_realloc64(p, n); |
| 22486 | if( !pNew ){ |
| 22487 | db->mallocFailed = 1; |
| 22488 | } |
| 22489 | sqlite3MemdebugSetType(pNew, |
| 22490 | (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); |
| 22491 | } |
| 22492 | } |
| 22493 | return pNew; |
| 22494 | } |
| 22495 | |
| @@ -22527,15 +22586,16 @@ | |
| 22527 | } |
| 22528 | return zNew; |
| 22529 | } |
| 22530 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ |
| 22531 | char *zNew; |
| 22532 | if( z==0 ){ |
| 22533 | return 0; |
| 22534 | } |
| 22535 | assert( (n&0x7fffffff)==n ); |
| 22536 | zNew = sqlite3DbMallocRaw(db, n+1); |
| 22537 | if( zNew ){ |
| 22538 | memcpy(zNew, z, (size_t)n); |
| 22539 | zNew[n] = 0; |
| 22540 | } |
| 22541 | return zNew; |
| @@ -22546,16 +22606,48 @@ | |
| 22546 | */ |
| 22547 | SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ |
| 22548 | sqlite3DbFree(db, *pz); |
| 22549 | *pz = sqlite3DbStrDup(db, zNew); |
| 22550 | } |
| 22551 | |
| 22552 | /* |
| 22553 | ** Take actions at the end of an API call to indicate an OOM error |
| 22554 | */ |
| 22555 | static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ |
| 22556 | db->mallocFailed = 0; |
| 22557 | sqlite3Error(db, SQLITE_NOMEM); |
| 22558 | return SQLITE_NOMEM; |
| 22559 | } |
| 22560 | |
| 22561 | /* |
| @@ -22756,11 +22848,10 @@ | |
| 22756 | /* |
| 22757 | ** Render a string given by "fmt" into the StrAccum object. |
| 22758 | */ |
| 22759 | SQLITE_PRIVATE void sqlite3VXPrintf( |
| 22760 | StrAccum *pAccum, /* Accumulate results here */ |
| 22761 | u32 bFlags, /* SQLITE_PRINTF_* flags */ |
| 22762 | const char *fmt, /* Format string */ |
| 22763 | va_list ap /* arguments */ |
| 22764 | ){ |
| 22765 | int c; /* Next character in the format string */ |
| 22766 | char *bufpt; /* Pointer to the conversion buffer */ |
| @@ -22796,15 +22887,15 @@ | |
| 22796 | #endif |
| 22797 | PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ |
| 22798 | char buf[etBUFSIZE]; /* Conversion buffer */ |
| 22799 | |
| 22800 | bufpt = 0; |
| 22801 | if( bFlags ){ |
| 22802 | if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ |
| 22803 | pArgList = va_arg(ap, PrintfArguments*); |
| 22804 | } |
| 22805 | useIntern = bFlags & SQLITE_PRINTF_INTERNAL; |
| 22806 | }else{ |
| 22807 | bArgList = useIntern = 0; |
| 22808 | } |
| 22809 | for(; (c=(*fmt))!=0; ++fmt){ |
| 22810 | if( c!='%' ){ |
| @@ -23351,13 +23442,13 @@ | |
| 23351 | if( p->mxAlloc==0 ){ |
| 23352 | N = p->nAlloc - p->nChar - 1; |
| 23353 | setStrAccumError(p, STRACCUM_TOOBIG); |
| 23354 | return N; |
| 23355 | }else{ |
| 23356 | char *zOld = p->bMalloced ? p->zText : 0; |
| 23357 | i64 szNew = p->nChar; |
| 23358 | assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23359 | szNew += N + 1; |
| 23360 | if( szNew+p->nChar<=p->mxAlloc ){ |
| 23361 | /* Force exponential buffer size growth as long as it does not overflow, |
| 23362 | ** to avoid having to call this routine too often */ |
| 23363 | szNew += p->nChar; |
| @@ -23374,14 +23465,14 @@ | |
| 23374 | }else{ |
| 23375 | zNew = sqlite3_realloc64(zOld, p->nAlloc); |
| 23376 | } |
| 23377 | if( zNew ){ |
| 23378 | assert( p->zText!=0 || p->nChar==0 ); |
| 23379 | if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); |
| 23380 | p->zText = zNew; |
| 23381 | p->nAlloc = sqlite3DbMallocSize(p->db, zNew); |
| 23382 | p->bMalloced = 1; |
| 23383 | }else{ |
| 23384 | sqlite3StrAccumReset(p); |
| 23385 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23386 | return 0; |
| 23387 | } |
| @@ -23395,11 +23486,11 @@ | |
| 23395 | SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ |
| 23396 | testcase( p->nChar + (i64)N > 0x7fffffff ); |
| 23397 | if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ |
| 23398 | return; |
| 23399 | } |
| 23400 | assert( (p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23401 | while( (N--)>0 ) p->zText[p->nChar++] = c; |
| 23402 | } |
| 23403 | |
| 23404 | /* |
| 23405 | ** The StrAccum "p" is not large enough to accept N new bytes of z[]. |
| @@ -23413,11 +23504,11 @@ | |
| 23413 | N = sqlite3StrAccumEnlarge(p, N); |
| 23414 | if( N>0 ){ |
| 23415 | memcpy(&p->zText[p->nChar], z, N); |
| 23416 | p->nChar += N; |
| 23417 | } |
| 23418 | assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23419 | } |
| 23420 | |
| 23421 | /* |
| 23422 | ** Append N bytes of text from z to the StrAccum object. Increase the |
| 23423 | ** size of the memory allocation for StrAccum if necessary. |
| @@ -23449,17 +23540,17 @@ | |
| 23449 | ** Return a pointer to the resulting string. Return a NULL |
| 23450 | ** pointer if any kind of error was encountered. |
| 23451 | */ |
| 23452 | SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ |
| 23453 | if( p->zText ){ |
| 23454 | assert( (p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23455 | p->zText[p->nChar] = 0; |
| 23456 | if( p->mxAlloc>0 && p->bMalloced==0 ){ |
| 23457 | p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
| 23458 | if( p->zText ){ |
| 23459 | memcpy(p->zText, p->zBase, p->nChar+1); |
| 23460 | p->bMalloced = 1; |
| 23461 | }else{ |
| 23462 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23463 | } |
| 23464 | } |
| 23465 | } |
| @@ -23468,14 +23559,14 @@ | |
| 23468 | |
| 23469 | /* |
| 23470 | ** Reset an StrAccum string. Reclaim all malloced memory. |
| 23471 | */ |
| 23472 | SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ |
| 23473 | assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23474 | if( p->bMalloced ){ |
| 23475 | sqlite3DbFree(p->db, p->zText); |
| 23476 | p->bMalloced = 0; |
| 23477 | } |
| 23478 | p->zText = 0; |
| 23479 | } |
| 23480 | |
| 23481 | /* |
| @@ -23497,11 +23588,11 @@ | |
| 23497 | p->db = db; |
| 23498 | p->nChar = 0; |
| 23499 | p->nAlloc = n; |
| 23500 | p->mxAlloc = mx; |
| 23501 | p->accError = 0; |
| 23502 | p->bMalloced = 0; |
| 23503 | } |
| 23504 | |
| 23505 | /* |
| 23506 | ** Print into memory obtained from sqliteMalloc(). Use the internal |
| 23507 | ** %-conversion extensions. |
| @@ -23511,14 +23602,15 @@ | |
| 23511 | char zBase[SQLITE_PRINT_BUF_SIZE]; |
| 23512 | StrAccum acc; |
| 23513 | assert( db!=0 ); |
| 23514 | sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), |
| 23515 | db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 23516 | sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); |
| 23517 | z = sqlite3StrAccumFinish(&acc); |
| 23518 | if( acc.accError==STRACCUM_NOMEM ){ |
| 23519 | db->mallocFailed = 1; |
| 23520 | } |
| 23521 | return z; |
| 23522 | } |
| 23523 | |
| 23524 | /* |
| @@ -23551,11 +23643,11 @@ | |
| 23551 | #endif |
| 23552 | #ifndef SQLITE_OMIT_AUTOINIT |
| 23553 | if( sqlite3_initialize() ) return 0; |
| 23554 | #endif |
| 23555 | sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); |
| 23556 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23557 | z = sqlite3StrAccumFinish(&acc); |
| 23558 | return z; |
| 23559 | } |
| 23560 | |
| 23561 | /* |
| @@ -23596,11 +23688,11 @@ | |
| 23596 | if( zBuf ) zBuf[0] = 0; |
| 23597 | return zBuf; |
| 23598 | } |
| 23599 | #endif |
| 23600 | sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); |
| 23601 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23602 | return sqlite3StrAccumFinish(&acc); |
| 23603 | } |
| 23604 | SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
| 23605 | char *z; |
| 23606 | va_list ap; |
| @@ -23627,11 +23719,11 @@ | |
| 23627 | static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
| 23628 | StrAccum acc; /* String accumulator */ |
| 23629 | char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
| 23630 | |
| 23631 | sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); |
| 23632 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23633 | sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
| 23634 | sqlite3StrAccumFinish(&acc)); |
| 23635 | } |
| 23636 | |
| 23637 | /* |
| @@ -23656,11 +23748,11 @@ | |
| 23656 | va_list ap; |
| 23657 | StrAccum acc; |
| 23658 | char zBuf[500]; |
| 23659 | sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); |
| 23660 | va_start(ap,zFormat); |
| 23661 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23662 | va_end(ap); |
| 23663 | sqlite3StrAccumFinish(&acc); |
| 23664 | fprintf(stdout,"%s", zBuf); |
| 23665 | fflush(stdout); |
| 23666 | } |
| @@ -23669,14 +23761,14 @@ | |
| 23669 | |
| 23670 | /* |
| 23671 | ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument |
| 23672 | ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. |
| 23673 | */ |
| 23674 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ |
| 23675 | va_list ap; |
| 23676 | va_start(ap,zFormat); |
| 23677 | sqlite3VXPrintf(p, bFlags, zFormat, ap); |
| 23678 | va_end(ap); |
| 23679 | } |
| 23680 | |
| 23681 | /************** End of printf.c **********************************************/ |
| 23682 | /************** Begin file treeview.c ****************************************/ |
| @@ -23743,11 +23835,11 @@ | |
| 23743 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); |
| 23744 | } |
| 23745 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); |
| 23746 | } |
| 23747 | va_start(ap, zFormat); |
| 23748 | sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23749 | va_end(ap); |
| 23750 | if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); |
| 23751 | sqlite3StrAccumFinish(&acc); |
| 23752 | fprintf(stdout,"%s", zBuf); |
| 23753 | fflush(stdout); |
| @@ -23778,21 +23870,21 @@ | |
| 23778 | for(i=0; i<pWith->nCte; i++){ |
| 23779 | StrAccum x; |
| 23780 | char zLine[1000]; |
| 23781 | const struct Cte *pCte = &pWith->a[i]; |
| 23782 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23783 | sqlite3XPrintf(&x, 0, "%s", pCte->zName); |
| 23784 | if( pCte->pCols && pCte->pCols->nExpr>0 ){ |
| 23785 | char cSep = '('; |
| 23786 | int j; |
| 23787 | for(j=0; j<pCte->pCols->nExpr; j++){ |
| 23788 | sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName); |
| 23789 | cSep = ','; |
| 23790 | } |
| 23791 | sqlite3XPrintf(&x, 0, ")"); |
| 23792 | } |
| 23793 | sqlite3XPrintf(&x, 0, " AS"); |
| 23794 | sqlite3StrAccumFinish(&x); |
| 23795 | sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1); |
| 23796 | sqlite3TreeViewSelect(pView, pCte->pSelect, 0); |
| 23797 | sqlite3TreeViewPop(pView); |
| 23798 | } |
| @@ -23839,24 +23931,24 @@ | |
| 23839 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 23840 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 23841 | StrAccum x; |
| 23842 | char zLine[100]; |
| 23843 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23844 | sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); |
| 23845 | if( pItem->zDatabase ){ |
| 23846 | sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); |
| 23847 | }else if( pItem->zName ){ |
| 23848 | sqlite3XPrintf(&x, 0, " %s", pItem->zName); |
| 23849 | } |
| 23850 | if( pItem->pTab ){ |
| 23851 | sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); |
| 23852 | } |
| 23853 | if( pItem->zAlias ){ |
| 23854 | sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); |
| 23855 | } |
| 23856 | if( pItem->fg.jointype & JT_LEFT ){ |
| 23857 | sqlite3XPrintf(&x, 0, " LEFT-JOIN"); |
| 23858 | } |
| 23859 | sqlite3StrAccumFinish(&x); |
| 23860 | sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); |
| 23861 | if( pItem->pSelect ){ |
| 23862 | sqlite3TreeViewSelect(pView, pItem->pSelect, 0); |
| @@ -24899,11 +24991,11 @@ | |
| 24899 | *z = 0; |
| 24900 | assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); |
| 24901 | |
| 24902 | c = pMem->flags; |
| 24903 | sqlite3VdbeMemRelease(pMem); |
| 24904 | pMem->flags = MEM_Str|MEM_Term|(c&MEM_AffMask); |
| 24905 | pMem->enc = desiredEnc; |
| 24906 | pMem->z = (char*)zOut; |
| 24907 | pMem->zMalloc = pMem->z; |
| 24908 | pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); |
| 24909 | |
| @@ -25349,10 +25441,18 @@ | |
| 25349 | } |
| 25350 | } |
| 25351 | z[j] = 0; |
| 25352 | return j; |
| 25353 | } |
| 25354 | |
| 25355 | /* Convenient short-hand */ |
| 25356 | #define UpperToLower sqlite3UpperToLower |
| 25357 | |
| 25358 | /* |
| @@ -26258,11 +26358,11 @@ | |
| 26258 | */ |
| 26259 | SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ |
| 26260 | char *zBlob; |
| 26261 | int i; |
| 26262 | |
| 26263 | zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1); |
| 26264 | n--; |
| 26265 | if( zBlob ){ |
| 26266 | for(i=0; i<n; i+=2){ |
| 26267 | zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]); |
| 26268 | } |
| @@ -26796,95 +26896,96 @@ | |
| 26796 | # define OpHelp(X) "\0" X |
| 26797 | #else |
| 26798 | # define OpHelp(X) |
| 26799 | #endif |
| 26800 | SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ |
| 26801 | static const char *const azName[] = { "?", |
| 26802 | /* 1 */ "Savepoint" OpHelp(""), |
| 26803 | /* 2 */ "AutoCommit" OpHelp(""), |
| 26804 | /* 3 */ "Transaction" OpHelp(""), |
| 26805 | /* 4 */ "SorterNext" OpHelp(""), |
| 26806 | /* 5 */ "PrevIfOpen" OpHelp(""), |
| 26807 | /* 6 */ "NextIfOpen" OpHelp(""), |
| 26808 | /* 7 */ "Prev" OpHelp(""), |
| 26809 | /* 8 */ "Next" OpHelp(""), |
| 26810 | /* 9 */ "Checkpoint" OpHelp(""), |
| 26811 | /* 10 */ "JournalMode" OpHelp(""), |
| 26812 | /* 11 */ "Vacuum" OpHelp(""), |
| 26813 | /* 12 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), |
| 26814 | /* 13 */ "VUpdate" OpHelp("data=r[P3@P2]"), |
| 26815 | /* 14 */ "Goto" OpHelp(""), |
| 26816 | /* 15 */ "Gosub" OpHelp(""), |
| 26817 | /* 16 */ "Return" OpHelp(""), |
| 26818 | /* 17 */ "InitCoroutine" OpHelp(""), |
| 26819 | /* 18 */ "EndCoroutine" OpHelp(""), |
| 26820 | /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), |
| 26821 | /* 20 */ "Yield" OpHelp(""), |
| 26822 | /* 21 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), |
| 26823 | /* 22 */ "Halt" OpHelp(""), |
| 26824 | /* 23 */ "Integer" OpHelp("r[P2]=P1"), |
| 26825 | /* 24 */ "Int64" OpHelp("r[P2]=P4"), |
| 26826 | /* 25 */ "String" OpHelp("r[P2]='P4' (len=P1)"), |
| 26827 | /* 26 */ "Null" OpHelp("r[P2..P3]=NULL"), |
| 26828 | /* 27 */ "SoftNull" OpHelp("r[P1]=NULL"), |
| 26829 | /* 28 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), |
| 26830 | /* 29 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), |
| 26831 | /* 30 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), |
| 26832 | /* 31 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), |
| 26833 | /* 32 */ "SCopy" OpHelp("r[P2]=r[P1]"), |
| 26834 | /* 33 */ "IntCopy" OpHelp("r[P2]=r[P1]"), |
| 26835 | /* 34 */ "ResultRow" OpHelp("output=r[P1@P2]"), |
| 26836 | /* 35 */ "CollSeq" OpHelp(""), |
| 26837 | /* 36 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), |
| 26838 | /* 37 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), |
| 26839 | /* 38 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), |
| 26840 | /* 39 */ "MustBeInt" OpHelp(""), |
| 26841 | /* 40 */ "RealAffinity" OpHelp(""), |
| 26842 | /* 41 */ "Cast" OpHelp("affinity(r[P1])"), |
| 26843 | /* 42 */ "Permutation" OpHelp(""), |
| 26844 | /* 43 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), |
| 26845 | /* 44 */ "Jump" OpHelp(""), |
| 26846 | /* 45 */ "Once" OpHelp(""), |
| 26847 | /* 46 */ "If" OpHelp(""), |
| 26848 | /* 47 */ "IfNot" OpHelp(""), |
| 26849 | /* 48 */ "Column" OpHelp("r[P3]=PX"), |
| 26850 | /* 49 */ "Affinity" OpHelp("affinity(r[P1@P2])"), |
| 26851 | /* 50 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), |
| 26852 | /* 51 */ "Count" OpHelp("r[P2]=count()"), |
| 26853 | /* 52 */ "ReadCookie" OpHelp(""), |
| 26854 | /* 53 */ "SetCookie" OpHelp(""), |
| 26855 | /* 54 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), |
| 26856 | /* 55 */ "OpenRead" OpHelp("root=P2 iDb=P3"), |
| 26857 | /* 56 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), |
| 26858 | /* 57 */ "OpenAutoindex" OpHelp("nColumn=P2"), |
| 26859 | /* 58 */ "OpenEphemeral" OpHelp("nColumn=P2"), |
| 26860 | /* 59 */ "SorterOpen" OpHelp(""), |
| 26861 | /* 60 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), |
| 26862 | /* 61 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), |
| 26863 | /* 62 */ "Close" OpHelp(""), |
| 26864 | /* 63 */ "ColumnsUsed" OpHelp(""), |
| 26865 | /* 64 */ "SeekLT" OpHelp("key=r[P3@P4]"), |
| 26866 | /* 65 */ "SeekLE" OpHelp("key=r[P3@P4]"), |
| 26867 | /* 66 */ "SeekGE" OpHelp("key=r[P3@P4]"), |
| 26868 | /* 67 */ "SeekGT" OpHelp("key=r[P3@P4]"), |
| 26869 | /* 68 */ "Seek" OpHelp("intkey=r[P2]"), |
| 26870 | /* 69 */ "NoConflict" OpHelp("key=r[P3@P4]"), |
| 26871 | /* 70 */ "NotFound" OpHelp("key=r[P3@P4]"), |
| 26872 | /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), |
| 26873 | /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), |
| 26874 | /* 73 */ "Found" OpHelp("key=r[P3@P4]"), |
| 26875 | /* 74 */ "NotExists" OpHelp("intkey=r[P3]"), |
| 26876 | /* 75 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), |
| 26877 | /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), |
| 26878 | /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), |
| 26879 | /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), |
| 26880 | /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), |
| 26881 | /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), |
| 26882 | /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), |
| 26883 | /* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"), |
| 26884 | /* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"), |
| 26885 | /* 84 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 26886 | /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), |
| 26887 | /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), |
| 26888 | /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), |
| 26889 | /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), |
| 26890 | /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), |
| @@ -26891,78 +26992,77 @@ | |
| 26891 | /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), |
| 26892 | /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), |
| 26893 | /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), |
| 26894 | /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), |
| 26895 | /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), |
| 26896 | /* 95 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 26897 | /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), |
| 26898 | /* 97 */ "String8" OpHelp("r[P2]='P4'"), |
| 26899 | /* 98 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), |
| 26900 | /* 99 */ "Delete" OpHelp(""), |
| 26901 | /* 100 */ "ResetCount" OpHelp(""), |
| 26902 | /* 101 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), |
| 26903 | /* 102 */ "SorterData" OpHelp("r[P2]=data"), |
| 26904 | /* 103 */ "RowKey" OpHelp("r[P2]=key"), |
| 26905 | /* 104 */ "RowData" OpHelp("r[P2]=data"), |
| 26906 | /* 105 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 26907 | /* 106 */ "NullRow" OpHelp(""), |
| 26908 | /* 107 */ "Last" OpHelp(""), |
| 26909 | /* 108 */ "SorterSort" OpHelp(""), |
| 26910 | /* 109 */ "Sort" OpHelp(""), |
| 26911 | /* 110 */ "Rewind" OpHelp(""), |
| 26912 | /* 111 */ "SorterInsert" OpHelp(""), |
| 26913 | /* 112 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 26914 | /* 113 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 26915 | /* 114 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 26916 | /* 115 */ "IdxLE" OpHelp("key=r[P3@P4]"), |
| 26917 | /* 116 */ "IdxGT" OpHelp("key=r[P3@P4]"), |
| 26918 | /* 117 */ "IdxLT" OpHelp("key=r[P3@P4]"), |
| 26919 | /* 118 */ "IdxGE" OpHelp("key=r[P3@P4]"), |
| 26920 | /* 119 */ "Destroy" OpHelp(""), |
| 26921 | /* 120 */ "Clear" OpHelp(""), |
| 26922 | /* 121 */ "ResetSorter" OpHelp(""), |
| 26923 | /* 122 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 26924 | /* 123 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 26925 | /* 124 */ "ParseSchema" OpHelp(""), |
| 26926 | /* 125 */ "LoadAnalysis" OpHelp(""), |
| 26927 | /* 126 */ "DropTable" OpHelp(""), |
| 26928 | /* 127 */ "DropIndex" OpHelp(""), |
| 26929 | /* 128 */ "DropTrigger" OpHelp(""), |
| 26930 | /* 129 */ "IntegrityCk" OpHelp(""), |
| 26931 | /* 130 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), |
| 26932 | /* 131 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), |
| 26933 | /* 132 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), |
| 26934 | /* 133 */ "Real" OpHelp("r[P2]=P4"), |
| 26935 | /* 134 */ "Program" OpHelp(""), |
| 26936 | /* 135 */ "Param" OpHelp(""), |
| 26937 | /* 136 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), |
| 26938 | /* 137 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), |
| 26939 | /* 138 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), |
| 26940 | /* 139 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), |
| 26941 | /* 140 */ "SetIfNotPos" OpHelp("if r[P1]<=0 then r[P2]=P3"), |
| 26942 | /* 141 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), |
| 26943 | /* 142 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), |
| 26944 | /* 143 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), |
| 26945 | /* 144 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 26946 | /* 145 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 26947 | /* 146 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), |
| 26948 | /* 147 */ "IncrVacuum" OpHelp(""), |
| 26949 | /* 148 */ "Expire" OpHelp(""), |
| 26950 | /* 149 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), |
| 26951 | /* 150 */ "VBegin" OpHelp(""), |
| 26952 | /* 151 */ "VCreate" OpHelp(""), |
| 26953 | /* 152 */ "VDestroy" OpHelp(""), |
| 26954 | /* 153 */ "VOpen" OpHelp(""), |
| 26955 | /* 154 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), |
| 26956 | /* 155 */ "VNext" OpHelp(""), |
| 26957 | /* 156 */ "VRename" OpHelp(""), |
| 26958 | /* 157 */ "Pagecount" OpHelp(""), |
| 26959 | /* 158 */ "MaxPgcnt" OpHelp(""), |
| 26960 | /* 159 */ "Init" OpHelp("Start at P2"), |
| 26961 | /* 160 */ "CursorHint" OpHelp(""), |
| 26962 | /* 161 */ "Noop" OpHelp(""), |
| 26963 | /* 162 */ "Explain" OpHelp(""), |
| 26964 | }; |
| 26965 | return azName[i]; |
| 26966 | } |
| 26967 | #endif |
| 26968 | |
| @@ -27117,10 +27217,15 @@ | |
| 27117 | /* |
| 27118 | ** Maximum supported path-length. |
| 27119 | */ |
| 27120 | #define MAX_PATHNAME 512 |
| 27121 | |
| 27122 | /* Always cast the getpid() return type for compatibility with |
| 27123 | ** kernel modules in VxWorks. */ |
| 27124 | #define osGetpid(X) (pid_t)getpid() |
| 27125 | |
| 27126 | /* |
| @@ -27641,10 +27746,16 @@ | |
| 27641 | #else |
| 27642 | { "readlink", (sqlite3_syscall_ptr)0, 0 }, |
| 27643 | #endif |
| 27644 | #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) |
| 27645 | |
| 27646 | |
| 27647 | }; /* End of the overrideable system calls */ |
| 27648 | |
| 27649 | |
| 27650 | /* |
| @@ -33042,16 +33153,11 @@ | |
| 33042 | #ifndef SQLITE_DISABLE_DIRSYNC |
| 33043 | if( (dirSync & 1)!=0 ){ |
| 33044 | int fd; |
| 33045 | rc = osOpenDirectory(zPath, &fd); |
| 33046 | if( rc==SQLITE_OK ){ |
| 33047 | #if OS_VXWORKS |
| 33048 | if( fsync(fd)==-1 ) |
| 33049 | #else |
| 33050 | if( fsync(fd) ) |
| 33051 | #endif |
| 33052 | { |
| 33053 | rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); |
| 33054 | } |
| 33055 | robust_close(0, fd, __LINE__); |
| 33056 | }else{ |
| 33057 | assert( rc==SQLITE_CANTOPEN ); |
| @@ -33093,10 +33199,36 @@ | |
| 33093 | *pResOut = osAccess(zPath, W_OK|R_OK)==0; |
| 33094 | } |
| 33095 | return SQLITE_OK; |
| 33096 | } |
| 33097 | |
| 33098 | |
| 33099 | /* |
| 33100 | ** Turn a relative pathname into a full pathname. The relative path |
| 33101 | ** is stored as a nul-terminated string in the buffer pointed to by |
| 33102 | ** zPath. |
| @@ -33109,73 +33241,85 @@ | |
| 33109 | sqlite3_vfs *pVfs, /* Pointer to vfs object */ |
| 33110 | const char *zPath, /* Possibly relative input path */ |
| 33111 | int nOut, /* Size of output buffer in bytes */ |
| 33112 | char *zOut /* Output buffer */ |
| 33113 | ){ |
| 33114 | int nByte; |
| 33115 | |
| 33116 | /* It's odd to simulate an io-error here, but really this is just |
| 33117 | ** using the io-error infrastructure to test that SQLite handles this |
| 33118 | ** function failing. This function could fail if, for example, the |
| 33119 | ** current working directory has been unlinked. |
| 33120 | */ |
| 33121 | SimulateIOError( return SQLITE_ERROR ); |
| 33122 | |
| 33123 | assert( pVfs->mxPathname==MAX_PATHNAME ); |
| 33124 | UNUSED_PARAMETER(pVfs); |
| 33125 | |
| 33126 | #if defined(HAVE_READLINK) |
| 33127 | /* Attempt to resolve the path as if it were a symbolic link. If it is |
| 33128 | ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if |
| 33129 | ** the identified file is not a symbolic link or does not exist, then |
| 33130 | ** zPath is copied directly into zOut. Either way, nByte is left set to |
| 33131 | ** the size of the string copied into zOut[] in bytes. */ |
| 33132 | nByte = osReadlink(zPath, zOut, nOut-1); |
| 33133 | if( nByte<0 ){ |
| 33134 | if( errno!=EINVAL && errno!=ENOENT ){ |
| 33135 | return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath); |
| 33136 | } |
| 33137 | sqlite3_snprintf(nOut, zOut, "%s", zPath); |
| 33138 | nByte = sqlite3Strlen30(zOut); |
| 33139 | }else{ |
| 33140 | zOut[nByte] = '\0'; |
| 33141 | } |
| 33142 | #endif |
| 33143 | |
| 33144 | /* If buffer zOut[] now contains an absolute path there is nothing more |
| 33145 | ** to do. If it contains a relative path, do the following: |
| 33146 | ** |
| 33147 | ** * move the relative path string so that it is at the end of th |
| 33148 | ** zOut[] buffer. |
| 33149 | ** * Call getcwd() to read the path of the current working directory |
| 33150 | ** into the start of the zOut[] buffer. |
| 33151 | ** * Append a '/' character to the cwd string and move the |
| 33152 | ** relative path back within the buffer so that it immediately |
| 33153 | ** follows the '/'. |
| 33154 | ** |
| 33155 | ** This code is written so that if the combination of the CWD and relative |
| 33156 | ** path are larger than the allocated size of zOut[] the CWD is silently |
| 33157 | ** truncated to make it fit. This is Ok, as SQLite refuses to open any |
| 33158 | ** file for which this function returns a full path larger than (nOut-8) |
| 33159 | ** bytes in size. */ |
| 33160 | testcase( nByte==nOut-5 ); |
| 33161 | testcase( nByte==nOut-4 ); |
| 33162 | if( zOut[0]!='/' && nByte<nOut-4 ){ |
| 33163 | int nCwd; |
| 33164 | int nRem = nOut-nByte-1; |
| 33165 | memmove(&zOut[nRem], zOut, nByte+1); |
| 33166 | zOut[nRem-1] = '\0'; |
| 33167 | if( osGetcwd(zOut, nRem-1)==0 ){ |
| 33168 | return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); |
| 33169 | } |
| 33170 | nCwd = sqlite3Strlen30(zOut); |
| 33171 | assert( nCwd<=nRem-1 ); |
| 33172 | zOut[nCwd] = '/'; |
| 33173 | memmove(&zOut[nCwd+1], &zOut[nRem], nByte+1); |
| 33174 | } |
| 33175 | |
| 33176 | return SQLITE_OK; |
| 33177 | } |
| 33178 | |
| 33179 | |
| 33180 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 33181 | /* |
| @@ -33353,11 +33497,11 @@ | |
| 33353 | #endif |
| 33354 | UNUSED_PARAMETER(NotUsed); |
| 33355 | return rc; |
| 33356 | } |
| 33357 | |
| 33358 | #if 0 /* Not used */ |
| 33359 | /* |
| 33360 | ** Find the current time (in Universal Coordinated Time). Write the |
| 33361 | ** current time and date as a Julian Day number into *prNow and |
| 33362 | ** return 0. Return 1 if the time and date cannot be found. |
| 33363 | */ |
| @@ -33371,11 +33515,11 @@ | |
| 33371 | } |
| 33372 | #else |
| 33373 | # define unixCurrentTime 0 |
| 33374 | #endif |
| 33375 | |
| 33376 | #if 0 /* Not used */ |
| 33377 | /* |
| 33378 | ** We added the xGetLastError() method with the intention of providing |
| 33379 | ** better low-level error messages when operating-system problems come up |
| 33380 | ** during SQLite operation. But so far, none of that has been implemented |
| 33381 | ** in the core. So this routine is never called. For now, it is merely |
| @@ -34053,11 +34197,11 @@ | |
| 34053 | strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); |
| 34054 | } |
| 34055 | writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); |
| 34056 | robust_ftruncate(conchFile->h, writeSize); |
| 34057 | rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); |
| 34058 | fsync(conchFile->h); |
| 34059 | /* If we created a new conch file (not just updated the contents of a |
| 34060 | ** valid conch file), try to match the permissions of the database |
| 34061 | */ |
| 34062 | if( rc==SQLITE_OK && createConch ){ |
| 34063 | struct stat buf; |
| @@ -34670,11 +34814,11 @@ | |
| 34670 | }; |
| 34671 | unsigned int i; /* Loop counter */ |
| 34672 | |
| 34673 | /* Double-check that the aSyscall[] array has been constructed |
| 34674 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 34675 | assert( ArraySize(aSyscall)==27 ); |
| 34676 | |
| 34677 | /* Register all VFSes defined in the aVfs[] array */ |
| 34678 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 34679 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 34680 | } |
| @@ -34970,10 +35114,14 @@ | |
| 34970 | |
| 34971 | #ifndef NTDDI_WINBLUE |
| 34972 | # define NTDDI_WINBLUE 0x06030000 |
| 34973 | #endif |
| 34974 | |
| 34975 | /* |
| 34976 | ** Check to see if the GetVersionEx[AW] functions are deprecated on the |
| 34977 | ** target system. GetVersionEx was first deprecated in Win8.1. |
| 34978 | */ |
| 34979 | #ifndef SQLITE_WIN32_GETVERSIONEX |
| @@ -34982,10 +35130,23 @@ | |
| 34982 | # else |
| 34983 | # define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ |
| 34984 | # endif |
| 34985 | #endif |
| 34986 | |
| 34987 | /* |
| 34988 | ** This constant should already be defined (in the "WinDef.h" SDK file). |
| 34989 | */ |
| 34990 | #ifndef MAX_PATH |
| 34991 | # define MAX_PATH (260) |
| @@ -35388,12 +35549,13 @@ | |
| 35388 | #endif |
| 35389 | |
| 35390 | #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ |
| 35391 | LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) |
| 35392 | |
| 35393 | #if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ |
| 35394 | (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) |
| 35395 | { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, |
| 35396 | #else |
| 35397 | { "CreateFileMappingA", (SYSCALL)0, 0 }, |
| 35398 | #endif |
| 35399 | |
| @@ -35619,22 +35781,21 @@ | |
| 35619 | { "GetTickCount", (SYSCALL)0, 0 }, |
| 35620 | #endif |
| 35621 | |
| 35622 | #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) |
| 35623 | |
| 35624 | #if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \ |
| 35625 | SQLITE_WIN32_GETVERSIONEX |
| 35626 | { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, |
| 35627 | #else |
| 35628 | { "GetVersionExA", (SYSCALL)0, 0 }, |
| 35629 | #endif |
| 35630 | |
| 35631 | #define osGetVersionExA ((BOOL(WINAPI*)( \ |
| 35632 | LPOSVERSIONINFOA))aSyscall[34].pCurrent) |
| 35633 | |
| 35634 | #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ |
| 35635 | defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX |
| 35636 | { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, |
| 35637 | #else |
| 35638 | { "GetVersionExW", (SYSCALL)0, 0 }, |
| 35639 | #endif |
| 35640 | |
| @@ -36241,11 +36402,11 @@ | |
| 36241 | ** this routine is used to determine if the host is Win95/98/ME or |
| 36242 | ** WinNT/2K/XP so that we will know whether or not we can safely call |
| 36243 | ** the LockFileEx() API. |
| 36244 | */ |
| 36245 | |
| 36246 | #if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX |
| 36247 | # define osIsNT() (1) |
| 36248 | #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) |
| 36249 | # define osIsNT() (1) |
| 36250 | #elif !defined(SQLITE_WIN32_HAS_WIDE) |
| 36251 | # define osIsNT() (0) |
| @@ -36262,11 +36423,11 @@ | |
| 36262 | /* |
| 36263 | ** NOTE: The WinRT sub-platform is always assumed to be based on the NT |
| 36264 | ** kernel. |
| 36265 | */ |
| 36266 | return 1; |
| 36267 | #elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX |
| 36268 | if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ |
| 36269 | #if defined(SQLITE_WIN32_HAS_ANSI) |
| 36270 | OSVERSIONINFOA sInfo; |
| 36271 | sInfo.dwOSVersionInfoSize = sizeof(sInfo); |
| 36272 | osGetVersionExA(&sInfo); |
| @@ -38846,11 +39007,11 @@ | |
| 38846 | ); |
| 38847 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 38848 | hMap = osCreateFileMappingW(pShmNode->hFile.h, |
| 38849 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 38850 | ); |
| 38851 | #elif defined(SQLITE_WIN32_HAS_ANSI) |
| 38852 | hMap = osCreateFileMappingA(pShmNode->hFile.h, |
| 38853 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 38854 | ); |
| 38855 | #endif |
| 38856 | OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", |
| @@ -39002,11 +39163,11 @@ | |
| 39002 | pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); |
| 39003 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 39004 | pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, |
| 39005 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39006 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39007 | #elif defined(SQLITE_WIN32_HAS_ANSI) |
| 39008 | pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, |
| 39009 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39010 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39011 | #endif |
| 39012 | if( pFd->hMap==NULL ){ |
| @@ -43066,11 +43227,11 @@ | |
| 43066 | */ |
| 43067 | static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ |
| 43068 | assert( p!=0 ); |
| 43069 | if( p->nFresh==0 ){ |
| 43070 | struct RowSetChunk *pNew; |
| 43071 | pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); |
| 43072 | if( pNew==0 ){ |
| 43073 | return 0; |
| 43074 | } |
| 43075 | pNew->pNextChunk = p->pChunk; |
| 43076 | p->pChunk = pNew; |
| @@ -43973,10 +44134,24 @@ | |
| 43973 | ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. |
| 43974 | ** This could conceivably cause corruption following a power failure on |
| 43975 | ** such a system. This is currently an undocumented limit. |
| 43976 | */ |
| 43977 | #define MAX_SECTOR_SIZE 0x10000 |
| 43978 | |
| 43979 | /* |
| 43980 | ** An instance of the following structure is allocated for each active |
| 43981 | ** savepoint and statement transaction in the system. All such structures |
| 43982 | ** are stored in the Pager.aSavepoint[] array, which is allocated and |
| @@ -44169,10 +44344,11 @@ | |
| 44169 | u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ |
| 44170 | u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
| 44171 | u8 useJournal; /* Use a rollback journal on this file */ |
| 44172 | u8 noSync; /* Do not sync the journal if true */ |
| 44173 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 44174 | u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ |
| 44175 | u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ |
| 44176 | u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ |
| 44177 | u8 tempFile; /* zFilename is a temporary or immutable file */ |
| 44178 | u8 noLock; /* Do not lock (except in WAL mode) */ |
| @@ -45529,11 +45705,11 @@ | |
| 45529 | || pPager->journalMode==PAGER_JOURNALMODE_MEMORY |
| 45530 | || pPager->journalMode==PAGER_JOURNALMODE_WAL |
| 45531 | ); |
| 45532 | sqlite3OsClose(pPager->jfd); |
| 45533 | if( bDelete ){ |
| 45534 | rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); |
| 45535 | } |
| 45536 | } |
| 45537 | } |
| 45538 | |
| 45539 | #ifdef SQLITE_CHECK_PAGES |
| @@ -47035,13 +47211,19 @@ | |
| 47035 | SQLITE_PRIVATE void sqlite3PagerSetFlags( |
| 47036 | Pager *pPager, /* The pager to set safety level for */ |
| 47037 | unsigned pgFlags /* Various flags */ |
| 47038 | ){ |
| 47039 | unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; |
| 47040 | assert( level>=1 && level<=3 ); |
| 47041 | pPager->noSync = (level==1 || pPager->tempFile) ?1:0; |
| 47042 | pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; |
| 47043 | if( pPager->noSync ){ |
| 47044 | pPager->syncFlags = 0; |
| 47045 | pPager->ckptSyncFlags = 0; |
| 47046 | }else if( pgFlags & PAGER_FULLFSYNC ){ |
| 47047 | pPager->syncFlags = SQLITE_SYNC_FULL; |
| @@ -48342,15 +48524,21 @@ | |
| 48342 | pPager->readOnly = (u8)readOnly; |
| 48343 | assert( useJournal || pPager->tempFile ); |
| 48344 | pPager->noSync = pPager->tempFile; |
| 48345 | if( pPager->noSync ){ |
| 48346 | assert( pPager->fullSync==0 ); |
| 48347 | assert( pPager->syncFlags==0 ); |
| 48348 | assert( pPager->walSyncFlags==0 ); |
| 48349 | assert( pPager->ckptSyncFlags==0 ); |
| 48350 | }else{ |
| 48351 | pPager->fullSync = 1; |
| 48352 | pPager->syncFlags = SQLITE_SYNC_NORMAL; |
| 48353 | pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; |
| 48354 | pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; |
| 48355 | } |
| 48356 | /* pPager->pFirst = 0; */ |
| @@ -57680,11 +57868,10 @@ | |
| 57680 | MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) |
| 57681 | if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ |
| 57682 | pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); |
| 57683 | if( pBt->mutex==0 ){ |
| 57684 | rc = SQLITE_NOMEM; |
| 57685 | db->mallocFailed = 0; |
| 57686 | goto btree_open_out; |
| 57687 | } |
| 57688 | } |
| 57689 | sqlite3_mutex_enter(mutexShared); |
| 57690 | pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList); |
| @@ -59391,17 +59578,17 @@ | |
| 59391 | ** iTable. If a read-only cursor is requested, it is assumed that |
| 59392 | ** the caller already has at least a read-only transaction open |
| 59393 | ** on the database already. If a write-cursor is requested, then |
| 59394 | ** the caller is assumed to have an open write transaction. |
| 59395 | ** |
| 59396 | ** If wrFlag==0, then the cursor can only be used for reading. |
| 59397 | ** If wrFlag==1, then the cursor can be used for reading or for |
| 59398 | ** writing if other conditions for writing are also met. These |
| 59399 | ** are the conditions that must be met in order for writing to |
| 59400 | ** be allowed: |
| 59401 | ** |
| 59402 | ** 1: The cursor must have been opened with wrFlag==1 |
| 59403 | ** |
| 59404 | ** 2: Other database connections that share the same pager cache |
| 59405 | ** but which are not in the READ_UNCOMMITTED state may not have |
| 59406 | ** cursors open with wrFlag==0 on the same table. Otherwise |
| 59407 | ** the changes made by this write cursor would be visible to |
| @@ -59408,10 +59595,20 @@ | |
| 59408 | ** the read cursors in the other database connection. |
| 59409 | ** |
| 59410 | ** 3: The database must be writable (not on read-only media) |
| 59411 | ** |
| 59412 | ** 4: There must be an active transaction. |
| 59413 | ** |
| 59414 | ** No checking is done to make sure that page iTable really is the |
| 59415 | ** root page of a b-tree. If it is not, then the cursor acquired |
| 59416 | ** will not work correctly. |
| 59417 | ** |
| @@ -61481,11 +61678,11 @@ | |
| 61481 | */ |
| 61482 | #if SQLITE_DEBUG |
| 61483 | { |
| 61484 | CellInfo info; |
| 61485 | pPage->xParseCell(pPage, pCell, &info); |
| 61486 | assert( nHeader=(int)(info.pPayload - pCell) ); |
| 61487 | assert( info.nKey==nKey ); |
| 61488 | assert( *pnSize == info.nSize ); |
| 61489 | assert( spaceLeft == info.nLocal ); |
| 61490 | } |
| 61491 | #endif |
| @@ -63140,12 +63337,12 @@ | |
| 63140 | int rc = SQLITE_OK; |
| 63141 | const int nMin = pCur->pBt->usableSize * 2 / 3; |
| 63142 | u8 aBalanceQuickSpace[13]; |
| 63143 | u8 *pFree = 0; |
| 63144 | |
| 63145 | TESTONLY( int balance_quick_called = 0 ); |
| 63146 | TESTONLY( int balance_deeper_called = 0 ); |
| 63147 | |
| 63148 | do { |
| 63149 | int iPage = pCur->iPage; |
| 63150 | MemPage *pPage = pCur->apPage[iPage]; |
| 63151 | |
| @@ -63154,11 +63351,12 @@ | |
| 63154 | /* The root page of the b-tree is overfull. In this case call the |
| 63155 | ** balance_deeper() function to create a new child for the root-page |
| 63156 | ** and copy the current contents of the root-page to it. The |
| 63157 | ** next iteration of the do-loop will balance the child page. |
| 63158 | */ |
| 63159 | assert( (balance_deeper_called++)==0 ); |
| 63160 | rc = balance_deeper(pPage, &pCur->apPage[1]); |
| 63161 | if( rc==SQLITE_OK ){ |
| 63162 | pCur->iPage = 1; |
| 63163 | pCur->aiIdx[0] = 0; |
| 63164 | pCur->aiIdx[1] = 0; |
| @@ -63193,11 +63391,12 @@ | |
| 63193 | ** The purpose of the following assert() is to check that only a |
| 63194 | ** single call to balance_quick() is made for each call to this |
| 63195 | ** function. If this were not verified, a subtle bug involving reuse |
| 63196 | ** of the aBalanceQuickSpace[] might sneak in. |
| 63197 | */ |
| 63198 | assert( (balance_quick_called++)==0 ); |
| 63199 | rc = balance_quick(pParent, pPage, aBalanceQuickSpace); |
| 63200 | }else |
| 63201 | #endif |
| 63202 | { |
| 63203 | /* In this case, call balance_nonroot() to redistribute cells |
| @@ -63424,35 +63623,45 @@ | |
| 63424 | } |
| 63425 | |
| 63426 | /* |
| 63427 | ** Delete the entry that the cursor is pointing to. |
| 63428 | ** |
| 63429 | ** If the second parameter is zero, then the cursor is left pointing at an |
| 63430 | ** arbitrary location after the delete. If it is non-zero, then the cursor |
| 63431 | ** is left in a state such that the next call to BtreeNext() or BtreePrev() |
| 63432 | ** moves it to the same row as it would if the call to BtreeDelete() had |
| 63433 | ** been omitted. |
| 63434 | */ |
| 63435 | SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ |
| 63436 | Btree *p = pCur->pBtree; |
| 63437 | BtShared *pBt = p->pBt; |
| 63438 | int rc; /* Return code */ |
| 63439 | MemPage *pPage; /* Page to delete cell from */ |
| 63440 | unsigned char *pCell; /* Pointer to cell to delete */ |
| 63441 | int iCellIdx; /* Index of cell to delete */ |
| 63442 | int iCellDepth; /* Depth of node containing pCell */ |
| 63443 | u16 szCell; /* Size of the cell being deleted */ |
| 63444 | int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ |
| 63445 | |
| 63446 | assert( cursorOwnsBtShared(pCur) ); |
| 63447 | assert( pBt->inTransaction==TRANS_WRITE ); |
| 63448 | assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); |
| 63449 | assert( pCur->curFlags & BTCF_WriteFlag ); |
| 63450 | assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); |
| 63451 | assert( !hasReadConflicts(p, pCur->pgnoRoot) ); |
| 63452 | assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); |
| 63453 | assert( pCur->eState==CURSOR_VALID ); |
| 63454 | |
| 63455 | iCellDepth = pCur->iPage; |
| 63456 | iCellIdx = pCur->aiIdx[iCellDepth]; |
| 63457 | pPage = pCur->apPage[iCellDepth]; |
| 63458 | pCell = findCell(pPage, iCellIdx); |
| @@ -63561,11 +63770,11 @@ | |
| 63561 | } |
| 63562 | |
| 63563 | if( rc==SQLITE_OK ){ |
| 63564 | if( bSkipnext ){ |
| 63565 | assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); |
| 63566 | assert( pPage==pCur->apPage[pCur->iPage] ); |
| 63567 | assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); |
| 63568 | pCur->eState = CURSOR_SKIPNEXT; |
| 63569 | if( iCellIdx>=pPage->nCell ){ |
| 63570 | pCur->skipNext = -1; |
| 63571 | pCur->aiIdx[iCellDepth] = pPage->nCell-1; |
| @@ -64147,13 +64356,13 @@ | |
| 64147 | va_start(ap, zFormat); |
| 64148 | if( pCheck->errMsg.nChar ){ |
| 64149 | sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); |
| 64150 | } |
| 64151 | if( pCheck->zPfx ){ |
| 64152 | sqlite3XPrintf(&pCheck->errMsg, 0, pCheck->zPfx, pCheck->v1, pCheck->v2); |
| 64153 | } |
| 64154 | sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); |
| 64155 | va_end(ap); |
| 64156 | if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ |
| 64157 | pCheck->mallocFailed = 1; |
| 64158 | } |
| 64159 | } |
| @@ -64650,11 +64859,12 @@ | |
| 64650 | char zErr[100]; |
| 64651 | VVA_ONLY( int nRef ); |
| 64652 | |
| 64653 | sqlite3BtreeEnter(p); |
| 64654 | assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); |
| 64655 | assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 ); |
| 64656 | sCheck.pBt = pBt; |
| 64657 | sCheck.pPager = pBt->pPager; |
| 64658 | sCheck.nPage = btreePagecount(sCheck.pBt); |
| 64659 | sCheck.mxErr = mxErr; |
| 64660 | sCheck.nErr = 0; |
| @@ -64663,10 +64873,11 @@ | |
| 64663 | sCheck.v1 = 0; |
| 64664 | sCheck.v2 = 0; |
| 64665 | sCheck.aPgRef = 0; |
| 64666 | sCheck.heap = 0; |
| 64667 | sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); |
| 64668 | if( sCheck.nPage==0 ){ |
| 64669 | goto integrity_ck_cleanup; |
| 64670 | } |
| 64671 | |
| 64672 | sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); |
| @@ -65939,10 +66150,11 @@ | |
| 65939 | ** in pMem->z is discarded. |
| 65940 | */ |
| 65941 | SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ |
| 65942 | assert( sqlite3VdbeCheckMemInvariants(pMem) ); |
| 65943 | assert( (pMem->flags&MEM_RowSet)==0 ); |
| 65944 | |
| 65945 | /* If the bPreserve flag is set to true, then the memory cell must already |
| 65946 | ** contain a valid string or blob value. */ |
| 65947 | assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); |
| 65948 | testcase( bPreserve && pMem->z==0 ); |
| @@ -66542,11 +66754,11 @@ | |
| 66542 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ |
| 66543 | sqlite3 *db = pMem->db; |
| 66544 | assert( db!=0 ); |
| 66545 | assert( (pMem->flags & MEM_RowSet)==0 ); |
| 66546 | sqlite3VdbeMemRelease(pMem); |
| 66547 | pMem->zMalloc = sqlite3DbMallocRaw(db, 64); |
| 66548 | if( db->mallocFailed ){ |
| 66549 | pMem->flags = MEM_Null; |
| 66550 | pMem->szMalloc = 0; |
| 66551 | }else{ |
| 66552 | assert( pMem->zMalloc ); |
| @@ -67204,11 +67416,11 @@ | |
| 67204 | |
| 67205 | *ppVal = pVal; |
| 67206 | return rc; |
| 67207 | |
| 67208 | no_mem: |
| 67209 | db->mallocFailed = 1; |
| 67210 | sqlite3DbFree(db, zVal); |
| 67211 | assert( *ppVal==0 ); |
| 67212 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 67213 | if( pCtx==0 ) sqlite3ValueFree(pVal); |
| 67214 | #else |
| @@ -67263,11 +67475,11 @@ | |
| 67263 | iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); |
| 67264 | nSerial = sqlite3VarintLen(iSerial); |
| 67265 | db = sqlite3_context_db_handle(context); |
| 67266 | |
| 67267 | nRet = 1 + nSerial + nVal; |
| 67268 | aRet = sqlite3DbMallocRaw(db, nRet); |
| 67269 | if( aRet==0 ){ |
| 67270 | sqlite3_result_error_nomem(context); |
| 67271 | }else{ |
| 67272 | aRet[0] = nSerial+1; |
| 67273 | putVarint32(&aRet[1], iSerial); |
| @@ -67715,11 +67927,11 @@ | |
| 67715 | int i; |
| 67716 | VdbeOp *pOp; |
| 67717 | |
| 67718 | i = p->nOp; |
| 67719 | assert( p->magic==VDBE_MAGIC_INIT ); |
| 67720 | assert( op>0 && op<0xff ); |
| 67721 | if( p->pParse->nOpAlloc<=i ){ |
| 67722 | return growOp3(p, op, p1, p2, p3); |
| 67723 | } |
| 67724 | p->nOp++; |
| 67725 | pOp = &p->aOp[i]; |
| @@ -67833,11 +68045,11 @@ | |
| 67833 | int p2, /* The P2 operand */ |
| 67834 | int p3, /* The P3 operand */ |
| 67835 | const u8 *zP4, /* The P4 operand */ |
| 67836 | int p4type /* P4 operand type */ |
| 67837 | ){ |
| 67838 | char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8); |
| 67839 | if( p4copy ) memcpy(p4copy, zP4, 8); |
| 67840 | return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); |
| 67841 | } |
| 67842 | |
| 67843 | /* |
| @@ -67867,10 +68079,25 @@ | |
| 67867 | ){ |
| 67868 | int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); |
| 67869 | sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); |
| 67870 | return addr; |
| 67871 | } |
| 67872 | |
| 67873 | /* |
| 67874 | ** Create a new symbolic label for an instruction that has yet to be |
| 67875 | ** coded. The symbolic label is really just a negative number. The |
| 67876 | ** label can be used as the P2 value of an operation. Later, when |
| @@ -68078,11 +68305,11 @@ | |
| 68078 | p->readOnly = 1; |
| 68079 | p->bIsReader = 0; |
| 68080 | for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ |
| 68081 | u8 opcode = pOp->opcode; |
| 68082 | |
| 68083 | /* NOTE: Be sure to update mkopcodeh.awk when adding or removing |
| 68084 | ** cases from this switch! */ |
| 68085 | switch( opcode ){ |
| 68086 | case OP_Transaction: { |
| 68087 | if( pOp->p2!=0 ) p->readOnly = 0; |
| 68088 | /* fall thru */ |
| @@ -68190,10 +68417,13 @@ | |
| 68190 | } |
| 68191 | |
| 68192 | /* |
| 68193 | ** Add a whole list of operations to the operation stack. Return a |
| 68194 | ** pointer to the first operation inserted. |
| 68195 | */ |
| 68196 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList( |
| 68197 | Vdbe *p, /* Add opcodes to the prepared statement */ |
| 68198 | int nOp, /* Number of opcodes to add */ |
| 68199 | VdbeOpList const *aOp, /* The opcodes to be added */ |
| @@ -68210,10 +68440,13 @@ | |
| 68210 | for(i=0; i<nOp; i++, aOp++, pOut++){ |
| 68211 | pOut->opcode = aOp->opcode; |
| 68212 | pOut->p1 = aOp->p1; |
| 68213 | pOut->p2 = aOp->p2; |
| 68214 | assert( aOp->p2>=0 ); |
| 68215 | pOut->p3 = aOp->p3; |
| 68216 | pOut->p4type = P4_NOTUSED; |
| 68217 | pOut->p4.p = 0; |
| 68218 | pOut->p5 = 0; |
| 68219 | #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS |
| @@ -68661,32 +68894,31 @@ | |
| 68661 | #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) |
| 68662 | /* |
| 68663 | ** Translate the P4.pExpr value for an OP_CursorHint opcode into text |
| 68664 | ** that can be displayed in the P4 column of EXPLAIN output. |
| 68665 | */ |
| 68666 | static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ |
| 68667 | const char *zOp = 0; |
| 68668 | int n; |
| 68669 | switch( pExpr->op ){ |
| 68670 | case TK_STRING: |
| 68671 | sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken); |
| 68672 | break; |
| 68673 | case TK_INTEGER: |
| 68674 | sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue); |
| 68675 | break; |
| 68676 | case TK_NULL: |
| 68677 | sqlite3_snprintf(nTemp, zTemp, "NULL"); |
| 68678 | break; |
| 68679 | case TK_REGISTER: { |
| 68680 | sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable); |
| 68681 | break; |
| 68682 | } |
| 68683 | case TK_COLUMN: { |
| 68684 | if( pExpr->iColumn<0 ){ |
| 68685 | sqlite3_snprintf(nTemp, zTemp, "rowid"); |
| 68686 | }else{ |
| 68687 | sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn); |
| 68688 | } |
| 68689 | break; |
| 68690 | } |
| 68691 | case TK_LT: zOp = "LT"; break; |
| 68692 | case TK_LE: zOp = "LE"; break; |
| @@ -68714,25 +68946,23 @@ | |
| 68714 | case TK_NOT: zOp = "NOT"; break; |
| 68715 | case TK_ISNULL: zOp = "ISNULL"; break; |
| 68716 | case TK_NOTNULL: zOp = "NOTNULL"; break; |
| 68717 | |
| 68718 | default: |
| 68719 | sqlite3_snprintf(nTemp, zTemp, "%s", "expr"); |
| 68720 | break; |
| 68721 | } |
| 68722 | |
| 68723 | if( zOp ){ |
| 68724 | sqlite3_snprintf(nTemp, zTemp, "%s(", zOp); |
| 68725 | n = sqlite3Strlen30(zTemp); |
| 68726 | n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft); |
| 68727 | if( n<nTemp-1 && pExpr->pRight ){ |
| 68728 | zTemp[n++] = ','; |
| 68729 | n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight); |
| 68730 | } |
| 68731 | sqlite3_snprintf(nTemp-n, zTemp+n, ")"); |
| 68732 | } |
| 68733 | return sqlite3Strlen30(zTemp); |
| 68734 | } |
| 68735 | #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ |
| 68736 | |
| 68737 | |
| 68738 | #if VDBE_DISPLAY_P4 |
| @@ -68740,107 +68970,100 @@ | |
| 68740 | ** Compute a string that describes the P4 parameter for an opcode. |
| 68741 | ** Use zTemp for any required temporary buffer space. |
| 68742 | */ |
| 68743 | static char *displayP4(Op *pOp, char *zTemp, int nTemp){ |
| 68744 | char *zP4 = zTemp; |
| 68745 | assert( nTemp>=20 ); |
| 68746 | switch( pOp->p4type ){ |
| 68747 | case P4_KEYINFO: { |
| 68748 | int i, j; |
| 68749 | KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; |
| 68750 | assert( pKeyInfo->aSortOrder!=0 ); |
| 68751 | sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField); |
| 68752 | i = sqlite3Strlen30(zTemp); |
| 68753 | for(j=0; j<pKeyInfo->nField; j++){ |
| 68754 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 68755 | const char *zColl = pColl ? pColl->zName : "nil"; |
| 68756 | int n = sqlite3Strlen30(zColl); |
| 68757 | if( n==6 && memcmp(zColl,"BINARY",6)==0 ){ |
| 68758 | zColl = "B"; |
| 68759 | n = 1; |
| 68760 | } |
| 68761 | if( i+n>nTemp-7 ){ |
| 68762 | memcpy(&zTemp[i],",...",4); |
| 68763 | i += 4; |
| 68764 | break; |
| 68765 | } |
| 68766 | zTemp[i++] = ','; |
| 68767 | if( pKeyInfo->aSortOrder[j] ){ |
| 68768 | zTemp[i++] = '-'; |
| 68769 | } |
| 68770 | memcpy(&zTemp[i], zColl, n+1); |
| 68771 | i += n; |
| 68772 | } |
| 68773 | zTemp[i++] = ')'; |
| 68774 | zTemp[i] = 0; |
| 68775 | assert( i<nTemp ); |
| 68776 | break; |
| 68777 | } |
| 68778 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 68779 | case P4_EXPR: { |
| 68780 | displayP4Expr(nTemp, zTemp, pOp->p4.pExpr); |
| 68781 | break; |
| 68782 | } |
| 68783 | #endif |
| 68784 | case P4_COLLSEQ: { |
| 68785 | CollSeq *pColl = pOp->p4.pColl; |
| 68786 | sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); |
| 68787 | break; |
| 68788 | } |
| 68789 | case P4_FUNCDEF: { |
| 68790 | FuncDef *pDef = pOp->p4.pFunc; |
| 68791 | sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); |
| 68792 | break; |
| 68793 | } |
| 68794 | #ifdef SQLITE_DEBUG |
| 68795 | case P4_FUNCCTX: { |
| 68796 | FuncDef *pDef = pOp->p4.pCtx->pFunc; |
| 68797 | sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); |
| 68798 | break; |
| 68799 | } |
| 68800 | #endif |
| 68801 | case P4_INT64: { |
| 68802 | sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); |
| 68803 | break; |
| 68804 | } |
| 68805 | case P4_INT32: { |
| 68806 | sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i); |
| 68807 | break; |
| 68808 | } |
| 68809 | case P4_REAL: { |
| 68810 | sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal); |
| 68811 | break; |
| 68812 | } |
| 68813 | case P4_MEM: { |
| 68814 | Mem *pMem = pOp->p4.pMem; |
| 68815 | if( pMem->flags & MEM_Str ){ |
| 68816 | zP4 = pMem->z; |
| 68817 | }else if( pMem->flags & MEM_Int ){ |
| 68818 | sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); |
| 68819 | }else if( pMem->flags & MEM_Real ){ |
| 68820 | sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r); |
| 68821 | }else if( pMem->flags & MEM_Null ){ |
| 68822 | sqlite3_snprintf(nTemp, zTemp, "NULL"); |
| 68823 | }else{ |
| 68824 | assert( pMem->flags & MEM_Blob ); |
| 68825 | zP4 = "(blob)"; |
| 68826 | } |
| 68827 | break; |
| 68828 | } |
| 68829 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 68830 | case P4_VTAB: { |
| 68831 | sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; |
| 68832 | sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); |
| 68833 | break; |
| 68834 | } |
| 68835 | #endif |
| 68836 | case P4_INTARRAY: { |
| 68837 | sqlite3_snprintf(nTemp, zTemp, "intarray"); |
| 68838 | break; |
| 68839 | } |
| 68840 | case P4_SUBPROGRAM: { |
| 68841 | sqlite3_snprintf(nTemp, zTemp, "program"); |
| 68842 | break; |
| 68843 | } |
| 68844 | case P4_ADVANCE: { |
| 68845 | zTemp[0] = 0; |
| 68846 | break; |
| @@ -68851,10 +69074,11 @@ | |
| 68851 | zP4 = zTemp; |
| 68852 | zTemp[0] = 0; |
| 68853 | } |
| 68854 | } |
| 68855 | } |
| 68856 | assert( zP4!=0 ); |
| 68857 | return zP4; |
| 68858 | } |
| 68859 | #endif /* VDBE_DISPLAY_P4 */ |
| 68860 | |
| @@ -68970,11 +69194,10 @@ | |
| 68970 | */ |
| 68971 | static void releaseMemArray(Mem *p, int N){ |
| 68972 | if( p && N ){ |
| 68973 | Mem *pEnd = &p[N]; |
| 68974 | sqlite3 *db = p->db; |
| 68975 | u8 malloc_failed = db->mallocFailed; |
| 68976 | if( db->pnBytesFreed ){ |
| 68977 | do{ |
| 68978 | if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); |
| 68979 | }while( (++p)<pEnd ); |
| 68980 | return; |
| @@ -69006,11 +69229,10 @@ | |
| 69006 | p->szMalloc = 0; |
| 69007 | } |
| 69008 | |
| 69009 | p->flags = MEM_Undefined; |
| 69010 | }while( (++p)<pEnd ); |
| 69011 | db->mallocFailed = malloc_failed; |
| 69012 | } |
| 69013 | } |
| 69014 | |
| 69015 | /* |
| 69016 | ** Delete a VdbeFrame object and its contents. VdbeFrame objects are |
| @@ -69067,11 +69289,11 @@ | |
| 69067 | p->pResultSet = 0; |
| 69068 | |
| 69069 | if( p->rc==SQLITE_NOMEM ){ |
| 69070 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 69071 | ** sqlite3_column_text16() failed. */ |
| 69072 | db->mallocFailed = 1; |
| 69073 | return SQLITE_ERROR; |
| 69074 | } |
| 69075 | |
| 69076 | /* When the number of output rows reaches nRow, that means the |
| 69077 | ** listing has finished and sqlite3_step() should return SQLITE_DONE. |
| @@ -69265,45 +69487,47 @@ | |
| 69265 | sqlite3IoTrace("SQL %s\n", z); |
| 69266 | } |
| 69267 | } |
| 69268 | #endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ |
| 69269 | |
| 69270 | /* |
| 69271 | ** Allocate space from a fixed size buffer and return a pointer to |
| 69272 | ** that space. If insufficient space is available, return NULL. |
| 69273 | ** |
| 69274 | ** The pBuf parameter is the initial value of a pointer which will |
| 69275 | ** receive the new memory. pBuf is normally NULL. If pBuf is not |
| 69276 | ** NULL, it means that memory space has already been allocated and that |
| 69277 | ** this routine should not allocate any new memory. When pBuf is not |
| 69278 | ** NULL simply return pBuf. Only allocate new memory space when pBuf |
| 69279 | ** is NULL. |
| 69280 | ** |
| 69281 | ** nByte is the number of bytes of space needed. |
| 69282 | ** |
| 69283 | ** pFrom points to *pnFrom bytes of available space. New space is allocated |
| 69284 | ** from the end of the pFrom buffer and *pnFrom is decremented. |
| 69285 | ** |
| 69286 | ** *pnNeeded is a counter of the number of bytes of space that have failed |
| 69287 | ** to allocate. If there is insufficient space in pFrom to satisfy the |
| 69288 | ** request, then increment *pnNeeded by the amount of the request. |
| 69289 | */ |
| 69290 | static void *allocSpace( |
| 69291 | void *pBuf, /* Where return pointer will be stored */ |
| 69292 | int nByte, /* Number of bytes to allocate */ |
| 69293 | u8 *pFrom, /* Memory available for allocation */ |
| 69294 | int *pnFrom, /* IN/OUT: Space available at pFrom */ |
| 69295 | int *pnNeeded /* If allocation cannot be made, increment *pnByte */ |
| 69296 | ){ |
| 69297 | assert( EIGHT_BYTE_ALIGNMENT(pFrom) ); |
| 69298 | if( pBuf==0 ){ |
| 69299 | nByte = ROUND8(nByte); |
| 69300 | if( nByte <= *pnFrom ){ |
| 69301 | *pnFrom -= nByte; |
| 69302 | pBuf = &pFrom[*pnFrom]; |
| 69303 | }else{ |
| 69304 | *pnNeeded += nByte; |
| 69305 | } |
| 69306 | } |
| 69307 | assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); |
| 69308 | return pBuf; |
| 69309 | } |
| @@ -69332,11 +69556,10 @@ | |
| 69332 | } |
| 69333 | #endif |
| 69334 | p->pc = -1; |
| 69335 | p->rc = SQLITE_OK; |
| 69336 | p->errorAction = OE_Abort; |
| 69337 | p->magic = VDBE_MAGIC_RUN; |
| 69338 | p->nChange = 0; |
| 69339 | p->cacheCtr = 1; |
| 69340 | p->minWriteFileFormat = 255; |
| 69341 | p->iStatement = 0; |
| 69342 | p->nFkConstraint = 0; |
| @@ -69375,13 +69598,11 @@ | |
| 69375 | int nMem; /* Number of VM memory registers */ |
| 69376 | int nCursor; /* Number of cursors required */ |
| 69377 | int nArg; /* Number of arguments in subprograms */ |
| 69378 | int nOnce; /* Number of OP_Once instructions */ |
| 69379 | int n; /* Loop counter */ |
| 69380 | int nFree; /* Available free space */ |
| 69381 | u8 *zCsr; /* Memory available for allocation */ |
| 69382 | int nByte; /* How much extra memory is needed */ |
| 69383 | |
| 69384 | assert( p!=0 ); |
| 69385 | assert( p->nOp>0 ); |
| 69386 | assert( pParse!=0 ); |
| 69387 | assert( p->magic==VDBE_MAGIC_INIT ); |
| @@ -69395,69 +69616,64 @@ | |
| 69395 | nOnce = pParse->nOnce; |
| 69396 | if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ |
| 69397 | |
| 69398 | /* For each cursor required, also allocate a memory cell. Memory |
| 69399 | ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by |
| 69400 | ** the vdbe program. Instead they are used to allocate space for |
| 69401 | ** VdbeCursor/BtCursor structures. The blob of memory associated with |
| 69402 | ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) |
| 69403 | ** stores the blob of memory associated with cursor 1, etc. |
| 69404 | ** |
| 69405 | ** See also: allocateCursor(). |
| 69406 | */ |
| 69407 | nMem += nCursor; |
| 69408 | |
| 69409 | /* zCsr will initially point to nFree bytes of unused space at the |
| 69410 | ** end of the opcode array, p->aOp. The computation of nFree is |
| 69411 | ** conservative - it might be smaller than the true number of free |
| 69412 | ** bytes, but never larger. nFree must be a multiple of 8 - it is |
| 69413 | ** rounded down if is not. |
| 69414 | */ |
| 69415 | n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */ |
| 69416 | zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */ |
| 69417 | assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); |
| 69418 | nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */ |
| 69419 | assert( nFree>=0 ); |
| 69420 | if( nFree>0 ){ |
| 69421 | memset(zCsr, 0, nFree); |
| 69422 | assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) ); |
| 69423 | } |
| 69424 | |
| 69425 | resolveP2Values(p, &nArg); |
| 69426 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| 69427 | if( pParse->explain && nMem<10 ){ |
| 69428 | nMem = 10; |
| 69429 | } |
| 69430 | p->expired = 0; |
| 69431 | |
| 69432 | /* Memory for registers, parameters, cursor, etc, is allocated in two |
| 69433 | ** passes. On the first pass, we try to reuse unused space at the |
| 69434 | ** end of the opcode array. If we are unable to satisfy all memory |
| 69435 | ** requirements by reusing the opcode array tail, then the second |
| 69436 | ** pass will fill in the rest using a fresh allocation. |
| 69437 | ** |
| 69438 | ** This two-pass approach that reuses as much memory as possible from |
| 69439 | ** the leftover space at the end of the opcode array can significantly |
| 69440 | ** reduce the amount of memory held by a prepared statement. |
| 69441 | */ |
| 69442 | do { |
| 69443 | nByte = 0; |
| 69444 | p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte); |
| 69445 | p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte); |
| 69446 | p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte); |
| 69447 | p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), |
| 69448 | zCsr, &nFree, &nByte); |
| 69449 | p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte); |
| 69450 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 69451 | p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte); |
| 69452 | #endif |
| 69453 | if( nByte ){ |
| 69454 | p->pFree = sqlite3DbMallocZero(db, nByte); |
| 69455 | } |
| 69456 | zCsr = p->pFree; |
| 69457 | nFree = nByte; |
| 69458 | }while( nByte && !db->mallocFailed ); |
| 69459 | |
| 69460 | p->nCursor = nCursor; |
| 69461 | p->nOnceFlag = nOnce; |
| 69462 | if( p->aVar ){ |
| 69463 | p->nVar = (ynVar)nVar; |
| @@ -70066,11 +70282,11 @@ | |
| 70066 | ** Then the internal cache might have been left in an inconsistent |
| 70067 | ** state. We need to rollback the statement transaction, if there is |
| 70068 | ** one, or the complete transaction if there is no statement transaction. |
| 70069 | */ |
| 70070 | |
| 70071 | if( p->db->mallocFailed ){ |
| 70072 | p->rc = SQLITE_NOMEM; |
| 70073 | } |
| 70074 | if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); |
| 70075 | closeAllCursors(p); |
| 70076 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| @@ -70227,11 +70443,11 @@ | |
| 70227 | assert( db->nVdbeRead>=db->nVdbeWrite ); |
| 70228 | assert( db->nVdbeWrite>=0 ); |
| 70229 | } |
| 70230 | p->magic = VDBE_MAGIC_HALT; |
| 70231 | checkActiveVdbeCnt(db); |
| 70232 | if( p->db->mallocFailed ){ |
| 70233 | p->rc = SQLITE_NOMEM; |
| 70234 | } |
| 70235 | |
| 70236 | /* If the auto-commit flag is set to true, then any locks that were held |
| 70237 | ** by connection db have now been released. Call sqlite3ConnectionUnlocked() |
| @@ -70264,16 +70480,16 @@ | |
| 70264 | */ |
| 70265 | SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ |
| 70266 | sqlite3 *db = p->db; |
| 70267 | int rc = p->rc; |
| 70268 | if( p->zErrMsg ){ |
| 70269 | u8 mallocFailed = db->mallocFailed; |
| 70270 | sqlite3BeginBenignMalloc(); |
| 70271 | if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); |
| 70272 | sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); |
| 70273 | sqlite3EndBenignMalloc(); |
| 70274 | db->mallocFailed = mallocFailed; |
| 70275 | db->errCode = rc; |
| 70276 | }else{ |
| 70277 | sqlite3Error(db, rc); |
| 70278 | } |
| 70279 | return rc; |
| @@ -70558,13 +70774,20 @@ | |
| 70558 | ** a NULL row. |
| 70559 | ** |
| 70560 | ** If the cursor is already pointing to the correct row and that row has |
| 70561 | ** not been deleted out from under the cursor, then this routine is a no-op. |
| 70562 | */ |
| 70563 | SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ |
| 70564 | if( p->eCurType==CURTYPE_BTREE ){ |
| 70565 | if( p->deferredMoveto ){ |
| 70566 | return handleDeferredMoveto(p); |
| 70567 | } |
| 70568 | if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ |
| 70569 | return handleMovedCursor(p); |
| 70570 | } |
| @@ -72191,11 +72414,12 @@ | |
| 72191 | } |
| 72192 | SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ |
| 72193 | return sqlite3VdbeIntValue((Mem*)pVal); |
| 72194 | } |
| 72195 | SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){ |
| 72196 | return ((Mem*)pVal)->eSubtype; |
| 72197 | } |
| 72198 | SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ |
| 72199 | return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); |
| 72200 | } |
| 72201 | #ifndef SQLITE_OMIT_UTF16 |
| @@ -72372,12 +72596,14 @@ | |
| 72372 | SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ |
| 72373 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72374 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72375 | } |
| 72376 | SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ |
| 72377 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72378 | pCtx->pOut->eSubtype = eSubtype & 0xff; |
| 72379 | } |
| 72380 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text( |
| 72381 | sqlite3_context *pCtx, |
| 72382 | const char *z, |
| 72383 | int n, |
| @@ -72473,11 +72699,11 @@ | |
| 72473 | SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ |
| 72474 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72475 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72476 | pCtx->isError = SQLITE_NOMEM; |
| 72477 | pCtx->fErrorOrAux = 1; |
| 72478 | pCtx->pOut->db->mallocFailed = 1; |
| 72479 | } |
| 72480 | |
| 72481 | /* |
| 72482 | ** This function is called after a transaction has been committed. It |
| 72483 | ** invokes callbacks registered with sqlite3_wal_hook() as required. |
| @@ -73101,11 +73327,11 @@ | |
| 73101 | ret = xFunc(&p->aColName[N]); |
| 73102 | /* A malloc may have failed inside of the xFunc() call. If this |
| 73103 | ** is the case, clear the mallocFailed flag and return NULL. |
| 73104 | */ |
| 73105 | if( db->mallocFailed ){ |
| 73106 | db->mallocFailed = 0; |
| 73107 | ret = 0; |
| 73108 | } |
| 73109 | sqlite3_mutex_leave(db->mutex); |
| 73110 | } |
| 73111 | return ret; |
| @@ -73802,13 +74028,13 @@ | |
| 73802 | assert( idx>0 && idx<=p->nVar ); |
| 73803 | pVar = &p->aVar[idx-1]; |
| 73804 | if( pVar->flags & MEM_Null ){ |
| 73805 | sqlite3StrAccumAppend(&out, "NULL", 4); |
| 73806 | }else if( pVar->flags & MEM_Int ){ |
| 73807 | sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); |
| 73808 | }else if( pVar->flags & MEM_Real ){ |
| 73809 | sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r); |
| 73810 | }else if( pVar->flags & MEM_Str ){ |
| 73811 | int nOut; /* Number of bytes of the string text to include in output */ |
| 73812 | #ifndef SQLITE_OMIT_UTF16 |
| 73813 | u8 enc = ENC(db); |
| 73814 | Mem utf8; |
| @@ -73825,36 +74051,36 @@ | |
| 73825 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ |
| 73826 | nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 73827 | while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } |
| 73828 | } |
| 73829 | #endif |
| 73830 | sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z); |
| 73831 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73832 | if( nOut<pVar->n ){ |
| 73833 | sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); |
| 73834 | } |
| 73835 | #endif |
| 73836 | #ifndef SQLITE_OMIT_UTF16 |
| 73837 | if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); |
| 73838 | #endif |
| 73839 | }else if( pVar->flags & MEM_Zero ){ |
| 73840 | sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero); |
| 73841 | }else{ |
| 73842 | int nOut; /* Number of bytes of the blob to include in output */ |
| 73843 | assert( pVar->flags & MEM_Blob ); |
| 73844 | sqlite3StrAccumAppend(&out, "x'", 2); |
| 73845 | nOut = pVar->n; |
| 73846 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73847 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 73848 | #endif |
| 73849 | for(i=0; i<nOut; i++){ |
| 73850 | sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff); |
| 73851 | } |
| 73852 | sqlite3StrAccumAppend(&out, "'", 1); |
| 73853 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73854 | if( nOut<pVar->n ){ |
| 73855 | sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); |
| 73856 | } |
| 73857 | #endif |
| 73858 | } |
| 73859 | } |
| 73860 | } |
| @@ -74336,10 +74562,11 @@ | |
| 74336 | }else{ |
| 74337 | char zBuf[200]; |
| 74338 | sqlite3VdbeMemPrettyPrint(p, zBuf); |
| 74339 | printf(" %s", zBuf); |
| 74340 | } |
| 74341 | } |
| 74342 | static void registerTrace(int iReg, Mem *p){ |
| 74343 | printf("REG[%d] = ", iReg); |
| 74344 | memTracePrint(p); |
| 74345 | printf("\n"); |
| @@ -74506,10 +74733,13 @@ | |
| 74506 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 74507 | Op *pOp = aOp; /* Current operation */ |
| 74508 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 74509 | Op *pOrigOp; /* Value of pOp at the top of the loop */ |
| 74510 | #endif |
| 74511 | int rc = SQLITE_OK; /* Value to return */ |
| 74512 | sqlite3 *db = p->db; /* The database */ |
| 74513 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ |
| 74514 | u8 encoding = ENC(db); /* The database encoding */ |
| 74515 | int iCompare = 0; /* Result of last OP_Compare operation */ |
| @@ -74579,11 +74809,10 @@ | |
| 74579 | } |
| 74580 | sqlite3EndBenignMalloc(); |
| 74581 | #endif |
| 74582 | for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ |
| 74583 | assert( pOp>=aOp && pOp<&aOp[p->nOp]); |
| 74584 | if( db->mallocFailed ) goto no_mem; |
| 74585 | #ifdef VDBE_PROFILE |
| 74586 | start = sqlite3Hwtime(); |
| 74587 | #endif |
| 74588 | nVmStep++; |
| 74589 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| @@ -75577,11 +75806,11 @@ | |
| 75577 | assert( pOp->p4type==P4_FUNCDEF ); |
| 75578 | n = pOp->p5; |
| 75579 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 75580 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 75581 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 75582 | pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 75583 | if( pCtx==0 ) goto no_mem; |
| 75584 | pCtx->pOut = 0; |
| 75585 | pCtx->pFunc = pOp->p4.pFunc; |
| 75586 | pCtx->iOp = (int)(pOp - aOp); |
| 75587 | pCtx->pVdbe = p; |
| @@ -76021,15 +76250,18 @@ | |
| 76021 | ** of integers in P4. |
| 76022 | ** |
| 76023 | ** The permutation is only valid until the next OP_Compare that has |
| 76024 | ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should |
| 76025 | ** occur immediately prior to the OP_Compare. |
| 76026 | */ |
| 76027 | case OP_Permutation: { |
| 76028 | assert( pOp->p4type==P4_INTARRAY ); |
| 76029 | assert( pOp->p4.ai ); |
| 76030 | aPermute = pOp->p4.ai; |
| 76031 | break; |
| 76032 | } |
| 76033 | |
| 76034 | /* Opcode: Compare P1 P2 P3 P4 P5 |
| 76035 | ** Synopsis: r[P1@P3] <-> r[P2@P3] |
| @@ -76330,26 +76562,28 @@ | |
| 76330 | u64 offset64; /* 64-bit offset */ |
| 76331 | u32 avail; /* Number of bytes of available data */ |
| 76332 | u32 t; /* A type code from the record header */ |
| 76333 | Mem *pReg; /* PseudoTable input register */ |
| 76334 | |
| 76335 | p2 = pOp->p2; |
| 76336 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 76337 | pDest = &aMem[pOp->p3]; |
| 76338 | memAboutToChange(p, pDest); |
| 76339 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 76340 | pC = p->apCsr[pOp->p1]; |
| 76341 | assert( pC!=0 ); |
| 76342 | assert( p2<pC->nField ); |
| 76343 | aOffset = pC->aOffset; |
| 76344 | assert( pC->eCurType!=CURTYPE_VTAB ); |
| 76345 | assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); |
| 76346 | assert( pC->eCurType!=CURTYPE_SORTER ); |
| 76347 | pCrsr = pC->uc.pCursor; |
| 76348 | |
| 76349 | /* If the cursor cache is stale, bring it up-to-date */ |
| 76350 | rc = sqlite3VdbeCursorMoveto(pC); |
| 76351 | if( rc ) goto abort_due_to_error; |
| 76352 | if( pC->cacheStatus!=p->cacheCtr ){ |
| 76353 | if( pC->nullRow ){ |
| 76354 | if( pC->eCurType==CURTYPE_PSEUDO ){ |
| 76355 | assert( pC->uc.pseudoTableReg>0 ); |
| @@ -76816,11 +77050,11 @@ | |
| 76816 | db->nStatement+db->nSavepoint); |
| 76817 | if( rc!=SQLITE_OK ) goto abort_due_to_error; |
| 76818 | #endif |
| 76819 | |
| 76820 | /* Create a new savepoint structure. */ |
| 76821 | pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); |
| 76822 | if( pNew ){ |
| 76823 | pNew->zName = (char *)&pNew[1]; |
| 76824 | memcpy(pNew->zName, zName, nName+1); |
| 76825 | |
| 76826 | /* If there is no open transaction, then mark this as a special |
| @@ -76953,32 +77187,31 @@ | |
| 76953 | ** This instruction causes the VM to halt. |
| 76954 | */ |
| 76955 | case OP_AutoCommit: { |
| 76956 | int desiredAutoCommit; |
| 76957 | int iRollback; |
| 76958 | int turnOnAC; |
| 76959 | |
| 76960 | desiredAutoCommit = pOp->p1; |
| 76961 | iRollback = pOp->p2; |
| 76962 | turnOnAC = desiredAutoCommit && !db->autoCommit; |
| 76963 | assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); |
| 76964 | assert( desiredAutoCommit==1 || iRollback==0 ); |
| 76965 | assert( db->nVdbeActive>0 ); /* At least this one VM is active */ |
| 76966 | assert( p->bIsReader ); |
| 76967 | |
| 76968 | if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ |
| 76969 | /* If this instruction implements a COMMIT and other VMs are writing |
| 76970 | ** return an error indicating that the other VMs must complete first. |
| 76971 | */ |
| 76972 | sqlite3VdbeError(p, "cannot commit transaction - " |
| 76973 | "SQL statements in progress"); |
| 76974 | rc = SQLITE_BUSY; |
| 76975 | }else if( desiredAutoCommit!=db->autoCommit ){ |
| 76976 | if( iRollback ){ |
| 76977 | assert( desiredAutoCommit==1 ); |
| 76978 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 76979 | db->autoCommit = 1; |
| 76980 | }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ |
| 76981 | goto vdbe_return; |
| 76982 | }else{ |
| 76983 | db->autoCommit = (u8)desiredAutoCommit; |
| 76984 | } |
| @@ -77159,38 +77392,36 @@ | |
| 77159 | break; |
| 77160 | } |
| 77161 | |
| 77162 | /* Opcode: SetCookie P1 P2 P3 * * |
| 77163 | ** |
| 77164 | ** Write the content of register P3 (interpreted as an integer) |
| 77165 | ** into cookie number P2 of database P1. P2==1 is the schema version. |
| 77166 | ** P2==2 is the database format. P2==3 is the recommended pager cache |
| 77167 | ** size, and so forth. P1==0 is the main database file and P1==1 is the |
| 77168 | ** database file used to store temporary tables. |
| 77169 | ** |
| 77170 | ** A transaction must be started before executing this opcode. |
| 77171 | */ |
| 77172 | case OP_SetCookie: { /* in3 */ |
| 77173 | Db *pDb; |
| 77174 | assert( pOp->p2<SQLITE_N_BTREE_META ); |
| 77175 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 77176 | assert( DbMaskTest(p->btreeMask, pOp->p1) ); |
| 77177 | assert( p->readOnly==0 ); |
| 77178 | pDb = &db->aDb[pOp->p1]; |
| 77179 | assert( pDb->pBt!=0 ); |
| 77180 | assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); |
| 77181 | pIn3 = &aMem[pOp->p3]; |
| 77182 | sqlite3VdbeMemIntegerify(pIn3); |
| 77183 | /* See note about index shifting on OP_ReadCookie */ |
| 77184 | rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); |
| 77185 | if( pOp->p2==BTREE_SCHEMA_VERSION ){ |
| 77186 | /* When the schema cookie changes, record the new cookie internally */ |
| 77187 | pDb->pSchema->schema_cookie = (int)pIn3->u.i; |
| 77188 | db->flags |= SQLITE_InternChanges; |
| 77189 | }else if( pOp->p2==BTREE_FILE_FORMAT ){ |
| 77190 | /* Record changes in the file format */ |
| 77191 | pDb->pSchema->file_format = (u8)pIn3->u.i; |
| 77192 | } |
| 77193 | if( pOp->p1==1 ){ |
| 77194 | /* Invalidate all prepared statements whenever the TEMP database |
| 77195 | ** schema is changed. Ticket #1644 */ |
| 77196 | sqlite3ExpirePreparedStatements(db); |
| @@ -77346,10 +77577,13 @@ | |
| 77346 | pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); |
| 77347 | if( pCur==0 ) goto no_mem; |
| 77348 | pCur->nullRow = 1; |
| 77349 | pCur->isOrdered = 1; |
| 77350 | pCur->pgnoRoot = p2; |
| 77351 | rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); |
| 77352 | pCur->pKeyInfo = pKeyInfo; |
| 77353 | /* Set the VdbeCursor.isTable variable. Previous versions of |
| 77354 | ** SQLite used to check if the root-page flags were sane at this point |
| 77355 | ** and report database corruption if they were not, but this check has |
| @@ -77799,36 +78033,10 @@ | |
| 77799 | assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); |
| 77800 | pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ |
| 77801 | } |
| 77802 | break; |
| 77803 | } |
| 77804 | |
| 77805 | /* Opcode: Seek P1 P2 * * * |
| 77806 | ** Synopsis: intkey=r[P2] |
| 77807 | ** |
| 77808 | ** P1 is an open table cursor and P2 is a rowid integer. Arrange |
| 77809 | ** for P1 to move so that it points to the rowid given by P2. |
| 77810 | ** |
| 77811 | ** This is actually a deferred seek. Nothing actually happens until |
| 77812 | ** the cursor is used to read a record. That way, if no reads |
| 77813 | ** occur, no unnecessary I/O happens. |
| 77814 | */ |
| 77815 | case OP_Seek: { /* in2 */ |
| 77816 | VdbeCursor *pC; |
| 77817 | |
| 77818 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 77819 | pC = p->apCsr[pOp->p1]; |
| 77820 | assert( pC!=0 ); |
| 77821 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 77822 | assert( pC->uc.pCursor!=0 ); |
| 77823 | assert( pC->isTable ); |
| 77824 | pC->nullRow = 0; |
| 77825 | pIn2 = &aMem[pOp->p2]; |
| 77826 | pC->movetoTarget = sqlite3VdbeIntValue(pIn2); |
| 77827 | pC->deferredMoveto = 1; |
| 77828 | break; |
| 77829 | } |
| 77830 | |
| 77831 | |
| 77832 | /* Opcode: Found P1 P2 P3 P4 * |
| 77833 | ** Synopsis: key=r[P3@P4] |
| 77834 | ** |
| @@ -78295,18 +78503,26 @@ | |
| 78295 | |
| 78296 | /* Opcode: Delete P1 P2 * P4 P5 |
| 78297 | ** |
| 78298 | ** Delete the record at which the P1 cursor is currently pointing. |
| 78299 | ** |
| 78300 | ** If the P5 parameter is non-zero, the cursor will be left pointing at |
| 78301 | ** either the next or the previous record in the table. If it is left |
| 78302 | ** pointing at the next record, then the next Next instruction will be a |
| 78303 | ** no-op. As a result, in this case it is OK to delete a record from within a |
| 78304 | ** Next loop. If P5 is zero, then the cursor is left in an undefined state. |
| 78305 | ** |
| 78306 | ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is |
| 78307 | ** incremented (otherwise not). |
| 78308 | ** |
| 78309 | ** P1 must not be pseudo-table. It has to be a real table with |
| 78310 | ** multiple rows. |
| 78311 | ** |
| 78312 | ** If P4 is not NULL, then it is the name of the table that P1 is |
| @@ -78338,11 +78554,30 @@ | |
| 78338 | i64 iKey = 0; |
| 78339 | sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); |
| 78340 | assert( pC->movetoTarget==iKey ); |
| 78341 | } |
| 78342 | #endif |
| 78343 | |
| 78344 | rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); |
| 78345 | pC->cacheStatus = CACHE_STALE; |
| 78346 | |
| 78347 | /* Invoke the update-hook if required. */ |
| 78348 | if( rc==SQLITE_OK && hasUpdateCallback ){ |
| @@ -78883,62 +79118,98 @@ | |
| 78883 | assert( pOp->p5==0 ); |
| 78884 | r.pKeyInfo = pC->pKeyInfo; |
| 78885 | r.nField = (u16)pOp->p3; |
| 78886 | r.default_rc = 0; |
| 78887 | r.aMem = &aMem[pOp->p2]; |
| 78888 | #ifdef SQLITE_DEBUG |
| 78889 | { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } |
| 78890 | #endif |
| 78891 | rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); |
| 78892 | if( rc==SQLITE_OK && res==0 ){ |
| 78893 | rc = sqlite3BtreeDelete(pCrsr, 0); |
| 78894 | } |
| 78895 | assert( pC->deferredMoveto==0 ); |
| 78896 | pC->cacheStatus = CACHE_STALE; |
| 78897 | break; |
| 78898 | } |
| 78899 | |
| 78900 | /* Opcode: IdxRowid P1 P2 * * * |
| 78901 | ** Synopsis: r[P2]=rowid |
| 78902 | ** |
| 78903 | ** Write into register P2 an integer which is the last entry in the record at |
| 78904 | ** the end of the index key pointed to by cursor P1. This integer should be |
| 78905 | ** the rowid of the table entry to which this index entry points. |
| 78906 | ** |
| 78907 | ** See also: Rowid, MakeRecord. |
| 78908 | */ |
| 78909 | case OP_IdxRowid: { /* out2 */ |
| 78910 | BtCursor *pCrsr; |
| 78911 | VdbeCursor *pC; |
| 78912 | i64 rowid; |
| 78913 | |
| 78914 | pOut = out2Prerelease(p, pOp); |
| 78915 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 78916 | pC = p->apCsr[pOp->p1]; |
| 78917 | assert( pC!=0 ); |
| 78918 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 78919 | pCrsr = pC->uc.pCursor; |
| 78920 | assert( pCrsr!=0 ); |
| 78921 | pOut->flags = MEM_Null; |
| 78922 | assert( pC->isTable==0 ); |
| 78923 | assert( pC->deferredMoveto==0 ); |
| 78924 | |
| 78925 | /* sqlite3VbeCursorRestore() can only fail if the record has been deleted |
| 78926 | ** out from under the cursor. That will never happend for an IdxRowid |
| 78927 | ** opcode, hence the NEVER() arround the check of the return value. |
| 78928 | */ |
| 78929 | rc = sqlite3VdbeCursorRestore(pC); |
| 78930 | if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; |
| 78931 | |
| 78932 | if( !pC->nullRow ){ |
| 78933 | rowid = 0; /* Not needed. Only used to silence a warning. */ |
| 78934 | rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); |
| 78935 | if( rc!=SQLITE_OK ){ |
| 78936 | goto abort_due_to_error; |
| 78937 | } |
| 78938 | pOut->u.i = rowid; |
| 78939 | pOut->flags = MEM_Int; |
| 78940 | } |
| 78941 | break; |
| 78942 | } |
| 78943 | |
| 78944 | /* Opcode: IdxGE P1 P2 P3 P4 P5 |
| @@ -79329,11 +79600,11 @@ | |
| 79329 | Mem *pnErr; /* Register keeping track of errors remaining */ |
| 79330 | |
| 79331 | assert( p->bIsReader ); |
| 79332 | nRoot = pOp->p2; |
| 79333 | assert( nRoot>0 ); |
| 79334 | aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); |
| 79335 | if( aRoot==0 ) goto no_mem; |
| 79336 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 79337 | pnErr = &aMem[pOp->p3]; |
| 79338 | assert( (pnErr->flags & MEM_Int)!=0 ); |
| 79339 | assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); |
| @@ -79711,24 +79982,35 @@ | |
| 79711 | goto jump_to_p2; |
| 79712 | } |
| 79713 | break; |
| 79714 | } |
| 79715 | |
| 79716 | /* Opcode: SetIfNotPos P1 P2 P3 * * |
| 79717 | ** Synopsis: if r[P1]<=0 then r[P2]=P3 |
| 79718 | ** |
| 79719 | ** Register P1 must contain an integer. |
| 79720 | ** If the value of register P1 is not positive (if it is less than 1) then |
| 79721 | ** set the value of register P2 to be the integer P3. |
| 79722 | */ |
| 79723 | case OP_SetIfNotPos: { /* in1, in2 */ |
| 79724 | pIn1 = &aMem[pOp->p1]; |
| 79725 | assert( pIn1->flags&MEM_Int ); |
| 79726 | if( pIn1->u.i<=0 ){ |
| 79727 | pOut = out2Prerelease(p, pOp); |
| 79728 | pOut->u.i = pOp->p3; |
| 79729 | } |
| 79730 | break; |
| 79731 | } |
| 79732 | |
| 79733 | /* Opcode: IfNotZero P1 P2 P3 * * |
| 79734 | ** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 |
| @@ -79815,11 +80097,11 @@ | |
| 79815 | assert( pOp->p4type==P4_FUNCDEF ); |
| 79816 | n = pOp->p5; |
| 79817 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 79818 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 79819 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 79820 | pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 79821 | if( pCtx==0 ) goto no_mem; |
| 79822 | pCtx->pMem = 0; |
| 79823 | pCtx->pFunc = pOp->p4.pFunc; |
| 79824 | pCtx->iOp = (int)(pOp - aOp); |
| 79825 | pCtx->pVdbe = p; |
| @@ -80682,11 +80964,11 @@ | |
| 80682 | p->rc = rc; |
| 80683 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 80684 | sqlite3_log(rc, "statement aborts at %d: [%s] %s", |
| 80685 | (int)(pOp - aOp), p->zSql, p->zErrMsg); |
| 80686 | sqlite3VdbeHalt(p); |
| 80687 | if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; |
| 80688 | rc = SQLITE_ERROR; |
| 80689 | if( resetSchemaOnFault>0 ){ |
| 80690 | sqlite3ResetOneSchema(db, resetSchemaOnFault-1); |
| 80691 | } |
| 80692 | |
| @@ -80696,10 +80978,13 @@ | |
| 80696 | vdbe_return: |
| 80697 | db->lastRowid = lastRowid; |
| 80698 | testcase( nVmStep>0 ); |
| 80699 | p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; |
| 80700 | sqlite3VdbeLeave(p); |
| 80701 | return rc; |
| 80702 | |
| 80703 | /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH |
| 80704 | ** is encountered. |
| 80705 | */ |
| @@ -80709,11 +80994,11 @@ | |
| 80709 | goto vdbe_error_halt; |
| 80710 | |
| 80711 | /* Jump to here if a malloc() fails. |
| 80712 | */ |
| 80713 | no_mem: |
| 80714 | db->mallocFailed = 1; |
| 80715 | sqlite3VdbeError(p, "out of memory"); |
| 80716 | rc = SQLITE_NOMEM; |
| 80717 | goto vdbe_error_halt; |
| 80718 | |
| 80719 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| @@ -80730,11 +81015,11 @@ | |
| 80730 | /* Jump to here if the sqlite3_interrupt() API sets the interrupt |
| 80731 | ** flag. |
| 80732 | */ |
| 80733 | abort_due_to_interrupt: |
| 80734 | assert( db->u1.isInterrupted ); |
| 80735 | rc = SQLITE_INTERRUPT; |
| 80736 | p->rc = rc; |
| 80737 | sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); |
| 80738 | goto vdbe_error_halt; |
| 80739 | } |
| 80740 | |
| @@ -80990,23 +81275,21 @@ | |
| 80990 | ** |
| 80991 | ** The sqlite3_blob_close() function finalizes the vdbe program, |
| 80992 | ** which closes the b-tree cursor and (possibly) commits the |
| 80993 | ** transaction. |
| 80994 | */ |
| 80995 | static const int iLn = VDBE_OFFSET_LINENO(4); |
| 80996 | static const VdbeOpList openBlob[] = { |
| 80997 | /* addr/ofst */ |
| 80998 | /* {OP_Transaction, 0, 0, 0}, // 0/ inserted separately */ |
| 80999 | {OP_TableLock, 0, 0, 0}, /* 1/0: Acquire a read or write lock */ |
| 81000 | {OP_OpenRead, 0, 0, 0}, /* 2/1: Open a cursor */ |
| 81001 | {OP_Variable, 1, 1, 0}, /* 3/2: Move ?1 into reg[1] */ |
| 81002 | {OP_NotExists, 0, 8, 1}, /* 4/3: Seek the cursor */ |
| 81003 | {OP_Column, 0, 0, 1}, /* 5/4 */ |
| 81004 | {OP_ResultRow, 1, 0, 0}, /* 6/5 */ |
| 81005 | {OP_Goto, 0, 3, 0}, /* 7/6 */ |
| 81006 | {OP_Close, 0, 0, 0}, /* 8/7 */ |
| 81007 | {OP_Halt, 0, 0, 0}, /* 9/8 */ |
| 81008 | }; |
| 81009 | Vdbe *v = (Vdbe *)pBlob->pStmt; |
| 81010 | int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 81011 | VdbeOp *aOp; |
| 81012 | |
| @@ -83044,27 +83327,28 @@ | |
| 83044 | if( pSorter->list.aMemory ){ |
| 83045 | int nMin = pSorter->iMemory + nReq; |
| 83046 | |
| 83047 | if( nMin>pSorter->nMemory ){ |
| 83048 | u8 *aNew; |
| 83049 | int nNew = pSorter->nMemory * 2; |
| 83050 | while( nNew < nMin ) nNew = nNew*2; |
| 83051 | if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; |
| 83052 | if( nNew < nMin ) nNew = nMin; |
| 83053 | |
| 83054 | aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); |
| 83055 | if( !aNew ) return SQLITE_NOMEM; |
| 83056 | pSorter->list.pList = (SorterRecord*)( |
| 83057 | aNew + ((u8*)pSorter->list.pList - pSorter->list.aMemory) |
| 83058 | ); |
| 83059 | pSorter->list.aMemory = aNew; |
| 83060 | pSorter->nMemory = nNew; |
| 83061 | } |
| 83062 | |
| 83063 | pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; |
| 83064 | pSorter->iMemory += ROUND8(nReq); |
| 83065 | pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); |
| 83066 | }else{ |
| 83067 | pNew = (SorterRecord *)sqlite3Malloc(nReq); |
| 83068 | if( pNew==0 ){ |
| 83069 | return SQLITE_NOMEM; |
| 83070 | } |
| @@ -86230,12 +86514,11 @@ | |
| 86230 | return pExpr; |
| 86231 | } |
| 86232 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
| 86233 | Token s; |
| 86234 | assert( zC!=0 ); |
| 86235 | s.z = zC; |
| 86236 | s.n = sqlite3Strlen30(s.z); |
| 86237 | return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); |
| 86238 | } |
| 86239 | |
| 86240 | /* |
| 86241 | ** Skip over any TK_COLLATE operators and any unlikely() |
| @@ -86599,18 +86882,19 @@ | |
| 86599 | ){ |
| 86600 | Expr *pNew; |
| 86601 | int nExtra = 0; |
| 86602 | int iValue = 0; |
| 86603 | |
| 86604 | if( pToken ){ |
| 86605 | if( op!=TK_INTEGER || pToken->z==0 |
| 86606 | || sqlite3GetInt32(pToken->z, &iValue)==0 ){ |
| 86607 | nExtra = pToken->n+1; |
| 86608 | assert( iValue>=0 ); |
| 86609 | } |
| 86610 | } |
| 86611 | pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra); |
| 86612 | if( pNew ){ |
| 86613 | memset(pNew, 0, sizeof(Expr)); |
| 86614 | pNew->op = (u8)op; |
| 86615 | pNew->iAgg = -1; |
| 86616 | if( pToken ){ |
| @@ -86845,11 +87129,14 @@ | |
| 86845 | } |
| 86846 | if( x>0 ){ |
| 86847 | if( x>pParse->nzVar ){ |
| 86848 | char **a; |
| 86849 | a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); |
| 86850 | if( a==0 ) return; /* Error reported through db->mallocFailed */ |
| 86851 | pParse->azVar = a; |
| 86852 | memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); |
| 86853 | pParse->nzVar = x; |
| 86854 | } |
| 86855 | if( z[0]!='?' || pParse->azVar[x-1]==0 ){ |
| @@ -87000,10 +87287,11 @@ | |
| 87000 | ** portion of the buffer copied into by this function. |
| 87001 | */ |
| 87002 | static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ |
| 87003 | Expr *pNew = 0; /* Value to return */ |
| 87004 | assert( flags==0 || flags==EXPRDUP_REDUCE ); |
| 87005 | if( p ){ |
| 87006 | const int isReduced = (flags&EXPRDUP_REDUCE); |
| 87007 | u8 *zAlloc; |
| 87008 | u32 staticFlag = 0; |
| 87009 | |
| @@ -87012,11 +87300,11 @@ | |
| 87012 | /* Figure out where to write the new Expr structure. */ |
| 87013 | if( pzBuffer ){ |
| 87014 | zAlloc = *pzBuffer; |
| 87015 | staticFlag = EP_Static; |
| 87016 | }else{ |
| 87017 | zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); |
| 87018 | } |
| 87019 | pNew = (Expr *)zAlloc; |
| 87020 | |
| 87021 | if( pNew ){ |
| 87022 | /* Set nNewSize to the size allocated for the structure pointed to |
| @@ -87135,16 +87423,17 @@ | |
| 87135 | } |
| 87136 | SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ |
| 87137 | ExprList *pNew; |
| 87138 | struct ExprList_item *pItem, *pOldItem; |
| 87139 | int i; |
| 87140 | if( p==0 ) return 0; |
| 87141 | pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); |
| 87142 | if( pNew==0 ) return 0; |
| 87143 | pNew->nExpr = i = p->nExpr; |
| 87144 | if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){} |
| 87145 | pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) ); |
| 87146 | if( pItem==0 ){ |
| 87147 | sqlite3DbFree(db, pNew); |
| 87148 | return 0; |
| 87149 | } |
| 87150 | pOldItem = p->a; |
| @@ -87171,13 +87460,14 @@ | |
| 87171 | || !defined(SQLITE_OMIT_SUBQUERY) |
| 87172 | SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ |
| 87173 | SrcList *pNew; |
| 87174 | int i; |
| 87175 | int nByte; |
| 87176 | if( p==0 ) return 0; |
| 87177 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); |
| 87178 | pNew = sqlite3DbMallocRaw(db, nByte ); |
| 87179 | if( pNew==0 ) return 0; |
| 87180 | pNew->nSrc = pNew->nAlloc = p->nSrc; |
| 87181 | for(i=0; i<p->nSrc; i++){ |
| 87182 | struct SrcList_item *pNewItem = &pNew->a[i]; |
| 87183 | struct SrcList_item *pOldItem = &p->a[i]; |
| @@ -87210,15 +87500,16 @@ | |
| 87210 | return pNew; |
| 87211 | } |
| 87212 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ |
| 87213 | IdList *pNew; |
| 87214 | int i; |
| 87215 | if( p==0 ) return 0; |
| 87216 | pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); |
| 87217 | if( pNew==0 ) return 0; |
| 87218 | pNew->nId = p->nId; |
| 87219 | pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); |
| 87220 | if( pNew->a==0 ){ |
| 87221 | sqlite3DbFree(db, pNew); |
| 87222 | return 0; |
| 87223 | } |
| 87224 | /* Note that because the size of the allocation for p->a[] is not |
| @@ -87232,12 +87523,13 @@ | |
| 87232 | } |
| 87233 | return pNew; |
| 87234 | } |
| 87235 | SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ |
| 87236 | Select *pNew, *pPrior; |
| 87237 | if( p==0 ) return 0; |
| 87238 | pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); |
| 87239 | if( pNew==0 ) return 0; |
| 87240 | pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); |
| 87241 | pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); |
| 87242 | pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); |
| 87243 | pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); |
| @@ -87279,17 +87571,18 @@ | |
| 87279 | Parse *pParse, /* Parsing context */ |
| 87280 | ExprList *pList, /* List to which to append. Might be NULL */ |
| 87281 | Expr *pExpr /* Expression to be appended. Might be NULL */ |
| 87282 | ){ |
| 87283 | sqlite3 *db = pParse->db; |
| 87284 | if( pList==0 ){ |
| 87285 | pList = sqlite3DbMallocRaw(db, sizeof(ExprList) ); |
| 87286 | if( pList==0 ){ |
| 87287 | goto no_mem; |
| 87288 | } |
| 87289 | pList->nExpr = 0; |
| 87290 | pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0])); |
| 87291 | if( pList->a==0 ) goto no_mem; |
| 87292 | }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ |
| 87293 | struct ExprList_item *a; |
| 87294 | assert( pList->nExpr>0 ); |
| 87295 | a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0])); |
| @@ -91009,11 +91302,11 @@ | |
| 91009 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); |
| 91010 | sqlite3VdbeUsesBtree(v, iDb); |
| 91011 | sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); |
| 91012 | addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); |
| 91013 | sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); |
| 91014 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); |
| 91015 | sqlite3VdbeJumpHere(v, addr1); |
| 91016 | sqlite3ReleaseTempReg(pParse, r1); |
| 91017 | sqlite3ReleaseTempReg(pParse, r2); |
| 91018 | } |
| 91019 | } |
| @@ -91096,11 +91389,11 @@ | |
| 91096 | sqlite3_value *pVal = 0; |
| 91097 | int rc; |
| 91098 | rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); |
| 91099 | assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); |
| 91100 | if( rc!=SQLITE_OK ){ |
| 91101 | db->mallocFailed = 1; |
| 91102 | return; |
| 91103 | } |
| 91104 | if( !pVal ){ |
| 91105 | sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); |
| 91106 | return; |
| @@ -91204,11 +91497,11 @@ | |
| 91204 | nAlloc = (((pNew->nCol-1)/8)*8)+8; |
| 91205 | assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); |
| 91206 | pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); |
| 91207 | pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); |
| 91208 | if( !pNew->aCol || !pNew->zName ){ |
| 91209 | db->mallocFailed = 1; |
| 91210 | goto exit_begin_add_column; |
| 91211 | } |
| 91212 | memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); |
| 91213 | for(i=0; i<pNew->nCol; i++){ |
| 91214 | Column *pCol = &pNew->aCol[i]; |
| @@ -91549,11 +91842,11 @@ | |
| 91549 | */ |
| 91550 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 91551 | static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ |
| 91552 | assert( db!=0 ); |
| 91553 | if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); |
| 91554 | p->u.aRowid = sqlite3DbMallocRaw(db, n); |
| 91555 | if( p->u.aRowid ){ |
| 91556 | p->nRowid = n; |
| 91557 | memcpy(p->u.aRowid, pData, n); |
| 91558 | }else{ |
| 91559 | p->nRowid = 0; |
| @@ -92351,11 +92644,11 @@ | |
| 92351 | addrNextRow = sqlite3VdbeCurrentAddr(v); |
| 92352 | |
| 92353 | if( nColTest>0 ){ |
| 92354 | int endDistinctTest = sqlite3VdbeMakeLabel(v); |
| 92355 | int *aGotoChng; /* Array of jump instruction addresses */ |
| 92356 | aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest); |
| 92357 | if( aGotoChng==0 ) continue; |
| 92358 | |
| 92359 | /* |
| 92360 | ** next_row: |
| 92361 | ** regChng = 0 |
| @@ -92759,11 +93052,11 @@ | |
| 92759 | /* Index.aiRowEst may already be set here if there are duplicate |
| 92760 | ** sqlite_stat1 entries for this index. In that case just clobber |
| 92761 | ** the old data with the new instead of allocating a new array. */ |
| 92762 | if( pIndex->aiRowEst==0 ){ |
| 92763 | pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); |
| 92764 | if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; |
| 92765 | } |
| 92766 | aiRowEst = pIndex->aiRowEst; |
| 92767 | #endif |
| 92768 | pIndex->bUnordered = 0; |
| 92769 | decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); |
| @@ -92906,11 +93199,11 @@ | |
| 92906 | sqlite3_stmt *pStmt = 0; /* An SQL statement being run */ |
| 92907 | char *zSql; /* Text of the SQL statement */ |
| 92908 | Index *pPrevIdx = 0; /* Previous index in the loop */ |
| 92909 | IndexSample *pSample; /* A slot in pIdx->aSample[] */ |
| 92910 | |
| 92911 | assert( db->lookaside.bEnabled==0 ); |
| 92912 | zSql = sqlite3MPrintf(db, zSql1, zDb); |
| 92913 | if( !zSql ){ |
| 92914 | return SQLITE_NOMEM; |
| 92915 | } |
| 92916 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| @@ -93020,11 +93313,11 @@ | |
| 93020 | ** the Index.aSample[] arrays of all indices. |
| 93021 | */ |
| 93022 | static int loadStat4(sqlite3 *db, const char *zDb){ |
| 93023 | int rc = SQLITE_OK; /* Result codes from subroutines */ |
| 93024 | |
| 93025 | assert( db->lookaside.bEnabled==0 ); |
| 93026 | if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ |
| 93027 | rc = loadStatTbl(db, 0, |
| 93028 | "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", |
| 93029 | "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", |
| 93030 | zDb |
| @@ -93102,24 +93395,23 @@ | |
| 93102 | |
| 93103 | |
| 93104 | /* Load the statistics from the sqlite_stat4 table. */ |
| 93105 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 93106 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 93107 | int lookasideEnabled = db->lookaside.bEnabled; |
| 93108 | db->lookaside.bEnabled = 0; |
| 93109 | rc = loadStat4(db, sInfo.zDatabase); |
| 93110 | db->lookaside.bEnabled = lookasideEnabled; |
| 93111 | } |
| 93112 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 93113 | Index *pIdx = sqliteHashData(i); |
| 93114 | sqlite3_free(pIdx->aiRowEst); |
| 93115 | pIdx->aiRowEst = 0; |
| 93116 | } |
| 93117 | #endif |
| 93118 | |
| 93119 | if( rc==SQLITE_NOMEM ){ |
| 93120 | db->mallocFailed = 1; |
| 93121 | } |
| 93122 | return rc; |
| 93123 | } |
| 93124 | |
| 93125 | |
| @@ -93236,11 +93528,11 @@ | |
| 93236 | |
| 93237 | /* Allocate the new entry in the db->aDb[] array and initialize the schema |
| 93238 | ** hash tables. |
| 93239 | */ |
| 93240 | if( db->aDb==db->aDbStatic ){ |
| 93241 | aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); |
| 93242 | if( aNew==0 ) return; |
| 93243 | memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); |
| 93244 | }else{ |
| 93245 | aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); |
| 93246 | if( aNew==0 ) return; |
| @@ -93254,11 +93546,11 @@ | |
| 93254 | ** or may not be initialized. |
| 93255 | */ |
| 93256 | flags = db->openFlags; |
| 93257 | rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); |
| 93258 | if( rc!=SQLITE_OK ){ |
| 93259 | if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 93260 | sqlite3_result_error(context, zErr, -1); |
| 93261 | sqlite3_free(zErr); |
| 93262 | return; |
| 93263 | } |
| 93264 | assert( pVfs ); |
| @@ -93283,11 +93575,12 @@ | |
| 93283 | pPager = sqlite3BtreePager(aNew->pBt); |
| 93284 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 93285 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 93286 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 93287 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 93288 | sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 93289 | #endif |
| 93290 | sqlite3BtreeLeave(aNew->pBt); |
| 93291 | } |
| 93292 | aNew->safety_level = 3; |
| 93293 | aNew->zName = sqlite3DbStrDup(db, zName); |
| @@ -93356,11 +93649,11 @@ | |
| 93356 | db->aDb[iDb].pSchema = 0; |
| 93357 | } |
| 93358 | sqlite3ResetAllSchemasOfConnection(db); |
| 93359 | db->nDb = iDb; |
| 93360 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 93361 | db->mallocFailed = 1; |
| 93362 | sqlite3DbFree(db, zErrDyn); |
| 93363 | zErrDyn = sqlite3MPrintf(db, "out of memory"); |
| 93364 | }else if( zErrDyn==0 ){ |
| 93365 | zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); |
| 93366 | } |
| @@ -94053,11 +94346,11 @@ | |
| 94053 | p->iTab = iTab; |
| 94054 | p->isWriteLock = isWriteLock; |
| 94055 | p->zName = zName; |
| 94056 | }else{ |
| 94057 | pToplevel->nTableLock = 0; |
| 94058 | pToplevel->db->mallocFailed = 1; |
| 94059 | } |
| 94060 | } |
| 94061 | |
| 94062 | /* |
| 94063 | ** Code an OP_TableLock instruction for each table locked by the |
| @@ -94901,11 +95194,11 @@ | |
| 94901 | } |
| 94902 | } |
| 94903 | |
| 94904 | pTable = sqlite3DbMallocZero(db, sizeof(Table)); |
| 94905 | if( pTable==0 ){ |
| 94906 | db->mallocFailed = 1; |
| 94907 | pParse->rc = SQLITE_NOMEM; |
| 94908 | pParse->nErr++; |
| 94909 | goto begin_table_error; |
| 94910 | } |
| 94911 | pTable->zName = zName; |
| @@ -94958,14 +95251,12 @@ | |
| 94958 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); |
| 94959 | sqlite3VdbeUsesBtree(v, iDb); |
| 94960 | addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); |
| 94961 | fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? |
| 94962 | 1 : SQLITE_MAX_FILE_FORMAT; |
| 94963 | sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); |
| 94964 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3); |
| 94965 | sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); |
| 94966 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3); |
| 94967 | sqlite3VdbeJumpHere(v, addr1); |
| 94968 | |
| 94969 | /* This just creates a place-holder record in the sqlite_master table. |
| 94970 | ** The record created does not contain anything yet. It will be replaced |
| 94971 | ** by the real entry in code generated at sqlite3EndTable(). |
| @@ -95446,17 +95737,15 @@ | |
| 95446 | ** set back to prior value. But schema changes are infrequent |
| 95447 | ** and the probability of hitting the same cookie value is only |
| 95448 | ** 1 chance in 2^32. So we're safe enough. |
| 95449 | */ |
| 95450 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ |
| 95451 | int r1 = sqlite3GetTempReg(pParse); |
| 95452 | sqlite3 *db = pParse->db; |
| 95453 | Vdbe *v = pParse->pVdbe; |
| 95454 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 95455 | sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); |
| 95456 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1); |
| 95457 | sqlite3ReleaseTempReg(pParse, r1); |
| 95458 | } |
| 95459 | |
| 95460 | /* |
| 95461 | ** Measure the number of characters needed to output the given |
| 95462 | ** identifier. The number returned includes any quotes used |
| @@ -95534,11 +95823,11 @@ | |
| 95534 | zEnd = "\n)"; |
| 95535 | } |
| 95536 | n += 35 + 6*p->nCol; |
| 95537 | zStmt = sqlite3DbMallocRaw(0, n); |
| 95538 | if( zStmt==0 ){ |
| 95539 | db->mallocFailed = 1; |
| 95540 | return 0; |
| 95541 | } |
| 95542 | sqlite3_snprintf(n, zStmt, "CREATE TABLE "); |
| 95543 | k = sqlite3Strlen30(zStmt); |
| 95544 | identPut(zStmt, &k, p->zName); |
| @@ -95683,12 +95972,11 @@ | |
| 95683 | ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. |
| 95684 | */ |
| 95685 | if( pTab->iPKey>=0 ){ |
| 95686 | ExprList *pList; |
| 95687 | Token ipkToken; |
| 95688 | ipkToken.z = pTab->aCol[pTab->iPKey].zName; |
| 95689 | ipkToken.n = sqlite3Strlen30(ipkToken.z); |
| 95690 | pList = sqlite3ExprListAppend(pParse, 0, |
| 95691 | sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); |
| 95692 | if( pList==0 ) return; |
| 95693 | pList->a[0].sortOrder = pParse->iPkSortOrder; |
| 95694 | assert( pParse->pNewTable==pTab ); |
| @@ -95934,11 +96222,11 @@ | |
| 95934 | pParse->nTab = 2; |
| 95935 | addrTop = sqlite3VdbeCurrentAddr(v) + 1; |
| 95936 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); |
| 95937 | sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); |
| 95938 | sqlite3Select(pParse, pSelect, &dest); |
| 95939 | sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); |
| 95940 | sqlite3VdbeJumpHere(v, addrTop - 1); |
| 95941 | if( pParse->nErr ) return; |
| 95942 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); |
| 95943 | if( pSelTab==0 ) return; |
| 95944 | assert( p->aCol==0 ); |
| @@ -96018,11 +96306,11 @@ | |
| 96018 | Schema *pSchema = p->pSchema; |
| 96019 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 96020 | pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); |
| 96021 | if( pOld ){ |
| 96022 | assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 96023 | db->mallocFailed = 1; |
| 96024 | return; |
| 96025 | } |
| 96026 | pParse->pNewTable = 0; |
| 96027 | db->flags |= SQLITE_InternChanges; |
| 96028 | |
| @@ -96122,11 +96410,10 @@ | |
| 96122 | Select *pSel; /* Copy of the SELECT that implements the view */ |
| 96123 | int nErr = 0; /* Number of errors encountered */ |
| 96124 | int n; /* Temporarily holds the number of cursors assigned */ |
| 96125 | sqlite3 *db = pParse->db; /* Database connection for malloc errors */ |
| 96126 | sqlite3_xauth xAuth; /* Saved xAuth pointer */ |
| 96127 | u8 bEnabledLA; /* Saved db->lookaside.bEnabled state */ |
| 96128 | |
| 96129 | assert( pTable ); |
| 96130 | |
| 96131 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 96132 | if( sqlite3VtabCallConnect(pParse, pTable) ){ |
| @@ -96168,30 +96455,31 @@ | |
| 96168 | ** to the elements of the FROM clause. But we do not want these changes |
| 96169 | ** to be permanent. So the computation is done on a copy of the SELECT |
| 96170 | ** statement that defines the view. |
| 96171 | */ |
| 96172 | assert( pTable->pSelect ); |
| 96173 | bEnabledLA = db->lookaside.bEnabled; |
| 96174 | if( pTable->pCheck ){ |
| 96175 | db->lookaside.bEnabled = 0; |
| 96176 | sqlite3ColumnsFromExprList(pParse, pTable->pCheck, |
| 96177 | &pTable->nCol, &pTable->aCol); |
| 96178 | }else{ |
| 96179 | pSel = sqlite3SelectDup(db, pTable->pSelect, 0); |
| 96180 | if( pSel ){ |
| 96181 | n = pParse->nTab; |
| 96182 | sqlite3SrcListAssignCursors(pParse, pSel->pSrc); |
| 96183 | pTable->nCol = -1; |
| 96184 | db->lookaside.bEnabled = 0; |
| 96185 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 96186 | xAuth = db->xAuth; |
| 96187 | db->xAuth = 0; |
| 96188 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96189 | db->xAuth = xAuth; |
| 96190 | #else |
| 96191 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96192 | #endif |
| 96193 | pParse->nTab = n; |
| 96194 | if( pSelTab ){ |
| 96195 | assert( pTable->aCol==0 ); |
| 96196 | pTable->nCol = pSelTab->nCol; |
| 96197 | pTable->aCol = pSelTab->aCol; |
| @@ -96206,11 +96494,10 @@ | |
| 96206 | sqlite3SelectDelete(db, pSel); |
| 96207 | } else { |
| 96208 | nErr++; |
| 96209 | } |
| 96210 | } |
| 96211 | db->lookaside.bEnabled = bEnabledLA; |
| 96212 | pTable->pSchema->schemaFlags |= DB_UnresetViews; |
| 96213 | #endif /* SQLITE_OMIT_VIEW */ |
| 96214 | return nErr; |
| 96215 | } |
| 96216 | #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ |
| @@ -96672,11 +96959,11 @@ | |
| 96672 | assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); |
| 96673 | pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, |
| 96674 | pFKey->zTo, (void *)pFKey |
| 96675 | ); |
| 96676 | if( pNextTo==pFKey ){ |
| 96677 | db->mallocFailed = 1; |
| 96678 | goto fk_end; |
| 96679 | } |
| 96680 | if( pNextTo ){ |
| 96681 | assert( pNextTo->pPrevTo==0 ); |
| 96682 | pFKey->pNextTo = pNextTo; |
| @@ -97032,12 +97319,11 @@ | |
| 97032 | ** key out of the last column added to the table under construction. |
| 97033 | ** So create a fake list to simulate this. |
| 97034 | */ |
| 97035 | if( pList==0 ){ |
| 97036 | Token prevCol; |
| 97037 | prevCol.z = pTab->aCol[pTab->nCol-1].zName; |
| 97038 | prevCol.n = sqlite3Strlen30(prevCol.z); |
| 97039 | pList = sqlite3ExprListAppend(pParse, 0, |
| 97040 | sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); |
| 97041 | if( pList==0 ) goto exit_create_index; |
| 97042 | assert( pList->nExpr==1 ); |
| 97043 | sqlite3ExprListSetSortOrder(pList, sortOrder); |
| @@ -97255,11 +97541,11 @@ | |
| 97255 | assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); |
| 97256 | p = sqlite3HashInsert(&pIndex->pSchema->idxHash, |
| 97257 | pIndex->zName, pIndex); |
| 97258 | if( p ){ |
| 97259 | assert( p==pIndex ); /* Malloc must have failed */ |
| 97260 | db->mallocFailed = 1; |
| 97261 | goto exit_create_index; |
| 97262 | } |
| 97263 | db->flags |= SQLITE_InternChanges; |
| 97264 | if( pTblName!=0 ){ |
| 97265 | pIndex->tnum = db->init.newTnum; |
| @@ -97684,12 +97970,13 @@ | |
| 97684 | Token *pTable, /* Table to append */ |
| 97685 | Token *pDatabase /* Database of the table */ |
| 97686 | ){ |
| 97687 | struct SrcList_item *pItem; |
| 97688 | assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ |
| 97689 | if( pList==0 ){ |
| 97690 | pList = sqlite3DbMallocRaw(db, sizeof(SrcList) ); |
| 97691 | if( pList==0 ) return 0; |
| 97692 | pList->nAlloc = 1; |
| 97693 | pList->nSrc = 0; |
| 97694 | } |
| 97695 | pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); |
| @@ -97869,21 +98156,20 @@ | |
| 97869 | p->a[0].fg.jointype = 0; |
| 97870 | } |
| 97871 | } |
| 97872 | |
| 97873 | /* |
| 97874 | ** Begin a transaction |
| 97875 | */ |
| 97876 | SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ |
| 97877 | sqlite3 *db; |
| 97878 | Vdbe *v; |
| 97879 | int i; |
| 97880 | |
| 97881 | assert( pParse!=0 ); |
| 97882 | db = pParse->db; |
| 97883 | assert( db!=0 ); |
| 97884 | /* if( db->aDb[0].pBt==0 ) return; */ |
| 97885 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ |
| 97886 | return; |
| 97887 | } |
| 97888 | v = sqlite3GetVdbe(pParse); |
| 97889 | if( !v ) return; |
| @@ -97891,15 +98177,15 @@ | |
| 97891 | for(i=0; i<db->nDb; i++){ |
| 97892 | sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); |
| 97893 | sqlite3VdbeUsesBtree(v, i); |
| 97894 | } |
| 97895 | } |
| 97896 | sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0); |
| 97897 | } |
| 97898 | |
| 97899 | /* |
| 97900 | ** Commit a transaction |
| 97901 | */ |
| 97902 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){ |
| 97903 | Vdbe *v; |
| 97904 | |
| 97905 | assert( pParse!=0 ); |
| @@ -97907,16 +98193,16 @@ | |
| 97907 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ |
| 97908 | return; |
| 97909 | } |
| 97910 | v = sqlite3GetVdbe(pParse); |
| 97911 | if( v ){ |
| 97912 | sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); |
| 97913 | } |
| 97914 | } |
| 97915 | |
| 97916 | /* |
| 97917 | ** Rollback a transaction |
| 97918 | */ |
| 97919 | SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){ |
| 97920 | Vdbe *v; |
| 97921 | |
| 97922 | assert( pParse!=0 ); |
| @@ -97974,11 +98260,11 @@ | |
| 97974 | return 1; |
| 97975 | } |
| 97976 | db->aDb[1].pBt = pBt; |
| 97977 | assert( db->aDb[1].pSchema ); |
| 97978 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 97979 | db->mallocFailed = 1; |
| 97980 | return 1; |
| 97981 | } |
| 97982 | } |
| 97983 | return 0; |
| 97984 | } |
| @@ -98109,18 +98395,18 @@ | |
| 98109 | StrAccum errMsg; |
| 98110 | Table *pTab = pIdx->pTable; |
| 98111 | |
| 98112 | sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); |
| 98113 | if( pIdx->aColExpr ){ |
| 98114 | sqlite3XPrintf(&errMsg, 0, "index '%q'", pIdx->zName); |
| 98115 | }else{ |
| 98116 | for(j=0; j<pIdx->nKeyCol; j++){ |
| 98117 | char *zCol; |
| 98118 | assert( pIdx->aiColumn[j]>=0 ); |
| 98119 | zCol = pTab->aCol[pIdx->aiColumn[j]].zName; |
| 98120 | if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); |
| 98121 | sqlite3XPrintf(&errMsg, 0, "%s.%s", pTab->zName, zCol); |
| 98122 | } |
| 98123 | } |
| 98124 | zErr = sqlite3StrAccumFinish(&errMsg); |
| 98125 | sqlite3HaltConstraint(pParse, |
| 98126 | IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY |
| @@ -98349,14 +98635,13 @@ | |
| 98349 | int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); |
| 98350 | pNew = sqlite3DbRealloc(db, pWith, nByte); |
| 98351 | }else{ |
| 98352 | pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); |
| 98353 | } |
| 98354 | assert( zName!=0 || pNew==0 ); |
| 98355 | assert( db->mallocFailed==0 || pNew==0 ); |
| 98356 | |
| 98357 | if( pNew==0 ){ |
| 98358 | sqlite3ExprListDelete(db, pArglist); |
| 98359 | sqlite3SelectDelete(db, pQuery); |
| 98360 | sqlite3DbFree(db, zName); |
| 98361 | pNew = pWith; |
| 98362 | }else{ |
| @@ -98566,11 +98851,11 @@ | |
| 98566 | ** return the pColl pointer to be deleted (because it wasn't added |
| 98567 | ** to the hash table). |
| 98568 | */ |
| 98569 | assert( pDel==0 || pDel==pColl ); |
| 98570 | if( pDel!=0 ){ |
| 98571 | db->mallocFailed = 1; |
| 98572 | sqlite3DbFree(db, pDel); |
| 98573 | pColl = 0; |
| 98574 | } |
| 98575 | } |
| 98576 | } |
| @@ -98854,11 +99139,11 @@ | |
| 98854 | p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); |
| 98855 | }else{ |
| 98856 | p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); |
| 98857 | } |
| 98858 | if( !p ){ |
| 98859 | db->mallocFailed = 1; |
| 98860 | }else if ( 0==p->file_format ){ |
| 98861 | sqlite3HashInit(&p->tblHash); |
| 98862 | sqlite3HashInit(&p->idxHash); |
| 98863 | sqlite3HashInit(&p->trigHash); |
| 98864 | sqlite3HashInit(&p->fkeyHash); |
| @@ -99308,11 +99593,11 @@ | |
| 99308 | if( eOnePass!=ONEPASS_OFF ){ |
| 99309 | /* For ONEPASS, no need to store the rowid/primary-key. There is only |
| 99310 | ** one, so just keep it in its register(s) and fall through to the |
| 99311 | ** delete code. */ |
| 99312 | nKey = nPk; /* OP_Found will use an unpacked key */ |
| 99313 | aToOpen = sqlite3DbMallocRaw(db, nIdx+2); |
| 99314 | if( aToOpen==0 ){ |
| 99315 | sqlite3WhereEnd(pWInfo); |
| 99316 | goto delete_from_cleanup; |
| 99317 | } |
| 99318 | memset(aToOpen, 1, nIdx+1); |
| @@ -99348,17 +99633,16 @@ | |
| 99348 | ** only effect this statement has is to fire the INSTEAD OF |
| 99349 | ** triggers. |
| 99350 | */ |
| 99351 | if( !isView ){ |
| 99352 | int iAddrOnce = 0; |
| 99353 | u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE); |
| 99354 | if( eOnePass==ONEPASS_MULTI ){ |
| 99355 | iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); |
| 99356 | } |
| 99357 | testcase( IsVirtual(pTab) ); |
| 99358 | sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, |
| 99359 | aToOpen, &iDataCur, &iIdxCur); |
| 99360 | assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); |
| 99361 | assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); |
| 99362 | if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); |
| 99363 | } |
| 99364 | |
| @@ -99587,19 +99871,24 @@ | |
| 99587 | |
| 99588 | /* Delete the index and table entries. Skip this step if pTab is really |
| 99589 | ** a view (in which case the only effect of the DELETE statement is to |
| 99590 | ** fire the INSTEAD OF triggers). */ |
| 99591 | if( pTab->pSelect==0 ){ |
| 99592 | sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); |
| 99593 | sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); |
| 99594 | if( count ){ |
| 99595 | sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); |
| 99596 | } |
| 99597 | if( iIdxNoSeek>=0 ){ |
| 99598 | sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); |
| 99599 | } |
| 99600 | sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI); |
| 99601 | } |
| 99602 | |
| 99603 | /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
| 99604 | ** handle rows (possibly in other tables) that refer via a foreign key |
| 99605 | ** to the row just deleted. */ |
| @@ -100005,11 +100294,12 @@ | |
| 100005 | if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
| 100006 | x.nArg = argc-1; |
| 100007 | x.nUsed = 0; |
| 100008 | x.apArg = argv+1; |
| 100009 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 100010 | sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); |
| 100011 | n = str.nChar; |
| 100012 | sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, |
| 100013 | SQLITE_DYNAMIC); |
| 100014 | } |
| 100015 | } |
| @@ -101380,11 +101670,11 @@ | |
| 101380 | */ |
| 101381 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ |
| 101382 | int rc = sqlite3_overload_function(db, "MATCH", 2); |
| 101383 | assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); |
| 101384 | if( rc==SQLITE_NOMEM ){ |
| 101385 | db->mallocFailed = 1; |
| 101386 | } |
| 101387 | } |
| 101388 | |
| 101389 | /* |
| 101390 | ** Set the LIKEOPT flag on the 2-argument function with the given name. |
| @@ -101795,11 +102085,11 @@ | |
| 101795 | if( !zKey ) return 0; |
| 101796 | if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; |
| 101797 | } |
| 101798 | }else if( paiCol ){ |
| 101799 | assert( nCol>1 ); |
| 101800 | aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int)); |
| 101801 | if( !aiCol ) return 1; |
| 101802 | *paiCol = aiCol; |
| 101803 | } |
| 101804 | |
| 101805 | for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ |
| @@ -102741,11 +103031,10 @@ | |
| 102741 | |
| 102742 | action = pFKey->aAction[iAction]; |
| 102743 | pTrigger = pFKey->apTrigger[iAction]; |
| 102744 | |
| 102745 | if( action!=OE_None && !pTrigger ){ |
| 102746 | u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ |
| 102747 | char const *zFrom; /* Name of child table */ |
| 102748 | int nFrom; /* Length in bytes of zFrom */ |
| 102749 | Index *pIdx = 0; /* Parent key index for this FK */ |
| 102750 | int *aiCol = 0; /* child table cols -> parent key cols */ |
| 102751 | TriggerStep *pStep = 0; /* First (only) step of trigger program */ |
| @@ -102768,15 +103057,13 @@ | |
| 102768 | |
| 102769 | iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 102770 | assert( iFromCol>=0 ); |
| 102771 | assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 102772 | assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
| 102773 | tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; |
| 102774 | tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; |
| 102775 | |
| 102776 | tToCol.n = sqlite3Strlen30(tToCol.z); |
| 102777 | tFromCol.n = sqlite3Strlen30(tFromCol.z); |
| 102778 | |
| 102779 | /* Create the expression "OLD.zToCol = zFromCol". It is important |
| 102780 | ** that the "OLD.zToCol" term is on the LHS of the = operator, so |
| 102781 | ** that the affinity and collation sequence associated with the |
| 102782 | ** parent table are used for the comparison. */ |
| @@ -102852,12 +103139,11 @@ | |
| 102852 | ); |
| 102853 | pWhere = 0; |
| 102854 | } |
| 102855 | |
| 102856 | /* Disable lookaside memory allocation */ |
| 102857 | enableLookaside = db->lookaside.bEnabled; |
| 102858 | db->lookaside.bEnabled = 0; |
| 102859 | |
| 102860 | pTrigger = (Trigger *)sqlite3DbMallocZero(db, |
| 102861 | sizeof(Trigger) + /* struct Trigger */ |
| 102862 | sizeof(TriggerStep) + /* Single step in trigger program */ |
| 102863 | nFrom + 1 /* Space for pStep->zTarget */ |
| @@ -102875,11 +103161,11 @@ | |
| 102875 | pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
| 102876 | } |
| 102877 | } |
| 102878 | |
| 102879 | /* Re-enable the lookaside buffer, if it was disabled earlier. */ |
| 102880 | db->lookaside.bEnabled = enableLookaside; |
| 102881 | |
| 102882 | sqlite3ExprDelete(db, pWhere); |
| 102883 | sqlite3ExprDelete(db, pWhen); |
| 102884 | sqlite3ExprListDelete(db, pList); |
| 102885 | sqlite3SelectDelete(db, pSelect); |
| @@ -103070,11 +103356,11 @@ | |
| 103070 | */ |
| 103071 | int n; |
| 103072 | Table *pTab = pIdx->pTable; |
| 103073 | pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); |
| 103074 | if( !pIdx->zColAff ){ |
| 103075 | db->mallocFailed = 1; |
| 103076 | return 0; |
| 103077 | } |
| 103078 | for(n=0; n<pIdx->nColumn; n++){ |
| 103079 | i16 x = pIdx->aiColumn[n]; |
| 103080 | if( x>=0 ){ |
| @@ -103121,11 +103407,11 @@ | |
| 103121 | char *zColAff = pTab->zColAff; |
| 103122 | if( zColAff==0 ){ |
| 103123 | sqlite3 *db = sqlite3VdbeDb(v); |
| 103124 | zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); |
| 103125 | if( !zColAff ){ |
| 103126 | db->mallocFailed = 1; |
| 103127 | return; |
| 103128 | } |
| 103129 | |
| 103130 | for(i=0; i<pTab->nCol; i++){ |
| 103131 | zColAff[i] = pTab->aCol[i].affinity; |
| @@ -103217,11 +103503,11 @@ | |
| 103217 | AutoincInfo *pInfo; |
| 103218 | |
| 103219 | pInfo = pToplevel->pAinc; |
| 103220 | while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } |
| 103221 | if( pInfo==0 ){ |
| 103222 | pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo)); |
| 103223 | if( pInfo==0 ) return 0; |
| 103224 | pInfo->pNext = pToplevel->pAinc; |
| 103225 | pToplevel->pAinc = pInfo; |
| 103226 | pInfo->pTab = pTab; |
| 103227 | pInfo->iDb = iDb; |
| @@ -103241,47 +103527,59 @@ | |
| 103241 | SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ |
| 103242 | AutoincInfo *p; /* Information about an AUTOINCREMENT */ |
| 103243 | sqlite3 *db = pParse->db; /* The database connection */ |
| 103244 | Db *pDb; /* Database only autoinc table */ |
| 103245 | int memId; /* Register holding max rowid */ |
| 103246 | int addr; /* A VDBE address */ |
| 103247 | Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
| 103248 | |
| 103249 | /* This routine is never called during trigger-generation. It is |
| 103250 | ** only called from the top-level */ |
| 103251 | assert( pParse->pTriggerTab==0 ); |
| 103252 | assert( sqlite3IsToplevel(pParse) ); |
| 103253 | |
| 103254 | assert( v ); /* We failed long ago if this is not so */ |
| 103255 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103256 | pDb = &db->aDb[p->iDb]; |
| 103257 | memId = p->regCtr; |
| 103258 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103259 | sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); |
| 103260 | sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); |
| 103261 | addr = sqlite3VdbeCurrentAddr(v); |
| 103262 | sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); |
| 103263 | sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v); |
| 103264 | sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); |
| 103265 | sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v); |
| 103266 | sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); |
| 103267 | sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); |
| 103268 | sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); |
| 103269 | sqlite3VdbeGoto(v, addr+9); |
| 103270 | sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v); |
| 103271 | sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); |
| 103272 | sqlite3VdbeAddOp0(v, OP_Close); |
| 103273 | } |
| 103274 | } |
| 103275 | |
| 103276 | /* |
| 103277 | ** Update the maximum rowid for an autoincrement calculation. |
| 103278 | ** |
| 103279 | ** This routine should be called when the top of the stack holds a |
| 103280 | ** new rowid that is about to be inserted. If that new rowid is |
| 103281 | ** larger than the maximum rowid in the memId memory cell, then the |
| 103282 | ** memory cell is updated. The stack is unchanged. |
| 103283 | */ |
| 103284 | static void autoIncStep(Parse *pParse, int memId, int regRowid){ |
| 103285 | if( memId>0 ){ |
| 103286 | sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); |
| 103287 | } |
| @@ -103292,34 +103590,47 @@ | |
| 103292 | ** maximum rowid values back into the sqlite_sequence register. |
| 103293 | ** Every statement that might do an INSERT into an autoincrement |
| 103294 | ** table (either directly or through triggers) needs to call this |
| 103295 | ** routine just before the "exit" code. |
| 103296 | */ |
| 103297 | SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ |
| 103298 | AutoincInfo *p; |
| 103299 | Vdbe *v = pParse->pVdbe; |
| 103300 | sqlite3 *db = pParse->db; |
| 103301 | |
| 103302 | assert( v ); |
| 103303 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103304 | Db *pDb = &db->aDb[p->iDb]; |
| 103305 | int addr1; |
| 103306 | int iRec; |
| 103307 | int memId = p->regCtr; |
| 103308 | |
| 103309 | iRec = sqlite3GetTempReg(pParse); |
| 103310 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103311 | sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); |
| 103312 | addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v); |
| 103313 | sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); |
| 103314 | sqlite3VdbeJumpHere(v, addr1); |
| 103315 | sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); |
| 103316 | sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); |
| 103317 | sqlite3VdbeChangeP5(v, OPFLAG_APPEND); |
| 103318 | sqlite3VdbeAddOp0(v, OP_Close); |
| 103319 | sqlite3ReleaseTempReg(pParse, iRec); |
| 103320 | } |
| 103321 | } |
| 103322 | #else |
| 103323 | /* |
| 103324 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines |
| 103325 | ** above are all no-ops |
| @@ -103647,11 +103958,11 @@ | |
| 103647 | dest.iSdst = bIdListInOrder ? regData : 0; |
| 103648 | dest.nSdst = pTab->nCol; |
| 103649 | rc = sqlite3Select(pParse, pSelect, &dest); |
| 103650 | regFromSelect = dest.iSdst; |
| 103651 | if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; |
| 103652 | sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); |
| 103653 | sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ |
| 103654 | assert( pSelect->pEList ); |
| 103655 | nColumn = pSelect->pEList->nExpr; |
| 103656 | |
| 103657 | /* Set useTempTable to TRUE if the result of the SELECT statement |
| @@ -103749,11 +104060,11 @@ | |
| 103749 | /* If this is not a view, open the table and and all indices */ |
| 103750 | if( !isView ){ |
| 103751 | int nIdx; |
| 103752 | nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, |
| 103753 | &iDataCur, &iIdxCur); |
| 103754 | aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); |
| 103755 | if( aRegIdx==0 ){ |
| 103756 | goto insert_cleanup; |
| 103757 | } |
| 103758 | for(i=0; i<nIdx; i++){ |
| 103759 | aRegIdx[i] = ++pParse->nMem; |
| @@ -104634,11 +104945,11 @@ | |
| 104634 | */ |
| 104635 | SQLITE_PRIVATE int sqlite3OpenTableAndIndices( |
| 104636 | Parse *pParse, /* Parsing context */ |
| 104637 | Table *pTab, /* Table to be opened */ |
| 104638 | int op, /* OP_OpenRead or OP_OpenWrite */ |
| 104639 | u8 p5, /* P5 value for OP_Open* instructions */ |
| 104640 | int iBase, /* Use this for the table cursor, if there is one */ |
| 104641 | u8 *aToOpen, /* If not NULL: boolean for each table and index */ |
| 104642 | int *piDataCur, /* Write the database source cursor number here */ |
| 104643 | int *piIdxCur /* Write the first index cursor number here */ |
| 104644 | ){ |
| @@ -104669,18 +104980,19 @@ | |
| 104669 | } |
| 104670 | if( piIdxCur ) *piIdxCur = iBase; |
| 104671 | for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ |
| 104672 | int iIdxCur = iBase++; |
| 104673 | assert( pIdx->pSchema==pTab->pSchema ); |
| 104674 | if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){ |
| 104675 | *piDataCur = iIdxCur; |
| 104676 | } |
| 104677 | if( aToOpen==0 || aToOpen[i+1] ){ |
| 104678 | sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); |
| 104679 | sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
| 104680 | sqlite3VdbeChangeP5(v, p5); |
| 104681 | VdbeComment((v, "%s", pIdx->zName)); |
| 104682 | } |
| 104683 | } |
| 104684 | if( iBase>pParse->nTab ) pParse->nTab = iBase; |
| 104685 | return i; |
| 104686 | } |
| @@ -105167,11 +105479,11 @@ | |
| 105167 | if( rc==SQLITE_ROW ){ |
| 105168 | azVals = &azCols[nCol]; |
| 105169 | for(i=0; i<nCol; i++){ |
| 105170 | azVals[i] = (char *)sqlite3_column_text(pStmt, i); |
| 105171 | if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 105172 | db->mallocFailed = 1; |
| 105173 | goto exec_out; |
| 105174 | } |
| 105175 | } |
| 105176 | } |
| 105177 | if( xCallback(pArg, nCol, azVals, azCols) ){ |
| @@ -107055,32 +107367,35 @@ | |
| 107055 | /************** End of pragma.h **********************************************/ |
| 107056 | /************** Continuing where we left off in pragma.c *********************/ |
| 107057 | |
| 107058 | /* |
| 107059 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| 107060 | ** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or |
| 107061 | ** unrecognized string argument. The FULL option is disallowed |
| 107062 | ** if the omitFull parameter it 1. |
| 107063 | ** |
| 107064 | ** Note that the values returned are one less that the values that |
| 107065 | ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done |
| 107066 | ** to support legacy SQL code. The safety level used to be boolean |
| 107067 | ** and older scripts may have used numbers 0 for OFF and 1 for ON. |
| 107068 | */ |
| 107069 | static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ |
| 107070 | /* 123456789 123456789 */ |
| 107071 | static const char zText[] = "onoffalseyestruefull"; |
| 107072 | static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; |
| 107073 | static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; |
| 107074 | static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; |
| 107075 | int i, n; |
| 107076 | if( sqlite3Isdigit(*z) ){ |
| 107077 | return (u8)sqlite3Atoi(z); |
| 107078 | } |
| 107079 | n = sqlite3Strlen30(z); |
| 107080 | for(i=0; i<ArraySize(iLength)-omitFull; i++){ |
| 107081 | if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ |
| 107082 | return iValue[i]; |
| 107083 | } |
| 107084 | } |
| 107085 | return dflt; |
| 107086 | } |
| @@ -107467,12 +107782,11 @@ | |
| 107467 | aOp[1].p1 = iDb; |
| 107468 | aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE; |
| 107469 | }else{ |
| 107470 | int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); |
| 107471 | sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 107472 | sqlite3VdbeAddOp2(v, OP_Integer, size, 1); |
| 107473 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); |
| 107474 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 107475 | pDb->pSchema->cache_size = size; |
| 107476 | sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
| 107477 | } |
| 107478 | break; |
| @@ -107499,11 +107813,11 @@ | |
| 107499 | /* Malloc may fail when setting the page-size, as there is an internal |
| 107500 | ** buffer that the pager module resizes using sqlite3_realloc(). |
| 107501 | */ |
| 107502 | db->nextPagesize = sqlite3Atoi(zRight); |
| 107503 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ |
| 107504 | db->mallocFailed = 1; |
| 107505 | } |
| 107506 | } |
| 107507 | break; |
| 107508 | } |
| 107509 | |
| @@ -107706,23 +108020,22 @@ | |
| 107706 | static const VdbeOpList setMeta6[] = { |
| 107707 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 107708 | { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, |
| 107709 | { OP_If, 1, 0, 0}, /* 2 */ |
| 107710 | { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ |
| 107711 | { OP_Integer, 0, 1, 0}, /* 4 */ |
| 107712 | { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ |
| 107713 | }; |
| 107714 | VdbeOp *aOp; |
| 107715 | int iAddr = sqlite3VdbeCurrentAddr(v); |
| 107716 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setMeta6)); |
| 107717 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); |
| 107718 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 107719 | aOp[0].p1 = iDb; |
| 107720 | aOp[1].p1 = iDb; |
| 107721 | aOp[2].p2 = iAddr+4; |
| 107722 | aOp[4].p1 = eAuto - 1; |
| 107723 | aOp[5].p1 = iDb; |
| 107724 | sqlite3VdbeUsesBtree(v, iDb); |
| 107725 | } |
| 107726 | } |
| 107727 | break; |
| 107728 | } |
| @@ -107997,11 +108310,11 @@ | |
| 107997 | } |
| 107998 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 107999 | |
| 108000 | /* |
| 108001 | ** PRAGMA [schema.]synchronous |
| 108002 | ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL |
| 108003 | ** |
| 108004 | ** Return or set the local value of the synchronous flag. Changing |
| 108005 | ** the local value does not make changes to the disk file and the |
| 108006 | ** default value will be restored the next time the database is |
| 108007 | ** opened. |
| @@ -108624,20 +108937,19 @@ | |
| 108624 | } |
| 108625 | { |
| 108626 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 108627 | static const VdbeOpList endCode[] = { |
| 108628 | { OP_AddImm, 1, 0, 0}, /* 0 */ |
| 108629 | { OP_If, 1, 0, 0}, /* 1 */ |
| 108630 | { OP_String8, 0, 3, 0}, /* 2 */ |
| 108631 | { OP_ResultRow, 3, 1, 0}, |
| 108632 | }; |
| 108633 | VdbeOp *aOp; |
| 108634 | |
| 108635 | aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
| 108636 | if( aOp ){ |
| 108637 | aOp[0].p2 = -mxErr; |
| 108638 | aOp[1].p2 = sqlite3VdbeCurrentAddr(v); |
| 108639 | aOp[2].p4type = P4_STATIC; |
| 108640 | aOp[2].p4.z = "ok"; |
| 108641 | } |
| 108642 | } |
| 108643 | } |
| @@ -108751,21 +109063,20 @@ | |
| 108751 | sqlite3VdbeUsesBtree(v, iDb); |
| 108752 | if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ |
| 108753 | /* Write the specified cookie value */ |
| 108754 | static const VdbeOpList setCookie[] = { |
| 108755 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 108756 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 108757 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| 108758 | }; |
| 108759 | VdbeOp *aOp; |
| 108760 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); |
| 108761 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); |
| 108762 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 108763 | aOp[0].p1 = iDb; |
| 108764 | aOp[1].p1 = sqlite3Atoi(zRight); |
| 108765 | aOp[2].p1 = iDb; |
| 108766 | aOp[2].p2 = iCookie; |
| 108767 | }else{ |
| 108768 | /* Read the specified cookie value */ |
| 108769 | static const VdbeOpList readCookie[] = { |
| 108770 | { OP_Transaction, 0, 0, 0}, /* 0 */ |
| 108771 | { OP_ReadCookie, 0, 1, 0}, /* 1 */ |
| @@ -109033,15 +109344,14 @@ | |
| 109033 | ){ |
| 109034 | sqlite3 *db = pData->db; |
| 109035 | if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ |
| 109036 | char *z; |
| 109037 | if( zObj==0 ) zObj = "?"; |
| 109038 | z = sqlite3_mprintf("malformed database schema (%s)", zObj); |
| 109039 | if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra); |
| 109040 | sqlite3DbFree(db, *pData->pzErrMsg); |
| 109041 | *pData->pzErrMsg = z; |
| 109042 | if( z==0 ) db->mallocFailed = 1; |
| 109043 | } |
| 109044 | pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; |
| 109045 | } |
| 109046 | |
| 109047 | /* |
| @@ -109096,11 +109406,11 @@ | |
| 109096 | if( db->init.orphanTrigger ){ |
| 109097 | assert( iDb==1 ); |
| 109098 | }else{ |
| 109099 | pData->rc = rc; |
| 109100 | if( rc==SQLITE_NOMEM ){ |
| 109101 | db->mallocFailed = 1; |
| 109102 | }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ |
| 109103 | corruptSchema(pData, argv[0], sqlite3_errmsg(db)); |
| 109104 | } |
| 109105 | } |
| 109106 | } |
| @@ -109341,11 +109651,11 @@ | |
| 109341 | } |
| 109342 | sqlite3BtreeLeave(pDb->pBt); |
| 109343 | |
| 109344 | error_out: |
| 109345 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109346 | db->mallocFailed = 1; |
| 109347 | } |
| 109348 | return rc; |
| 109349 | } |
| 109350 | |
| 109351 | /* |
| @@ -109439,11 +109749,11 @@ | |
| 109439 | ** on the b-tree database, open one now. If a transaction is opened, it |
| 109440 | ** will be closed immediately after reading the meta-value. */ |
| 109441 | if( !sqlite3BtreeIsInReadTrans(pBt) ){ |
| 109442 | rc = sqlite3BtreeBeginTrans(pBt, 0); |
| 109443 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109444 | db->mallocFailed = 1; |
| 109445 | } |
| 109446 | if( rc!=SQLITE_OK ) return; |
| 109447 | openedTransaction = 1; |
| 109448 | } |
| 109449 | |
| @@ -109502,10 +109812,15 @@ | |
| 109502 | SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ |
| 109503 | if( pParse ){ |
| 109504 | sqlite3 *db = pParse->db; |
| 109505 | sqlite3DbFree(db, pParse->aLabel); |
| 109506 | sqlite3ExprListDelete(db, pParse->pConstExpr); |
| 109507 | } |
| 109508 | } |
| 109509 | |
| 109510 | /* |
| 109511 | ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. |
| @@ -109530,11 +109845,11 @@ | |
| 109530 | rc = SQLITE_NOMEM; |
| 109531 | goto end_prepare; |
| 109532 | } |
| 109533 | pParse->pReprepare = pReprepare; |
| 109534 | assert( ppStmt && *ppStmt==0 ); |
| 109535 | assert( !db->mallocFailed ); |
| 109536 | assert( sqlite3_mutex_held(db->mutex) ); |
| 109537 | |
| 109538 | /* Check to verify that it is possible to get a read lock on all |
| 109539 | ** database schemas. The inability to get a read lock indicates that |
| 109540 | ** some other database connection is holding a write-lock, which in |
| @@ -109587,23 +109902,20 @@ | |
| 109587 | goto end_prepare; |
| 109588 | } |
| 109589 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 109590 | if( zSqlCopy ){ |
| 109591 | sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); |
| 109592 | sqlite3DbFree(db, zSqlCopy); |
| 109593 | pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; |
| 109594 | }else{ |
| 109595 | pParse->zTail = &zSql[nBytes]; |
| 109596 | } |
| 109597 | }else{ |
| 109598 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 109599 | } |
| 109600 | assert( 0==pParse->nQueryLoop ); |
| 109601 | |
| 109602 | if( db->mallocFailed ){ |
| 109603 | pParse->rc = SQLITE_NOMEM; |
| 109604 | } |
| 109605 | if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; |
| 109606 | if( pParse->checkSchema ){ |
| 109607 | schemaIsValid(pParse); |
| 109608 | } |
| 109609 | if( db->mallocFailed ){ |
| @@ -109721,11 +110033,11 @@ | |
| 109721 | db = sqlite3VdbeDb(p); |
| 109722 | assert( sqlite3_mutex_held(db->mutex) ); |
| 109723 | rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0); |
| 109724 | if( rc ){ |
| 109725 | if( rc==SQLITE_NOMEM ){ |
| 109726 | db->mallocFailed = 1; |
| 109727 | } |
| 109728 | assert( pNew==0 ); |
| 109729 | return rc; |
| 109730 | }else{ |
| 109731 | assert( pNew!=0 ); |
| @@ -109975,11 +110287,11 @@ | |
| 109975 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 109976 | ){ |
| 109977 | Select *pNew; |
| 109978 | Select standin; |
| 109979 | sqlite3 *db = pParse->db; |
| 109980 | pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); |
| 109981 | if( pNew==0 ){ |
| 109982 | assert( db->mallocFailed ); |
| 109983 | pNew = &standin; |
| 109984 | } |
| 109985 | if( pEList==0 ){ |
| @@ -110879,11 +111191,11 @@ | |
| 110879 | p->enc = ENC(db); |
| 110880 | p->db = db; |
| 110881 | p->nRef = 1; |
| 110882 | memset(&p[1], 0, nExtra); |
| 110883 | }else{ |
| 110884 | db->mallocFailed = 1; |
| 110885 | } |
| 110886 | return p; |
| 110887 | } |
| 110888 | |
| 110889 | /* |
| @@ -111540,11 +111852,11 @@ | |
| 111540 | if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); |
| 111541 | } |
| 111542 | pCol->zName = zName; |
| 111543 | sqlite3ColumnPropertiesFromName(0, pCol); |
| 111544 | if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ |
| 111545 | db->mallocFailed = 1; |
| 111546 | } |
| 111547 | } |
| 111548 | sqlite3HashClear(&ht); |
| 111549 | if( db->mallocFailed ){ |
| 111550 | for(j=0; j<i; j++){ |
| @@ -111627,11 +111939,11 @@ | |
| 111627 | if( pTab==0 ){ |
| 111628 | return 0; |
| 111629 | } |
| 111630 | /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside |
| 111631 | ** is disabled */ |
| 111632 | assert( db->lookaside.bEnabled==0 ); |
| 111633 | pTab->nRef = 1; |
| 111634 | pTab->zName = 0; |
| 111635 | pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 111636 | sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
| 111637 | selectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
| @@ -111723,14 +112035,12 @@ | |
| 111723 | p->iOffset = iOffset = ++pParse->nMem; |
| 111724 | pParse->nMem++; /* Allocate an extra register for limit+offset */ |
| 111725 | sqlite3ExprCode(pParse, p->pOffset, iOffset); |
| 111726 | sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); |
| 111727 | VdbeComment((v, "OFFSET counter")); |
| 111728 | sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0); |
| 111729 | sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); |
| 111730 | VdbeComment((v, "LIMIT+OFFSET")); |
| 111731 | sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1); |
| 111732 | } |
| 111733 | } |
| 111734 | } |
| 111735 | |
| 111736 | #ifndef SQLITE_OMIT_COMPOUND_SELECT |
| @@ -112143,13 +112453,12 @@ | |
| 112143 | p->iOffset = pPrior->iOffset; |
| 112144 | if( p->iLimit ){ |
| 112145 | addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); |
| 112146 | VdbeComment((v, "Jump ahead if LIMIT reached")); |
| 112147 | if( p->iOffset ){ |
| 112148 | sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0); |
| 112149 | sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1); |
| 112150 | sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1); |
| 112151 | } |
| 112152 | } |
| 112153 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 112154 | rc = sqlite3Select(pParse, p, &dest); |
| 112155 | testcase( rc!=SQLITE_OK ); |
| @@ -112736,14 +113045,15 @@ | |
| 112736 | ** row of results comes from selectA or selectB. Also add explicit |
| 112737 | ** collations to the ORDER BY clause terms so that when the subqueries |
| 112738 | ** to the right and the left are evaluated, they use the correct |
| 112739 | ** collation. |
| 112740 | */ |
| 112741 | aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); |
| 112742 | if( aPermute ){ |
| 112743 | struct ExprList_item *pItem; |
| 112744 | for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ |
| 112745 | assert( pItem->u.x.iOrderByCol>0 ); |
| 112746 | assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
| 112747 | aPermute[i] = pItem->u.x.iOrderByCol - 1; |
| 112748 | } |
| 112749 | pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); |
| @@ -112817,11 +113127,11 @@ | |
| 112817 | addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
| 112818 | VdbeComment((v, "left SELECT")); |
| 112819 | pPrior->iLimit = regLimitA; |
| 112820 | explainSetInteger(iSub1, pParse->iNextSelectId); |
| 112821 | sqlite3Select(pParse, pPrior, &destA); |
| 112822 | sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA); |
| 112823 | sqlite3VdbeJumpHere(v, addr1); |
| 112824 | |
| 112825 | /* Generate a coroutine to evaluate the SELECT statement on |
| 112826 | ** the right - the "B" select |
| 112827 | */ |
| @@ -112834,11 +113144,11 @@ | |
| 112834 | p->iOffset = 0; |
| 112835 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 112836 | sqlite3Select(pParse, p, &destB); |
| 112837 | p->iLimit = savedLimit; |
| 112838 | p->iOffset = savedOffset; |
| 112839 | sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB); |
| 112840 | |
| 112841 | /* Generate a subroutine that outputs the current row of the A |
| 112842 | ** select as the next output row of the compound select. |
| 112843 | */ |
| 112844 | VdbeNoopComment((v, "Output routine for A")); |
| @@ -114301,12 +114611,11 @@ | |
| 114301 | } |
| 114302 | }else{ |
| 114303 | pExpr = pRight; |
| 114304 | } |
| 114305 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 114306 | sColname.z = zColname; |
| 114307 | sColname.n = sqlite3Strlen30(zColname); |
| 114308 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 114309 | if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ |
| 114310 | struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; |
| 114311 | if( pSub ){ |
| 114312 | pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); |
| @@ -114856,11 +115165,11 @@ | |
| 114856 | explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
| 114857 | sqlite3Select(pParse, pSub, &dest); |
| 114858 | pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); |
| 114859 | pItem->fg.viaCoroutine = 1; |
| 114860 | pItem->regResult = dest.iSdst; |
| 114861 | sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); |
| 114862 | sqlite3VdbeJumpHere(v, addrTop-1); |
| 114863 | sqlite3ClearTempRegCache(pParse); |
| 114864 | }else{ |
| 114865 | /* Generate a subroutine that will fill an ephemeral table with |
| 114866 | ** the content of this subquery. pItem->addrFillSub will point |
| @@ -115428,11 +115737,12 @@ | |
| 115428 | assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); |
| 115429 | |
| 115430 | if( flag ){ |
| 115431 | pMinMax = sqlite3ExprListDup(db, pMinMax, 0); |
| 115432 | pDel = pMinMax; |
| 115433 | if( pMinMax && !db->mallocFailed ){ |
| 115434 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 115435 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 115436 | } |
| 115437 | } |
| 115438 | |
| @@ -116001,12 +116311,11 @@ | |
| 116001 | pTrig->step_list = pStepList; |
| 116002 | while( pStepList ){ |
| 116003 | pStepList->pTrig = pTrig; |
| 116004 | pStepList = pStepList->pNext; |
| 116005 | } |
| 116006 | nameToken.z = pTrig->zName; |
| 116007 | nameToken.n = sqlite3Strlen30(nameToken.z); |
| 116008 | sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
| 116009 | if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) |
| 116010 | || sqlite3FixExpr(&sFix, pTrig->pWhen) |
| 116011 | ){ |
| 116012 | goto triggerfinish_cleanup; |
| @@ -116038,11 +116347,11 @@ | |
| 116038 | Trigger *pLink = pTrig; |
| 116039 | Hash *pHash = &db->aDb[iDb].pSchema->trigHash; |
| 116040 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 116041 | pTrig = sqlite3HashInsert(pHash, zName, pTrig); |
| 116042 | if( pTrig ){ |
| 116043 | db->mallocFailed = 1; |
| 116044 | }else if( pLink->pSchema==pLink->pTabSchema ){ |
| 116045 | Table *pTab; |
| 116046 | pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); |
| 116047 | assert( pTab!=0 ); |
| 116048 | pLink->pNext = pTab->pTrigger; |
| @@ -117014,11 +117323,11 @@ | |
| 117014 | } |
| 117015 | |
| 117016 | /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. |
| 117017 | ** Initialize aXRef[] and aToOpen[] to their default values. |
| 117018 | */ |
| 117019 | aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); |
| 117020 | if( aXRef==0 ) goto update_cleanup; |
| 117021 | aRegIdx = aXRef+pTab->nCol; |
| 117022 | aToOpen = (u8*)(aRegIdx+nIdx); |
| 117023 | memset(aToOpen, 1, nIdx+1); |
| 117024 | aToOpen[nIdx+1] = 0; |
| @@ -118054,11 +118363,11 @@ | |
| 118054 | nName = sqlite3Strlen30(zName); |
| 118055 | if( sqlite3HashFind(&db->aModule, zName) ){ |
| 118056 | rc = SQLITE_MISUSE_BKPT; |
| 118057 | }else{ |
| 118058 | Module *pMod; |
| 118059 | pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); |
| 118060 | if( pMod ){ |
| 118061 | Module *pDel; |
| 118062 | char *zCopy = (char *)(&pMod[1]); |
| 118063 | memcpy(zCopy, zName, nName+1); |
| 118064 | pMod->zName = zCopy; |
| @@ -118067,11 +118376,11 @@ | |
| 118067 | pMod->xDestroy = xDestroy; |
| 118068 | pMod->pEpoTab = 0; |
| 118069 | pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); |
| 118070 | assert( pDel==0 || pDel==pMod ); |
| 118071 | if( pDel ){ |
| 118072 | db->mallocFailed = 1; |
| 118073 | sqlite3DbFree(db, pDel); |
| 118074 | } |
| 118075 | } |
| 118076 | } |
| 118077 | rc = sqlite3ApiExit(db, rc); |
| @@ -118444,11 +118753,11 @@ | |
| 118444 | Schema *pSchema = pTab->pSchema; |
| 118445 | const char *zName = pTab->zName; |
| 118446 | assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); |
| 118447 | pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); |
| 118448 | if( pOld ){ |
| 118449 | db->mallocFailed = 1; |
| 118450 | assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 118451 | return; |
| 118452 | } |
| 118453 | pParse->pNewTable = 0; |
| 118454 | } |
| @@ -118535,11 +118844,11 @@ | |
| 118535 | sCtx.pPrior = db->pVtabCtx; |
| 118536 | sCtx.bDeclared = 0; |
| 118537 | db->pVtabCtx = &sCtx; |
| 118538 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 118539 | db->pVtabCtx = sCtx.pPrior; |
| 118540 | if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 118541 | assert( sCtx.pTab==pTab ); |
| 118542 | |
| 118543 | if( SQLITE_OK!=rc ){ |
| 118544 | if( zErr==0 ){ |
| 118545 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| @@ -119093,11 +119402,11 @@ | |
| 119093 | apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); |
| 119094 | if( apVtabLock ){ |
| 119095 | pToplevel->apVtabLock = apVtabLock; |
| 119096 | pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; |
| 119097 | }else{ |
| 119098 | pToplevel->db->mallocFailed = 1; |
| 119099 | } |
| 119100 | } |
| 119101 | |
| 119102 | /* |
| 119103 | ** Check to see if virtual tale module pMod can be have an eponymous |
| @@ -119835,11 +120144,11 @@ | |
| 119835 | if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; |
| 119836 | sqlite3StrAccumAppend(pStr, " (", 2); |
| 119837 | for(i=0; i<nEq; i++){ |
| 119838 | const char *z = explainIndexColumnName(pIndex, i); |
| 119839 | if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5); |
| 119840 | sqlite3XPrintf(pStr, 0, i>=nSkip ? "%s=?" : "ANY(%s)", z); |
| 119841 | } |
| 119842 | |
| 119843 | j = i; |
| 119844 | if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ |
| 119845 | const char *z = explainIndexColumnName(pIndex, i); |
| @@ -119894,17 +120203,17 @@ | |
| 119894 | || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); |
| 119895 | |
| 119896 | sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); |
| 119897 | sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); |
| 119898 | if( pItem->pSelect ){ |
| 119899 | sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); |
| 119900 | }else{ |
| 119901 | sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName); |
| 119902 | } |
| 119903 | |
| 119904 | if( pItem->zAlias ){ |
| 119905 | sqlite3XPrintf(&str, 0, " AS %s", pItem->zAlias); |
| 119906 | } |
| 119907 | if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ |
| 119908 | const char *zFmt = 0; |
| 119909 | Index *pIdx; |
| 119910 | |
| @@ -119924,11 +120233,11 @@ | |
| 119924 | }else{ |
| 119925 | zFmt = "INDEX %s"; |
| 119926 | } |
| 119927 | if( zFmt ){ |
| 119928 | sqlite3StrAccumAppend(&str, " USING ", 7); |
| 119929 | sqlite3XPrintf(&str, 0, zFmt, pIdx->zName); |
| 119930 | explainIndexRange(&str, pLoop); |
| 119931 | } |
| 119932 | }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ |
| 119933 | const char *zRangeOp; |
| 119934 | if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ |
| @@ -119939,21 +120248,21 @@ | |
| 119939 | zRangeOp = ">"; |
| 119940 | }else{ |
| 119941 | assert( flags&WHERE_TOP_LIMIT); |
| 119942 | zRangeOp = "<"; |
| 119943 | } |
| 119944 | sqlite3XPrintf(&str, 0, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); |
| 119945 | } |
| 119946 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 119947 | else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ |
| 119948 | sqlite3XPrintf(&str, 0, " VIRTUAL TABLE INDEX %d:%s", |
| 119949 | pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); |
| 119950 | } |
| 119951 | #endif |
| 119952 | #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS |
| 119953 | if( pLoop->nOut>=10 ){ |
| 119954 | sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); |
| 119955 | }else{ |
| 119956 | sqlite3StrAccumAppend(&str, " (~1 row)", 9); |
| 119957 | } |
| 119958 | #endif |
| 119959 | zMsg = sqlite3StrAccumFinish(&str); |
| @@ -120254,13 +120563,11 @@ | |
| 120254 | regBase = pParse->nMem + 1; |
| 120255 | nReg = pLoop->u.btree.nEq + nExtraReg; |
| 120256 | pParse->nMem += nReg; |
| 120257 | |
| 120258 | zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); |
| 120259 | if( !zAff ){ |
| 120260 | pParse->db->mallocFailed = 1; |
| 120261 | } |
| 120262 | |
| 120263 | if( nSkip ){ |
| 120264 | int iIdxCur = pLevel->iIdxCur; |
| 120265 | sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); |
| 120266 | VdbeCoverageIf(v, bRev==0); |
| @@ -120504,10 +120811,58 @@ | |
| 120504 | } |
| 120505 | } |
| 120506 | #else |
| 120507 | # define codeCursorHint(A,B,C) /* No-op */ |
| 120508 | #endif /* SQLITE_ENABLE_CURSOR_HINTS */ |
| 120509 | |
| 120510 | /* |
| 120511 | ** Generate code for the start of the iLevel-th loop in the WHERE clause |
| 120512 | ** implementation described by pWInfo. |
| 120513 | */ |
| @@ -120984,18 +121339,18 @@ | |
| 120984 | disableTerm(pLevel, pRangeStart); |
| 120985 | disableTerm(pLevel, pRangeEnd); |
| 120986 | if( omitTable ){ |
| 120987 | /* pIdx is a covering index. No need to access the main table. */ |
| 120988 | }else if( HasRowid(pIdx->pTable) ){ |
| 120989 | iRowidReg = ++pParse->nMem; |
| 120990 | sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); |
| 120991 | sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); |
| 120992 | if( pWInfo->eOnePass!=ONEPASS_OFF ){ |
| 120993 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); |
| 120994 | VdbeCoverage(v); |
| 120995 | }else{ |
| 120996 | sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ |
| 120997 | } |
| 120998 | }else if( iCur!=iIdxCur ){ |
| 120999 | Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); |
| 121000 | iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); |
| 121001 | for(j=0; j<pPk->nKeyCol; j++){ |
| @@ -121160,11 +121515,13 @@ | |
| 121160 | int iTerm; |
| 121161 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 121162 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 121163 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 121164 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 121165 | if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; |
| 121166 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 121167 | testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); |
| 121168 | pExpr = sqlite3ExprDup(db, pExpr, 0); |
| 121169 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
| 121170 | } |
| @@ -121500,11 +121857,11 @@ | |
| 121500 | int idx; |
| 121501 | testcase( wtFlags & TERM_VIRTUAL ); |
| 121502 | if( pWC->nTerm>=pWC->nSlot ){ |
| 121503 | WhereTerm *pOld = pWC->a; |
| 121504 | sqlite3 *db = pWC->pWInfo->pParse->db; |
| 121505 | pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); |
| 121506 | if( pWC->a==0 ){ |
| 121507 | if( wtFlags & TERM_DYNAMIC ){ |
| 121508 | sqlite3ExprDelete(db, p); |
| 121509 | } |
| 121510 | pWC->a = pOld; |
| @@ -121985,11 +122342,11 @@ | |
| 121985 | for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ |
| 121986 | if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ |
| 121987 | WhereAndInfo *pAndInfo; |
| 121988 | assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); |
| 121989 | chngToIN = 0; |
| 121990 | pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); |
| 121991 | if( pAndInfo ){ |
| 121992 | WhereClause *pAndWC; |
| 121993 | WhereTerm *pAndTerm; |
| 121994 | int j; |
| 121995 | Bitmask b = 0; |
| @@ -121999,11 +122356,10 @@ | |
| 121999 | pAndWC = &pAndInfo->wc; |
| 122000 | sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); |
| 122001 | sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); |
| 122002 | sqlite3WhereExprAnalyze(pSrc, pAndWC); |
| 122003 | pAndWC->pOuter = pWC; |
| 122004 | testcase( db->mallocFailed ); |
| 122005 | if( !db->mallocFailed ){ |
| 122006 | for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ |
| 122007 | assert( pAndTerm->pExpr ); |
| 122008 | if( allowedOp(pAndTerm->pExpr->op) ){ |
| 122009 | b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); |
| @@ -123742,11 +124098,11 @@ | |
| 123742 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 123743 | TRACE_IDX_OUTPUTS(p); |
| 123744 | |
| 123745 | if( rc!=SQLITE_OK ){ |
| 123746 | if( rc==SQLITE_NOMEM ){ |
| 123747 | pParse->db->mallocFailed = 1; |
| 123748 | }else if( !pVtab->zErrMsg ){ |
| 123749 | sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); |
| 123750 | }else{ |
| 123751 | sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); |
| 123752 | } |
| @@ -124534,11 +124890,11 @@ | |
| 124534 | */ |
| 124535 | static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ |
| 124536 | WhereTerm **paNew; |
| 124537 | if( p->nLSlot>=n ) return SQLITE_OK; |
| 124538 | n = (n+7)&~7; |
| 124539 | paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n); |
| 124540 | if( paNew==0 ) return SQLITE_NOMEM; |
| 124541 | memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); |
| 124542 | if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm); |
| 124543 | p->aLTerm = paNew; |
| 124544 | p->nLSlot = n; |
| @@ -124831,11 +125187,11 @@ | |
| 124831 | whereLoopPrint(pTemplate, pBuilder->pWC); |
| 124832 | } |
| 124833 | #endif |
| 124834 | if( p==0 ){ |
| 124835 | /* Allocate a new WhereLoop to add to the end of the list */ |
| 124836 | *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); |
| 124837 | if( p==0 ) return SQLITE_NOMEM; |
| 124838 | whereLoopInit(p); |
| 124839 | p->pNextLoop = 0; |
| 124840 | }else{ |
| 124841 | /* We will be overwriting WhereLoop p[]. But before we do, first |
| @@ -126328,11 +126684,11 @@ | |
| 126328 | } |
| 126329 | |
| 126330 | /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ |
| 126331 | nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; |
| 126332 | nSpace += sizeof(LogEst) * nOrderBy; |
| 126333 | pSpace = sqlite3DbMallocRaw(db, nSpace); |
| 126334 | if( pSpace==0 ) return SQLITE_NOMEM; |
| 126335 | aTo = (WherePath*)pSpace; |
| 126336 | aFrom = aTo+mxChoice; |
| 126337 | memset(aFrom, 0, sizeof(aFrom[0])); |
| 126338 | pX = (WhereLoop**)(aFrom+mxChoice); |
| @@ -126813,11 +127169,11 @@ | |
| 126813 | WhereLevel *pLevel; /* A single level in pWInfo->a[] */ |
| 126814 | WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ |
| 126815 | int ii; /* Loop counter */ |
| 126816 | sqlite3 *db; /* Database connection */ |
| 126817 | int rc; /* Return code */ |
| 126818 | u8 bFordelete = 0; |
| 126819 | |
| 126820 | assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( |
| 126821 | (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 |
| 126822 | && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 |
| 126823 | )); |
| @@ -127058,20 +127414,19 @@ | |
| 127058 | WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); |
| 127059 | pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; |
| 127060 | |
| 127061 | /* If the caller is an UPDATE or DELETE statement that is requesting |
| 127062 | ** to use a one-pass algorithm, determine if this is appropriate. |
| 127063 | ** The one-pass algorithm only works if the WHERE clause constrains |
| 127064 | ** the statement to update or delete a single row. |
| 127065 | */ |
| 127066 | assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); |
| 127067 | if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ |
| 127068 | int wsFlags = pWInfo->a[0].pWLoop->wsFlags; |
| 127069 | int bOnerow = (wsFlags & WHERE_ONEROW)!=0; |
| 127070 | if( bOnerow || ( (wctrlFlags & WHERE_ONEPASS_MULTIROW) |
| 127071 | && 0==(wsFlags & WHERE_VIRTUALTABLE) |
| 127072 | )){ |
| 127073 | pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; |
| 127074 | if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ |
| 127075 | if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ |
| 127076 | bFordelete = OPFLAG_FORDELETE; |
| 127077 | } |
| @@ -127511,10 +127866,19 @@ | |
| 127511 | /* |
| 127512 | ** An instance of this structure holds the ATTACH key and the key type. |
| 127513 | */ |
| 127514 | struct AttachKey { int type; Token key; }; |
| 127515 | |
| 127516 | |
| 127517 | /* |
| 127518 | ** For a compound SELECT statement, make sure p->pPrior->pNext==p for |
| 127519 | ** all elements in the list. And make sure list length does not exceed |
| 127520 | ** SQLITE_LIMIT_COMPOUND_SELECT. |
| @@ -127593,11 +127957,11 @@ | |
| 127593 | |
| 127594 | /* A routine to convert a binary TK_IS or TK_ISNOT expression into a |
| 127595 | ** unary TK_ISNULL or TK_NOTNULL expression. */ |
| 127596 | static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ |
| 127597 | sqlite3 *db = pParse->db; |
| 127598 | if( pY && pA && pY->op==TK_NULL ){ |
| 127599 | pA->op = (u8)op; |
| 127600 | sqlite3ExprDelete(db, pA->pRight); |
| 127601 | pA->pRight = 0; |
| 127602 | } |
| 127603 | } |
| @@ -129635,11 +129999,11 @@ | |
| 129635 | sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); |
| 129636 | } |
| 129637 | break; |
| 129638 | case 27: /* createkw ::= CREATE */ |
| 129639 | { |
| 129640 | pParse->db->lookaside.bEnabled = 0; |
| 129641 | yygotominor.yy0 = yymsp[0].minor.yy0; |
| 129642 | } |
| 129643 | break; |
| 129644 | case 28: /* ifnotexists ::= */ |
| 129645 | case 31: /* temp ::= */ yytestcase(yyruleno==31); |
| @@ -130717,11 +131081,11 @@ | |
| 130717 | sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); |
| 130718 | } |
| 130719 | break; |
| 130720 | case 307: /* add_column_fullname ::= fullname */ |
| 130721 | { |
| 130722 | pParse->db->lookaside.bEnabled = 0; |
| 130723 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); |
| 130724 | } |
| 130725 | break; |
| 130726 | case 310: /* cmd ::= create_vtab */ |
| 130727 | {sqlite3VtabFinishParse(pParse,0);} |
| @@ -131097,16 +131461,96 @@ | |
| 131097 | ** parser for analysis. |
| 131098 | */ |
| 131099 | /* #include "sqliteInt.h" */ |
| 131100 | /* #include <stdlib.h> */ |
| 131101 | |
| 131102 | /* |
| 131103 | ** The charMap() macro maps alphabetic characters into their |
| 131104 | ** lower-case ASCII equivalent. On ASCII machines, this is just |
| 131105 | ** an upper-to-lower case map. On EBCDIC machines we also need |
| 131106 | ** to adjust the encoding. Only alphabetic characters and underscores |
| 131107 | ** need to be translated. |
| 131108 | */ |
| 131109 | #ifdef SQLITE_ASCII |
| 131110 | # define charMap(X) sqlite3UpperToLower[(unsigned char)X] |
| 131111 | #endif |
| 131112 | #ifdef SQLITE_EBCDIC |
| @@ -131136,11 +131580,11 @@ | |
| 131136 | ** The sqlite3KeywordCode function looks up an identifier to determine if |
| 131137 | ** it is a keyword. If it is a keyword, the token code of that keyword is |
| 131138 | ** returned. If the input is not a keyword, TK_ID is returned. |
| 131139 | ** |
| 131140 | ** The implementation of this routine was generated by a program, |
| 131141 | ** mkkeywordhash.h, located in the tool subdirectory of the distribution. |
| 131142 | ** The output of the mkkeywordhash.c program is written into a file |
| 131143 | ** named keywordhash.h and then included into this source file by |
| 131144 | ** the #include below. |
| 131145 | */ |
| 131146 | /************** Include keywordhash.h in the middle of tokenize.c ************/ |
| @@ -131277,142 +131721,151 @@ | |
| 131277 | TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, |
| 131278 | TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, |
| 131279 | TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, |
| 131280 | TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, |
| 131281 | }; |
| 131282 | int h, i; |
| 131283 | if( n>=2 ){ |
| 131284 | h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; |
| 131285 | for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ |
| 131286 | if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ |
| 131287 | testcase( i==0 ); /* REINDEX */ |
| 131288 | testcase( i==1 ); /* INDEXED */ |
| 131289 | testcase( i==2 ); /* INDEX */ |
| 131290 | testcase( i==3 ); /* DESC */ |
| 131291 | testcase( i==4 ); /* ESCAPE */ |
| 131292 | testcase( i==5 ); /* EACH */ |
| 131293 | testcase( i==6 ); /* CHECK */ |
| 131294 | testcase( i==7 ); /* KEY */ |
| 131295 | testcase( i==8 ); /* BEFORE */ |
| 131296 | testcase( i==9 ); /* FOREIGN */ |
| 131297 | testcase( i==10 ); /* FOR */ |
| 131298 | testcase( i==11 ); /* IGNORE */ |
| 131299 | testcase( i==12 ); /* REGEXP */ |
| 131300 | testcase( i==13 ); /* EXPLAIN */ |
| 131301 | testcase( i==14 ); /* INSTEAD */ |
| 131302 | testcase( i==15 ); /* ADD */ |
| 131303 | testcase( i==16 ); /* DATABASE */ |
| 131304 | testcase( i==17 ); /* AS */ |
| 131305 | testcase( i==18 ); /* SELECT */ |
| 131306 | testcase( i==19 ); /* TABLE */ |
| 131307 | testcase( i==20 ); /* LEFT */ |
| 131308 | testcase( i==21 ); /* THEN */ |
| 131309 | testcase( i==22 ); /* END */ |
| 131310 | testcase( i==23 ); /* DEFERRABLE */ |
| 131311 | testcase( i==24 ); /* ELSE */ |
| 131312 | testcase( i==25 ); /* EXCEPT */ |
| 131313 | testcase( i==26 ); /* TRANSACTION */ |
| 131314 | testcase( i==27 ); /* ACTION */ |
| 131315 | testcase( i==28 ); /* ON */ |
| 131316 | testcase( i==29 ); /* NATURAL */ |
| 131317 | testcase( i==30 ); /* ALTER */ |
| 131318 | testcase( i==31 ); /* RAISE */ |
| 131319 | testcase( i==32 ); /* EXCLUSIVE */ |
| 131320 | testcase( i==33 ); /* EXISTS */ |
| 131321 | testcase( i==34 ); /* SAVEPOINT */ |
| 131322 | testcase( i==35 ); /* INTERSECT */ |
| 131323 | testcase( i==36 ); /* TRIGGER */ |
| 131324 | testcase( i==37 ); /* REFERENCES */ |
| 131325 | testcase( i==38 ); /* CONSTRAINT */ |
| 131326 | testcase( i==39 ); /* INTO */ |
| 131327 | testcase( i==40 ); /* OFFSET */ |
| 131328 | testcase( i==41 ); /* OF */ |
| 131329 | testcase( i==42 ); /* SET */ |
| 131330 | testcase( i==43 ); /* TEMPORARY */ |
| 131331 | testcase( i==44 ); /* TEMP */ |
| 131332 | testcase( i==45 ); /* OR */ |
| 131333 | testcase( i==46 ); /* UNIQUE */ |
| 131334 | testcase( i==47 ); /* QUERY */ |
| 131335 | testcase( i==48 ); /* WITHOUT */ |
| 131336 | testcase( i==49 ); /* WITH */ |
| 131337 | testcase( i==50 ); /* OUTER */ |
| 131338 | testcase( i==51 ); /* RELEASE */ |
| 131339 | testcase( i==52 ); /* ATTACH */ |
| 131340 | testcase( i==53 ); /* HAVING */ |
| 131341 | testcase( i==54 ); /* GROUP */ |
| 131342 | testcase( i==55 ); /* UPDATE */ |
| 131343 | testcase( i==56 ); /* BEGIN */ |
| 131344 | testcase( i==57 ); /* INNER */ |
| 131345 | testcase( i==58 ); /* RECURSIVE */ |
| 131346 | testcase( i==59 ); /* BETWEEN */ |
| 131347 | testcase( i==60 ); /* NOTNULL */ |
| 131348 | testcase( i==61 ); /* NOT */ |
| 131349 | testcase( i==62 ); /* NO */ |
| 131350 | testcase( i==63 ); /* NULL */ |
| 131351 | testcase( i==64 ); /* LIKE */ |
| 131352 | testcase( i==65 ); /* CASCADE */ |
| 131353 | testcase( i==66 ); /* ASC */ |
| 131354 | testcase( i==67 ); /* DELETE */ |
| 131355 | testcase( i==68 ); /* CASE */ |
| 131356 | testcase( i==69 ); /* COLLATE */ |
| 131357 | testcase( i==70 ); /* CREATE */ |
| 131358 | testcase( i==71 ); /* CURRENT_DATE */ |
| 131359 | testcase( i==72 ); /* DETACH */ |
| 131360 | testcase( i==73 ); /* IMMEDIATE */ |
| 131361 | testcase( i==74 ); /* JOIN */ |
| 131362 | testcase( i==75 ); /* INSERT */ |
| 131363 | testcase( i==76 ); /* MATCH */ |
| 131364 | testcase( i==77 ); /* PLAN */ |
| 131365 | testcase( i==78 ); /* ANALYZE */ |
| 131366 | testcase( i==79 ); /* PRAGMA */ |
| 131367 | testcase( i==80 ); /* ABORT */ |
| 131368 | testcase( i==81 ); /* VALUES */ |
| 131369 | testcase( i==82 ); /* VIRTUAL */ |
| 131370 | testcase( i==83 ); /* LIMIT */ |
| 131371 | testcase( i==84 ); /* WHEN */ |
| 131372 | testcase( i==85 ); /* WHERE */ |
| 131373 | testcase( i==86 ); /* RENAME */ |
| 131374 | testcase( i==87 ); /* AFTER */ |
| 131375 | testcase( i==88 ); /* REPLACE */ |
| 131376 | testcase( i==89 ); /* AND */ |
| 131377 | testcase( i==90 ); /* DEFAULT */ |
| 131378 | testcase( i==91 ); /* AUTOINCREMENT */ |
| 131379 | testcase( i==92 ); /* TO */ |
| 131380 | testcase( i==93 ); /* IN */ |
| 131381 | testcase( i==94 ); /* CAST */ |
| 131382 | testcase( i==95 ); /* COLUMN */ |
| 131383 | testcase( i==96 ); /* COMMIT */ |
| 131384 | testcase( i==97 ); /* CONFLICT */ |
| 131385 | testcase( i==98 ); /* CROSS */ |
| 131386 | testcase( i==99 ); /* CURRENT_TIMESTAMP */ |
| 131387 | testcase( i==100 ); /* CURRENT_TIME */ |
| 131388 | testcase( i==101 ); /* PRIMARY */ |
| 131389 | testcase( i==102 ); /* DEFERRED */ |
| 131390 | testcase( i==103 ); /* DISTINCT */ |
| 131391 | testcase( i==104 ); /* IS */ |
| 131392 | testcase( i==105 ); /* DROP */ |
| 131393 | testcase( i==106 ); /* FAIL */ |
| 131394 | testcase( i==107 ); /* FROM */ |
| 131395 | testcase( i==108 ); /* FULL */ |
| 131396 | testcase( i==109 ); /* GLOB */ |
| 131397 | testcase( i==110 ); /* BY */ |
| 131398 | testcase( i==111 ); /* IF */ |
| 131399 | testcase( i==112 ); /* ISNULL */ |
| 131400 | testcase( i==113 ); /* ORDER */ |
| 131401 | testcase( i==114 ); /* RESTRICT */ |
| 131402 | testcase( i==115 ); /* RIGHT */ |
| 131403 | testcase( i==116 ); /* ROLLBACK */ |
| 131404 | testcase( i==117 ); /* ROW */ |
| 131405 | testcase( i==118 ); /* UNION */ |
| 131406 | testcase( i==119 ); /* USING */ |
| 131407 | testcase( i==120 ); /* VACUUM */ |
| 131408 | testcase( i==121 ); /* VIEW */ |
| 131409 | testcase( i==122 ); /* INITIALLY */ |
| 131410 | testcase( i==123 ); /* ALL */ |
| 131411 | *pType = aCode[i]; |
| 131412 | break; |
| 131413 | } |
| 131414 | } |
| 131415 | } |
| 131416 | return n; |
| 131417 | } |
| 131418 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ |
| @@ -131469,74 +131922,76 @@ | |
| 131469 | SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } |
| 131470 | #endif |
| 131471 | |
| 131472 | |
| 131473 | /* |
| 131474 | ** Return the length of the token that begins at z[0]. |
| 131475 | ** Store the token type in *tokenType before returning. |
| 131476 | */ |
| 131477 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ |
| 131478 | int i, c; |
| 131479 | switch( *z ){ |
| 131480 | case ' ': case '\t': case '\n': case '\f': case '\r': { |
| 131481 | testcase( z[0]==' ' ); |
| 131482 | testcase( z[0]=='\t' ); |
| 131483 | testcase( z[0]=='\n' ); |
| 131484 | testcase( z[0]=='\f' ); |
| 131485 | testcase( z[0]=='\r' ); |
| 131486 | for(i=1; sqlite3Isspace(z[i]); i++){} |
| 131487 | *tokenType = TK_SPACE; |
| 131488 | return i; |
| 131489 | } |
| 131490 | case '-': { |
| 131491 | if( z[1]=='-' ){ |
| 131492 | for(i=2; (c=z[i])!=0 && c!='\n'; i++){} |
| 131493 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131494 | return i; |
| 131495 | } |
| 131496 | *tokenType = TK_MINUS; |
| 131497 | return 1; |
| 131498 | } |
| 131499 | case '(': { |
| 131500 | *tokenType = TK_LP; |
| 131501 | return 1; |
| 131502 | } |
| 131503 | case ')': { |
| 131504 | *tokenType = TK_RP; |
| 131505 | return 1; |
| 131506 | } |
| 131507 | case ';': { |
| 131508 | *tokenType = TK_SEMI; |
| 131509 | return 1; |
| 131510 | } |
| 131511 | case '+': { |
| 131512 | *tokenType = TK_PLUS; |
| 131513 | return 1; |
| 131514 | } |
| 131515 | case '*': { |
| 131516 | *tokenType = TK_STAR; |
| 131517 | return 1; |
| 131518 | } |
| 131519 | case '/': { |
| 131520 | if( z[1]!='*' || z[2]==0 ){ |
| 131521 | *tokenType = TK_SLASH; |
| 131522 | return 1; |
| 131523 | } |
| 131524 | for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} |
| 131525 | if( c ) i++; |
| 131526 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131527 | return i; |
| 131528 | } |
| 131529 | case '%': { |
| 131530 | *tokenType = TK_REM; |
| 131531 | return 1; |
| 131532 | } |
| 131533 | case '=': { |
| 131534 | *tokenType = TK_EQ; |
| 131535 | return 1 + (z[1]=='='); |
| 131536 | } |
| 131537 | case '<': { |
| 131538 | if( (c=z[1])=='=' ){ |
| 131539 | *tokenType = TK_LE; |
| 131540 | return 2; |
| 131541 | }else if( c=='>' ){ |
| 131542 | *tokenType = TK_NE; |
| @@ -131547,11 +132002,11 @@ | |
| 131547 | }else{ |
| 131548 | *tokenType = TK_LT; |
| 131549 | return 1; |
| 131550 | } |
| 131551 | } |
| 131552 | case '>': { |
| 131553 | if( (c=z[1])=='=' ){ |
| 131554 | *tokenType = TK_GE; |
| 131555 | return 2; |
| 131556 | }else if( c=='>' ){ |
| 131557 | *tokenType = TK_RSHIFT; |
| @@ -131559,43 +132014,41 @@ | |
| 131559 | }else{ |
| 131560 | *tokenType = TK_GT; |
| 131561 | return 1; |
| 131562 | } |
| 131563 | } |
| 131564 | case '!': { |
| 131565 | if( z[1]!='=' ){ |
| 131566 | *tokenType = TK_ILLEGAL; |
| 131567 | return 2; |
| 131568 | }else{ |
| 131569 | *tokenType = TK_NE; |
| 131570 | return 2; |
| 131571 | } |
| 131572 | } |
| 131573 | case '|': { |
| 131574 | if( z[1]!='|' ){ |
| 131575 | *tokenType = TK_BITOR; |
| 131576 | return 1; |
| 131577 | }else{ |
| 131578 | *tokenType = TK_CONCAT; |
| 131579 | return 2; |
| 131580 | } |
| 131581 | } |
| 131582 | case ',': { |
| 131583 | *tokenType = TK_COMMA; |
| 131584 | return 1; |
| 131585 | } |
| 131586 | case '&': { |
| 131587 | *tokenType = TK_BITAND; |
| 131588 | return 1; |
| 131589 | } |
| 131590 | case '~': { |
| 131591 | *tokenType = TK_BITNOT; |
| 131592 | return 1; |
| 131593 | } |
| 131594 | case '`': |
| 131595 | case '\'': |
| 131596 | case '"': { |
| 131597 | int delim = z[0]; |
| 131598 | testcase( delim=='`' ); |
| 131599 | testcase( delim=='\'' ); |
| 131600 | testcase( delim=='"' ); |
| 131601 | for(i=1; (c=z[i])!=0; i++){ |
| @@ -131616,11 +132069,11 @@ | |
| 131616 | }else{ |
| 131617 | *tokenType = TK_ILLEGAL; |
| 131618 | return i; |
| 131619 | } |
| 131620 | } |
| 131621 | case '.': { |
| 131622 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 131623 | if( !sqlite3Isdigit(z[1]) ) |
| 131624 | #endif |
| 131625 | { |
| 131626 | *tokenType = TK_DOT; |
| @@ -131627,12 +132080,11 @@ | |
| 131627 | return 1; |
| 131628 | } |
| 131629 | /* If the next character is a digit, this is a floating point |
| 131630 | ** number that begins with ".". Fall thru into the next case */ |
| 131631 | } |
| 131632 | case '0': case '1': case '2': case '3': case '4': |
| 131633 | case '5': case '6': case '7': case '8': case '9': { |
| 131634 | testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); |
| 131635 | testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); |
| 131636 | testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); |
| 131637 | testcase( z[0]=='9' ); |
| 131638 | *tokenType = TK_INTEGER; |
| @@ -131663,26 +132115,22 @@ | |
| 131663 | *tokenType = TK_ILLEGAL; |
| 131664 | i++; |
| 131665 | } |
| 131666 | return i; |
| 131667 | } |
| 131668 | case '[': { |
| 131669 | for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} |
| 131670 | *tokenType = c==']' ? TK_ID : TK_ILLEGAL; |
| 131671 | return i; |
| 131672 | } |
| 131673 | case '?': { |
| 131674 | *tokenType = TK_VARIABLE; |
| 131675 | for(i=1; sqlite3Isdigit(z[i]); i++){} |
| 131676 | return i; |
| 131677 | } |
| 131678 | #ifndef SQLITE_OMIT_TCL_VARIABLE |
| 131679 | case '$': |
| 131680 | #endif |
| 131681 | case '@': /* For compatibility with MS SQL Server */ |
| 131682 | case '#': |
| 131683 | case ':': { |
| 131684 | int n = 0; |
| 131685 | testcase( z[0]=='$' ); testcase( z[0]=='@' ); |
| 131686 | testcase( z[0]==':' ); testcase( z[0]=='#' ); |
| 131687 | *tokenType = TK_VARIABLE; |
| 131688 | for(i=1; (c=z[i])!=0; i++){ |
| @@ -131707,12 +132155,24 @@ | |
| 131707 | } |
| 131708 | } |
| 131709 | if( n==0 ) *tokenType = TK_ILLEGAL; |
| 131710 | return i; |
| 131711 | } |
| 131712 | #ifndef SQLITE_OMIT_BLOB_LITERAL |
| 131713 | case 'x': case 'X': { |
| 131714 | testcase( z[0]=='x' ); testcase( z[0]=='X' ); |
| 131715 | if( z[1]=='\'' ){ |
| 131716 | *tokenType = TK_BLOB; |
| 131717 | for(i=2; sqlite3Isxdigit(z[i]); i++){} |
| 131718 | if( z[i]!='\'' || i%2 ){ |
| @@ -131720,24 +132180,26 @@ | |
| 131720 | while( z[i] && z[i]!='\'' ){ i++; } |
| 131721 | } |
| 131722 | if( z[i] ) i++; |
| 131723 | return i; |
| 131724 | } |
| 131725 | /* Otherwise fall through to the next case */ |
| 131726 | } |
| 131727 | #endif |
| 131728 | default: { |
| 131729 | if( !IdChar(*z) ){ |
| 131730 | break; |
| 131731 | } |
| 131732 | for(i=1; IdChar(z[i]); i++){} |
| 131733 | *tokenType = TK_ID; |
| 131734 | return keywordCode((char*)z, i, tokenType); |
| 131735 | } |
| 131736 | } |
| 131737 | *tokenType = TK_ILLEGAL; |
| 131738 | return 1; |
| 131739 | } |
| 131740 | |
| 131741 | /* |
| 131742 | ** Run the parser on the given SQL string. The parser structure is |
| 131743 | ** passed in. An SQLITE_ status code is returned. If an error occurs |
| @@ -131749,11 +132211,10 @@ | |
| 131749 | int nErr = 0; /* Number of errors encountered */ |
| 131750 | int i; /* Loop counter */ |
| 131751 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 131752 | int tokenType; /* type of the next token */ |
| 131753 | int lastTokenParsed = -1; /* type of the previous token */ |
| 131754 | u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 131755 | sqlite3 *db = pParse->db; /* The database connection */ |
| 131756 | int mxSqlLen; /* Max length of an SQL string */ |
| 131757 | |
| 131758 | assert( zSql!=0 ); |
| 131759 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| @@ -131765,20 +132226,18 @@ | |
| 131765 | i = 0; |
| 131766 | assert( pzErrMsg!=0 ); |
| 131767 | /* sqlite3ParserTrace(stdout, "parser: "); */ |
| 131768 | pEngine = sqlite3ParserAlloc(sqlite3Malloc); |
| 131769 | if( pEngine==0 ){ |
| 131770 | db->mallocFailed = 1; |
| 131771 | return SQLITE_NOMEM; |
| 131772 | } |
| 131773 | assert( pParse->pNewTable==0 ); |
| 131774 | assert( pParse->pNewTrigger==0 ); |
| 131775 | assert( pParse->nVar==0 ); |
| 131776 | assert( pParse->nzVar==0 ); |
| 131777 | assert( pParse->azVar==0 ); |
| 131778 | enableLookaside = db->lookaside.bEnabled; |
| 131779 | if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; |
| 131780 | while( zSql[i]!=0 ){ |
| 131781 | assert( i>=0 ); |
| 131782 | pParse->sLastToken.z = &zSql[i]; |
| 131783 | pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); |
| 131784 | i += pParse->sLastToken.n; |
| @@ -131787,11 +132246,10 @@ | |
| 131787 | break; |
| 131788 | } |
| 131789 | if( tokenType>=TK_SPACE ){ |
| 131790 | assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); |
| 131791 | if( db->u1.isInterrupted ){ |
| 131792 | sqlite3ErrorMsg(pParse, "interrupt"); |
| 131793 | pParse->rc = SQLITE_INTERRUPT; |
| 131794 | break; |
| 131795 | } |
| 131796 | if( tokenType==TK_ILLEGAL ){ |
| 131797 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", |
| @@ -131822,11 +132280,10 @@ | |
| 131822 | sqlite3ParserStackPeak(pEngine) |
| 131823 | ); |
| 131824 | sqlite3_mutex_leave(sqlite3MallocMutex()); |
| 131825 | #endif /* YYDEBUG */ |
| 131826 | sqlite3ParserFree(pEngine, sqlite3_free); |
| 131827 | db->lookaside.bEnabled = enableLookaside; |
| 131828 | if( db->mallocFailed ){ |
| 131829 | pParse->rc = SQLITE_NOMEM; |
| 131830 | } |
| 131831 | if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ |
| 131832 | pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); |
| @@ -132963,16 +133420,16 @@ | |
| 132963 | p->pNext = db->lookaside.pFree; |
| 132964 | db->lookaside.pFree = p; |
| 132965 | p = (LookasideSlot*)&((u8*)p)[sz]; |
| 132966 | } |
| 132967 | db->lookaside.pEnd = p; |
| 132968 | db->lookaside.bEnabled = 1; |
| 132969 | db->lookaside.bMalloced = pBuf==0 ?1:0; |
| 132970 | }else{ |
| 132971 | db->lookaside.pStart = db; |
| 132972 | db->lookaside.pEnd = db; |
| 132973 | db->lookaside.bEnabled = 0; |
| 132974 | db->lookaside.bMalloced = 0; |
| 132975 | } |
| 132976 | #endif /* SQLITE_OMIT_LOOKASIDE */ |
| 132977 | return SQLITE_OK; |
| 132978 | } |
| @@ -134473,11 +134930,11 @@ | |
| 134473 | /* A malloc() may have failed within the call to sqlite3_value_text16() |
| 134474 | ** above. If this is the case, then the db->mallocFailed flag needs to |
| 134475 | ** be cleared before returning. Do this directly, instead of via |
| 134476 | ** sqlite3ApiExit(), to avoid setting the database handle error message. |
| 134477 | */ |
| 134478 | db->mallocFailed = 0; |
| 134479 | } |
| 134480 | sqlite3_mutex_leave(db->mutex); |
| 134481 | return z; |
| 134482 | } |
| 134483 | #endif /* SQLITE_OMIT_UTF16 */ |
| @@ -135111,11 +135568,11 @@ | |
| 135111 | |
| 135112 | /* Parse the filename/URI argument. */ |
| 135113 | db->openFlags = flags; |
| 135114 | rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); |
| 135115 | if( rc!=SQLITE_OK ){ |
| 135116 | if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 135117 | sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); |
| 135118 | sqlite3_free(zErrMsg); |
| 135119 | goto opendb_out; |
| 135120 | } |
| 135121 | |
| @@ -135831,11 +136288,11 @@ | |
| 135831 | ** process aborts. If X is false and assert() is disabled, then the |
| 135832 | ** return value is zero. |
| 135833 | */ |
| 135834 | case SQLITE_TESTCTRL_ASSERT: { |
| 135835 | volatile int x = 0; |
| 135836 | assert( (x = va_arg(ap,int))!=0 ); |
| 135837 | rc = x; |
| 135838 | break; |
| 135839 | } |
| 135840 | |
| 135841 | |
| @@ -146361,10 +146818,11 @@ | |
| 146361 | |
| 146362 | zName = sqlite3_value_text(argv[0]); |
| 146363 | nName = sqlite3_value_bytes(argv[0])+1; |
| 146364 | |
| 146365 | if( argc==2 ){ |
| 146366 | void *pOld; |
| 146367 | int n = sqlite3_value_bytes(argv[1]); |
| 146368 | if( zName==0 || n!=sizeof(pPtr) ){ |
| 146369 | sqlite3_result_error(context, "argument type mismatch", -1); |
| 146370 | return; |
| @@ -146373,11 +146831,18 @@ | |
| 146373 | pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); |
| 146374 | if( pOld==pPtr ){ |
| 146375 | sqlite3_result_error(context, "out of memory", -1); |
| 146376 | return; |
| 146377 | } |
| 146378 | }else{ |
| 146379 | if( zName ){ |
| 146380 | pPtr = sqlite3Fts3HashFind(pHash, zName, nName); |
| 146381 | } |
| 146382 | if( !pPtr ){ |
| 146383 | char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); |
| @@ -146622,10 +147087,11 @@ | |
| 146622 | sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); |
| 146623 | } |
| 146624 | Tcl_DecrRefCount(pRet); |
| 146625 | } |
| 146626 | |
| 146627 | static |
| 146628 | int registerTokenizer( |
| 146629 | sqlite3 *db, |
| 146630 | char *zName, |
| 146631 | const sqlite3_tokenizer_module *p |
| @@ -146643,10 +147109,12 @@ | |
| 146643 | sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); |
| 146644 | sqlite3_step(pStmt); |
| 146645 | |
| 146646 | return sqlite3_finalize(pStmt); |
| 146647 | } |
| 146648 | |
| 146649 | static |
| 146650 | int queryTokenizer( |
| 146651 | sqlite3 *db, |
| 146652 | char *zName, |
| @@ -146714,15 +147182,17 @@ | |
| 146714 | assert( rc==SQLITE_ERROR ); |
| 146715 | assert( p2==0 ); |
| 146716 | assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); |
| 146717 | |
| 146718 | /* Test the storage function */ |
| 146719 | rc = registerTokenizer(db, "nosuchtokenizer", p1); |
| 146720 | assert( rc==SQLITE_OK ); |
| 146721 | rc = queryTokenizer(db, "nosuchtokenizer", &p2); |
| 146722 | assert( rc==SQLITE_OK ); |
| 146723 | assert( p2==p1 ); |
| 146724 | |
| 146725 | sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); |
| 146726 | } |
| 146727 | |
| 146728 | #endif |
| @@ -164601,11 +165071,13 @@ | |
| 164601 | StatTable *pTab = 0; |
| 164602 | int rc = SQLITE_OK; |
| 164603 | int iDb; |
| 164604 | |
| 164605 | if( argc>=4 ){ |
| 164606 | iDb = sqlite3FindDbName(db, argv[3]); |
| 164607 | if( iDb<0 ){ |
| 164608 | *pzErr = sqlite3_mprintf("no such database: %s", argv[3]); |
| 164609 | return SQLITE_ERROR; |
| 164610 | } |
| 164611 | }else{ |
| @@ -165431,14 +165903,37 @@ | |
| 165431 | static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ |
| 165432 | u32 i; |
| 165433 | if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; |
| 165434 | p->zBuf[p->nUsed++] = '"'; |
| 165435 | for(i=0; i<N; i++){ |
| 165436 | char c = zIn[i]; |
| 165437 | if( c=='"' || c=='\\' ){ |
| 165438 | if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; |
| 165439 | p->zBuf[p->nUsed++] = '\\'; |
| 165440 | } |
| 165441 | p->zBuf[p->nUsed++] = c; |
| 165442 | } |
| 165443 | p->zBuf[p->nUsed++] = '"'; |
| 165444 | assert( p->nUsed<p->nAlloc ); |
| @@ -165475,11 +165970,11 @@ | |
| 165475 | break; |
| 165476 | } |
| 165477 | default: { |
| 165478 | if( p->bErr==0 ){ |
| 165479 | sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); |
| 165480 | p->bErr = 1; |
| 165481 | jsonReset(p); |
| 165482 | } |
| 165483 | break; |
| 165484 | } |
| 165485 | } |
| @@ -166703,11 +167198,11 @@ | |
| 166703 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 166704 | if( pStr ){ |
| 166705 | pStr->pCtx = ctx; |
| 166706 | jsonAppendChar(pStr, ']'); |
| 166707 | if( pStr->bErr ){ |
| 166708 | sqlite3_result_error_nomem(ctx); |
| 166709 | assert( pStr->bStatic ); |
| 166710 | }else{ |
| 166711 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 166712 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 166713 | pStr->bStatic = 1; |
| @@ -166751,11 +167246,11 @@ | |
| 166751 | JsonString *pStr; |
| 166752 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 166753 | if( pStr ){ |
| 166754 | jsonAppendChar(pStr, '}'); |
| 166755 | if( pStr->bErr ){ |
| 166756 | sqlite3_result_error_nomem(ctx); |
| 166757 | assert( pStr->bStatic ); |
| 166758 | }else{ |
| 166759 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 166760 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 166761 | pStr->bStatic = 1; |
| @@ -167940,11 +168435,11 @@ | |
| 167940 | typedef unsigned int u32; |
| 167941 | typedef unsigned short u16; |
| 167942 | typedef sqlite3_int64 i64; |
| 167943 | typedef sqlite3_uint64 u64; |
| 167944 | |
| 167945 | #define ArraySize(x) (sizeof(x) / sizeof(x[0])) |
| 167946 | |
| 167947 | #define testcase(x) |
| 167948 | #define ALWAYS(x) 1 |
| 167949 | #define NEVER(x) 0 |
| 167950 | |
| @@ -168136,12 +168631,12 @@ | |
| 168136 | ** Buffer object for the incremental building of string data. |
| 168137 | */ |
| 168138 | typedef struct Fts5Buffer Fts5Buffer; |
| 168139 | struct Fts5Buffer { |
| 168140 | u8 *p; |
| 168141 | u32 n; |
| 168142 | u32 nSpace; |
| 168143 | }; |
| 168144 | |
| 168145 | static int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32); |
| 168146 | static void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64); |
| 168147 | static void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, u32, const u8*); |
| @@ -168158,11 +168653,11 @@ | |
| 168158 | #define fts5BufferFree(a) sqlite3Fts5BufferFree(a) |
| 168159 | #define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d) |
| 168160 | #define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) |
| 168161 | |
| 168162 | #define fts5BufferGrow(pRc,pBuf,nn) ( \ |
| 168163 | (pBuf)->n + (nn) <= (pBuf)->nSpace ? 0 : \ |
| 168164 | sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \ |
| 168165 | ) |
| 168166 | |
| 168167 | /* Write and decode big-endian 32-bit integer values */ |
| 168168 | static void sqlite3Fts5Put32(u8*, int); |
| @@ -168193,10 +168688,11 @@ | |
| 168193 | typedef struct Fts5PoslistWriter Fts5PoslistWriter; |
| 168194 | struct Fts5PoslistWriter { |
| 168195 | i64 iPrev; |
| 168196 | }; |
| 168197 | static int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); |
| 168198 | |
| 168199 | static int sqlite3Fts5PoslistNext64( |
| 168200 | const u8 *a, int n, /* Buffer containing poslist */ |
| 168201 | int *pi, /* IN/OUT: Offset within a[] */ |
| 168202 | i64 *piOff /* IN/OUT: Current offset */ |
| @@ -168226,17 +168722,32 @@ | |
| 168226 | */ |
| 168227 | |
| 168228 | typedef struct Fts5Index Fts5Index; |
| 168229 | typedef struct Fts5IndexIter Fts5IndexIter; |
| 168230 | |
| 168231 | /* |
| 168232 | ** Values used as part of the flags argument passed to IndexQuery(). |
| 168233 | */ |
| 168234 | #define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ |
| 168235 | #define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ |
| 168236 | #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ |
| 168237 | #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ |
| 168238 | |
| 168239 | /* |
| 168240 | ** Create/destroy an Fts5Index object. |
| 168241 | */ |
| 168242 | static int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); |
| @@ -168289,16 +168800,13 @@ | |
| 168289 | |
| 168290 | /* |
| 168291 | ** The various operations on open token or token prefix iterators opened |
| 168292 | ** using sqlite3Fts5IndexQuery(). |
| 168293 | */ |
| 168294 | static int sqlite3Fts5IterEof(Fts5IndexIter*); |
| 168295 | static int sqlite3Fts5IterNext(Fts5IndexIter*); |
| 168296 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); |
| 168297 | static i64 sqlite3Fts5IterRowid(Fts5IndexIter*); |
| 168298 | static int sqlite3Fts5IterPoslist(Fts5IndexIter*,Fts5Colset*, const u8**, int*, i64*); |
| 168299 | static int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf); |
| 168300 | |
| 168301 | /* |
| 168302 | ** Close an iterator opened by sqlite3Fts5IndexQuery(). |
| 168303 | */ |
| 168304 | static void sqlite3Fts5IterClose(Fts5IndexIter*); |
| @@ -168380,12 +168888,10 @@ | |
| 168380 | static int sqlite3Fts5IndexOptimize(Fts5Index *p); |
| 168381 | static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); |
| 168382 | |
| 168383 | static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); |
| 168384 | |
| 168385 | static int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*); |
| 168386 | |
| 168387 | /* |
| 168388 | ** End of interface to code in fts5_index.c. |
| 168389 | **************************************************************************/ |
| 168390 | |
| 168391 | /************************************************************************** |
| @@ -170432,11 +170938,11 @@ | |
| 170432 | { "bm25", 0, fts5Bm25Function, 0 }, |
| 170433 | }; |
| 170434 | int rc = SQLITE_OK; /* Return code */ |
| 170435 | int i; /* To iterate through builtin functions */ |
| 170436 | |
| 170437 | for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ |
| 170438 | rc = pApi->xCreateFunction(pApi, |
| 170439 | aBuiltin[i].zFunc, |
| 170440 | aBuiltin[i].pUserData, |
| 170441 | aBuiltin[i].xFunc, |
| 170442 | aBuiltin[i].xDestroy |
| @@ -170464,22 +170970,24 @@ | |
| 170464 | |
| 170465 | |
| 170466 | /* #include "fts5Int.h" */ |
| 170467 | |
| 170468 | static int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){ |
| 170469 | u32 nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64; |
| 170470 | u8 *pNew; |
| 170471 | while( nNew<nByte ){ |
| 170472 | nNew = nNew * 2; |
| 170473 | } |
| 170474 | pNew = sqlite3_realloc(pBuf->p, nNew); |
| 170475 | if( pNew==0 ){ |
| 170476 | *pRc = SQLITE_NOMEM; |
| 170477 | return 1; |
| 170478 | }else{ |
| 170479 | pBuf->nSpace = nNew; |
| 170480 | pBuf->p = pNew; |
| 170481 | } |
| 170482 | return 0; |
| 170483 | } |
| 170484 | |
| 170485 | |
| @@ -170655,28 +171163,41 @@ | |
| 170655 | pIter->a = a; |
| 170656 | pIter->n = n; |
| 170657 | sqlite3Fts5PoslistReaderNext(pIter); |
| 170658 | return pIter->bEof; |
| 170659 | } |
| 170660 | |
| 170661 | static int sqlite3Fts5PoslistWriterAppend( |
| 170662 | Fts5Buffer *pBuf, |
| 170663 | Fts5PoslistWriter *pWriter, |
| 170664 | i64 iPos |
| 170665 | ){ |
| 170666 | static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; |
| 170667 | int rc = SQLITE_OK; |
| 170668 | if( 0==fts5BufferGrow(&rc, pBuf, 5+5+5) ){ |
| 170669 | if( (iPos & colmask) != (pWriter->iPrev & colmask) ){ |
| 170670 | pBuf->p[pBuf->n++] = 1; |
| 170671 | pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); |
| 170672 | pWriter->iPrev = (iPos & colmask); |
| 170673 | } |
| 170674 | pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-pWriter->iPrev)+2); |
| 170675 | pWriter->iPrev = iPos; |
| 170676 | } |
| 170677 | return rc; |
| 170678 | } |
| 170679 | |
| 170680 | static void *sqlite3Fts5MallocZero(int *pRc, int nByte){ |
| 170681 | void *pRet = 0; |
| 170682 | if( *pRc==SQLITE_OK ){ |
| @@ -170770,11 +171291,11 @@ | |
| 170770 | ){ |
| 170771 | int rc = SQLITE_OK; |
| 170772 | *pbPresent = 0; |
| 170773 | if( p ){ |
| 170774 | int i; |
| 170775 | int hash = 13; |
| 170776 | Fts5TermsetEntry *pEntry; |
| 170777 | |
| 170778 | /* Calculate a hash value for this term. This is the same hash checksum |
| 170779 | ** used by the fts5_hash.c module. This is not important for correct |
| 170780 | ** operation of the module, but is necessary to ensure that some tests |
| @@ -170787,11 +171308,11 @@ | |
| 170787 | |
| 170788 | for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){ |
| 170789 | if( pEntry->iIdx==iIdx |
| 170790 | && pEntry->nTerm==nTerm |
| 170791 | && memcmp(pEntry->pTerm, pTerm, nTerm)==0 |
| 170792 | ){ |
| 170793 | *pbPresent = 1; |
| 170794 | break; |
| 170795 | } |
| 170796 | } |
| 170797 | |
| @@ -170811,11 +171332,11 @@ | |
| 170811 | return rc; |
| 170812 | } |
| 170813 | |
| 170814 | static void sqlite3Fts5TermsetFree(Fts5Termset *p){ |
| 170815 | if( p ){ |
| 170816 | int i; |
| 170817 | for(i=0; i<ArraySize(p->apHash); i++){ |
| 170818 | Fts5TermsetEntry *pEntry = p->apHash[i]; |
| 170819 | while( pEntry ){ |
| 170820 | Fts5TermsetEntry *pDel = pEntry; |
| 170821 | pEntry = pEntry->pNext; |
| @@ -171838,10 +172359,13 @@ | |
| 171838 | struct Fts5ExprNode { |
| 171839 | int eType; /* Node type */ |
| 171840 | int bEof; /* True at EOF */ |
| 171841 | int bNomatch; /* True if entry is not a match */ |
| 171842 | |
| 171843 | i64 iRowid; /* Current rowid */ |
| 171844 | Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ |
| 171845 | |
| 171846 | /* Child nodes. For a NOT node, this array always contains 2 entries. For |
| 171847 | ** AND or OR nodes, it contains 2 or more entries. */ |
| @@ -171849,10 +172373,16 @@ | |
| 171849 | Fts5ExprNode *apChild[1]; /* Array of child nodes */ |
| 171850 | }; |
| 171851 | |
| 171852 | #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) |
| 171853 | |
| 171854 | /* |
| 171855 | ** An instance of the following structure represents a single search term |
| 171856 | ** or term prefix. |
| 171857 | */ |
| 171858 | struct Fts5ExprTerm { |
| @@ -172010,11 +172540,19 @@ | |
| 172010 | *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); |
| 172011 | if( pNew==0 ){ |
| 172012 | sParse.rc = SQLITE_NOMEM; |
| 172013 | sqlite3Fts5ParseNodeFree(sParse.pExpr); |
| 172014 | }else{ |
| 172015 | pNew->pRoot = sParse.pExpr; |
| 172016 | pNew->pIndex = 0; |
| 172017 | pNew->pConfig = pConfig; |
| 172018 | pNew->apExprPhrase = sParse.apPhrase; |
| 172019 | pNew->nPhrase = sParse.nPhrase; |
| 172020 | sParse.apPhrase = 0; |
| @@ -172062,11 +172600,11 @@ | |
| 172062 | |
| 172063 | assert( pTerm->pSynonym ); |
| 172064 | assert( bDesc==0 || bDesc==1 ); |
| 172065 | for(p=pTerm; p; p=p->pSynonym){ |
| 172066 | if( 0==sqlite3Fts5IterEof(p->pIter) ){ |
| 172067 | i64 iRowid = sqlite3Fts5IterRowid(p->pIter); |
| 172068 | if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){ |
| 172069 | iRet = iRowid; |
| 172070 | bRetValid = 1; |
| 172071 | } |
| 172072 | } |
| @@ -172082,11 +172620,11 @@ | |
| 172082 | static int fts5ExprSynonymList( |
| 172083 | Fts5ExprTerm *pTerm, |
| 172084 | int bCollist, |
| 172085 | Fts5Colset *pColset, |
| 172086 | i64 iRowid, |
| 172087 | int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ |
| 172088 | u8 **pa, int *pn |
| 172089 | ){ |
| 172090 | Fts5PoslistReader aStatic[4]; |
| 172091 | Fts5PoslistReader *aIter = aStatic; |
| 172092 | int nIter = 0; |
| @@ -172095,23 +172633,12 @@ | |
| 172095 | Fts5ExprTerm *p; |
| 172096 | |
| 172097 | assert( pTerm->pSynonym ); |
| 172098 | for(p=pTerm; p; p=p->pSynonym){ |
| 172099 | Fts5IndexIter *pIter = p->pIter; |
| 172100 | if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){ |
| 172101 | const u8 *a; |
| 172102 | int n; |
| 172103 | |
| 172104 | if( bCollist ){ |
| 172105 | rc = sqlite3Fts5IterCollist(pIter, &a, &n); |
| 172106 | }else{ |
| 172107 | i64 dummy; |
| 172108 | rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy); |
| 172109 | } |
| 172110 | |
| 172111 | if( rc!=SQLITE_OK ) goto synonym_poslist_out; |
| 172112 | if( n==0 ) continue; |
| 172113 | if( nIter==nAlloc ){ |
| 172114 | int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; |
| 172115 | Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172116 | if( aNew==0 ){ |
| 172117 | rc = SQLITE_NOMEM; |
| @@ -172120,24 +172647,23 @@ | |
| 172120 | memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); |
| 172121 | nAlloc = nAlloc*2; |
| 172122 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| 172123 | aIter = aNew; |
| 172124 | } |
| 172125 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]); |
| 172126 | assert( aIter[nIter].bEof==0 ); |
| 172127 | nIter++; |
| 172128 | } |
| 172129 | } |
| 172130 | |
| 172131 | assert( *pbDel==0 ); |
| 172132 | if( nIter==1 ){ |
| 172133 | *pa = (u8*)aIter[0].a; |
| 172134 | *pn = aIter[0].n; |
| 172135 | }else{ |
| 172136 | Fts5PoslistWriter writer = {0}; |
| 172137 | Fts5Buffer buf = {0,0,0}; |
| 172138 | i64 iPrev = -1; |
| 172139 | while( 1 ){ |
| 172140 | int i; |
| 172141 | i64 iMin = FTS5_LARGEST_INT64; |
| 172142 | for(i=0; i<nIter; i++){ |
| 172143 | if( aIter[i].bEof==0 ){ |
| @@ -172148,19 +172674,16 @@ | |
| 172148 | iMin = aIter[i].iPos; |
| 172149 | } |
| 172150 | } |
| 172151 | } |
| 172152 | if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break; |
| 172153 | rc = sqlite3Fts5PoslistWriterAppend(&buf, &writer, iMin); |
| 172154 | iPrev = iMin; |
| 172155 | } |
| 172156 | if( rc ){ |
| 172157 | sqlite3_free(buf.p); |
| 172158 | }else{ |
| 172159 | *pa = buf.p; |
| 172160 | *pn = buf.n; |
| 172161 | *pbDel = 1; |
| 172162 | } |
| 172163 | } |
| 172164 | |
| 172165 | synonym_poslist_out: |
| 172166 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| @@ -172193,32 +172716,37 @@ | |
| 172193 | |
| 172194 | fts5BufferZero(&pPhrase->poslist); |
| 172195 | |
| 172196 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172197 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172198 | if( pPhrase->nTerm>(int)ArraySize(aStatic) ){ |
| 172199 | int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; |
| 172200 | aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172201 | if( !aIter ) return SQLITE_NOMEM; |
| 172202 | } |
| 172203 | memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm); |
| 172204 | |
| 172205 | /* Initialize a term iterator for each term in the phrase */ |
| 172206 | for(i=0; i<pPhrase->nTerm; i++){ |
| 172207 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 172208 | i64 dummy; |
| 172209 | int n = 0; |
| 172210 | int bFlag = 0; |
| 172211 | const u8 *a = 0; |
| 172212 | if( pTerm->pSynonym ){ |
| 172213 | rc = fts5ExprSynonymList( |
| 172214 | pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n |
| 172215 | ); |
| 172216 | }else{ |
| 172217 | rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); |
| 172218 | } |
| 172219 | if( rc!=SQLITE_OK ) goto ismatch_out; |
| 172220 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); |
| 172221 | aIter[i].bFlag = (u8)bFlag; |
| 172222 | if( aIter[i].bEof ) goto ismatch_out; |
| 172223 | } |
| 172224 | |
| @@ -172286,16 +172814,10 @@ | |
| 172286 | p->n = n; |
| 172287 | fts5LookaheadReaderNext(p); |
| 172288 | return fts5LookaheadReaderNext(p); |
| 172289 | } |
| 172290 | |
| 172291 | #if 0 |
| 172292 | static int fts5LookaheadReaderEof(Fts5LookaheadReader *p){ |
| 172293 | return (p->iPos==FTS5_LOOKAHEAD_EOF); |
| 172294 | } |
| 172295 | #endif |
| 172296 | |
| 172297 | typedef struct Fts5NearTrimmer Fts5NearTrimmer; |
| 172298 | struct Fts5NearTrimmer { |
| 172299 | Fts5LookaheadReader reader; /* Input iterator */ |
| 172300 | Fts5PoslistWriter writer; /* Writer context */ |
| 172301 | Fts5Buffer *pOut; /* Output poslist */ |
| @@ -172329,11 +172851,11 @@ | |
| 172329 | |
| 172330 | assert( pNear->nPhrase>1 ); |
| 172331 | |
| 172332 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172333 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172334 | if( pNear->nPhrase>(int)ArraySize(aStatic) ){ |
| 172335 | int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; |
| 172336 | a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); |
| 172337 | }else{ |
| 172338 | memset(aStatic, 0, sizeof(aStatic)); |
| 172339 | } |
| @@ -172406,75 +172928,10 @@ | |
| 172406 | if( a!=aStatic ) sqlite3_free(a); |
| 172407 | return bRet; |
| 172408 | } |
| 172409 | } |
| 172410 | |
| 172411 | /* |
| 172412 | ** Advance the first term iterator in the first phrase of pNear. Set output |
| 172413 | ** variable *pbEof to true if it reaches EOF or if an error occurs. |
| 172414 | ** |
| 172415 | ** Return SQLITE_OK if successful, or an SQLite error code if an error |
| 172416 | ** occurs. |
| 172417 | */ |
| 172418 | static int fts5ExprNearAdvanceFirst( |
| 172419 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 172420 | Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ |
| 172421 | int bFromValid, |
| 172422 | i64 iFrom |
| 172423 | ){ |
| 172424 | Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; |
| 172425 | int rc = SQLITE_OK; |
| 172426 | |
| 172427 | if( pTerm->pSynonym ){ |
| 172428 | int bEof = 1; |
| 172429 | Fts5ExprTerm *p; |
| 172430 | |
| 172431 | /* Find the firstest rowid any synonym points to. */ |
| 172432 | i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); |
| 172433 | |
| 172434 | /* Advance each iterator that currently points to iRowid. Or, if iFrom |
| 172435 | ** is valid - each iterator that points to a rowid before iFrom. */ |
| 172436 | for(p=pTerm; p; p=p->pSynonym){ |
| 172437 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 172438 | i64 ii = sqlite3Fts5IterRowid(p->pIter); |
| 172439 | if( ii==iRowid |
| 172440 | || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) |
| 172441 | ){ |
| 172442 | if( bFromValid ){ |
| 172443 | rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); |
| 172444 | }else{ |
| 172445 | rc = sqlite3Fts5IterNext(p->pIter); |
| 172446 | } |
| 172447 | if( rc!=SQLITE_OK ) break; |
| 172448 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 172449 | bEof = 0; |
| 172450 | } |
| 172451 | }else{ |
| 172452 | bEof = 0; |
| 172453 | } |
| 172454 | } |
| 172455 | } |
| 172456 | |
| 172457 | /* Set the EOF flag if either all synonym iterators are at EOF or an |
| 172458 | ** error has occurred. */ |
| 172459 | pNode->bEof = (rc || bEof); |
| 172460 | }else{ |
| 172461 | Fts5IndexIter *pIter = pTerm->pIter; |
| 172462 | |
| 172463 | assert( Fts5NodeIsString(pNode) ); |
| 172464 | if( bFromValid ){ |
| 172465 | rc = sqlite3Fts5IterNextFrom(pIter, iFrom); |
| 172466 | }else{ |
| 172467 | rc = sqlite3Fts5IterNext(pIter); |
| 172468 | } |
| 172469 | |
| 172470 | pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); |
| 172471 | } |
| 172472 | |
| 172473 | return rc; |
| 172474 | } |
| 172475 | |
| 172476 | /* |
| 172477 | ** Advance iterator pIter until it points to a value equal to or laster |
| 172478 | ** than the initial value of *piLast. If this means the iterator points |
| 172479 | ** to a value laster than *piLast, update *piLast to the new lastest value. |
| 172480 | ** |
| @@ -172490,19 +172947,19 @@ | |
| 172490 | int *pbEof /* OUT: Set to true if EOF */ |
| 172491 | ){ |
| 172492 | i64 iLast = *piLast; |
| 172493 | i64 iRowid; |
| 172494 | |
| 172495 | iRowid = sqlite3Fts5IterRowid(pIter); |
| 172496 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172497 | int rc = sqlite3Fts5IterNextFrom(pIter, iLast); |
| 172498 | if( rc || sqlite3Fts5IterEof(pIter) ){ |
| 172499 | *pRc = rc; |
| 172500 | *pbEof = 1; |
| 172501 | return 1; |
| 172502 | } |
| 172503 | iRowid = sqlite3Fts5IterRowid(pIter); |
| 172504 | assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) ); |
| 172505 | } |
| 172506 | *piLast = iRowid; |
| 172507 | |
| 172508 | return 0; |
| @@ -172519,11 +172976,11 @@ | |
| 172519 | Fts5ExprTerm *p; |
| 172520 | int bEof = 0; |
| 172521 | |
| 172522 | for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){ |
| 172523 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 172524 | i64 iRowid = sqlite3Fts5IterRowid(p->pIter); |
| 172525 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172526 | rc = sqlite3Fts5IterNextFrom(p->pIter, iLast); |
| 172527 | } |
| 172528 | } |
| 172529 | } |
| @@ -172551,17 +173008,11 @@ | |
| 172551 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 172552 | pPhrase->poslist.n = 0; |
| 172553 | for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ |
| 172554 | Fts5IndexIter *pIter = pTerm->pIter; |
| 172555 | if( sqlite3Fts5IterEof(pIter)==0 ){ |
| 172556 | int n; |
| 172557 | i64 iRowid; |
| 172558 | rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid); |
| 172559 | if( rc!=SQLITE_OK ){ |
| 172560 | *pRc = rc; |
| 172561 | return 0; |
| 172562 | }else if( iRowid==pNode->iRowid && n>0 ){ |
| 172563 | pPhrase->poslist.n = 1; |
| 172564 | } |
| 172565 | } |
| 172566 | } |
| 172567 | return pPhrase->poslist.n; |
| @@ -172576,13 +173027,12 @@ | |
| 172576 | if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ |
| 172577 | int bMatch = 0; |
| 172578 | rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch); |
| 172579 | if( bMatch==0 ) break; |
| 172580 | }else{ |
| 172581 | rc = sqlite3Fts5IterPoslistBuffer( |
| 172582 | pPhrase->aTerm[0].pIter, &pPhrase->poslist |
| 172583 | ); |
| 172584 | } |
| 172585 | } |
| 172586 | |
| 172587 | *pRc = rc; |
| 172588 | if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){ |
| @@ -172590,107 +173040,10 @@ | |
| 172590 | } |
| 172591 | return 0; |
| 172592 | } |
| 172593 | } |
| 172594 | |
| 172595 | static int fts5ExprTokenTest( |
| 172596 | Fts5Expr *pExpr, /* Expression that pNear is a part of */ |
| 172597 | Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ |
| 172598 | ){ |
| 172599 | /* As this "NEAR" object is actually a single phrase that consists |
| 172600 | ** of a single term only, grab pointers into the poslist managed by the |
| 172601 | ** fts5_index.c iterator object. This is much faster than synthesizing |
| 172602 | ** a new poslist the way we have to for more complicated phrase or NEAR |
| 172603 | ** expressions. */ |
| 172604 | Fts5ExprNearset *pNear = pNode->pNear; |
| 172605 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 172606 | Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 172607 | Fts5Colset *pColset = pNear->pColset; |
| 172608 | int rc; |
| 172609 | |
| 172610 | assert( pNode->eType==FTS5_TERM ); |
| 172611 | assert( pNear->nPhrase==1 && pPhrase->nTerm==1 ); |
| 172612 | assert( pPhrase->aTerm[0].pSynonym==0 ); |
| 172613 | |
| 172614 | rc = sqlite3Fts5IterPoslist(pIter, pColset, |
| 172615 | (const u8**)&pPhrase->poslist.p, (int*)&pPhrase->poslist.n, &pNode->iRowid |
| 172616 | ); |
| 172617 | pNode->bNomatch = (pPhrase->poslist.n==0); |
| 172618 | return rc; |
| 172619 | } |
| 172620 | |
| 172621 | /* |
| 172622 | ** All individual term iterators in pNear are guaranteed to be valid when |
| 172623 | ** this function is called. This function checks if all term iterators |
| 172624 | ** point to the same rowid, and if not, advances them until they do. |
| 172625 | ** If an EOF is reached before this happens, *pbEof is set to true before |
| 172626 | ** returning. |
| 172627 | ** |
| 172628 | ** SQLITE_OK is returned if an error occurs, or an SQLite error code |
| 172629 | ** otherwise. It is not considered an error code if an iterator reaches |
| 172630 | ** EOF. |
| 172631 | */ |
| 172632 | static int fts5ExprNearNextMatch( |
| 172633 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 172634 | Fts5ExprNode *pNode |
| 172635 | ){ |
| 172636 | Fts5ExprNearset *pNear = pNode->pNear; |
| 172637 | Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; |
| 172638 | int rc = SQLITE_OK; |
| 172639 | i64 iLast; /* Lastest rowid any iterator points to */ |
| 172640 | int i, j; /* Phrase and token index, respectively */ |
| 172641 | int bMatch; /* True if all terms are at the same rowid */ |
| 172642 | const int bDesc = pExpr->bDesc; |
| 172643 | |
| 172644 | /* Check that this node should not be FTS5_TERM */ |
| 172645 | assert( pNear->nPhrase>1 |
| 172646 | || pNear->apPhrase[0]->nTerm>1 |
| 172647 | || pNear->apPhrase[0]->aTerm[0].pSynonym |
| 172648 | ); |
| 172649 | |
| 172650 | /* Initialize iLast, the "lastest" rowid any iterator points to. If the |
| 172651 | ** iterator skips through rowids in the default ascending order, this means |
| 172652 | ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it |
| 172653 | ** means the minimum rowid. */ |
| 172654 | if( pLeft->aTerm[0].pSynonym ){ |
| 172655 | iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); |
| 172656 | }else{ |
| 172657 | iLast = sqlite3Fts5IterRowid(pLeft->aTerm[0].pIter); |
| 172658 | } |
| 172659 | |
| 172660 | do { |
| 172661 | bMatch = 1; |
| 172662 | for(i=0; i<pNear->nPhrase; i++){ |
| 172663 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 172664 | for(j=0; j<pPhrase->nTerm; j++){ |
| 172665 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; |
| 172666 | if( pTerm->pSynonym ){ |
| 172667 | i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); |
| 172668 | if( iRowid==iLast ) continue; |
| 172669 | bMatch = 0; |
| 172670 | if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ |
| 172671 | pNode->bEof = 1; |
| 172672 | return rc; |
| 172673 | } |
| 172674 | }else{ |
| 172675 | Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; |
| 172676 | i64 iRowid = sqlite3Fts5IterRowid(pIter); |
| 172677 | if( iRowid==iLast ) continue; |
| 172678 | bMatch = 0; |
| 172679 | if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ |
| 172680 | return rc; |
| 172681 | } |
| 172682 | } |
| 172683 | } |
| 172684 | } |
| 172685 | }while( bMatch==0 ); |
| 172686 | |
| 172687 | pNode->iRowid = iLast; |
| 172688 | pNode->bNomatch = (0==fts5ExprNearTest(&rc, pExpr, pNode)); |
| 172689 | |
| 172690 | return rc; |
| 172691 | } |
| 172692 | |
| 172693 | /* |
| 172694 | ** Initialize all term iterators in the pNear object. If any term is found |
| 172695 | ** to match no documents at all, return immediately without initializing any |
| 172696 | ** further iterators. |
| @@ -172701,10 +173054,11 @@ | |
| 172701 | ){ |
| 172702 | Fts5ExprNearset *pNear = pNode->pNear; |
| 172703 | int i, j; |
| 172704 | int rc = SQLITE_OK; |
| 172705 | |
| 172706 | for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){ |
| 172707 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 172708 | for(j=0; j<pPhrase->nTerm; j++){ |
| 172709 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; |
| 172710 | Fts5ExprTerm *p; |
| @@ -172735,14 +173089,10 @@ | |
| 172735 | } |
| 172736 | } |
| 172737 | |
| 172738 | return rc; |
| 172739 | } |
| 172740 | |
| 172741 | /* fts5ExprNodeNext() calls fts5ExprNodeNextMatch(). And vice-versa. */ |
| 172742 | static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*); |
| 172743 | |
| 172744 | |
| 172745 | /* |
| 172746 | ** If pExpr is an ASC iterator, this function returns a value with the |
| 172747 | ** same sign as: |
| 172748 | ** |
| @@ -172768,10 +173118,11 @@ | |
| 172768 | } |
| 172769 | |
| 172770 | static void fts5ExprSetEof(Fts5ExprNode *pNode){ |
| 172771 | int i; |
| 172772 | pNode->bEof = 1; |
| 172773 | for(i=0; i<pNode->nChild; i++){ |
| 172774 | fts5ExprSetEof(pNode->apChild[i]); |
| 172775 | } |
| 172776 | } |
| 172777 | |
| @@ -172790,16 +173141,279 @@ | |
| 172790 | } |
| 172791 | } |
| 172792 | } |
| 172793 | |
| 172794 | |
| 172795 | static int fts5ExprNodeNext(Fts5Expr*, Fts5ExprNode*, int, i64); |
| 172796 | |
| 172797 | /* |
| 172798 | ** Argument pNode is an FTS5_AND node. |
| 172799 | */ |
| 172800 | static int fts5ExprAndNextRowid( |
| 172801 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 172802 | Fts5ExprNode *pAnd /* FTS5_AND node to advance */ |
| 172803 | ){ |
| 172804 | int iChild; |
| 172805 | i64 iLast = pAnd->iRowid; |
| @@ -172810,19 +173424,15 @@ | |
| 172810 | do { |
| 172811 | pAnd->bNomatch = 0; |
| 172812 | bMatch = 1; |
| 172813 | for(iChild=0; iChild<pAnd->nChild; iChild++){ |
| 172814 | Fts5ExprNode *pChild = pAnd->apChild[iChild]; |
| 172815 | if( 0 && pChild->eType==FTS5_STRING ){ |
| 172816 | /* TODO */ |
| 172817 | }else{ |
| 172818 | int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); |
| 172819 | if( cmp>0 ){ |
| 172820 | /* Advance pChild until it points to iLast or laster */ |
| 172821 | rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); |
| 172822 | if( rc!=SQLITE_OK ) return rc; |
| 172823 | } |
| 172824 | } |
| 172825 | |
| 172826 | /* If the child node is now at EOF, so is the parent AND node. Otherwise, |
| 172827 | ** the child node is guaranteed to have advanced at least as far as |
| 172828 | ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the |
| @@ -172848,190 +173458,99 @@ | |
| 172848 | } |
| 172849 | pAnd->iRowid = iLast; |
| 172850 | return SQLITE_OK; |
| 172851 | } |
| 172852 | |
| 172853 | |
| 172854 | /* |
| 172855 | ** Compare the values currently indicated by the two nodes as follows: |
| 172856 | ** |
| 172857 | ** res = (*p1) - (*p2) |
| 172858 | ** |
| 172859 | ** Nodes that point to values that come later in the iteration order are |
| 172860 | ** considered to be larger. Nodes at EOF are the largest of all. |
| 172861 | ** |
| 172862 | ** This means that if the iteration order is ASC, then numerically larger |
| 172863 | ** rowids are considered larger. Or if it is the default DESC, numerically |
| 172864 | ** smaller rowids are larger. |
| 172865 | */ |
| 172866 | static int fts5NodeCompare( |
| 172867 | Fts5Expr *pExpr, |
| 172868 | Fts5ExprNode *p1, |
| 172869 | Fts5ExprNode *p2 |
| 172870 | ){ |
| 172871 | if( p2->bEof ) return -1; |
| 172872 | if( p1->bEof ) return +1; |
| 172873 | return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); |
| 172874 | } |
| 172875 | |
| 172876 | /* |
| 172877 | ** Advance node iterator pNode, part of expression pExpr. If argument |
| 172878 | ** bFromValid is zero, then pNode is advanced exactly once. Or, if argument |
| 172879 | ** bFromValid is non-zero, then pNode is advanced until it is at or past |
| 172880 | ** rowid value iFrom. Whether "past" means "less than" or "greater than" |
| 172881 | ** depends on whether this is an ASC or DESC iterator. |
| 172882 | */ |
| 172883 | static int fts5ExprNodeNext( |
| 172884 | Fts5Expr *pExpr, |
| 172885 | Fts5ExprNode *pNode, |
| 172886 | int bFromValid, |
| 172887 | i64 iFrom |
| 172888 | ){ |
| 172889 | int rc = SQLITE_OK; |
| 172890 | |
| 172891 | if( pNode->bEof==0 ){ |
| 172892 | switch( pNode->eType ){ |
| 172893 | case FTS5_STRING: { |
| 172894 | rc = fts5ExprNearAdvanceFirst(pExpr, pNode, bFromValid, iFrom); |
| 172895 | break; |
| 172896 | }; |
| 172897 | |
| 172898 | case FTS5_TERM: { |
| 172899 | Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; |
| 172900 | if( bFromValid ){ |
| 172901 | rc = sqlite3Fts5IterNextFrom(pIter, iFrom); |
| 172902 | }else{ |
| 172903 | rc = sqlite3Fts5IterNext(pIter); |
| 172904 | } |
| 172905 | if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ |
| 172906 | assert( rc==SQLITE_OK ); |
| 172907 | rc = fts5ExprTokenTest(pExpr, pNode); |
| 172908 | }else{ |
| 172909 | pNode->bEof = 1; |
| 172910 | } |
| 172911 | return rc; |
| 172912 | }; |
| 172913 | |
| 172914 | case FTS5_AND: { |
| 172915 | Fts5ExprNode *pLeft = pNode->apChild[0]; |
| 172916 | rc = fts5ExprNodeNext(pExpr, pLeft, bFromValid, iFrom); |
| 172917 | break; |
| 172918 | } |
| 172919 | |
| 172920 | case FTS5_OR: { |
| 172921 | int i; |
| 172922 | i64 iLast = pNode->iRowid; |
| 172923 | |
| 172924 | for(i=0; rc==SQLITE_OK && i<pNode->nChild; i++){ |
| 172925 | Fts5ExprNode *p1 = pNode->apChild[i]; |
| 172926 | assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); |
| 172927 | if( p1->bEof==0 ){ |
| 172928 | if( (p1->iRowid==iLast) |
| 172929 | || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) |
| 172930 | ){ |
| 172931 | rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); |
| 172932 | } |
| 172933 | } |
| 172934 | } |
| 172935 | |
| 172936 | break; |
| 172937 | } |
| 172938 | |
| 172939 | default: assert( pNode->eType==FTS5_NOT ); { |
| 172940 | assert( pNode->nChild==2 ); |
| 172941 | rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 172942 | break; |
| 172943 | } |
| 172944 | } |
| 172945 | |
| 172946 | if( rc==SQLITE_OK ){ |
| 172947 | rc = fts5ExprNodeNextMatch(pExpr, pNode); |
| 172948 | } |
| 172949 | } |
| 172950 | |
| 172951 | /* Assert that if bFromValid was true, either: |
| 172952 | ** |
| 172953 | ** a) an error occurred, or |
| 172954 | ** b) the node is now at EOF, or |
| 172955 | ** c) the node is now at or past rowid iFrom. |
| 172956 | */ |
| 172957 | assert( bFromValid==0 |
| 172958 | || rc!=SQLITE_OK /* a */ |
| 172959 | || pNode->bEof /* b */ |
| 172960 | || pNode->iRowid==iFrom || pExpr->bDesc==(pNode->iRowid<iFrom) /* c */ |
| 172961 | ); |
| 172962 | |
| 172963 | return rc; |
| 172964 | } |
| 172965 | |
| 172966 | |
| 172967 | /* |
| 172968 | ** If pNode currently points to a match, this function returns SQLITE_OK |
| 172969 | ** without modifying it. Otherwise, pNode is advanced until it does point |
| 172970 | ** to a match or EOF is reached. |
| 172971 | */ |
| 172972 | static int fts5ExprNodeNextMatch( |
| 172973 | Fts5Expr *pExpr, /* Expression of which pNode is a part */ |
| 172974 | Fts5ExprNode *pNode /* Expression node to test */ |
| 172975 | ){ |
| 172976 | int rc = SQLITE_OK; |
| 172977 | if( pNode->bEof==0 ){ |
| 172978 | switch( pNode->eType ){ |
| 172979 | |
| 172980 | case FTS5_STRING: { |
| 172981 | /* Advance the iterators until they all point to the same rowid */ |
| 172982 | rc = fts5ExprNearNextMatch(pExpr, pNode); |
| 172983 | break; |
| 172984 | } |
| 172985 | |
| 172986 | case FTS5_TERM: { |
| 172987 | rc = fts5ExprTokenTest(pExpr, pNode); |
| 172988 | break; |
| 172989 | } |
| 172990 | |
| 172991 | case FTS5_AND: { |
| 172992 | rc = fts5ExprAndNextRowid(pExpr, pNode); |
| 172993 | break; |
| 172994 | } |
| 172995 | |
| 172996 | case FTS5_OR: { |
| 172997 | Fts5ExprNode *pNext = pNode->apChild[0]; |
| 172998 | int i; |
| 172999 | |
| 173000 | for(i=1; i<pNode->nChild; i++){ |
| 173001 | Fts5ExprNode *pChild = pNode->apChild[i]; |
| 173002 | int cmp = fts5NodeCompare(pExpr, pNext, pChild); |
| 173003 | if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ |
| 173004 | pNext = pChild; |
| 173005 | } |
| 173006 | } |
| 173007 | pNode->iRowid = pNext->iRowid; |
| 173008 | pNode->bEof = pNext->bEof; |
| 173009 | pNode->bNomatch = pNext->bNomatch; |
| 173010 | break; |
| 173011 | } |
| 173012 | |
| 173013 | default: assert( pNode->eType==FTS5_NOT ); { |
| 173014 | Fts5ExprNode *p1 = pNode->apChild[0]; |
| 173015 | Fts5ExprNode *p2 = pNode->apChild[1]; |
| 173016 | assert( pNode->nChild==2 ); |
| 173017 | |
| 173018 | while( rc==SQLITE_OK && p1->bEof==0 ){ |
| 173019 | int cmp = fts5NodeCompare(pExpr, p1, p2); |
| 173020 | if( cmp>0 ){ |
| 173021 | rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); |
| 173022 | cmp = fts5NodeCompare(pExpr, p1, p2); |
| 173023 | } |
| 173024 | assert( rc!=SQLITE_OK || cmp<=0 ); |
| 173025 | if( cmp || p2->bNomatch ) break; |
| 173026 | rc = fts5ExprNodeNext(pExpr, p1, 0, 0); |
| 173027 | } |
| 173028 | pNode->bEof = p1->bEof; |
| 173029 | pNode->iRowid = p1->iRowid; |
| 173030 | if( p1->bEof ){ |
| 173031 | fts5ExprNodeZeroPoslist(p2); |
| 173032 | } |
| 173033 | break; |
| 173034 | } |
| 173035 | } |
| 173036 | } |
| 173037 | return rc; |
| @@ -173046,24 +173565,44 @@ | |
| 173046 | ** It is not an error if there are no matches. |
| 173047 | */ |
| 173048 | static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ |
| 173049 | int rc = SQLITE_OK; |
| 173050 | pNode->bEof = 0; |
| 173051 | |
| 173052 | if( Fts5NodeIsString(pNode) ){ |
| 173053 | /* Initialize all term iterators in the NEAR object. */ |
| 173054 | rc = fts5ExprNearInitAll(pExpr, pNode); |
| 173055 | }else{ |
| 173056 | int i; |
| 173057 | for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){ |
| 173058 | rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]); |
| 173059 | } |
| 173060 | pNode->iRowid = pNode->apChild[0]->iRowid; |
| 173061 | } |
| 173062 | |
| 173063 | if( rc==SQLITE_OK ){ |
| 173064 | rc = fts5ExprNodeNextMatch(pExpr, pNode); |
| 173065 | } |
| 173066 | return rc; |
| 173067 | } |
| 173068 | |
| 173069 | |
| @@ -173083,11 +173622,11 @@ | |
| 173083 | ** is not considered an error if the query does not match any documents. |
| 173084 | */ |
| 173085 | static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ |
| 173086 | Fts5ExprNode *pRoot = p->pRoot; |
| 173087 | int rc = SQLITE_OK; |
| 173088 | if( pRoot ){ |
| 173089 | p->pIndex = pIdx; |
| 173090 | p->bDesc = bDesc; |
| 173091 | rc = fts5ExprNodeFirst(p, pRoot); |
| 173092 | |
| 173093 | /* If not at EOF but the current rowid occurs earlier than iFirst in |
| @@ -173095,11 +173634,12 @@ | |
| 173095 | if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ |
| 173096 | rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); |
| 173097 | } |
| 173098 | |
| 173099 | /* If the iterator is not at a real match, skip forward until it is. */ |
| 173100 | while( pRoot->bNomatch && rc==SQLITE_OK && pRoot->bEof==0 ){ |
| 173101 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173102 | } |
| 173103 | } |
| 173104 | return rc; |
| 173105 | } |
| @@ -173111,21 +173651,23 @@ | |
| 173111 | ** is not considered an error if the query does not match any documents. |
| 173112 | */ |
| 173113 | static int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ |
| 173114 | int rc; |
| 173115 | Fts5ExprNode *pRoot = p->pRoot; |
| 173116 | do { |
| 173117 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173118 | }while( pRoot->bNomatch && pRoot->bEof==0 && rc==SQLITE_OK ); |
| 173119 | if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ |
| 173120 | pRoot->bEof = 1; |
| 173121 | } |
| 173122 | return rc; |
| 173123 | } |
| 173124 | |
| 173125 | static int sqlite3Fts5ExprEof(Fts5Expr *p){ |
| 173126 | return (p->pRoot==0 || p->pRoot->bEof); |
| 173127 | } |
| 173128 | |
| 173129 | static i64 sqlite3Fts5ExprRowid(Fts5Expr *p){ |
| 173130 | return p->pRoot->iRowid; |
| 173131 | } |
| @@ -173146,14 +173688,14 @@ | |
| 173146 | Fts5ExprTerm *pSyn; |
| 173147 | Fts5ExprTerm *pNext; |
| 173148 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 173149 | sqlite3_free(pTerm->zTerm); |
| 173150 | sqlite3Fts5IterClose(pTerm->pIter); |
| 173151 | |
| 173152 | for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ |
| 173153 | pNext = pSyn->pSynonym; |
| 173154 | sqlite3Fts5IterClose(pSyn->pIter); |
| 173155 | sqlite3_free(pSyn); |
| 173156 | } |
| 173157 | } |
| 173158 | if( pPhrase->poslist.nSpace>0 ) fts5BufferFree(&pPhrase->poslist); |
| 173159 | sqlite3_free(pPhrase); |
| @@ -173237,17 +173779,17 @@ | |
| 173237 | if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; |
| 173238 | |
| 173239 | assert( pPhrase==0 || pPhrase->nTerm>0 ); |
| 173240 | if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ |
| 173241 | Fts5ExprTerm *pSyn; |
| 173242 | int nByte = sizeof(Fts5ExprTerm) + nToken+1; |
| 173243 | pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); |
| 173244 | if( pSyn==0 ){ |
| 173245 | rc = SQLITE_NOMEM; |
| 173246 | }else{ |
| 173247 | memset(pSyn, 0, nByte); |
| 173248 | pSyn->zTerm = (char*)&pSyn[1]; |
| 173249 | memcpy(pSyn->zTerm, pToken, nToken); |
| 173250 | pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; |
| 173251 | pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; |
| 173252 | } |
| 173253 | }else{ |
| @@ -173422,12 +173964,14 @@ | |
| 173422 | pNew->pRoot->pNear->nPhrase = 1; |
| 173423 | sCtx.pPhrase->pNode = pNew->pRoot; |
| 173424 | |
| 173425 | if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ |
| 173426 | pNew->pRoot->eType = FTS5_TERM; |
| 173427 | }else{ |
| 173428 | pNew->pRoot->eType = FTS5_STRING; |
| 173429 | } |
| 173430 | }else{ |
| 173431 | sqlite3Fts5ExprFree(pNew); |
| 173432 | fts5ExprPhraseFree(sCtx.pPhrase); |
| 173433 | pNew = 0; |
| @@ -173570,10 +174114,42 @@ | |
| 173570 | pNear->pColset = pColset; |
| 173571 | }else{ |
| 173572 | sqlite3_free(pColset); |
| 173573 | } |
| 173574 | } |
| 173575 | |
| 173576 | static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ |
| 173577 | if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){ |
| 173578 | int nByte = sizeof(Fts5ExprNode*) * pSub->nChild; |
| 173579 | memcpy(&p->apChild[p->nChild], pSub->apChild, nByte); |
| @@ -173620,20 +174196,20 @@ | |
| 173620 | pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); |
| 173621 | |
| 173622 | if( pRet ){ |
| 173623 | pRet->eType = eType; |
| 173624 | pRet->pNear = pNear; |
| 173625 | if( eType==FTS5_STRING ){ |
| 173626 | int iPhrase; |
| 173627 | for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){ |
| 173628 | pNear->apPhrase[iPhrase]->pNode = pRet; |
| 173629 | } |
| 173630 | if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){ |
| 173631 | if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){ |
| 173632 | pRet->eType = FTS5_TERM; |
| 173633 | } |
| 173634 | }else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ |
| 173635 | assert( pParse->rc==SQLITE_OK ); |
| 173636 | pParse->rc = SQLITE_ERROR; |
| 173637 | assert( pParse->zErr==0 ); |
| 173638 | pParse->zErr = sqlite3_mprintf( |
| 173639 | "fts5: %s queries are not supported (detail!=full)", |
| @@ -173640,10 +174216,11 @@ | |
| 173640 | pNear->nPhrase==1 ? "phrase": "NEAR" |
| 173641 | ); |
| 173642 | sqlite3_free(pRet); |
| 173643 | pRet = 0; |
| 173644 | } |
| 173645 | }else{ |
| 173646 | fts5ExprAddChildren(pRet, pLeft); |
| 173647 | fts5ExprAddChildren(pRet, pRight); |
| 173648 | } |
| 173649 | } |
| @@ -173922,11 +174499,11 @@ | |
| 173922 | if( rc==SQLITE_OK ){ |
| 173923 | rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr); |
| 173924 | } |
| 173925 | if( rc==SQLITE_OK ){ |
| 173926 | char *zText; |
| 173927 | if( pExpr->pRoot==0 ){ |
| 173928 | zText = sqlite3_mprintf(""); |
| 173929 | }else if( bTcl ){ |
| 173930 | zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot); |
| 173931 | }else{ |
| 173932 | zText = fts5ExprPrint(pConfig, pExpr->pRoot); |
| @@ -174022,11 +174599,11 @@ | |
| 174022 | }; |
| 174023 | int i; |
| 174024 | int rc = SQLITE_OK; |
| 174025 | void *pCtx = (void*)pGlobal; |
| 174026 | |
| 174027 | for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){ |
| 174028 | struct Fts5ExprFunc *p = &aFunc[i]; |
| 174029 | rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); |
| 174030 | } |
| 174031 | |
| 174032 | /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ |
| @@ -174260,30 +174837,25 @@ | |
| 174260 | Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase]; |
| 174261 | Fts5ExprNode *pNode = pPhrase->pNode; |
| 174262 | int rc = SQLITE_OK; |
| 174263 | |
| 174264 | assert( iPhrase>=0 && iPhrase<pExpr->nPhrase ); |
| 174265 | if( pNode->bEof==0 |
| 174266 | && pNode->iRowid==pExpr->pRoot->iRowid |
| 174267 | && pPhrase->poslist.n>0 |
| 174268 | ){ |
| 174269 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; |
| 174270 | if( pTerm->pSynonym ){ |
| 174271 | int bDel = 0; |
| 174272 | u8 *a; |
| 174273 | rc = fts5ExprSynonymList( |
| 174274 | pTerm, 1, 0, pNode->iRowid, &bDel, &a, pnCollist |
| 174275 | ); |
| 174276 | if( bDel ){ |
| 174277 | sqlite3Fts5BufferSet(&rc, &pPhrase->poslist, *pnCollist, a); |
| 174278 | *ppCollist = pPhrase->poslist.p; |
| 174279 | sqlite3_free(a); |
| 174280 | }else{ |
| 174281 | *ppCollist = a; |
| 174282 | } |
| 174283 | }else{ |
| 174284 | sqlite3Fts5IterCollist(pPhrase->aTerm[0].pIter, ppCollist, pnCollist); |
| 174285 | } |
| 174286 | }else{ |
| 174287 | *ppCollist = 0; |
| 174288 | *pnCollist = 0; |
| 174289 | } |
| @@ -175080,10 +175652,11 @@ | |
| 175080 | |
| 175081 | typedef struct Fts5Data Fts5Data; |
| 175082 | typedef struct Fts5DlidxIter Fts5DlidxIter; |
| 175083 | typedef struct Fts5DlidxLvl Fts5DlidxLvl; |
| 175084 | typedef struct Fts5DlidxWriter Fts5DlidxWriter; |
| 175085 | typedef struct Fts5PageWriter Fts5PageWriter; |
| 175086 | typedef struct Fts5SegIter Fts5SegIter; |
| 175087 | typedef struct Fts5DoclistIter Fts5DoclistIter; |
| 175088 | typedef struct Fts5SegWriter Fts5SegWriter; |
| 175089 | typedef struct Fts5Structure Fts5Structure; |
| @@ -175322,20 +175895,24 @@ | |
| 175322 | ** |
| 175323 | ** poslist: |
| 175324 | ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. |
| 175325 | ** There is no way to tell if this is populated or not. |
| 175326 | */ |
| 175327 | struct Fts5IndexIter { |
| 175328 | Fts5Index *pIndex; /* Index that owns this iterator */ |
| 175329 | Fts5Structure *pStruct; /* Database structure for this iterator */ |
| 175330 | Fts5Buffer poslist; /* Buffer containing current poslist */ |
| 175331 | |
| 175332 | int nSeg; /* Size of aSeg[] array */ |
| 175333 | int bRev; /* True to iterate in reverse order */ |
| 175334 | u8 bSkipEmpty; /* True to skip deleted entries */ |
| 175335 | u8 bEof; /* True at EOF */ |
| 175336 | u8 bFiltered; /* True if column-filter already applied */ |
| 175337 | |
| 175338 | i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ |
| 175339 | Fts5CResult *aFirst; /* Current merge state (see above) */ |
| 175340 | Fts5SegIter aSeg[1]; /* Array of segment iterators */ |
| 175341 | }; |
| @@ -176571,11 +177148,11 @@ | |
| 176571 | /* |
| 176572 | ** Return true if the iterator passed as the second argument currently |
| 176573 | ** points to a delete marker. A delete marker is an entry with a 0 byte |
| 176574 | ** position-list. |
| 176575 | */ |
| 176576 | static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){ |
| 176577 | Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; |
| 176578 | return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0); |
| 176579 | } |
| 176580 | |
| 176581 | /* |
| @@ -176843,13 +177420,10 @@ | |
| 176843 | iPoslist = pIter->iTermLeafOffset; |
| 176844 | }else{ |
| 176845 | iPoslist = 4; |
| 176846 | } |
| 176847 | fts5IndexSkipVarint(pLeaf->p, iPoslist); |
| 176848 | assert( p->pConfig->eDetail==FTS5_DETAIL_NONE || iPoslist==( |
| 176849 | pIter->iLeafOffset - sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel) |
| 176850 | )); |
| 176851 | pIter->iLeafOffset = iPoslist; |
| 176852 | |
| 176853 | /* If this condition is true then the largest rowid for the current |
| 176854 | ** term may not be stored on the current page. So search forward to |
| 176855 | ** see where said rowid really is. */ |
| @@ -177077,13 +177651,10 @@ | |
| 177077 | ){ |
| 177078 | int iPg = 1; |
| 177079 | int bGe = (flags & FTS5INDEX_QUERY_SCAN); |
| 177080 | int bDlidx = 0; /* True if there is a doclist-index */ |
| 177081 | |
| 177082 | static int nCall = 0; |
| 177083 | nCall++; |
| 177084 | |
| 177085 | assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); |
| 177086 | assert( pTerm && nTerm ); |
| 177087 | memset(pIter, 0, sizeof(*pIter)); |
| 177088 | pIter->pSeg = pSeg; |
| 177089 | |
| @@ -177225,11 +177796,11 @@ | |
| 177225 | ** fts5AssertMultiIterSetup(). It ensures that the result currently stored |
| 177226 | ** in *pRes is the correct result of comparing the current positions of the |
| 177227 | ** two iterators. |
| 177228 | */ |
| 177229 | static void fts5AssertComparisonResult( |
| 177230 | Fts5IndexIter *pIter, |
| 177231 | Fts5SegIter *p1, |
| 177232 | Fts5SegIter *p2, |
| 177233 | Fts5CResult *pRes |
| 177234 | ){ |
| 177235 | int i1 = p1 - pIter->aSeg; |
| @@ -177266,16 +177837,16 @@ | |
| 177266 | ** This function is a no-op unless SQLITE_DEBUG is defined when this module |
| 177267 | ** is compiled. In that case, this function is essentially an assert() |
| 177268 | ** statement used to verify that the contents of the pIter->aFirst[] array |
| 177269 | ** are correct. |
| 177270 | */ |
| 177271 | static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5IndexIter *pIter){ |
| 177272 | if( p->rc==SQLITE_OK ){ |
| 177273 | Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177274 | int i; |
| 177275 | |
| 177276 | assert( (pFirst->pLeaf==0)==pIter->bEof ); |
| 177277 | |
| 177278 | /* Check that pIter->iSwitchRowid is set correctly. */ |
| 177279 | for(i=0; i<pIter->nSeg; i++){ |
| 177280 | Fts5SegIter *p1 = &pIter->aSeg[i]; |
| 177281 | assert( p1==pFirst |
| @@ -177311,11 +177882,11 @@ | |
| 177311 | ** If the returned value is non-zero, then it is the index of an entry |
| 177312 | ** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing |
| 177313 | ** to a key that is a duplicate of another, higher priority, |
| 177314 | ** segment-iterator in the pSeg->aSeg[] array. |
| 177315 | */ |
| 177316 | static int fts5MultiIterDoCompare(Fts5IndexIter *pIter, int iOut){ |
| 177317 | int i1; /* Index of left-hand Fts5SegIter */ |
| 177318 | int i2; /* Index of right-hand Fts5SegIter */ |
| 177319 | int iRes; |
| 177320 | Fts5SegIter *p1; /* Left-hand Fts5SegIter */ |
| 177321 | Fts5SegIter *p2; /* Right-hand Fts5SegIter */ |
| @@ -177457,11 +178028,11 @@ | |
| 177457 | |
| 177458 | |
| 177459 | /* |
| 177460 | ** Free the iterator object passed as the second argument. |
| 177461 | */ |
| 177462 | static void fts5MultiIterFree(Fts5Index *p, Fts5IndexIter *pIter){ |
| 177463 | if( pIter ){ |
| 177464 | int i; |
| 177465 | for(i=0; i<pIter->nSeg; i++){ |
| 177466 | fts5SegIterClear(&pIter->aSeg[i]); |
| 177467 | } |
| @@ -177471,11 +178042,11 @@ | |
| 177471 | } |
| 177472 | } |
| 177473 | |
| 177474 | static void fts5MultiIterAdvanced( |
| 177475 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177476 | Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ |
| 177477 | int iChanged, /* Index of sub-iterator just advanced */ |
| 177478 | int iMinset /* Minimum entry in aFirst[] to set */ |
| 177479 | ){ |
| 177480 | int i; |
| 177481 | for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){ |
| @@ -177499,12 +178070,13 @@ | |
| 177499 | ** on the iterator instead. That function does the same as this one, except |
| 177500 | ** that it deals with more complicated cases as well. |
| 177501 | */ |
| 177502 | static int fts5MultiIterAdvanceRowid( |
| 177503 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177504 | Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ |
| 177505 | int iChanged /* Index of sub-iterator just advanced */ |
| 177506 | ){ |
| 177507 | Fts5SegIter *pNew = &pIter->aSeg[iChanged]; |
| 177508 | |
| 177509 | if( pNew->iRowid==pIter->iSwitchRowid |
| 177510 | || (pNew->iRowid<pIter->iSwitchRowid)==pIter->bRev |
| @@ -177533,19 +178105,20 @@ | |
| 177533 | |
| 177534 | pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ]; |
| 177535 | } |
| 177536 | } |
| 177537 | |
| 177538 | return 0; |
| 177539 | } |
| 177540 | |
| 177541 | /* |
| 177542 | ** Set the pIter->bEof variable based on the state of the sub-iterators. |
| 177543 | */ |
| 177544 | static void fts5MultiIterSetEof(Fts5IndexIter *pIter){ |
| 177545 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177546 | pIter->bEof = pSeg->pLeaf==0; |
| 177547 | pIter->iSwitchRowid = pSeg->iRowid; |
| 177548 | } |
| 177549 | |
| 177550 | /* |
| 177551 | ** Move the iterator to the next entry. |
| @@ -177554,43 +178127,48 @@ | |
| 177554 | ** considered an error if the iterator reaches EOF, or if it is already at |
| 177555 | ** EOF when this function is called. |
| 177556 | */ |
| 177557 | static void fts5MultiIterNext( |
| 177558 | Fts5Index *p, |
| 177559 | Fts5IndexIter *pIter, |
| 177560 | int bFrom, /* True if argument iFrom is valid */ |
| 177561 | i64 iFrom /* Advance at least as far as this */ |
| 177562 | ){ |
| 177563 | if( p->rc==SQLITE_OK ){ |
| 177564 | int bUseFrom = bFrom; |
| 177565 | do { |
| 177566 | int iFirst = pIter->aFirst[1].iFirst; |
| 177567 | int bNewTerm = 0; |
| 177568 | Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; |
| 177569 | assert( p->rc==SQLITE_OK ); |
| 177570 | if( bUseFrom && pSeg->pDlidx ){ |
| 177571 | fts5SegIterNextFrom(p, pSeg, iFrom); |
| 177572 | }else{ |
| 177573 | pSeg->xNext(p, pSeg, &bNewTerm); |
| 177574 | } |
| 177575 | |
| 177576 | if( pSeg->pLeaf==0 || bNewTerm |
| 177577 | || fts5MultiIterAdvanceRowid(p, pIter, iFirst) |
| 177578 | ){ |
| 177579 | fts5MultiIterAdvanced(p, pIter, iFirst, 1); |
| 177580 | fts5MultiIterSetEof(pIter); |
| 177581 | } |
| 177582 | fts5AssertMultiIterSetup(p, pIter); |
| 177583 | |
| 177584 | bUseFrom = 0; |
| 177585 | }while( pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter) ); |
| 177586 | } |
| 177587 | } |
| 177588 | |
| 177589 | static void fts5MultiIterNext2( |
| 177590 | Fts5Index *p, |
| 177591 | Fts5IndexIter *pIter, |
| 177592 | int *pbNewTerm /* OUT: True if *might* be new term */ |
| 177593 | ){ |
| 177594 | assert( pIter->bSkipEmpty ); |
| 177595 | if( p->rc==SQLITE_OK ){ |
| 177596 | do { |
| @@ -177599,11 +178177,11 @@ | |
| 177599 | int bNewTerm = 0; |
| 177600 | |
| 177601 | assert( p->rc==SQLITE_OK ); |
| 177602 | pSeg->xNext(p, pSeg, &bNewTerm); |
| 177603 | if( pSeg->pLeaf==0 || bNewTerm |
| 177604 | || fts5MultiIterAdvanceRowid(p, pIter, iFirst) |
| 177605 | ){ |
| 177606 | fts5MultiIterAdvanced(p, pIter, iFirst, 1); |
| 177607 | fts5MultiIterSetEof(pIter); |
| 177608 | *pbNewTerm = 1; |
| 177609 | }else{ |
| @@ -177613,220 +178191,143 @@ | |
| 177613 | |
| 177614 | }while( fts5MultiIterIsEmpty(p, pIter) ); |
| 177615 | } |
| 177616 | } |
| 177617 | |
| 177618 | |
| 177619 | static Fts5IndexIter *fts5MultiIterAlloc( |
| 177620 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177621 | int nSeg |
| 177622 | ){ |
| 177623 | Fts5IndexIter *pNew; |
| 177624 | int nSlot; /* Power of two >= nSeg */ |
| 177625 | |
| 177626 | for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2); |
| 177627 | pNew = fts5IdxMalloc(p, |
| 177628 | sizeof(Fts5IndexIter) + /* pNew */ |
| 177629 | sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */ |
| 177630 | sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ |
| 177631 | ); |
| 177632 | if( pNew ){ |
| 177633 | pNew->nSeg = nSlot; |
| 177634 | pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; |
| 177635 | pNew->pIndex = p; |
| 177636 | } |
| 177637 | return pNew; |
| 177638 | } |
| 177639 | |
| 177640 | /* |
| 177641 | ** Allocate a new Fts5IndexIter object. |
| 177642 | ** |
| 177643 | ** The new object will be used to iterate through data in structure pStruct. |
| 177644 | ** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel |
| 177645 | ** is zero or greater, data from the first nSegment segments on level iLevel |
| 177646 | ** is merged. |
| 177647 | ** |
| 177648 | ** The iterator initially points to the first term/rowid entry in the |
| 177649 | ** iterated data. |
| 177650 | */ |
| 177651 | static void fts5MultiIterNew( |
| 177652 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177653 | Fts5Structure *pStruct, /* Structure of specific index */ |
| 177654 | int bSkipEmpty, /* True to ignore delete-keys */ |
| 177655 | int flags, /* FTS5INDEX_QUERY_XXX flags */ |
| 177656 | const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ |
| 177657 | int iLevel, /* Level to iterate (-1 for all) */ |
| 177658 | int nSegment, /* Number of segments to merge (iLevel>=0) */ |
| 177659 | Fts5IndexIter **ppOut /* New object */ |
| 177660 | ){ |
| 177661 | int nSeg = 0; /* Number of segment-iters in use */ |
| 177662 | int iIter = 0; /* */ |
| 177663 | int iSeg; /* Used to iterate through segments */ |
| 177664 | Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */ |
| 177665 | Fts5StructureLevel *pLvl; |
| 177666 | Fts5IndexIter *pNew; |
| 177667 | |
| 177668 | assert( (pTerm==0 && nTerm==0) || iLevel<0 ); |
| 177669 | |
| 177670 | /* Allocate space for the new multi-seg-iterator. */ |
| 177671 | if( p->rc==SQLITE_OK ){ |
| 177672 | if( iLevel<0 ){ |
| 177673 | assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); |
| 177674 | nSeg = pStruct->nSegment; |
| 177675 | nSeg += (p->pHash ? 1 : 0); |
| 177676 | }else{ |
| 177677 | nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); |
| 177678 | } |
| 177679 | } |
| 177680 | *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); |
| 177681 | if( pNew==0 ) return; |
| 177682 | pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); |
| 177683 | pNew->bSkipEmpty = (u8)bSkipEmpty; |
| 177684 | pNew->pStruct = pStruct; |
| 177685 | fts5StructureRef(pStruct); |
| 177686 | |
| 177687 | /* Initialize each of the component segment iterators. */ |
| 177688 | if( iLevel<0 ){ |
| 177689 | Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; |
| 177690 | if( p->pHash ){ |
| 177691 | /* Add a segment iterator for the current contents of the hash table. */ |
| 177692 | Fts5SegIter *pIter = &pNew->aSeg[iIter++]; |
| 177693 | fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); |
| 177694 | } |
| 177695 | for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){ |
| 177696 | for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){ |
| 177697 | Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; |
| 177698 | Fts5SegIter *pIter = &pNew->aSeg[iIter++]; |
| 177699 | if( pTerm==0 ){ |
| 177700 | fts5SegIterInit(p, pSeg, pIter); |
| 177701 | }else{ |
| 177702 | fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter); |
| 177703 | } |
| 177704 | } |
| 177705 | } |
| 177706 | }else{ |
| 177707 | pLvl = &pStruct->aLevel[iLevel]; |
| 177708 | for(iSeg=nSeg-1; iSeg>=0; iSeg--){ |
| 177709 | fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); |
| 177710 | } |
| 177711 | } |
| 177712 | assert( iIter==nSeg ); |
| 177713 | |
| 177714 | /* If the above was successful, each component iterators now points |
| 177715 | ** to the first entry in its segment. In this case initialize the |
| 177716 | ** aFirst[] array. Or, if an error has occurred, free the iterator |
| 177717 | ** object and set the output variable to NULL. */ |
| 177718 | if( p->rc==SQLITE_OK ){ |
| 177719 | for(iIter=pNew->nSeg-1; iIter>0; iIter--){ |
| 177720 | int iEq; |
| 177721 | if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ |
| 177722 | Fts5SegIter *pSeg = &pNew->aSeg[iEq]; |
| 177723 | if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); |
| 177724 | fts5MultiIterAdvanced(p, pNew, iEq, iIter); |
| 177725 | } |
| 177726 | } |
| 177727 | fts5MultiIterSetEof(pNew); |
| 177728 | fts5AssertMultiIterSetup(p, pNew); |
| 177729 | |
| 177730 | if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ |
| 177731 | fts5MultiIterNext(p, pNew, 0, 0); |
| 177732 | } |
| 177733 | }else{ |
| 177734 | fts5MultiIterFree(p, pNew); |
| 177735 | *ppOut = 0; |
| 177736 | } |
| 177737 | fts5BufferFree(&buf); |
| 177738 | } |
| 177739 | |
| 177740 | /* |
| 177741 | ** Create an Fts5IndexIter that iterates through the doclist provided |
| 177742 | ** as the second argument. |
| 177743 | */ |
| 177744 | static void fts5MultiIterNew2( |
| 177745 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177746 | Fts5Data *pData, /* Doclist to iterate through */ |
| 177747 | int bDesc, /* True for descending rowid order */ |
| 177748 | Fts5IndexIter **ppOut /* New object */ |
| 177749 | ){ |
| 177750 | Fts5IndexIter *pNew; |
| 177751 | pNew = fts5MultiIterAlloc(p, 2); |
| 177752 | if( pNew ){ |
| 177753 | Fts5SegIter *pIter = &pNew->aSeg[1]; |
| 177754 | |
| 177755 | pNew->bFiltered = 1; |
| 177756 | pIter->flags = FTS5_SEGITER_ONETERM; |
| 177757 | if( pData->szLeaf>0 ){ |
| 177758 | pIter->pLeaf = pData; |
| 177759 | pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); |
| 177760 | pIter->iEndofDoclist = pData->nn; |
| 177761 | pNew->aFirst[1].iFirst = 1; |
| 177762 | if( bDesc ){ |
| 177763 | pNew->bRev = 1; |
| 177764 | pIter->flags |= FTS5_SEGITER_REVERSE; |
| 177765 | fts5SegIterReverseInitPage(p, pIter); |
| 177766 | }else{ |
| 177767 | fts5SegIterLoadNPos(p, pIter); |
| 177768 | } |
| 177769 | pData = 0; |
| 177770 | }else{ |
| 177771 | pNew->bEof = 1; |
| 177772 | } |
| 177773 | fts5SegIterSetNext(p, pIter); |
| 177774 | |
| 177775 | *ppOut = pNew; |
| 177776 | } |
| 177777 | |
| 177778 | fts5DataRelease(pData); |
| 177779 | } |
| 177780 | |
| 177781 | /* |
| 177782 | ** Return true if the iterator is at EOF or if an error has occurred. |
| 177783 | ** False otherwise. |
| 177784 | */ |
| 177785 | static int fts5MultiIterEof(Fts5Index *p, Fts5IndexIter *pIter){ |
| 177786 | assert( p->rc |
| 177787 | || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->bEof |
| 177788 | ); |
| 177789 | return (p->rc || pIter->bEof); |
| 177790 | } |
| 177791 | |
| 177792 | /* |
| 177793 | ** Return the rowid of the entry that the iterator currently points |
| 177794 | ** to. If the iterator points to EOF when this function is called the |
| 177795 | ** results are undefined. |
| 177796 | */ |
| 177797 | static i64 fts5MultiIterRowid(Fts5IndexIter *pIter){ |
| 177798 | assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); |
| 177799 | return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; |
| 177800 | } |
| 177801 | |
| 177802 | /* |
| 177803 | ** Move the iterator to the next entry at or following iMatch. |
| 177804 | */ |
| 177805 | static void fts5MultiIterNextFrom( |
| 177806 | Fts5Index *p, |
| 177807 | Fts5IndexIter *pIter, |
| 177808 | i64 iMatch |
| 177809 | ){ |
| 177810 | while( 1 ){ |
| 177811 | i64 iRowid; |
| 177812 | fts5MultiIterNext(p, pIter, 1, iMatch); |
| 177813 | if( fts5MultiIterEof(p, pIter) ) break; |
| 177814 | iRowid = fts5MultiIterRowid(pIter); |
| 177815 | if( pIter->bRev==0 && iRowid>=iMatch ) break; |
| 177816 | if( pIter->bRev!=0 && iRowid<=iMatch ) break; |
| 177817 | } |
| 177818 | } |
| 177819 | |
| 177820 | /* |
| 177821 | ** Return a pointer to a buffer containing the term associated with the |
| 177822 | ** entry that the iterator currently points to. |
| 177823 | */ |
| 177824 | static const u8 *fts5MultiIterTerm(Fts5IndexIter *pIter, int *pn){ |
| 177825 | Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177826 | *pn = p->term.n; |
| 177827 | return p->term.p; |
| 177828 | } |
| 177829 | |
| 177830 | static void fts5ChunkIterate( |
| 177831 | Fts5Index *p, /* Index object */ |
| 177832 | Fts5SegIter *pSeg, /* Poslist of this iterator */ |
| @@ -177866,11 +178367,462 @@ | |
| 177866 | } |
| 177867 | } |
| 177868 | } |
| 177869 | } |
| 177870 | |
| 177871 | |
| 177872 | |
| 177873 | /* |
| 177874 | ** Allocate a new segment-id for the structure pStruct. The new segment |
| 177875 | ** id must be between 1 and 65335 inclusive, and must not be used by |
| 177876 | ** any currently existing segment. If a free segment id cannot be found, |
| @@ -178401,11 +179353,11 @@ | |
| 178401 | /* |
| 178402 | ** Iterator pIter was used to iterate through the input segments of on an |
| 178403 | ** incremental merge operation. This function is called if the incremental |
| 178404 | ** merge step has finished but the input has not been completely exhausted. |
| 178405 | */ |
| 178406 | static void fts5TrimSegments(Fts5Index *p, Fts5IndexIter *pIter){ |
| 178407 | int i; |
| 178408 | Fts5Buffer buf; |
| 178409 | memset(&buf, 0, sizeof(Fts5Buffer)); |
| 178410 | for(i=0; i<pIter->nSeg; i++){ |
| 178411 | Fts5SegIter *pSeg = &pIter->aSeg[i]; |
| @@ -178479,18 +179431,19 @@ | |
| 178479 | int *pnRem /* Write up to this many output leaves */ |
| 178480 | ){ |
| 178481 | Fts5Structure *pStruct = *ppStruct; |
| 178482 | Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; |
| 178483 | Fts5StructureLevel *pLvlOut; |
| 178484 | Fts5IndexIter *pIter = 0; /* Iterator to read input data */ |
| 178485 | int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */ |
| 178486 | int nInput; /* Number of input segments */ |
| 178487 | Fts5SegWriter writer; /* Writer object */ |
| 178488 | Fts5StructureSegment *pSeg; /* Output segment */ |
| 178489 | Fts5Buffer term; |
| 178490 | int bOldest; /* True if the output segment is the oldest */ |
| 178491 | int eDetail = p->pConfig->eDetail; |
| 178492 | |
| 178493 | assert( iLvl<pStruct->nLevel ); |
| 178494 | assert( pLvl->nMerge<=pLvl->nSeg ); |
| 178495 | |
| 178496 | memset(&writer, 0, sizeof(Fts5SegWriter)); |
| @@ -178531,11 +179484,11 @@ | |
| 178531 | nInput = pLvl->nSeg; |
| 178532 | } |
| 178533 | bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); |
| 178534 | |
| 178535 | assert( iLvl>=0 ); |
| 178536 | for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, iLvl, nInput, &pIter); |
| 178537 | fts5MultiIterEof(p, pIter)==0; |
| 178538 | fts5MultiIterNext(p, pIter, 0, 0) |
| 178539 | ){ |
| 178540 | Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 178541 | int nPos; /* position-list size field value */ |
| @@ -178976,279 +179929,32 @@ | |
| 178976 | fts5StructureRelease(pStruct); |
| 178977 | |
| 178978 | return fts5IndexReturn(p); |
| 178979 | } |
| 178980 | |
| 178981 | static void fts5PoslistCallback( |
| 178982 | Fts5Index *p, |
| 178983 | void *pContext, |
| 178984 | const u8 *pChunk, int nChunk |
| 178985 | ){ |
| 178986 | assert_nc( nChunk>=0 ); |
| 178987 | if( nChunk>0 ){ |
| 178988 | fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); |
| 178989 | } |
| 178990 | } |
| 178991 | |
| 178992 | typedef struct PoslistCallbackCtx PoslistCallbackCtx; |
| 178993 | struct PoslistCallbackCtx { |
| 178994 | Fts5Buffer *pBuf; /* Append to this buffer */ |
| 178995 | Fts5Colset *pColset; /* Restrict matches to this column */ |
| 178996 | int eState; /* See above */ |
| 178997 | }; |
| 178998 | |
| 178999 | typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; |
| 179000 | struct PoslistOffsetsCtx { |
| 179001 | Fts5Buffer *pBuf; /* Append to this buffer */ |
| 179002 | Fts5Colset *pColset; /* Restrict matches to this column */ |
| 179003 | int iRead; |
| 179004 | int iWrite; |
| 179005 | }; |
| 179006 | |
| 179007 | /* |
| 179008 | ** TODO: Make this more efficient! |
| 179009 | */ |
| 179010 | static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ |
| 179011 | int i; |
| 179012 | for(i=0; i<pColset->nCol; i++){ |
| 179013 | if( pColset->aiCol[i]==iCol ) return 1; |
| 179014 | } |
| 179015 | return 0; |
| 179016 | } |
| 179017 | |
| 179018 | static void fts5PoslistOffsetsCallback( |
| 179019 | Fts5Index *p, |
| 179020 | void *pContext, |
| 179021 | const u8 *pChunk, int nChunk |
| 179022 | ){ |
| 179023 | PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; |
| 179024 | assert_nc( nChunk>=0 ); |
| 179025 | if( nChunk>0 ){ |
| 179026 | int i = 0; |
| 179027 | while( i<nChunk ){ |
| 179028 | int iVal; |
| 179029 | i += fts5GetVarint32(&pChunk[i], iVal); |
| 179030 | iVal += pCtx->iRead - 2; |
| 179031 | pCtx->iRead = iVal; |
| 179032 | if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ |
| 179033 | fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); |
| 179034 | pCtx->iWrite = iVal; |
| 179035 | } |
| 179036 | } |
| 179037 | } |
| 179038 | } |
| 179039 | |
| 179040 | static void fts5PoslistFilterCallback( |
| 179041 | Fts5Index *p, |
| 179042 | void *pContext, |
| 179043 | const u8 *pChunk, int nChunk |
| 179044 | ){ |
| 179045 | PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; |
| 179046 | assert_nc( nChunk>=0 ); |
| 179047 | if( nChunk>0 ){ |
| 179048 | /* Search through to find the first varint with value 1. This is the |
| 179049 | ** start of the next columns hits. */ |
| 179050 | int i = 0; |
| 179051 | int iStart = 0; |
| 179052 | |
| 179053 | if( pCtx->eState==2 ){ |
| 179054 | int iCol; |
| 179055 | fts5FastGetVarint32(pChunk, i, iCol); |
| 179056 | if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ |
| 179057 | pCtx->eState = 1; |
| 179058 | fts5BufferSafeAppendVarint(pCtx->pBuf, 1); |
| 179059 | }else{ |
| 179060 | pCtx->eState = 0; |
| 179061 | } |
| 179062 | } |
| 179063 | |
| 179064 | do { |
| 179065 | while( i<nChunk && pChunk[i]!=0x01 ){ |
| 179066 | while( pChunk[i] & 0x80 ) i++; |
| 179067 | i++; |
| 179068 | } |
| 179069 | if( pCtx->eState ){ |
| 179070 | fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 179071 | } |
| 179072 | if( i<nChunk ){ |
| 179073 | int iCol; |
| 179074 | iStart = i; |
| 179075 | i++; |
| 179076 | if( i>=nChunk ){ |
| 179077 | pCtx->eState = 2; |
| 179078 | }else{ |
| 179079 | fts5FastGetVarint32(pChunk, i, iCol); |
| 179080 | pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); |
| 179081 | if( pCtx->eState ){ |
| 179082 | fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 179083 | iStart = i; |
| 179084 | } |
| 179085 | } |
| 179086 | } |
| 179087 | }while( i<nChunk ); |
| 179088 | } |
| 179089 | } |
| 179090 | |
| 179091 | /* |
| 179092 | ** Iterator pIter currently points to a valid entry (not EOF). This |
| 179093 | ** function appends the position list data for the current entry to |
| 179094 | ** buffer pBuf. It does not make a copy of the position-list size |
| 179095 | ** field. |
| 179096 | */ |
| 179097 | static void fts5SegiterPoslist( |
| 179098 | Fts5Index *p, |
| 179099 | Fts5SegIter *pSeg, |
| 179100 | Fts5Colset *pColset, |
| 179101 | Fts5Buffer *pBuf |
| 179102 | ){ |
| 179103 | if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ |
| 179104 | if( pColset==0 ){ |
| 179105 | fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); |
| 179106 | }else{ |
| 179107 | if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 179108 | PoslistCallbackCtx sCtx; |
| 179109 | sCtx.pBuf = pBuf; |
| 179110 | sCtx.pColset = pColset; |
| 179111 | sCtx.eState = fts5IndexColsetTest(pColset, 0); |
| 179112 | assert( sCtx.eState==0 || sCtx.eState==1 ); |
| 179113 | fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); |
| 179114 | }else{ |
| 179115 | PoslistOffsetsCtx sCtx; |
| 179116 | memset(&sCtx, 0, sizeof(sCtx)); |
| 179117 | sCtx.pBuf = pBuf; |
| 179118 | sCtx.pColset = pColset; |
| 179119 | fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); |
| 179120 | } |
| 179121 | } |
| 179122 | } |
| 179123 | } |
| 179124 | |
| 179125 | /* |
| 179126 | ** IN/OUT parameter (*pa) points to a position list n bytes in size. If |
| 179127 | ** the position list contains entries for column iCol, then (*pa) is set |
| 179128 | ** to point to the sub-position-list for that column and the number of |
| 179129 | ** bytes in it returned. Or, if the argument position list does not |
| 179130 | ** contain any entries for column iCol, return 0. |
| 179131 | */ |
| 179132 | static int fts5IndexExtractCol( |
| 179133 | const u8 **pa, /* IN/OUT: Pointer to poslist */ |
| 179134 | int n, /* IN: Size of poslist in bytes */ |
| 179135 | int iCol /* Column to extract from poslist */ |
| 179136 | ){ |
| 179137 | int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ |
| 179138 | const u8 *p = *pa; |
| 179139 | const u8 *pEnd = &p[n]; /* One byte past end of position list */ |
| 179140 | u8 prev = 0; |
| 179141 | |
| 179142 | while( iCol>iCurrent ){ |
| 179143 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 179144 | ** not part of a varint */ |
| 179145 | while( (prev & 0x80) || *p!=0x01 ){ |
| 179146 | prev = *p++; |
| 179147 | if( p==pEnd ) return 0; |
| 179148 | } |
| 179149 | *pa = p++; |
| 179150 | p += fts5GetVarint32(p, iCurrent); |
| 179151 | } |
| 179152 | if( iCol!=iCurrent ) return 0; |
| 179153 | |
| 179154 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 179155 | ** not part of a varint */ |
| 179156 | assert( (prev & 0x80)==0 ); |
| 179157 | while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){ |
| 179158 | prev = *p++; |
| 179159 | } |
| 179160 | return p - (*pa); |
| 179161 | } |
| 179162 | |
| 179163 | static int fts5AppendRowid( |
| 179164 | Fts5Index *p, |
| 179165 | i64 iDelta, |
| 179166 | Fts5IndexIter *pMulti, |
| 179167 | Fts5Colset *pColset, |
| 179168 | Fts5Buffer *pBuf |
| 179169 | ){ |
| 179170 | fts5BufferAppendVarint(&p->rc, pBuf, iDelta); |
| 179171 | return 0; |
| 179172 | } |
| 179173 | |
| 179174 | /* |
| 179175 | ** Iterator pMulti currently points to a valid entry (not EOF). This |
| 179176 | ** function appends the following to buffer pBuf: |
| 179177 | ** |
| 179178 | ** * The varint iDelta, and |
| 179179 | ** * the position list that currently points to, including the size field. |
| 179180 | ** |
| 179181 | ** If argument pColset is NULL, then the position list is filtered according |
| 179182 | ** to pColset before being appended to the buffer. If this means there are |
| 179183 | ** no entries in the position list, nothing is appended to the buffer (not |
| 179184 | ** even iDelta). |
| 179185 | ** |
| 179186 | ** If an error occurs, an error code is left in p->rc. |
| 179187 | */ |
| 179188 | static int fts5AppendPoslist( |
| 179189 | Fts5Index *p, |
| 179190 | i64 iDelta, |
| 179191 | Fts5IndexIter *pMulti, |
| 179192 | Fts5Colset *pColset, |
| 179193 | Fts5Buffer *pBuf |
| 179194 | ){ |
| 179195 | if( p->rc==SQLITE_OK ){ |
| 179196 | Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ]; |
| 179197 | assert( fts5MultiIterEof(p, pMulti)==0 ); |
| 179198 | assert( pSeg->nPos>0 ); |
| 179199 | if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){ |
| 179200 | if( p->pConfig->eDetail==FTS5_DETAIL_FULL |
| 179201 | && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf |
| 179202 | && (pColset==0 || pColset->nCol==1) |
| 179203 | ){ |
| 179204 | const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 179205 | int nPos; |
| 179206 | if( pColset ){ |
| 179207 | nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]); |
| 179208 | if( nPos==0 ) return 1; |
| 179209 | }else{ |
| 179210 | nPos = pSeg->nPos; |
| 179211 | } |
| 179212 | assert( nPos>0 ); |
| 179213 | fts5BufferSafeAppendVarint(pBuf, iDelta); |
| 179214 | fts5BufferSafeAppendVarint(pBuf, nPos*2); |
| 179215 | fts5BufferSafeAppendBlob(pBuf, pPos, nPos); |
| 179216 | }else{ |
| 179217 | int iSv1; |
| 179218 | int iSv2; |
| 179219 | int iData; |
| 179220 | |
| 179221 | /* Append iDelta */ |
| 179222 | iSv1 = pBuf->n; |
| 179223 | fts5BufferSafeAppendVarint(pBuf, iDelta); |
| 179224 | |
| 179225 | /* WRITEPOSLISTSIZE */ |
| 179226 | iSv2 = pBuf->n; |
| 179227 | fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2); |
| 179228 | iData = pBuf->n; |
| 179229 | |
| 179230 | fts5SegiterPoslist(p, pSeg, pColset, pBuf); |
| 179231 | |
| 179232 | if( pColset ){ |
| 179233 | int nActual = pBuf->n - iData; |
| 179234 | if( nActual!=pSeg->nPos ){ |
| 179235 | if( nActual==0 ){ |
| 179236 | pBuf->n = iSv1; |
| 179237 | return 1; |
| 179238 | }else{ |
| 179239 | int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2)); |
| 179240 | while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; } |
| 179241 | sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2); |
| 179242 | } |
| 179243 | } |
| 179244 | } |
| 179245 | } |
| 179246 | } |
| 179247 | } |
| 179248 | |
| 179249 | return 0; |
| 179250 | } |
| 179251 | |
| 179252 | |
| 179253 | static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ |
| 179254 | u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist; |
| @@ -179388,73 +180094,107 @@ | |
| 179388 | ){ |
| 179389 | if( p2->n ){ |
| 179390 | i64 iLastRowid = 0; |
| 179391 | Fts5DoclistIter i1; |
| 179392 | Fts5DoclistIter i2; |
| 179393 | Fts5Buffer out; |
| 179394 | Fts5Buffer tmp; |
| 179395 | memset(&out, 0, sizeof(out)); |
| 179396 | memset(&tmp, 0, sizeof(tmp)); |
| 179397 | |
| 179398 | sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n); |
| 179399 | fts5DoclistIterInit(p1, &i1); |
| 179400 | fts5DoclistIterInit(p2, &i2); |
| 179401 | while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){ |
| 179402 | if( i2.aPoslist==0 || (i1.aPoslist && i1.iRowid<i2.iRowid) ){ |
| 179403 | /* Copy entry from i1 */ |
| 179404 | fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); |
| 179405 | fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize); |
| 179406 | fts5DoclistIterNext(&i1); |
| 179407 | } |
| 179408 | else if( i1.aPoslist==0 || i2.iRowid!=i1.iRowid ){ |
| 179409 | /* Copy entry from i2 */ |
| 179410 | fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 179411 | fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize); |
| 179412 | fts5DoclistIterNext(&i2); |
| 179413 | } |
| 179414 | else{ |
| 179415 | i64 iPos1 = 0; |
| 179416 | i64 iPos2 = 0; |
| 179417 | int iOff1 = 0; |
| 179418 | int iOff2 = 0; |
| 179419 | u8 *a1 = &i1.aPoslist[i1.nSize]; |
| 179420 | u8 *a2 = &i2.aPoslist[i2.nSize]; |
| 179421 | |
| 179422 | Fts5PoslistWriter writer; |
| 179423 | memset(&writer, 0, sizeof(writer)); |
| 179424 | |
| 179425 | /* Merge the two position lists. */ |
| 179426 | fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 179427 | fts5BufferZero(&tmp); |
| 179428 | |
| 179429 | sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 179430 | sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 179431 | |
| 179432 | while( p->rc==SQLITE_OK && (iPos1>=0 || iPos2>=0) ){ |
| 179433 | i64 iNew; |
| 179434 | if( iPos2<0 || (iPos1>=0 && iPos1<iPos2) ){ |
| 179435 | iNew = iPos1; |
| 179436 | sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 179437 | }else{ |
| 179438 | iNew = iPos2; |
| 179439 | sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 179440 | if( iPos1==iPos2 ){ |
| 179441 | sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1); |
| 179442 | } |
| 179443 | } |
| 179444 | if( iNew!=writer.iPrev || tmp.n==0 ){ |
| 179445 | p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew); |
| 179446 | } |
| 179447 | } |
| 179448 | |
| 179449 | /* WRITEPOSLISTSIZE */ |
| 179450 | fts5BufferSafeAppendVarint(&out, tmp.n * 2); |
| 179451 | fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); |
| 179452 | fts5DoclistIterNext(&i1); |
| 179453 | fts5DoclistIterNext(&i2); |
| 179454 | } |
| 179455 | } |
| 179456 | |
| 179457 | fts5BufferSet(&p->rc, p1, out.n, out.p); |
| 179458 | fts5BufferFree(&tmp); |
| 179459 | fts5BufferFree(&out); |
| 179460 | } |
| @@ -179464,18 +180204,18 @@ | |
| 179464 | Fts5Index *p, /* Index to read from */ |
| 179465 | int bDesc, /* True for "ORDER BY rowid DESC" */ |
| 179466 | const u8 *pToken, /* Buffer containing prefix to match */ |
| 179467 | int nToken, /* Size of buffer pToken in bytes */ |
| 179468 | Fts5Colset *pColset, /* Restrict matches to these columns */ |
| 179469 | Fts5IndexIter **ppIter /* OUT: New iterator */ |
| 179470 | ){ |
| 179471 | Fts5Structure *pStruct; |
| 179472 | Fts5Buffer *aBuf; |
| 179473 | const int nBuf = 32; |
| 179474 | |
| 179475 | void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); |
| 179476 | int (*xAppend)(Fts5Index*, i64, Fts5IndexIter*, Fts5Colset*, Fts5Buffer*); |
| 179477 | if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 179478 | xMerge = fts5MergeRowidLists; |
| 179479 | xAppend = fts5AppendRowid; |
| 179480 | }else{ |
| 179481 | xMerge = fts5MergePrefixLists; |
| @@ -179484,32 +180224,40 @@ | |
| 179484 | |
| 179485 | aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf); |
| 179486 | pStruct = fts5StructureRead(p); |
| 179487 | |
| 179488 | if( aBuf && pStruct ){ |
| 179489 | const int flags = FTS5INDEX_QUERY_SCAN; |
| 179490 | int i; |
| 179491 | i64 iLastRowid = 0; |
| 179492 | Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */ |
| 179493 | Fts5Data *pData; |
| 179494 | Fts5Buffer doclist; |
| 179495 | int bNewTerm = 1; |
| 179496 | |
| 179497 | memset(&doclist, 0, sizeof(doclist)); |
| 179498 | for(fts5MultiIterNew(p, pStruct, 1, flags, pToken, nToken, -1, 0, &p1); |
| 179499 | fts5MultiIterEof(p, p1)==0; |
| 179500 | fts5MultiIterNext2(p, p1, &bNewTerm) |
| 179501 | ){ |
| 179502 | i64 iRowid = fts5MultiIterRowid(p1); |
| 179503 | int nTerm; |
| 179504 | const u8 *pTerm = fts5MultiIterTerm(p1, &nTerm); |
| 179505 | assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 ); |
| 179506 | if( bNewTerm ){ |
| 179507 | if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break; |
| 179508 | } |
| 179509 | |
| 179510 | if( doclist.n>0 && iRowid<=iLastRowid ){ |
| 179511 | for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ |
| 179512 | assert( i<nBuf ); |
| 179513 | if( aBuf[i].n==0 ){ |
| 179514 | fts5BufferSwap(&doclist, &aBuf[i]); |
| 179515 | fts5BufferZero(&doclist); |
| @@ -179519,13 +180267,12 @@ | |
| 179519 | } |
| 179520 | } |
| 179521 | iLastRowid = 0; |
| 179522 | } |
| 179523 | |
| 179524 | if( !xAppend(p, iRowid-iLastRowid, p1, pColset, &doclist) ){ |
| 179525 | iLastRowid = iRowid; |
| 179526 | } |
| 179527 | } |
| 179528 | |
| 179529 | for(i=0; i<nBuf; i++){ |
| 179530 | if( p->rc==SQLITE_OK ){ |
| 179531 | xMerge(p, &doclist, &aBuf[i]); |
| @@ -179591,11 +180338,11 @@ | |
| 179591 | ** records must be invalidated. |
| 179592 | */ |
| 179593 | static int sqlite3Fts5IndexRollback(Fts5Index *p){ |
| 179594 | fts5CloseReader(p); |
| 179595 | fts5IndexDiscardData(p); |
| 179596 | assert( p->rc==SQLITE_OK ); |
| 179597 | return SQLITE_OK; |
| 179598 | } |
| 179599 | |
| 179600 | /* |
| 179601 | ** The %_data table is completely empty when this function is called. This |
| @@ -179763,26 +180510,31 @@ | |
| 179763 | int flags, /* Mask of FTS5INDEX_QUERY_X flags */ |
| 179764 | Fts5Colset *pColset, /* Match these columns only */ |
| 179765 | Fts5IndexIter **ppIter /* OUT: New iterator object */ |
| 179766 | ){ |
| 179767 | Fts5Config *pConfig = p->pConfig; |
| 179768 | Fts5IndexIter *pRet = 0; |
| 179769 | int iIdx = 0; |
| 179770 | Fts5Buffer buf = {0, 0, 0}; |
| 179771 | |
| 179772 | /* If the QUERY_SCAN flag is set, all other flags must be clear. */ |
| 179773 | assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); |
| 179774 | |
| 179775 | if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ |
| 179776 | memcpy(&buf.p[1], pToken, nToken); |
| 179777 | |
| 179778 | #ifdef SQLITE_DEBUG |
| 179779 | /* If the QUERY_TEST_NOIDX flag was specified, then this must be a |
| 179780 | ** prefix-query. Instead of using a prefix-index (if one exists), |
| 179781 | ** evaluate the prefix query using the main FTS index. This is used |
| 179782 | ** for internal sanity checking by the integrity-check in debug |
| 179783 | ** mode only. */ |
| 179784 | if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ |
| 179785 | assert( flags & FTS5INDEX_QUERY_PREFIX ); |
| 179786 | iIdx = 1+pConfig->nPrefix; |
| 179787 | }else |
| 179788 | #endif |
| @@ -179792,54 +180544,62 @@ | |
| 179792 | if( pConfig->aPrefix[iIdx-1]==nChar ) break; |
| 179793 | } |
| 179794 | } |
| 179795 | |
| 179796 | if( iIdx<=pConfig->nPrefix ){ |
| 179797 | Fts5Structure *pStruct = fts5StructureRead(p); |
| 179798 | buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); |
| 179799 | if( pStruct ){ |
| 179800 | fts5MultiIterNew(p, pStruct, 1, flags, buf.p, nToken+1, -1, 0, &pRet); |
| 179801 | fts5StructureRelease(pStruct); |
| 179802 | } |
| 179803 | }else{ |
| 179804 | int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; |
| 179805 | buf.p[0] = FTS5_MAIN_PREFIX; |
| 179806 | fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); |
| 179807 | } |
| 179808 | |
| 179809 | if( p->rc ){ |
| 179810 | sqlite3Fts5IterClose(pRet); |
| 179811 | pRet = 0; |
| 179812 | fts5CloseReader(p); |
| 179813 | } |
| 179814 | *ppIter = pRet; |
| 179815 | sqlite3Fts5BufferFree(&buf); |
| 179816 | } |
| 179817 | return fts5IndexReturn(p); |
| 179818 | } |
| 179819 | |
| 179820 | /* |
| 179821 | ** Return true if the iterator passed as the only argument is at EOF. |
| 179822 | */ |
| 179823 | static int sqlite3Fts5IterEof(Fts5IndexIter *pIter){ |
| 179824 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179825 | return pIter->bEof; |
| 179826 | } |
| 179827 | |
| 179828 | /* |
| 179829 | ** Move to the next matching rowid. |
| 179830 | */ |
| 179831 | static int sqlite3Fts5IterNext(Fts5IndexIter *pIter){ |
| 179832 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179833 | fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); |
| 179834 | return fts5IndexReturn(pIter->pIndex); |
| 179835 | } |
| 179836 | |
| 179837 | /* |
| 179838 | ** Move to the next matching term/rowid. Used by the fts5vocab module. |
| 179839 | */ |
| 179840 | static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIter){ |
| 179841 | Fts5Index *p = pIter->pIndex; |
| 179842 | |
| 179843 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179844 | |
| 179845 | fts5MultiIterNext(p, pIter, 0, 0); |
| @@ -179846,11 +180606,11 @@ | |
| 179846 | if( p->rc==SQLITE_OK ){ |
| 179847 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 179848 | if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){ |
| 179849 | fts5DataRelease(pSeg->pLeaf); |
| 179850 | pSeg->pLeaf = 0; |
| 179851 | pIter->bEof = 1; |
| 179852 | } |
| 179853 | } |
| 179854 | |
| 179855 | return fts5IndexReturn(pIter->pIndex); |
| 179856 | } |
| @@ -179858,133 +180618,32 @@ | |
| 179858 | /* |
| 179859 | ** Move to the next matching rowid that occurs at or after iMatch. The |
| 179860 | ** definition of "at or after" depends on whether this iterator iterates |
| 179861 | ** in ascending or descending rowid order. |
| 179862 | */ |
| 179863 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIter, i64 iMatch){ |
| 179864 | fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); |
| 179865 | return fts5IndexReturn(pIter->pIndex); |
| 179866 | } |
| 179867 | |
| 179868 | /* |
| 179869 | ** Return the current rowid. |
| 179870 | */ |
| 179871 | static i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIter){ |
| 179872 | return fts5MultiIterRowid(pIter); |
| 179873 | } |
| 179874 | |
| 179875 | /* |
| 179876 | ** Return the current term. |
| 179877 | */ |
| 179878 | static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIter, int *pn){ |
| 179879 | int n; |
| 179880 | const char *z = (const char*)fts5MultiIterTerm(pIter, &n); |
| 179881 | *pn = n-1; |
| 179882 | return &z[1]; |
| 179883 | } |
| 179884 | |
| 179885 | |
| 179886 | static int fts5IndexExtractColset ( |
| 179887 | Fts5Colset *pColset, /* Colset to filter on */ |
| 179888 | const u8 *pPos, int nPos, /* Position list */ |
| 179889 | Fts5Buffer *pBuf /* Output buffer */ |
| 179890 | ){ |
| 179891 | int rc = SQLITE_OK; |
| 179892 | int i; |
| 179893 | |
| 179894 | fts5BufferZero(pBuf); |
| 179895 | for(i=0; i<pColset->nCol; i++){ |
| 179896 | const u8 *pSub = pPos; |
| 179897 | int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); |
| 179898 | if( nSub ){ |
| 179899 | fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); |
| 179900 | } |
| 179901 | } |
| 179902 | return rc; |
| 179903 | } |
| 179904 | |
| 179905 | |
| 179906 | /* |
| 179907 | ** Return a pointer to a buffer containing a copy of the position list for |
| 179908 | ** the current entry. Output variable *pn is set to the size of the buffer |
| 179909 | ** in bytes before returning. |
| 179910 | ** |
| 179911 | ** The returned position list does not include the "number of bytes" varint |
| 179912 | ** field that starts the position list on disk. |
| 179913 | */ |
| 179914 | static int sqlite3Fts5IterPoslist( |
| 179915 | Fts5IndexIter *pIter, |
| 179916 | Fts5Colset *pColset, /* Column filter (or NULL) */ |
| 179917 | const u8 **pp, /* OUT: Pointer to position-list data */ |
| 179918 | int *pn, /* OUT: Size of position-list in bytes */ |
| 179919 | i64 *piRowid /* OUT: Current rowid */ |
| 179920 | ){ |
| 179921 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 179922 | int eDetail = pIter->pIndex->pConfig->eDetail; |
| 179923 | |
| 179924 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179925 | *piRowid = pSeg->iRowid; |
| 179926 | if( eDetail==FTS5_DETAIL_NONE ){ |
| 179927 | *pn = pSeg->nPos; |
| 179928 | }else |
| 179929 | if( eDetail==FTS5_DETAIL_FULL |
| 179930 | && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf |
| 179931 | ){ |
| 179932 | u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 179933 | if( pColset==0 || pIter->bFiltered ){ |
| 179934 | *pn = pSeg->nPos; |
| 179935 | *pp = pPos; |
| 179936 | }else if( pColset->nCol==1 ){ |
| 179937 | *pp = pPos; |
| 179938 | *pn = fts5IndexExtractCol(pp, pSeg->nPos, pColset->aiCol[0]); |
| 179939 | }else{ |
| 179940 | fts5BufferZero(&pIter->poslist); |
| 179941 | fts5IndexExtractColset(pColset, pPos, pSeg->nPos, &pIter->poslist); |
| 179942 | *pp = pIter->poslist.p; |
| 179943 | *pn = pIter->poslist.n; |
| 179944 | } |
| 179945 | }else{ |
| 179946 | fts5BufferZero(&pIter->poslist); |
| 179947 | fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); |
| 179948 | if( eDetail==FTS5_DETAIL_FULL ){ |
| 179949 | *pp = pIter->poslist.p; |
| 179950 | } |
| 179951 | *pn = pIter->poslist.n; |
| 179952 | } |
| 179953 | return fts5IndexReturn(pIter->pIndex); |
| 179954 | } |
| 179955 | |
| 179956 | static int sqlite3Fts5IterCollist( |
| 179957 | Fts5IndexIter *pIter, |
| 179958 | const u8 **pp, /* OUT: Pointer to position-list data */ |
| 179959 | int *pn /* OUT: Size of position-list in bytes */ |
| 179960 | ){ |
| 179961 | assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); |
| 179962 | *pp = pIter->poslist.p; |
| 179963 | *pn = pIter->poslist.n; |
| 179964 | return SQLITE_OK; |
| 179965 | } |
| 179966 | |
| 179967 | /* |
| 179968 | ** This function is similar to sqlite3Fts5IterPoslist(), except that it |
| 179969 | ** copies the position list into the buffer supplied as the second |
| 179970 | ** argument. |
| 179971 | */ |
| 179972 | static int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf){ |
| 179973 | Fts5Index *p = pIter->pIndex; |
| 179974 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 179975 | assert( p->rc==SQLITE_OK ); |
| 179976 | fts5BufferZero(pBuf); |
| 179977 | fts5SegiterPoslist(p, pSeg, 0, pBuf); |
| 179978 | return fts5IndexReturn(p); |
| 179979 | } |
| 179980 | |
| 179981 | /* |
| 179982 | ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). |
| 179983 | */ |
| 179984 | static void sqlite3Fts5IterClose(Fts5IndexIter *pIter){ |
| 179985 | if( pIter ){ |
| 179986 | Fts5Index *pIndex = pIter->pIndex; |
| 179987 | fts5MultiIterFree(pIter->pIndex, pIter); |
| 179988 | fts5CloseReader(pIndex); |
| 179989 | } |
| 179990 | } |
| @@ -180147,39 +180806,34 @@ | |
| 180147 | int flags, /* Flags for Fts5IndexQuery */ |
| 180148 | u64 *pCksum /* IN/OUT: Checksum value */ |
| 180149 | ){ |
| 180150 | int eDetail = p->pConfig->eDetail; |
| 180151 | u64 cksum = *pCksum; |
| 180152 | Fts5IndexIter *pIdxIter = 0; |
| 180153 | Fts5Buffer buf = {0, 0, 0}; |
| 180154 | int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter); |
| 180155 | |
| 180156 | while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ |
| 180157 | i64 rowid = sqlite3Fts5IterRowid(pIdxIter); |
| 180158 | |
| 180159 | if( eDetail==FTS5_DETAIL_NONE ){ |
| 180160 | cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); |
| 180161 | }else{ |
| 180162 | rc = sqlite3Fts5IterPoslistBuffer(pIdxIter, &buf); |
| 180163 | if( rc==SQLITE_OK ){ |
| 180164 | Fts5PoslistReader sReader; |
| 180165 | for(sqlite3Fts5PoslistReaderInit(buf.p, buf.n, &sReader); |
| 180166 | sReader.bEof==0; |
| 180167 | sqlite3Fts5PoslistReaderNext(&sReader) |
| 180168 | ){ |
| 180169 | int iCol = FTS5_POS2COLUMN(sReader.iPos); |
| 180170 | int iOff = FTS5_POS2OFFSET(sReader.iPos); |
| 180171 | cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); |
| 180172 | } |
| 180173 | } |
| 180174 | } |
| 180175 | if( rc==SQLITE_OK ){ |
| 180176 | rc = sqlite3Fts5IterNext(pIdxIter); |
| 180177 | } |
| 180178 | } |
| 180179 | sqlite3Fts5IterClose(pIdxIter); |
| 180180 | fts5BufferFree(&buf); |
| 180181 | |
| 180182 | *pCksum = cksum; |
| 180183 | return rc; |
| 180184 | } |
| 180185 | |
| @@ -180480,18 +181134,19 @@ | |
| 180480 | */ |
| 180481 | static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ |
| 180482 | int eDetail = p->pConfig->eDetail; |
| 180483 | u64 cksum2 = 0; /* Checksum based on contents of indexes */ |
| 180484 | Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ |
| 180485 | Fts5IndexIter *pIter; /* Used to iterate through entire index */ |
| 180486 | Fts5Structure *pStruct; /* Index structure */ |
| 180487 | |
| 180488 | #ifdef SQLITE_DEBUG |
| 180489 | /* Used by extra internal tests only run if NDEBUG is not defined */ |
| 180490 | u64 cksum3 = 0; /* Checksum based on contents of indexes */ |
| 180491 | Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ |
| 180492 | #endif |
| 180493 | |
| 180494 | /* Load the FTS index structure */ |
| 180495 | pStruct = fts5StructureRead(p); |
| 180496 | |
| 180497 | /* Check that the internal nodes of each segment match the leaves */ |
| @@ -180516,11 +181171,11 @@ | |
| 180516 | ** |
| 180517 | ** As each term visited by the linear scans, a separate query for the |
| 180518 | ** same term is performed. cksum3 is calculated based on the entries |
| 180519 | ** extracted by these queries. |
| 180520 | */ |
| 180521 | for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, -1, 0, &pIter); |
| 180522 | fts5MultiIterEof(p, pIter)==0; |
| 180523 | fts5MultiIterNext(p, pIter, 0, 0) |
| 180524 | ){ |
| 180525 | int n; /* Size of term in bytes */ |
| 180526 | i64 iPos = 0; /* Position read from poslist */ |
| @@ -181234,14 +181889,14 @@ | |
| 181234 | #define FTS5_BI_ORDER_DESC 0x0080 |
| 181235 | |
| 181236 | /* |
| 181237 | ** Values for Fts5Cursor.csrflags |
| 181238 | */ |
| 181239 | #define FTS5CSR_REQUIRE_CONTENT 0x01 |
| 181240 | #define FTS5CSR_REQUIRE_DOCSIZE 0x02 |
| 181241 | #define FTS5CSR_REQUIRE_INST 0x04 |
| 181242 | #define FTS5CSR_EOF 0x08 |
| 181243 | #define FTS5CSR_FREE_ZRANK 0x10 |
| 181244 | #define FTS5CSR_REQUIRE_RESEEK 0x20 |
| 181245 | #define FTS5CSR_REQUIRE_POSLIST 0x40 |
| 181246 | |
| 181247 | #define BitFlagAllTest(x,y) (((x) & (y))==(y)) |
| @@ -181552,11 +182207,11 @@ | |
| 181552 | |
| 181553 | /* Set idxFlags flags for all WHERE clause terms that will be used. */ |
| 181554 | for(i=0; i<pInfo->nConstraint; i++){ |
| 181555 | struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; |
| 181556 | int j; |
| 181557 | for(j=0; j<(int)ArraySize(aConstraint); j++){ |
| 181558 | struct Constraint *pC = &aConstraint[j]; |
| 181559 | if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){ |
| 181560 | if( p->usable ){ |
| 181561 | pC->iConsIndex = i; |
| 181562 | idxFlags |= pC->fts5op; |
| @@ -181599,11 +182254,11 @@ | |
| 181599 | pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; |
| 181600 | } |
| 181601 | |
| 181602 | /* Assign argvIndex values to each constraint in use. */ |
| 181603 | iNext = 1; |
| 181604 | for(i=0; i<(int)ArraySize(aConstraint); i++){ |
| 181605 | struct Constraint *pC = &aConstraint[i]; |
| 181606 | if( pC->iConsIndex>=0 ){ |
| 181607 | pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; |
| 181608 | pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; |
| 181609 | } |
| @@ -181792,18 +182447,19 @@ | |
| 181792 | Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); |
| 181793 | int bDesc = pCsr->bDesc; |
| 181794 | i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); |
| 181795 | |
| 181796 | rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); |
| 181797 | if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ |
| 181798 | *pbSkip = 1; |
| 181799 | } |
| 181800 | |
| 181801 | CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); |
| 181802 | fts5CsrNewrow(pCsr); |
| 181803 | if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ |
| 181804 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 181805 | } |
| 181806 | } |
| 181807 | return rc; |
| 181808 | } |
| 181809 | |
| @@ -181816,28 +182472,28 @@ | |
| 181816 | ** even if we reach end-of-file. The fts5EofMethod() will be called |
| 181817 | ** subsequently to determine whether or not an EOF was hit. |
| 181818 | */ |
| 181819 | static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ |
| 181820 | Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; |
| 181821 | int rc = SQLITE_OK; |
| 181822 | |
| 181823 | assert( (pCsr->ePlan<3)== |
| 181824 | (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) |
| 181825 | ); |
| 181826 | |
| 181827 | if( pCsr->ePlan<3 ){ |
| 181828 | int bSkip = 0; |
| 181829 | if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; |
| 181830 | rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); |
| 181831 | if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ |
| 181832 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 181833 | } |
| 181834 | fts5CsrNewrow(pCsr); |
| 181835 | }else{ |
| 181836 | switch( pCsr->ePlan ){ |
| 181837 | case FTS5_PLAN_SPECIAL: { |
| 181838 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 181839 | break; |
| 181840 | } |
| 181841 | |
| 181842 | case FTS5_PLAN_SORTED_MATCH: { |
| 181843 | rc = fts5SorterNext(pCsr); |
| @@ -183605,11 +184261,11 @@ | |
| 183605 | sqlite3_context *pCtx, /* Function call context */ |
| 183606 | int nArg, /* Number of args */ |
| 183607 | sqlite3_value **apVal /* Function arguments */ |
| 183608 | ){ |
| 183609 | assert( nArg==0 ); |
| 183610 | sqlite3_result_text(pCtx, "fts5: 2016-01-20 14:22:41 204432ee72fda8e82d244c4aa18de7ec4811b8e1", -1, SQLITE_TRANSIENT); |
| 183611 | } |
| 183612 | |
| 183613 | static int fts5Init(sqlite3 *db){ |
| 183614 | static const sqlite3_module fts5Mod = { |
| 183615 | /* iVersion */ 2, |
| @@ -184050,11 +184706,11 @@ | |
| 184050 | int rc = SQLITE_OK; |
| 184051 | if( p ){ |
| 184052 | int i; |
| 184053 | |
| 184054 | /* Finalize all SQL statements */ |
| 184055 | for(i=0; i<(int)ArraySize(p->aStmt); i++){ |
| 184056 | sqlite3_finalize(p->aStmt[i]); |
| 184057 | } |
| 184058 | |
| 184059 | sqlite3_free(p); |
| 184060 | } |
| @@ -186055,11 +186711,11 @@ | |
| 186055 | }; |
| 186056 | |
| 186057 | int rc = SQLITE_OK; /* Return code */ |
| 186058 | int i; /* To iterate through builtin functions */ |
| 186059 | |
| 186060 | for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ |
| 186061 | rc = pApi->xCreateTokenizer(pApi, |
| 186062 | aBuiltin[i].zName, |
| 186063 | (void*)pApi, |
| 186064 | &aBuiltin[i].x, |
| 186065 | 0 |
| @@ -186765,11 +187421,14 @@ | |
| 186765 | return fts5PutVarint64(p,v); |
| 186766 | } |
| 186767 | |
| 186768 | |
| 186769 | static int sqlite3Fts5GetVarintLen(u32 iVal){ |
| 186770 | if( iVal<(1 << 7 ) ) return 1; |
| 186771 | if( iVal<(1 << 14) ) return 2; |
| 186772 | if( iVal<(1 << 21) ) return 3; |
| 186773 | if( iVal<(1 << 28) ) return 4; |
| 186774 | return 5; |
| 186775 | } |
| @@ -186959,11 +187618,11 @@ | |
| 186959 | int nTab = (int)strlen(zTab)+1; |
| 186960 | int eType = 0; |
| 186961 | |
| 186962 | rc = fts5VocabTableType(zType, pzErr, &eType); |
| 186963 | if( rc==SQLITE_OK ){ |
| 186964 | assert( eType>=0 && eType<sizeof(azSchema)/sizeof(azSchema[0]) ); |
| 186965 | rc = sqlite3_declare_vtab(db, azSchema[eType]); |
| 186966 | } |
| 186967 | |
| 186968 | nByte = sizeof(Fts5VocabTable) + nDb + nTab; |
| 186969 | pRet = sqlite3Fts5MallocZero(&rc, nByte); |
| @@ -187182,59 +187841,54 @@ | |
| 187182 | memset(pCsr->aDoc, 0, nCol * sizeof(i64)); |
| 187183 | pCsr->iCol = 0; |
| 187184 | |
| 187185 | assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); |
| 187186 | while( rc==SQLITE_OK ){ |
| 187187 | i64 dummy; |
| 187188 | const u8 *pPos; int nPos; /* Position list */ |
| 187189 | i64 iPos = 0; /* 64-bit position read from poslist */ |
| 187190 | int iOff = 0; /* Current offset within position list */ |
| 187191 | |
| 187192 | switch( pCsr->pConfig->eDetail ){ |
| 187193 | case FTS5_DETAIL_FULL: |
| 187194 | rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); |
| 187195 | if( rc==SQLITE_OK ){ |
| 187196 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 187197 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 187198 | pCsr->aCnt[0]++; |
| 187199 | } |
| 187200 | pCsr->aDoc[0]++; |
| 187201 | }else{ |
| 187202 | int iCol = -1; |
| 187203 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 187204 | int ii = FTS5_POS2COLUMN(iPos); |
| 187205 | pCsr->aCnt[ii]++; |
| 187206 | if( iCol!=ii ){ |
| 187207 | if( ii>=nCol ){ |
| 187208 | rc = FTS5_CORRUPT; |
| 187209 | break; |
| 187210 | } |
| 187211 | pCsr->aDoc[ii]++; |
| 187212 | iCol = ii; |
| 187213 | } |
| 187214 | } |
| 187215 | } |
| 187216 | } |
| 187217 | break; |
| 187218 | |
| 187219 | case FTS5_DETAIL_COLUMNS: |
| 187220 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 187221 | pCsr->aDoc[0]++; |
| 187222 | }else{ |
| 187223 | Fts5Buffer buf = {0, 0, 0}; |
| 187224 | rc = sqlite3Fts5IterPoslistBuffer(pCsr->pIter, &buf); |
| 187225 | if( rc==SQLITE_OK ){ |
| 187226 | while( 0==sqlite3Fts5PoslistNext64(buf.p, buf.n, &iOff,&iPos) ){ |
| 187227 | assert_nc( iPos>=0 && iPos<nCol ); |
| 187228 | if( iPos>=nCol ){ |
| 187229 | rc = FTS5_CORRUPT; |
| 187230 | break; |
| 187231 | } |
| 187232 | pCsr->aDoc[iPos]++; |
| 187233 | } |
| 187234 | } |
| 187235 | sqlite3Fts5BufferFree(&buf); |
| 187236 | } |
| 187237 | break; |
| 187238 | |
| 187239 | default: |
| 187240 | assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); |
| 187241 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -121,10 +121,11 @@ | |
| 121 | #else |
| 122 | /* This is not VxWorks. */ |
| 123 | #define OS_VXWORKS 0 |
| 124 | #define HAVE_FCHOWN 1 |
| 125 | #define HAVE_READLINK 1 |
| 126 | #define HAVE_LSTAT 1 |
| 127 | #endif /* defined(_WRS_KERNEL) */ |
| 128 | |
| 129 | /************** End of vxworks.h *********************************************/ |
| 130 | /************** Continuing where we left off in sqliteInt.h ******************/ |
| 131 | |
| @@ -327,11 +328,11 @@ | |
| 328 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 329 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 330 | */ |
| 331 | #define SQLITE_VERSION "3.11.0" |
| 332 | #define SQLITE_VERSION_NUMBER 3011000 |
| 333 | #define SQLITE_SOURCE_ID "2016-02-09 02:12:20 ca72be8618e5d466d6f35819ca8bbd2b84269959" |
| 334 | |
| 335 | /* |
| 336 | ** CAPI3REF: Run-Time Library Version Numbers |
| 337 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 338 | ** |
| @@ -5911,11 +5912,11 @@ | |
| 5912 | */ |
| 5913 | struct sqlite3_index_info { |
| 5914 | /* Inputs */ |
| 5915 | int nConstraint; /* Number of entries in aConstraint */ |
| 5916 | struct sqlite3_index_constraint { |
| 5917 | int iColumn; /* Column constrained. -1 for ROWID */ |
| 5918 | unsigned char op; /* Constraint operator */ |
| 5919 | unsigned char usable; /* True if this constraint is usable */ |
| 5920 | int iTermOffset; /* Used internally - xBestIndex should ignore */ |
| 5921 | } *aConstraint; /* Table of WHERE clause constraints */ |
| 5922 | int nOrderBy; /* Number of terms in the ORDER BY clause */ |
| @@ -10468,18 +10469,28 @@ | |
| 10469 | |
| 10470 | /* |
| 10471 | ** Flags passed as the third argument to sqlite3BtreeCursor(). |
| 10472 | ** |
| 10473 | ** For read-only cursors the wrFlag argument is always zero. For read-write |
| 10474 | ** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or just |
| 10475 | ** (BTREE_WRCSR). If the BTREE_FORDELETE bit is set, then the cursor will |
| 10476 | ** only be used by SQLite for the following: |
| 10477 | ** |
| 10478 | ** * to seek to and then delete specific entries, and/or |
| 10479 | ** |
| 10480 | ** * to read values that will be used to create keys that other |
| 10481 | ** BTREE_FORDELETE cursors will seek to and delete. |
| 10482 | ** |
| 10483 | ** The BTREE_FORDELETE flag is an optimization hint. It is not used by |
| 10484 | ** by this, the native b-tree engine of SQLite, but it is available to |
| 10485 | ** alternative storage engines that might be substituted in place of this |
| 10486 | ** b-tree system. For alternative storage engines in which a delete of |
| 10487 | ** the main table row automatically deletes corresponding index rows, |
| 10488 | ** the FORDELETE flag hint allows those alternative storage engines to |
| 10489 | ** skip a lot of work. Namely: FORDELETE cursors may treat all SEEK |
| 10490 | ** and DELETE operations as no-ops, and any READ operation against a |
| 10491 | ** FORDELETE cursor may return a null row: 0x01 0x00. |
| 10492 | */ |
| 10493 | #define BTREE_WRCSR 0x00000004 /* read-write cursor */ |
| 10494 | #define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */ |
| 10495 | |
| 10496 | SQLITE_PRIVATE int sqlite3BtreeCursor( |
| @@ -10504,11 +10515,16 @@ | |
| 10515 | int bias, |
| 10516 | int *pRes |
| 10517 | ); |
| 10518 | SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); |
| 10519 | SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); |
| 10520 | SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); |
| 10521 | |
| 10522 | /* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */ |
| 10523 | #define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ |
| 10524 | #define BTREE_AUXDELETE 0x04 /* not the primary delete operation */ |
| 10525 | |
| 10526 | SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, |
| 10527 | const void *pData, int nData, |
| 10528 | int nZero, int bias, int seekResult); |
| 10529 | SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); |
| 10530 | SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); |
| @@ -10762,94 +10778,95 @@ | |
| 10778 | */ |
| 10779 | /************** Include opcodes.h in the middle of vdbe.h ********************/ |
| 10780 | /************** Begin file opcodes.h *****************************************/ |
| 10781 | /* Automatically generated. Do not edit */ |
| 10782 | /* See the tool/mkopcodeh.tcl script for details */ |
| 10783 | #define OP_Savepoint 0 |
| 10784 | #define OP_AutoCommit 1 |
| 10785 | #define OP_Transaction 2 |
| 10786 | #define OP_SorterNext 3 |
| 10787 | #define OP_PrevIfOpen 4 |
| 10788 | #define OP_NextIfOpen 5 |
| 10789 | #define OP_Prev 6 |
| 10790 | #define OP_Next 7 |
| 10791 | #define OP_Checkpoint 8 |
| 10792 | #define OP_JournalMode 9 |
| 10793 | #define OP_Vacuum 10 |
| 10794 | #define OP_VFilter 11 /* synopsis: iplan=r[P3] zplan='P4' */ |
| 10795 | #define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */ |
| 10796 | #define OP_Goto 13 |
| 10797 | #define OP_Gosub 14 |
| 10798 | #define OP_Return 15 |
| 10799 | #define OP_InitCoroutine 16 |
| 10800 | #define OP_EndCoroutine 17 |
| 10801 | #define OP_Yield 18 |
| 10802 | #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ |
| 10803 | #define OP_HaltIfNull 20 /* synopsis: if r[P3]=null halt */ |
| 10804 | #define OP_Halt 21 |
| 10805 | #define OP_Integer 22 /* synopsis: r[P2]=P1 */ |
| 10806 | #define OP_Int64 23 /* synopsis: r[P2]=P4 */ |
| 10807 | #define OP_String 24 /* synopsis: r[P2]='P4' (len=P1) */ |
| 10808 | #define OP_Null 25 /* synopsis: r[P2..P3]=NULL */ |
| 10809 | #define OP_SoftNull 26 /* synopsis: r[P1]=NULL */ |
| 10810 | #define OP_Blob 27 /* synopsis: r[P2]=P4 (len=P1) */ |
| 10811 | #define OP_Variable 28 /* synopsis: r[P2]=parameter(P1,P4) */ |
| 10812 | #define OP_Move 29 /* synopsis: r[P2@P3]=r[P1@P3] */ |
| 10813 | #define OP_Copy 30 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ |
| 10814 | #define OP_SCopy 31 /* synopsis: r[P2]=r[P1] */ |
| 10815 | #define OP_IntCopy 32 /* synopsis: r[P2]=r[P1] */ |
| 10816 | #define OP_ResultRow 33 /* synopsis: output=r[P1@P2] */ |
| 10817 | #define OP_CollSeq 34 |
| 10818 | #define OP_Function0 35 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 10819 | #define OP_Function 36 /* synopsis: r[P3]=func(r[P2@P5]) */ |
| 10820 | #define OP_AddImm 37 /* synopsis: r[P1]=r[P1]+P2 */ |
| 10821 | #define OP_MustBeInt 38 |
| 10822 | #define OP_RealAffinity 39 |
| 10823 | #define OP_Cast 40 /* synopsis: affinity(r[P1]) */ |
| 10824 | #define OP_Permutation 41 |
| 10825 | #define OP_Compare 42 /* synopsis: r[P1@P3] <-> r[P2@P3] */ |
| 10826 | #define OP_Jump 43 |
| 10827 | #define OP_Once 44 |
| 10828 | #define OP_If 45 |
| 10829 | #define OP_IfNot 46 |
| 10830 | #define OP_Column 47 /* synopsis: r[P3]=PX */ |
| 10831 | #define OP_Affinity 48 /* synopsis: affinity(r[P1@P2]) */ |
| 10832 | #define OP_MakeRecord 49 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ |
| 10833 | #define OP_Count 50 /* synopsis: r[P2]=count() */ |
| 10834 | #define OP_ReadCookie 51 |
| 10835 | #define OP_SetCookie 52 |
| 10836 | #define OP_ReopenIdx 53 /* synopsis: root=P2 iDb=P3 */ |
| 10837 | #define OP_OpenRead 54 /* synopsis: root=P2 iDb=P3 */ |
| 10838 | #define OP_OpenWrite 55 /* synopsis: root=P2 iDb=P3 */ |
| 10839 | #define OP_OpenAutoindex 56 /* synopsis: nColumn=P2 */ |
| 10840 | #define OP_OpenEphemeral 57 /* synopsis: nColumn=P2 */ |
| 10841 | #define OP_SorterOpen 58 |
| 10842 | #define OP_SequenceTest 59 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ |
| 10843 | #define OP_OpenPseudo 60 /* synopsis: P3 columns in r[P2] */ |
| 10844 | #define OP_Close 61 |
| 10845 | #define OP_ColumnsUsed 62 |
| 10846 | #define OP_SeekLT 63 /* synopsis: key=r[P3@P4] */ |
| 10847 | #define OP_SeekLE 64 /* synopsis: key=r[P3@P4] */ |
| 10848 | #define OP_SeekGE 65 /* synopsis: key=r[P3@P4] */ |
| 10849 | #define OP_SeekGT 66 /* synopsis: key=r[P3@P4] */ |
| 10850 | #define OP_NoConflict 67 /* synopsis: key=r[P3@P4] */ |
| 10851 | #define OP_NotFound 68 /* synopsis: key=r[P3@P4] */ |
| 10852 | #define OP_Found 69 /* synopsis: key=r[P3@P4] */ |
| 10853 | #define OP_NotExists 70 /* synopsis: intkey=r[P3] */ |
| 10854 | #define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ |
| 10855 | #define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ |
| 10856 | #define OP_Sequence 73 /* synopsis: r[P2]=cursor[P1].ctr++ */ |
| 10857 | #define OP_NewRowid 74 /* synopsis: r[P2]=rowid */ |
| 10858 | #define OP_Insert 75 /* synopsis: intkey=r[P3] data=r[P2] */ |
| 10859 | #define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ |
| 10860 | #define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ |
| 10861 | #define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */ |
| 10862 | #define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */ |
| 10863 | #define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */ |
| 10864 | #define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */ |
| 10865 | #define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */ |
| 10866 | #define OP_Ge 83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */ |
| 10867 | #define OP_InsertInt 84 /* synopsis: intkey=P3 data=r[P2] */ |
| 10868 | #define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ |
| 10869 | #define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ |
| 10870 | #define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ |
| 10871 | #define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */ |
| 10872 | #define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ |
| @@ -10856,111 +10873,110 @@ | |
| 10873 | #define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ |
| 10874 | #define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ |
| 10875 | #define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ |
| 10876 | #define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ |
| 10877 | #define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ |
| 10878 | #define OP_Delete 95 |
| 10879 | #define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ |
| 10880 | #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ |
| 10881 | #define OP_ResetCount 98 |
| 10882 | #define OP_SorterCompare 99 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ |
| 10883 | #define OP_SorterData 100 /* synopsis: r[P2]=data */ |
| 10884 | #define OP_RowKey 101 /* synopsis: r[P2]=key */ |
| 10885 | #define OP_RowData 102 /* synopsis: r[P2]=data */ |
| 10886 | #define OP_Rowid 103 /* synopsis: r[P2]=rowid */ |
| 10887 | #define OP_NullRow 104 |
| 10888 | #define OP_Last 105 |
| 10889 | #define OP_SorterSort 106 |
| 10890 | #define OP_Sort 107 |
| 10891 | #define OP_Rewind 108 |
| 10892 | #define OP_SorterInsert 109 |
| 10893 | #define OP_IdxInsert 110 /* synopsis: key=r[P2] */ |
| 10894 | #define OP_IdxDelete 111 /* synopsis: key=r[P2@P3] */ |
| 10895 | #define OP_Seek 112 /* synopsis: Move P3 to P1.rowid */ |
| 10896 | #define OP_IdxRowid 113 /* synopsis: r[P2]=rowid */ |
| 10897 | #define OP_IdxLE 114 /* synopsis: key=r[P3@P4] */ |
| 10898 | #define OP_IdxGT 115 /* synopsis: key=r[P3@P4] */ |
| 10899 | #define OP_IdxLT 116 /* synopsis: key=r[P3@P4] */ |
| 10900 | #define OP_IdxGE 117 /* synopsis: key=r[P3@P4] */ |
| 10901 | #define OP_Destroy 118 |
| 10902 | #define OP_Clear 119 |
| 10903 | #define OP_ResetSorter 120 |
| 10904 | #define OP_CreateIndex 121 /* synopsis: r[P2]=root iDb=P1 */ |
| 10905 | #define OP_CreateTable 122 /* synopsis: r[P2]=root iDb=P1 */ |
| 10906 | #define OP_ParseSchema 123 |
| 10907 | #define OP_LoadAnalysis 124 |
| 10908 | #define OP_DropTable 125 |
| 10909 | #define OP_DropIndex 126 |
| 10910 | #define OP_DropTrigger 127 |
| 10911 | #define OP_IntegrityCk 128 |
| 10912 | #define OP_RowSetAdd 129 /* synopsis: rowset(P1)=r[P2] */ |
| 10913 | #define OP_RowSetRead 130 /* synopsis: r[P3]=rowset(P1) */ |
| 10914 | #define OP_RowSetTest 131 /* synopsis: if r[P3] in rowset(P1) goto P2 */ |
| 10915 | #define OP_Program 132 |
| 10916 | #define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 10917 | #define OP_Param 134 |
| 10918 | #define OP_FkCounter 135 /* synopsis: fkctr[P1]+=P2 */ |
| 10919 | #define OP_FkIfZero 136 /* synopsis: if fkctr[P1]==0 goto P2 */ |
| 10920 | #define OP_MemMax 137 /* synopsis: r[P1]=max(r[P1],r[P2]) */ |
| 10921 | #define OP_IfPos 138 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ |
| 10922 | #define OP_OffsetLimit 139 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ |
| 10923 | #define OP_IfNotZero 140 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ |
| 10924 | #define OP_DecrJumpZero 141 /* synopsis: if (--r[P1])==0 goto P2 */ |
| 10925 | #define OP_JumpZeroIncr 142 /* synopsis: if (r[P1]++)==0 ) goto P2 */ |
| 10926 | #define OP_AggStep0 143 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 10927 | #define OP_AggStep 144 /* synopsis: accum=r[P3] step(r[P2@P5]) */ |
| 10928 | #define OP_AggFinal 145 /* synopsis: accum=r[P1] N=P2 */ |
| 10929 | #define OP_IncrVacuum 146 |
| 10930 | #define OP_Expire 147 |
| 10931 | #define OP_TableLock 148 /* synopsis: iDb=P1 root=P2 write=P3 */ |
| 10932 | #define OP_VBegin 149 |
| 10933 | #define OP_VCreate 150 |
| 10934 | #define OP_VDestroy 151 |
| 10935 | #define OP_VOpen 152 |
| 10936 | #define OP_VColumn 153 /* synopsis: r[P3]=vcolumn(P2) */ |
| 10937 | #define OP_VNext 154 |
| 10938 | #define OP_VRename 155 |
| 10939 | #define OP_Pagecount 156 |
| 10940 | #define OP_MaxPgcnt 157 |
| 10941 | #define OP_Init 158 /* synopsis: Start at P2 */ |
| 10942 | #define OP_CursorHint 159 |
| 10943 | #define OP_Noop 160 |
| 10944 | #define OP_Explain 161 |
| 10945 | |
| 10946 | /* Properties such as "out2" or "jump" that are specified in |
| 10947 | ** comments following the "case" for each opcode in the vdbe.c |
| 10948 | ** are encoded into bitvectors as follows: |
| 10949 | */ |
| 10950 | #define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */ |
| 10951 | #define OPFLG_IN1 0x02 /* in1: P1 is an input */ |
| 10952 | #define OPFLG_IN2 0x04 /* in2: P2 is an input */ |
| 10953 | #define OPFLG_IN3 0x08 /* in3: P3 is an input */ |
| 10954 | #define OPFLG_OUT2 0x10 /* out2: P2 is an output */ |
| 10955 | #define OPFLG_OUT3 0x20 /* out3: P3 is an output */ |
| 10956 | #define OPFLG_INITIALIZER {\ |
| 10957 | /* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\ |
| 10958 | /* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x02,\ |
| 10959 | /* 16 */ 0x01, 0x02, 0x03, 0x12, 0x08, 0x00, 0x10, 0x10,\ |
| 10960 | /* 24 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\ |
| 10961 | /* 32 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02,\ |
| 10962 | /* 40 */ 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x00,\ |
| 10963 | /* 48 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ |
| 10964 | /* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,\ |
| 10965 | /* 64 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x26,\ |
| 10966 | /* 72 */ 0x26, 0x10, 0x10, 0x00, 0x03, 0x03, 0x0b, 0x0b,\ |
| 10967 | /* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x26, 0x26, 0x26,\ |
| 10968 | /* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\ |
| 10969 | /* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ |
| 10970 | /* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x00,\ |
| 10971 | /* 112 */ 0x00, 0x10, 0x01, 0x01, 0x01, 0x01, 0x10, 0x00,\ |
| 10972 | /* 120 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 10973 | /* 128 */ 0x00, 0x06, 0x23, 0x0b, 0x01, 0x10, 0x10, 0x00,\ |
| 10974 | /* 136 */ 0x01, 0x04, 0x03, 0x1a, 0x03, 0x03, 0x03, 0x00,\ |
| 10975 | /* 144 */ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 10976 | /* 152 */ 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x01, 0x00,\ |
| 10977 | /* 160 */ 0x00, 0x00,} |
| 10978 | |
| 10979 | /************** End of opcodes.h *********************************************/ |
| 10980 | /************** Continuing where we left off in vdbe.h ***********************/ |
| 10981 | |
| 10982 | /* |
| @@ -10976,10 +10992,11 @@ | |
| 10992 | SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...); |
| 10993 | SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); |
| 10994 | SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); |
| 10995 | SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); |
| 10996 | SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); |
| 10997 | SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int); |
| 10998 | #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) |
| 10999 | SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); |
| 11000 | #else |
| 11001 | # define sqlite3VdbeVerifyNoMallocRequired(A,B) |
| 11002 | #endif |
| @@ -11199,15 +11216,16 @@ | |
| 11216 | ** Flags for sqlite3PagerSetFlags() |
| 11217 | */ |
| 11218 | #define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */ |
| 11219 | #define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */ |
| 11220 | #define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */ |
| 11221 | #define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */ |
| 11222 | #define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */ |
| 11223 | #define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */ |
| 11224 | #define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */ |
| 11225 | #define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */ |
| 11226 | #define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */ |
| 11227 | |
| 11228 | /* |
| 11229 | ** The remainder of this file contains the declarations of the functions |
| 11230 | ** that make up the Pager sub-system API. See source code comments for |
| 11231 | ** a detailed description of each routine. |
| @@ -11963,12 +11981,12 @@ | |
| 11981 | ** is shared by multiple database connections. Therefore, while parsing |
| 11982 | ** schema information, the Lookaside.bEnabled flag is cleared so that |
| 11983 | ** lookaside allocations are not used to construct the schema objects. |
| 11984 | */ |
| 11985 | struct Lookaside { |
| 11986 | u32 bDisable; /* Only operate the lookaside when zero */ |
| 11987 | u16 sz; /* Size of each buffer in bytes */ |
| 11988 | u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ |
| 11989 | int nOut; /* Number of buffers currently checked out */ |
| 11990 | int mxOut; /* Highwater mark for nOut */ |
| 11991 | int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ |
| 11992 | LookasideSlot *pFree; /* List of available buffers */ |
| @@ -12047,10 +12065,11 @@ | |
| 12065 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 12066 | u8 enc; /* Text encoding */ |
| 12067 | u8 autoCommit; /* The auto-commit flag. */ |
| 12068 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 12069 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 12070 | u8 bBenignMalloc; /* Do not require OOMs if true */ |
| 12071 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 12072 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| 12073 | u8 suppressErr; /* Do not issue error messages if true */ |
| 12074 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
| 12075 | u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ |
| @@ -12155,14 +12174,14 @@ | |
| 12174 | /* |
| 12175 | ** Possible values for the sqlite3.flags. |
| 12176 | */ |
| 12177 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| 12178 | #define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ |
| 12179 | #define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ |
| 12180 | #define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */ |
| 12181 | #define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */ |
| 12182 | #define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */ |
| 12183 | #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ |
| 12184 | #define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ |
| 12185 | /* DELETE, or UPDATE and return */ |
| 12186 | /* the count using a callback. */ |
| 12187 | #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ |
| @@ -13510,11 +13529,11 @@ | |
| 13529 | /* |
| 13530 | ** During code generation of statements that do inserts into AUTOINCREMENT |
| 13531 | ** tables, the following information is attached to the Table.u.autoInc.p |
| 13532 | ** pointer of each autoincrement table to record some side information that |
| 13533 | ** the code generator needs. We have to keep per-table autoincrement |
| 13534 | ** information in case inserts are done within triggers. Triggers do not |
| 13535 | ** normally coordinate their activities, but we do need to coordinate the |
| 13536 | ** loading and saving of autoincrement information. |
| 13537 | */ |
| 13538 | struct AutoincInfo { |
| 13539 | AutoincInfo *pNext; /* Next info block in a list of them all */ |
| @@ -13602,10 +13621,11 @@ | |
| 13621 | u8 nTempReg; /* Number of temporary registers in aTempReg[] */ |
| 13622 | u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ |
| 13623 | u8 mayAbort; /* True if statement may throw an ABORT exception */ |
| 13624 | u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ |
| 13625 | u8 okConstFactor; /* OK to factor out constants */ |
| 13626 | u8 disableLookaside; /* Number of times lookaside has been disabled */ |
| 13627 | int aTempReg[8]; /* Holding area for temporary registers */ |
| 13628 | int nRangeReg; /* Size of the temporary register block */ |
| 13629 | int iRangeReg; /* First register in temporary register block */ |
| 13630 | int nErr; /* Number of errors seen */ |
| 13631 | int nTab; /* Number of previously allocated VDBE cursors */ |
| @@ -13716,23 +13736,26 @@ | |
| 13736 | }; |
| 13737 | |
| 13738 | /* |
| 13739 | ** Bitfield flags for P5 value in various opcodes. |
| 13740 | */ |
| 13741 | #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ |
| 13742 | /* Also used in P2 (not P5) of OP_Delete */ |
| 13743 | #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ |
| 13744 | #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ |
| 13745 | #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ |
| 13746 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ |
| 13747 | #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ |
| 13748 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 13749 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 13750 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 13751 | #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ |
| 13752 | #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ |
| 13753 | #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ |
| 13754 | #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ |
| 13755 | #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */ |
| 13756 | #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ |
| 13757 | |
| 13758 | /* |
| 13759 | * Each trigger present in the database schema is stored as an instance of |
| 13760 | * struct Trigger. |
| 13761 | * |
| @@ -13847,14 +13870,20 @@ | |
| 13870 | char *zText; /* The string collected so far */ |
| 13871 | u32 nChar; /* Length of the string so far */ |
| 13872 | u32 nAlloc; /* Amount of space allocated in zText */ |
| 13873 | u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ |
| 13874 | u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ |
| 13875 | u8 printfFlags; /* SQLITE_PRINTF flags below */ |
| 13876 | }; |
| 13877 | #define STRACCUM_NOMEM 1 |
| 13878 | #define STRACCUM_TOOBIG 2 |
| 13879 | #define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ |
| 13880 | #define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ |
| 13881 | #define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */ |
| 13882 | |
| 13883 | #define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0) |
| 13884 | |
| 13885 | |
| 13886 | /* |
| 13887 | ** A pointer to this structure is used to communicate information |
| 13888 | ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. |
| 13889 | */ |
| @@ -14085,10 +14114,11 @@ | |
| 14114 | SQLITE_PRIVATE void sqlite3MallocEnd(void); |
| 14115 | SQLITE_PRIVATE void *sqlite3Malloc(u64); |
| 14116 | SQLITE_PRIVATE void *sqlite3MallocZero(u64); |
| 14117 | SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); |
| 14118 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); |
| 14119 | SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64); |
| 14120 | SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); |
| 14121 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); |
| 14122 | SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); |
| 14123 | SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); |
| 14124 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); |
| @@ -14167,14 +14197,12 @@ | |
| 14197 | int nArg; /* Total number of arguments */ |
| 14198 | int nUsed; /* Number of arguments used so far */ |
| 14199 | sqlite3_value **apArg; /* The argument values */ |
| 14200 | }; |
| 14201 | |
| 14202 | SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, const char*, va_list); |
| 14203 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); |
| 14204 | SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); |
| 14205 | SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); |
| 14206 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 14207 | SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); |
| 14208 | #endif |
| @@ -14191,10 +14219,11 @@ | |
| 14219 | |
| 14220 | |
| 14221 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); |
| 14222 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 14223 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 14224 | SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); |
| 14225 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 14226 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 14227 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 14228 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| 14229 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); |
| @@ -14638,10 +14667,12 @@ | |
| 14667 | SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, |
| 14668 | void (*)(sqlite3_context*,int,sqlite3_value **), |
| 14669 | void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), |
| 14670 | FuncDestructor *pDestructor |
| 14671 | ); |
| 14672 | SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); |
| 14673 | SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); |
| 14674 | SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); |
| 14675 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); |
| 14676 | |
| 14677 | SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); |
| 14678 | SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); |
| @@ -15734,18 +15765,20 @@ | |
| 15765 | ** - On either an index or a table |
| 15766 | ** * A sorter |
| 15767 | ** * A virtual table |
| 15768 | ** * A one-row "pseudotable" stored in a single register |
| 15769 | */ |
| 15770 | typedef struct VdbeCursor VdbeCursor; |
| 15771 | struct VdbeCursor { |
| 15772 | u8 eCurType; /* One of the CURTYPE_* values above */ |
| 15773 | i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ |
| 15774 | u8 nullRow; /* True if pointing to a row with no data */ |
| 15775 | u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ |
| 15776 | u8 isTable; /* True for rowid tables. False for indexes */ |
| 15777 | #ifdef SQLITE_DEBUG |
| 15778 | u8 seekOp; /* Most recent seek operation on this cursor */ |
| 15779 | u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ |
| 15780 | #endif |
| 15781 | Bool isEphemeral:1; /* True for an ephemeral table */ |
| 15782 | Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ |
| 15783 | Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ |
| 15784 | Pgno pgnoRoot; /* Root page of the open btree cursor */ |
| @@ -15760,10 +15793,12 @@ | |
| 15793 | Btree *pBt; /* Separate file holding temporary table */ |
| 15794 | KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ |
| 15795 | int seekResult; /* Result of previous sqlite3BtreeMoveto() */ |
| 15796 | i64 seqCount; /* Sequence counter */ |
| 15797 | i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ |
| 15798 | VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ |
| 15799 | int *aAltMap; /* Mapping from table to index column numbers */ |
| 15800 | #ifdef SQLITE_ENABLE_COLUMN_USED_MASK |
| 15801 | u64 maskUsed; /* Mask of columns used by this cursor */ |
| 15802 | #endif |
| 15803 | |
| 15804 | /* Cached information about the header for the data record that the |
| @@ -15784,11 +15819,10 @@ | |
| 15819 | u32 aType[1]; /* Type values for all entries in the record */ |
| 15820 | /* 2*nField extra array elements allocated for aType[], beyond the one |
| 15821 | ** static element declared in the structure. nField total array slots for |
| 15822 | ** aType[] and nField+1 array slots for aOffset[] */ |
| 15823 | }; |
| 15824 | |
| 15825 | /* |
| 15826 | ** When a sub-program is executed (OP_Program), a structure of this type |
| 15827 | ** is allocated to store the current value of the program counter, as |
| 15828 | ** well as the current memory cell array and various other frame specific |
| @@ -15895,11 +15929,11 @@ | |
| 15929 | #define MEM_AffMask 0x001f /* Mask of affinity bits */ |
| 15930 | #define MEM_RowSet 0x0020 /* Value is a RowSet object */ |
| 15931 | #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ |
| 15932 | #define MEM_Undefined 0x0080 /* Value is undefined */ |
| 15933 | #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ |
| 15934 | #define MEM_TypeMask 0x81ff /* Mask of type bits */ |
| 15935 | |
| 15936 | |
| 15937 | /* Whenever Mem contains a valid string or blob representation, one of |
| 15938 | ** the following flags must be set to determine the memory management |
| 15939 | ** policy for Mem.z. The MEM_Term flag tells us whether or not the |
| @@ -15909,14 +15943,21 @@ | |
| 15943 | #define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ |
| 15944 | #define MEM_Static 0x0800 /* Mem.z points to a static string */ |
| 15945 | #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ |
| 15946 | #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ |
| 15947 | #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ |
| 15948 | #define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */ |
| 15949 | #ifdef SQLITE_OMIT_INCRBLOB |
| 15950 | #undef MEM_Zero |
| 15951 | #define MEM_Zero 0x0000 |
| 15952 | #endif |
| 15953 | |
| 15954 | /* Return TRUE if Mem X contains dynamically allocated content - anything |
| 15955 | ** that needs to be deallocated to avoid a leak. |
| 15956 | */ |
| 15957 | #define VdbeMemDynamic(X) \ |
| 15958 | (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) |
| 15959 | |
| 15960 | /* |
| 15961 | ** Clear any existing type flags from a Mem and replace them with f |
| 15962 | */ |
| 15963 | #define MemSetTypeFlag(p, f) \ |
| @@ -16083,11 +16124,11 @@ | |
| 16124 | ** Function prototypes |
| 16125 | */ |
| 16126 | SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); |
| 16127 | SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); |
| 16128 | void sqliteVdbePopStack(Vdbe*,int); |
| 16129 | SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); |
| 16130 | SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); |
| 16131 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 16132 | SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); |
| 16133 | #endif |
| 16134 | SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); |
| @@ -16129,12 +16170,10 @@ | |
| 16170 | SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); |
| 16171 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); |
| 16172 | SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); |
| 16173 | SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); |
| 16174 | SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); |
| 16175 | SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); |
| 16176 | SQLITE_PRIVATE const char *sqlite3OpcodeName(int); |
| 16177 | SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); |
| 16178 | SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); |
| 16179 | SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); |
| @@ -17492,11 +17531,11 @@ | |
| 17531 | z = zBuf; |
| 17532 | }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 17533 | sqlite3_result_error_toobig(context); |
| 17534 | return; |
| 17535 | }else{ |
| 17536 | z = sqlite3DbMallocRawNN(db, (int)n); |
| 17537 | if( z==0 ){ |
| 17538 | sqlite3_result_error_nomem(context); |
| 17539 | return; |
| 17540 | } |
| 17541 | } |
| @@ -20081,15 +20120,15 @@ | |
| 20120 | mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; |
| 20121 | while( ALWAYS(iLogsize<LOGMAX) ){ |
| 20122 | int iBuddy; |
| 20123 | if( (iBlock>>iLogsize) & 1 ){ |
| 20124 | iBuddy = iBlock - size; |
| 20125 | assert( iBuddy>=0 ); |
| 20126 | }else{ |
| 20127 | iBuddy = iBlock + size; |
| 20128 | if( iBuddy>=mem5.nBlock ) break; |
| 20129 | } |
| 20130 | if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; |
| 20131 | memsys5Unlink(iBuddy, iLogsize); |
| 20132 | iLogsize++; |
| 20133 | if( iBuddy<iBlock ){ |
| 20134 | mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize; |
| @@ -22386,14 +22425,28 @@ | |
| 22425 | /* |
| 22426 | ** Allocate and zero memory. If the allocation fails, make |
| 22427 | ** the mallocFailed flag in the connection pointer. |
| 22428 | */ |
| 22429 | SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){ |
| 22430 | void *p; |
| 22431 | testcase( db==0 ); |
| 22432 | p = sqlite3DbMallocRaw(db, n); |
| 22433 | if( p ) memset(p, 0, (size_t)n); |
| 22434 | return p; |
| 22435 | } |
| 22436 | |
| 22437 | |
| 22438 | /* Finish the work of sqlite3DbMallocRawNN for the unusual and |
| 22439 | ** slower case when the allocation cannot be fulfilled using lookaside. |
| 22440 | */ |
| 22441 | static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ |
| 22442 | void *p; |
| 22443 | assert( db!=0 ); |
| 22444 | p = sqlite3Malloc(n); |
| 22445 | if( !p ) sqlite3OomFault(db); |
| 22446 | sqlite3MemdebugSetType(p, |
| 22447 | (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); |
| 22448 | return p; |
| 22449 | } |
| 22450 | |
| 22451 | /* |
| 22452 | ** Allocate memory, either lookaside (if possible) or heap. |
| @@ -22411,71 +22464,77 @@ | |
| 22464 | ** int *b = (int*)sqlite3DbMallocRaw(db, 200); |
| 22465 | ** if( b ) a[10] = 9; |
| 22466 | ** |
| 22467 | ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed |
| 22468 | ** that all prior mallocs (ex: "a") worked too. |
| 22469 | ** |
| 22470 | ** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is |
| 22471 | ** not a NULL pointer. |
| 22472 | */ |
| 22473 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ |
| 22474 | void *p; |
| 22475 | if( db ) return sqlite3DbMallocRawNN(db, n); |
| 22476 | p = sqlite3Malloc(n); |
| 22477 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 22478 | return p; |
| 22479 | } |
| 22480 | SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ |
| 22481 | #ifndef SQLITE_OMIT_LOOKASIDE |
| 22482 | LookasideSlot *pBuf; |
| 22483 | assert( db!=0 ); |
| 22484 | assert( sqlite3_mutex_held(db->mutex) ); |
| 22485 | assert( db->pnBytesFreed==0 ); |
| 22486 | if( db->lookaside.bDisable==0 ){ |
| 22487 | assert( db->mallocFailed==0 ); |
| 22488 | if( n>db->lookaside.sz ){ |
| 22489 | db->lookaside.anStat[1]++; |
| 22490 | }else if( (pBuf = db->lookaside.pFree)==0 ){ |
| 22491 | db->lookaside.anStat[2]++; |
| 22492 | }else{ |
| 22493 | db->lookaside.pFree = pBuf->pNext; |
| 22494 | db->lookaside.nOut++; |
| 22495 | db->lookaside.anStat[0]++; |
| 22496 | if( db->lookaside.nOut>db->lookaside.mxOut ){ |
| 22497 | db->lookaside.mxOut = db->lookaside.nOut; |
| 22498 | } |
| 22499 | return (void*)pBuf; |
| 22500 | } |
| 22501 | }else if( db->mallocFailed ){ |
| 22502 | return 0; |
| 22503 | } |
| 22504 | #else |
| 22505 | assert( db!=0 ); |
| 22506 | assert( sqlite3_mutex_held(db->mutex) ); |
| 22507 | assert( db->pnBytesFreed==0 ); |
| 22508 | if( db->mallocFailed ){ |
| 22509 | return 0; |
| 22510 | } |
| 22511 | #endif |
| 22512 | return dbMallocRawFinish(db, n); |
| 22513 | } |
| 22514 | |
| 22515 | /* Forward declaration */ |
| 22516 | static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); |
| 22517 | |
| 22518 | /* |
| 22519 | ** Resize the block of memory pointed to by p to n bytes. If the |
| 22520 | ** resize fails, set the mallocFailed flag in the connection object. |
| 22521 | */ |
| 22522 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ |
| 22523 | assert( db!=0 ); |
| 22524 | if( p==0 ) return sqlite3DbMallocRawNN(db, n); |
| 22525 | assert( sqlite3_mutex_held(db->mutex) ); |
| 22526 | if( isLookaside(db,p) && n<=db->lookaside.sz ) return p; |
| 22527 | return dbReallocFinish(db, p, n); |
| 22528 | } |
| 22529 | static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ |
| 22530 | void *pNew = 0; |
| 22531 | assert( db!=0 ); |
| 22532 | assert( p!=0 ); |
| 22533 | if( db->mallocFailed==0 ){ |
| 22534 | if( isLookaside(db, p) ){ |
| 22535 | pNew = sqlite3DbMallocRawNN(db, n); |
| 22536 | if( pNew ){ |
| 22537 | memcpy(pNew, p, db->lookaside.sz); |
| 22538 | sqlite3DbFree(db, p); |
| 22539 | } |
| 22540 | }else{ |
| @@ -22482,14 +22541,14 @@ | |
| 22541 | assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22542 | assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22543 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 22544 | pNew = sqlite3_realloc64(p, n); |
| 22545 | if( !pNew ){ |
| 22546 | sqlite3OomFault(db); |
| 22547 | } |
| 22548 | sqlite3MemdebugSetType(pNew, |
| 22549 | (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); |
| 22550 | } |
| 22551 | } |
| 22552 | return pNew; |
| 22553 | } |
| 22554 | |
| @@ -22527,15 +22586,16 @@ | |
| 22586 | } |
| 22587 | return zNew; |
| 22588 | } |
| 22589 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ |
| 22590 | char *zNew; |
| 22591 | assert( db!=0 ); |
| 22592 | if( z==0 ){ |
| 22593 | return 0; |
| 22594 | } |
| 22595 | assert( (n&0x7fffffff)==n ); |
| 22596 | zNew = sqlite3DbMallocRawNN(db, n+1); |
| 22597 | if( zNew ){ |
| 22598 | memcpy(zNew, z, (size_t)n); |
| 22599 | zNew[n] = 0; |
| 22600 | } |
| 22601 | return zNew; |
| @@ -22546,16 +22606,48 @@ | |
| 22606 | */ |
| 22607 | SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ |
| 22608 | sqlite3DbFree(db, *pz); |
| 22609 | *pz = sqlite3DbStrDup(db, zNew); |
| 22610 | } |
| 22611 | |
| 22612 | /* |
| 22613 | ** Call this routine to record the fact that an OOM (out-of-memory) error |
| 22614 | ** has happened. This routine will set db->mallocFailed, and also |
| 22615 | ** temporarily disable the lookaside memory allocator and interrupt |
| 22616 | ** any running VDBEs. |
| 22617 | */ |
| 22618 | SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){ |
| 22619 | if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ |
| 22620 | db->mallocFailed = 1; |
| 22621 | if( db->nVdbeExec>0 ){ |
| 22622 | db->u1.isInterrupted = 1; |
| 22623 | } |
| 22624 | db->lookaside.bDisable++; |
| 22625 | } |
| 22626 | } |
| 22627 | |
| 22628 | /* |
| 22629 | ** This routine reactivates the memory allocator and clears the |
| 22630 | ** db->mallocFailed flag as necessary. |
| 22631 | ** |
| 22632 | ** The memory allocator is not restarted if there are running |
| 22633 | ** VDBEs. |
| 22634 | */ |
| 22635 | SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){ |
| 22636 | if( db->mallocFailed && db->nVdbeExec==0 ){ |
| 22637 | db->mallocFailed = 0; |
| 22638 | db->u1.isInterrupted = 0; |
| 22639 | assert( db->lookaside.bDisable>0 ); |
| 22640 | db->lookaside.bDisable--; |
| 22641 | } |
| 22642 | } |
| 22643 | |
| 22644 | /* |
| 22645 | ** Take actions at the end of an API call to indicate an OOM error |
| 22646 | */ |
| 22647 | static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ |
| 22648 | sqlite3OomClear(db); |
| 22649 | sqlite3Error(db, SQLITE_NOMEM); |
| 22650 | return SQLITE_NOMEM; |
| 22651 | } |
| 22652 | |
| 22653 | /* |
| @@ -22756,11 +22848,10 @@ | |
| 22848 | /* |
| 22849 | ** Render a string given by "fmt" into the StrAccum object. |
| 22850 | */ |
| 22851 | SQLITE_PRIVATE void sqlite3VXPrintf( |
| 22852 | StrAccum *pAccum, /* Accumulate results here */ |
| 22853 | const char *fmt, /* Format string */ |
| 22854 | va_list ap /* arguments */ |
| 22855 | ){ |
| 22856 | int c; /* Next character in the format string */ |
| 22857 | char *bufpt; /* Pointer to the conversion buffer */ |
| @@ -22796,15 +22887,15 @@ | |
| 22887 | #endif |
| 22888 | PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ |
| 22889 | char buf[etBUFSIZE]; /* Conversion buffer */ |
| 22890 | |
| 22891 | bufpt = 0; |
| 22892 | if( pAccum->printfFlags ){ |
| 22893 | if( (bArgList = (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ |
| 22894 | pArgList = va_arg(ap, PrintfArguments*); |
| 22895 | } |
| 22896 | useIntern = pAccum->printfFlags & SQLITE_PRINTF_INTERNAL; |
| 22897 | }else{ |
| 22898 | bArgList = useIntern = 0; |
| 22899 | } |
| 22900 | for(; (c=(*fmt))!=0; ++fmt){ |
| 22901 | if( c!='%' ){ |
| @@ -23351,13 +23442,13 @@ | |
| 23442 | if( p->mxAlloc==0 ){ |
| 23443 | N = p->nAlloc - p->nChar - 1; |
| 23444 | setStrAccumError(p, STRACCUM_TOOBIG); |
| 23445 | return N; |
| 23446 | }else{ |
| 23447 | char *zOld = isMalloced(p) ? p->zText : 0; |
| 23448 | i64 szNew = p->nChar; |
| 23449 | assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
| 23450 | szNew += N + 1; |
| 23451 | if( szNew+p->nChar<=p->mxAlloc ){ |
| 23452 | /* Force exponential buffer size growth as long as it does not overflow, |
| 23453 | ** to avoid having to call this routine too often */ |
| 23454 | szNew += p->nChar; |
| @@ -23374,14 +23465,14 @@ | |
| 23465 | }else{ |
| 23466 | zNew = sqlite3_realloc64(zOld, p->nAlloc); |
| 23467 | } |
| 23468 | if( zNew ){ |
| 23469 | assert( p->zText!=0 || p->nChar==0 ); |
| 23470 | if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); |
| 23471 | p->zText = zNew; |
| 23472 | p->nAlloc = sqlite3DbMallocSize(p->db, zNew); |
| 23473 | p->printfFlags |= SQLITE_PRINTF_MALLOCED; |
| 23474 | }else{ |
| 23475 | sqlite3StrAccumReset(p); |
| 23476 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23477 | return 0; |
| 23478 | } |
| @@ -23395,11 +23486,11 @@ | |
| 23486 | SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ |
| 23487 | testcase( p->nChar + (i64)N > 0x7fffffff ); |
| 23488 | if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ |
| 23489 | return; |
| 23490 | } |
| 23491 | assert( (p->zText==p->zBase)==!isMalloced(p) ); |
| 23492 | while( (N--)>0 ) p->zText[p->nChar++] = c; |
| 23493 | } |
| 23494 | |
| 23495 | /* |
| 23496 | ** The StrAccum "p" is not large enough to accept N new bytes of z[]. |
| @@ -23413,11 +23504,11 @@ | |
| 23504 | N = sqlite3StrAccumEnlarge(p, N); |
| 23505 | if( N>0 ){ |
| 23506 | memcpy(&p->zText[p->nChar], z, N); |
| 23507 | p->nChar += N; |
| 23508 | } |
| 23509 | assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
| 23510 | } |
| 23511 | |
| 23512 | /* |
| 23513 | ** Append N bytes of text from z to the StrAccum object. Increase the |
| 23514 | ** size of the memory allocation for StrAccum if necessary. |
| @@ -23449,17 +23540,17 @@ | |
| 23540 | ** Return a pointer to the resulting string. Return a NULL |
| 23541 | ** pointer if any kind of error was encountered. |
| 23542 | */ |
| 23543 | SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ |
| 23544 | if( p->zText ){ |
| 23545 | assert( (p->zText==p->zBase)==!isMalloced(p) ); |
| 23546 | p->zText[p->nChar] = 0; |
| 23547 | if( p->mxAlloc>0 && !isMalloced(p) ){ |
| 23548 | p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
| 23549 | if( p->zText ){ |
| 23550 | memcpy(p->zText, p->zBase, p->nChar+1); |
| 23551 | p->printfFlags |= SQLITE_PRINTF_MALLOCED; |
| 23552 | }else{ |
| 23553 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23554 | } |
| 23555 | } |
| 23556 | } |
| @@ -23468,14 +23559,14 @@ | |
| 23559 | |
| 23560 | /* |
| 23561 | ** Reset an StrAccum string. Reclaim all malloced memory. |
| 23562 | */ |
| 23563 | SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ |
| 23564 | assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
| 23565 | if( isMalloced(p) ){ |
| 23566 | sqlite3DbFree(p->db, p->zText); |
| 23567 | p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; |
| 23568 | } |
| 23569 | p->zText = 0; |
| 23570 | } |
| 23571 | |
| 23572 | /* |
| @@ -23497,11 +23588,11 @@ | |
| 23588 | p->db = db; |
| 23589 | p->nChar = 0; |
| 23590 | p->nAlloc = n; |
| 23591 | p->mxAlloc = mx; |
| 23592 | p->accError = 0; |
| 23593 | p->printfFlags = 0; |
| 23594 | } |
| 23595 | |
| 23596 | /* |
| 23597 | ** Print into memory obtained from sqliteMalloc(). Use the internal |
| 23598 | ** %-conversion extensions. |
| @@ -23511,14 +23602,15 @@ | |
| 23602 | char zBase[SQLITE_PRINT_BUF_SIZE]; |
| 23603 | StrAccum acc; |
| 23604 | assert( db!=0 ); |
| 23605 | sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), |
| 23606 | db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 23607 | acc.printfFlags = SQLITE_PRINTF_INTERNAL; |
| 23608 | sqlite3VXPrintf(&acc, zFormat, ap); |
| 23609 | z = sqlite3StrAccumFinish(&acc); |
| 23610 | if( acc.accError==STRACCUM_NOMEM ){ |
| 23611 | sqlite3OomFault(db); |
| 23612 | } |
| 23613 | return z; |
| 23614 | } |
| 23615 | |
| 23616 | /* |
| @@ -23551,11 +23643,11 @@ | |
| 23643 | #endif |
| 23644 | #ifndef SQLITE_OMIT_AUTOINIT |
| 23645 | if( sqlite3_initialize() ) return 0; |
| 23646 | #endif |
| 23647 | sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); |
| 23648 | sqlite3VXPrintf(&acc, zFormat, ap); |
| 23649 | z = sqlite3StrAccumFinish(&acc); |
| 23650 | return z; |
| 23651 | } |
| 23652 | |
| 23653 | /* |
| @@ -23596,11 +23688,11 @@ | |
| 23688 | if( zBuf ) zBuf[0] = 0; |
| 23689 | return zBuf; |
| 23690 | } |
| 23691 | #endif |
| 23692 | sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); |
| 23693 | sqlite3VXPrintf(&acc, zFormat, ap); |
| 23694 | return sqlite3StrAccumFinish(&acc); |
| 23695 | } |
| 23696 | SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
| 23697 | char *z; |
| 23698 | va_list ap; |
| @@ -23627,11 +23719,11 @@ | |
| 23719 | static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
| 23720 | StrAccum acc; /* String accumulator */ |
| 23721 | char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
| 23722 | |
| 23723 | sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); |
| 23724 | sqlite3VXPrintf(&acc, zFormat, ap); |
| 23725 | sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
| 23726 | sqlite3StrAccumFinish(&acc)); |
| 23727 | } |
| 23728 | |
| 23729 | /* |
| @@ -23656,11 +23748,11 @@ | |
| 23748 | va_list ap; |
| 23749 | StrAccum acc; |
| 23750 | char zBuf[500]; |
| 23751 | sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); |
| 23752 | va_start(ap,zFormat); |
| 23753 | sqlite3VXPrintf(&acc, zFormat, ap); |
| 23754 | va_end(ap); |
| 23755 | sqlite3StrAccumFinish(&acc); |
| 23756 | fprintf(stdout,"%s", zBuf); |
| 23757 | fflush(stdout); |
| 23758 | } |
| @@ -23669,14 +23761,14 @@ | |
| 23761 | |
| 23762 | /* |
| 23763 | ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument |
| 23764 | ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. |
| 23765 | */ |
| 23766 | SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ |
| 23767 | va_list ap; |
| 23768 | va_start(ap,zFormat); |
| 23769 | sqlite3VXPrintf(p, zFormat, ap); |
| 23770 | va_end(ap); |
| 23771 | } |
| 23772 | |
| 23773 | /************** End of printf.c **********************************************/ |
| 23774 | /************** Begin file treeview.c ****************************************/ |
| @@ -23743,11 +23835,11 @@ | |
| 23835 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); |
| 23836 | } |
| 23837 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); |
| 23838 | } |
| 23839 | va_start(ap, zFormat); |
| 23840 | sqlite3VXPrintf(&acc, zFormat, ap); |
| 23841 | va_end(ap); |
| 23842 | if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); |
| 23843 | sqlite3StrAccumFinish(&acc); |
| 23844 | fprintf(stdout,"%s", zBuf); |
| 23845 | fflush(stdout); |
| @@ -23778,21 +23870,21 @@ | |
| 23870 | for(i=0; i<pWith->nCte; i++){ |
| 23871 | StrAccum x; |
| 23872 | char zLine[1000]; |
| 23873 | const struct Cte *pCte = &pWith->a[i]; |
| 23874 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23875 | sqlite3XPrintf(&x, "%s", pCte->zName); |
| 23876 | if( pCte->pCols && pCte->pCols->nExpr>0 ){ |
| 23877 | char cSep = '('; |
| 23878 | int j; |
| 23879 | for(j=0; j<pCte->pCols->nExpr; j++){ |
| 23880 | sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); |
| 23881 | cSep = ','; |
| 23882 | } |
| 23883 | sqlite3XPrintf(&x, ")"); |
| 23884 | } |
| 23885 | sqlite3XPrintf(&x, " AS"); |
| 23886 | sqlite3StrAccumFinish(&x); |
| 23887 | sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1); |
| 23888 | sqlite3TreeViewSelect(pView, pCte->pSelect, 0); |
| 23889 | sqlite3TreeViewPop(pView); |
| 23890 | } |
| @@ -23839,24 +23931,24 @@ | |
| 23931 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 23932 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 23933 | StrAccum x; |
| 23934 | char zLine[100]; |
| 23935 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23936 | sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); |
| 23937 | if( pItem->zDatabase ){ |
| 23938 | sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); |
| 23939 | }else if( pItem->zName ){ |
| 23940 | sqlite3XPrintf(&x, " %s", pItem->zName); |
| 23941 | } |
| 23942 | if( pItem->pTab ){ |
| 23943 | sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); |
| 23944 | } |
| 23945 | if( pItem->zAlias ){ |
| 23946 | sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); |
| 23947 | } |
| 23948 | if( pItem->fg.jointype & JT_LEFT ){ |
| 23949 | sqlite3XPrintf(&x, " LEFT-JOIN"); |
| 23950 | } |
| 23951 | sqlite3StrAccumFinish(&x); |
| 23952 | sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); |
| 23953 | if( pItem->pSelect ){ |
| 23954 | sqlite3TreeViewSelect(pView, pItem->pSelect, 0); |
| @@ -24899,11 +24991,11 @@ | |
| 24991 | *z = 0; |
| 24992 | assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); |
| 24993 | |
| 24994 | c = pMem->flags; |
| 24995 | sqlite3VdbeMemRelease(pMem); |
| 24996 | pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype)); |
| 24997 | pMem->enc = desiredEnc; |
| 24998 | pMem->z = (char*)zOut; |
| 24999 | pMem->zMalloc = pMem->z; |
| 25000 | pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); |
| 25001 | |
| @@ -25349,10 +25441,18 @@ | |
| 25441 | } |
| 25442 | } |
| 25443 | z[j] = 0; |
| 25444 | return j; |
| 25445 | } |
| 25446 | |
| 25447 | /* |
| 25448 | ** Generate a Token object from a string |
| 25449 | */ |
| 25450 | SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ |
| 25451 | p->z = z; |
| 25452 | p->n = sqlite3Strlen30(z); |
| 25453 | } |
| 25454 | |
| 25455 | /* Convenient short-hand */ |
| 25456 | #define UpperToLower sqlite3UpperToLower |
| 25457 | |
| 25458 | /* |
| @@ -26258,11 +26358,11 @@ | |
| 26358 | */ |
| 26359 | SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ |
| 26360 | char *zBlob; |
| 26361 | int i; |
| 26362 | |
| 26363 | zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1); |
| 26364 | n--; |
| 26365 | if( zBlob ){ |
| 26366 | for(i=0; i<n; i+=2){ |
| 26367 | zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]); |
| 26368 | } |
| @@ -26796,95 +26896,96 @@ | |
| 26896 | # define OpHelp(X) "\0" X |
| 26897 | #else |
| 26898 | # define OpHelp(X) |
| 26899 | #endif |
| 26900 | SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ |
| 26901 | static const char *const azName[] = { |
| 26902 | /* 0 */ "Savepoint" OpHelp(""), |
| 26903 | /* 1 */ "AutoCommit" OpHelp(""), |
| 26904 | /* 2 */ "Transaction" OpHelp(""), |
| 26905 | /* 3 */ "SorterNext" OpHelp(""), |
| 26906 | /* 4 */ "PrevIfOpen" OpHelp(""), |
| 26907 | /* 5 */ "NextIfOpen" OpHelp(""), |
| 26908 | /* 6 */ "Prev" OpHelp(""), |
| 26909 | /* 7 */ "Next" OpHelp(""), |
| 26910 | /* 8 */ "Checkpoint" OpHelp(""), |
| 26911 | /* 9 */ "JournalMode" OpHelp(""), |
| 26912 | /* 10 */ "Vacuum" OpHelp(""), |
| 26913 | /* 11 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), |
| 26914 | /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"), |
| 26915 | /* 13 */ "Goto" OpHelp(""), |
| 26916 | /* 14 */ "Gosub" OpHelp(""), |
| 26917 | /* 15 */ "Return" OpHelp(""), |
| 26918 | /* 16 */ "InitCoroutine" OpHelp(""), |
| 26919 | /* 17 */ "EndCoroutine" OpHelp(""), |
| 26920 | /* 18 */ "Yield" OpHelp(""), |
| 26921 | /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), |
| 26922 | /* 20 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), |
| 26923 | /* 21 */ "Halt" OpHelp(""), |
| 26924 | /* 22 */ "Integer" OpHelp("r[P2]=P1"), |
| 26925 | /* 23 */ "Int64" OpHelp("r[P2]=P4"), |
| 26926 | /* 24 */ "String" OpHelp("r[P2]='P4' (len=P1)"), |
| 26927 | /* 25 */ "Null" OpHelp("r[P2..P3]=NULL"), |
| 26928 | /* 26 */ "SoftNull" OpHelp("r[P1]=NULL"), |
| 26929 | /* 27 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), |
| 26930 | /* 28 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), |
| 26931 | /* 29 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), |
| 26932 | /* 30 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), |
| 26933 | /* 31 */ "SCopy" OpHelp("r[P2]=r[P1]"), |
| 26934 | /* 32 */ "IntCopy" OpHelp("r[P2]=r[P1]"), |
| 26935 | /* 33 */ "ResultRow" OpHelp("output=r[P1@P2]"), |
| 26936 | /* 34 */ "CollSeq" OpHelp(""), |
| 26937 | /* 35 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), |
| 26938 | /* 36 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), |
| 26939 | /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), |
| 26940 | /* 38 */ "MustBeInt" OpHelp(""), |
| 26941 | /* 39 */ "RealAffinity" OpHelp(""), |
| 26942 | /* 40 */ "Cast" OpHelp("affinity(r[P1])"), |
| 26943 | /* 41 */ "Permutation" OpHelp(""), |
| 26944 | /* 42 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), |
| 26945 | /* 43 */ "Jump" OpHelp(""), |
| 26946 | /* 44 */ "Once" OpHelp(""), |
| 26947 | /* 45 */ "If" OpHelp(""), |
| 26948 | /* 46 */ "IfNot" OpHelp(""), |
| 26949 | /* 47 */ "Column" OpHelp("r[P3]=PX"), |
| 26950 | /* 48 */ "Affinity" OpHelp("affinity(r[P1@P2])"), |
| 26951 | /* 49 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), |
| 26952 | /* 50 */ "Count" OpHelp("r[P2]=count()"), |
| 26953 | /* 51 */ "ReadCookie" OpHelp(""), |
| 26954 | /* 52 */ "SetCookie" OpHelp(""), |
| 26955 | /* 53 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), |
| 26956 | /* 54 */ "OpenRead" OpHelp("root=P2 iDb=P3"), |
| 26957 | /* 55 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), |
| 26958 | /* 56 */ "OpenAutoindex" OpHelp("nColumn=P2"), |
| 26959 | /* 57 */ "OpenEphemeral" OpHelp("nColumn=P2"), |
| 26960 | /* 58 */ "SorterOpen" OpHelp(""), |
| 26961 | /* 59 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), |
| 26962 | /* 60 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), |
| 26963 | /* 61 */ "Close" OpHelp(""), |
| 26964 | /* 62 */ "ColumnsUsed" OpHelp(""), |
| 26965 | /* 63 */ "SeekLT" OpHelp("key=r[P3@P4]"), |
| 26966 | /* 64 */ "SeekLE" OpHelp("key=r[P3@P4]"), |
| 26967 | /* 65 */ "SeekGE" OpHelp("key=r[P3@P4]"), |
| 26968 | /* 66 */ "SeekGT" OpHelp("key=r[P3@P4]"), |
| 26969 | /* 67 */ "NoConflict" OpHelp("key=r[P3@P4]"), |
| 26970 | /* 68 */ "NotFound" OpHelp("key=r[P3@P4]"), |
| 26971 | /* 69 */ "Found" OpHelp("key=r[P3@P4]"), |
| 26972 | /* 70 */ "NotExists" OpHelp("intkey=r[P3]"), |
| 26973 | /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), |
| 26974 | /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), |
| 26975 | /* 73 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), |
| 26976 | /* 74 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 26977 | /* 75 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 26978 | /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), |
| 26979 | /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), |
| 26980 | /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), |
| 26981 | /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), |
| 26982 | /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), |
| 26983 | /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), |
| 26984 | /* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"), |
| 26985 | /* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"), |
| 26986 | /* 84 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), |
| 26987 | /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), |
| 26988 | /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), |
| 26989 | /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), |
| 26990 | /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), |
| 26991 | /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), |
| @@ -26891,78 +26992,77 @@ | |
| 26992 | /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), |
| 26993 | /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), |
| 26994 | /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), |
| 26995 | /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), |
| 26996 | /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), |
| 26997 | /* 95 */ "Delete" OpHelp(""), |
| 26998 | /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), |
| 26999 | /* 97 */ "String8" OpHelp("r[P2]='P4'"), |
| 27000 | /* 98 */ "ResetCount" OpHelp(""), |
| 27001 | /* 99 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), |
| 27002 | /* 100 */ "SorterData" OpHelp("r[P2]=data"), |
| 27003 | /* 101 */ "RowKey" OpHelp("r[P2]=key"), |
| 27004 | /* 102 */ "RowData" OpHelp("r[P2]=data"), |
| 27005 | /* 103 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 27006 | /* 104 */ "NullRow" OpHelp(""), |
| 27007 | /* 105 */ "Last" OpHelp(""), |
| 27008 | /* 106 */ "SorterSort" OpHelp(""), |
| 27009 | /* 107 */ "Sort" OpHelp(""), |
| 27010 | /* 108 */ "Rewind" OpHelp(""), |
| 27011 | /* 109 */ "SorterInsert" OpHelp(""), |
| 27012 | /* 110 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 27013 | /* 111 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 27014 | /* 112 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 27015 | /* 113 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 27016 | /* 114 */ "IdxLE" OpHelp("key=r[P3@P4]"), |
| 27017 | /* 115 */ "IdxGT" OpHelp("key=r[P3@P4]"), |
| 27018 | /* 116 */ "IdxLT" OpHelp("key=r[P3@P4]"), |
| 27019 | /* 117 */ "IdxGE" OpHelp("key=r[P3@P4]"), |
| 27020 | /* 118 */ "Destroy" OpHelp(""), |
| 27021 | /* 119 */ "Clear" OpHelp(""), |
| 27022 | /* 120 */ "ResetSorter" OpHelp(""), |
| 27023 | /* 121 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 27024 | /* 122 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 27025 | /* 123 */ "ParseSchema" OpHelp(""), |
| 27026 | /* 124 */ "LoadAnalysis" OpHelp(""), |
| 27027 | /* 125 */ "DropTable" OpHelp(""), |
| 27028 | /* 126 */ "DropIndex" OpHelp(""), |
| 27029 | /* 127 */ "DropTrigger" OpHelp(""), |
| 27030 | /* 128 */ "IntegrityCk" OpHelp(""), |
| 27031 | /* 129 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), |
| 27032 | /* 130 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), |
| 27033 | /* 131 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), |
| 27034 | /* 132 */ "Program" OpHelp(""), |
| 27035 | /* 133 */ "Real" OpHelp("r[P2]=P4"), |
| 27036 | /* 134 */ "Param" OpHelp(""), |
| 27037 | /* 135 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), |
| 27038 | /* 136 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), |
| 27039 | /* 137 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), |
| 27040 | /* 138 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), |
| 27041 | /* 139 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), |
| 27042 | /* 140 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), |
| 27043 | /* 141 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), |
| 27044 | /* 142 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), |
| 27045 | /* 143 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 27046 | /* 144 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 27047 | /* 145 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), |
| 27048 | /* 146 */ "IncrVacuum" OpHelp(""), |
| 27049 | /* 147 */ "Expire" OpHelp(""), |
| 27050 | /* 148 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), |
| 27051 | /* 149 */ "VBegin" OpHelp(""), |
| 27052 | /* 150 */ "VCreate" OpHelp(""), |
| 27053 | /* 151 */ "VDestroy" OpHelp(""), |
| 27054 | /* 152 */ "VOpen" OpHelp(""), |
| 27055 | /* 153 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), |
| 27056 | /* 154 */ "VNext" OpHelp(""), |
| 27057 | /* 155 */ "VRename" OpHelp(""), |
| 27058 | /* 156 */ "Pagecount" OpHelp(""), |
| 27059 | /* 157 */ "MaxPgcnt" OpHelp(""), |
| 27060 | /* 158 */ "Init" OpHelp("Start at P2"), |
| 27061 | /* 159 */ "CursorHint" OpHelp(""), |
| 27062 | /* 160 */ "Noop" OpHelp(""), |
| 27063 | /* 161 */ "Explain" OpHelp(""), |
| 27064 | }; |
| 27065 | return azName[i]; |
| 27066 | } |
| 27067 | #endif |
| 27068 | |
| @@ -27117,10 +27217,15 @@ | |
| 27217 | /* |
| 27218 | ** Maximum supported path-length. |
| 27219 | */ |
| 27220 | #define MAX_PATHNAME 512 |
| 27221 | |
| 27222 | /* |
| 27223 | ** Maximum supported symbolic links |
| 27224 | */ |
| 27225 | #define SQLITE_MAX_SYMLINKS 100 |
| 27226 | |
| 27227 | /* Always cast the getpid() return type for compatibility with |
| 27228 | ** kernel modules in VxWorks. */ |
| 27229 | #define osGetpid(X) (pid_t)getpid() |
| 27230 | |
| 27231 | /* |
| @@ -27641,10 +27746,16 @@ | |
| 27746 | #else |
| 27747 | { "readlink", (sqlite3_syscall_ptr)0, 0 }, |
| 27748 | #endif |
| 27749 | #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) |
| 27750 | |
| 27751 | #if defined(HAVE_LSTAT) |
| 27752 | { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, |
| 27753 | #else |
| 27754 | { "lstat", (sqlite3_syscall_ptr)0, 0 }, |
| 27755 | #endif |
| 27756 | #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) |
| 27757 | |
| 27758 | }; /* End of the overrideable system calls */ |
| 27759 | |
| 27760 | |
| 27761 | /* |
| @@ -33042,16 +33153,11 @@ | |
| 33153 | #ifndef SQLITE_DISABLE_DIRSYNC |
| 33154 | if( (dirSync & 1)!=0 ){ |
| 33155 | int fd; |
| 33156 | rc = osOpenDirectory(zPath, &fd); |
| 33157 | if( rc==SQLITE_OK ){ |
| 33158 | if( full_fsync(fd,0,0) ){ |
| 33159 | rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); |
| 33160 | } |
| 33161 | robust_close(0, fd, __LINE__); |
| 33162 | }else{ |
| 33163 | assert( rc==SQLITE_CANTOPEN ); |
| @@ -33093,10 +33199,36 @@ | |
| 33199 | *pResOut = osAccess(zPath, W_OK|R_OK)==0; |
| 33200 | } |
| 33201 | return SQLITE_OK; |
| 33202 | } |
| 33203 | |
| 33204 | /* |
| 33205 | ** |
| 33206 | */ |
| 33207 | static int mkFullPathname( |
| 33208 | const char *zPath, /* Input path */ |
| 33209 | char *zOut, /* Output buffer */ |
| 33210 | int nOut /* Allocated size of buffer zOut */ |
| 33211 | ){ |
| 33212 | int nPath = sqlite3Strlen30(zPath); |
| 33213 | int iOff = 0; |
| 33214 | if( zPath[0]!='/' ){ |
| 33215 | if( osGetcwd(zOut, nOut-2)==0 ){ |
| 33216 | return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); |
| 33217 | } |
| 33218 | iOff = sqlite3Strlen30(zOut); |
| 33219 | zOut[iOff++] = '/'; |
| 33220 | } |
| 33221 | if( (iOff+nPath+1)>nOut ){ |
| 33222 | /* SQLite assumes that xFullPathname() nul-terminates the output buffer |
| 33223 | ** even if it returns an error. */ |
| 33224 | zOut[iOff] = '\0'; |
| 33225 | return SQLITE_CANTOPEN_BKPT; |
| 33226 | } |
| 33227 | sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); |
| 33228 | return SQLITE_OK; |
| 33229 | } |
| 33230 | |
| 33231 | /* |
| 33232 | ** Turn a relative pathname into a full pathname. The relative path |
| 33233 | ** is stored as a nul-terminated string in the buffer pointed to by |
| 33234 | ** zPath. |
| @@ -33109,73 +33241,85 @@ | |
| 33241 | sqlite3_vfs *pVfs, /* Pointer to vfs object */ |
| 33242 | const char *zPath, /* Possibly relative input path */ |
| 33243 | int nOut, /* Size of output buffer in bytes */ |
| 33244 | char *zOut /* Output buffer */ |
| 33245 | ){ |
| 33246 | #if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT) |
| 33247 | return mkFullPathname(zPath, zOut, nOut); |
| 33248 | #else |
| 33249 | int rc = SQLITE_OK; |
| 33250 | int nByte; |
| 33251 | int nLink = 1; /* Number of symbolic links followed so far */ |
| 33252 | const char *zIn = zPath; /* Input path for each iteration of loop */ |
| 33253 | char *zDel = 0; |
| 33254 | |
| 33255 | assert( pVfs->mxPathname==MAX_PATHNAME ); |
| 33256 | UNUSED_PARAMETER(pVfs); |
| 33257 | |
| 33258 | /* It's odd to simulate an io-error here, but really this is just |
| 33259 | ** using the io-error infrastructure to test that SQLite handles this |
| 33260 | ** function failing. This function could fail if, for example, the |
| 33261 | ** current working directory has been unlinked. |
| 33262 | */ |
| 33263 | SimulateIOError( return SQLITE_ERROR ); |
| 33264 | |
| 33265 | do { |
| 33266 | |
| 33267 | /* Call stat() on path zIn. Set bLink to true if the path is a symbolic |
| 33268 | ** link, or false otherwise. */ |
| 33269 | int bLink = 0; |
| 33270 | struct stat buf; |
| 33271 | if( osLstat(zIn, &buf)!=0 ){ |
| 33272 | if( errno!=ENOENT ){ |
| 33273 | rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); |
| 33274 | } |
| 33275 | }else{ |
| 33276 | bLink = S_ISLNK(buf.st_mode); |
| 33277 | } |
| 33278 | |
| 33279 | if( bLink ){ |
| 33280 | if( zDel==0 ){ |
| 33281 | zDel = sqlite3_malloc(nOut); |
| 33282 | if( zDel==0 ) rc = SQLITE_NOMEM; |
| 33283 | }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ |
| 33284 | rc = SQLITE_CANTOPEN_BKPT; |
| 33285 | } |
| 33286 | |
| 33287 | if( rc==SQLITE_OK ){ |
| 33288 | nByte = osReadlink(zIn, zDel, nOut-1); |
| 33289 | if( nByte<0 ){ |
| 33290 | rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); |
| 33291 | }else{ |
| 33292 | if( zDel[0]!='/' ){ |
| 33293 | int n; |
| 33294 | for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); |
| 33295 | if( nByte+n+1>nOut ){ |
| 33296 | rc = SQLITE_CANTOPEN_BKPT; |
| 33297 | }else{ |
| 33298 | memmove(&zDel[n], zDel, nByte+1); |
| 33299 | memcpy(zDel, zIn, n); |
| 33300 | nByte += n; |
| 33301 | } |
| 33302 | } |
| 33303 | zDel[nByte] = '\0'; |
| 33304 | } |
| 33305 | } |
| 33306 | |
| 33307 | zIn = zDel; |
| 33308 | } |
| 33309 | |
| 33310 | assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' ); |
| 33311 | if( rc==SQLITE_OK && zIn!=zOut ){ |
| 33312 | rc = mkFullPathname(zIn, zOut, nOut); |
| 33313 | } |
| 33314 | if( bLink==0 ) break; |
| 33315 | zIn = zOut; |
| 33316 | }while( rc==SQLITE_OK ); |
| 33317 | |
| 33318 | sqlite3_free(zDel); |
| 33319 | return rc; |
| 33320 | #endif /* HAVE_READLINK && HAVE_LSTAT */ |
| 33321 | } |
| 33322 | |
| 33323 | |
| 33324 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 33325 | /* |
| @@ -33353,11 +33497,11 @@ | |
| 33497 | #endif |
| 33498 | UNUSED_PARAMETER(NotUsed); |
| 33499 | return rc; |
| 33500 | } |
| 33501 | |
| 33502 | #ifndef SQLITE_OMIT_DEPRECATED |
| 33503 | /* |
| 33504 | ** Find the current time (in Universal Coordinated Time). Write the |
| 33505 | ** current time and date as a Julian Day number into *prNow and |
| 33506 | ** return 0. Return 1 if the time and date cannot be found. |
| 33507 | */ |
| @@ -33371,11 +33515,11 @@ | |
| 33515 | } |
| 33516 | #else |
| 33517 | # define unixCurrentTime 0 |
| 33518 | #endif |
| 33519 | |
| 33520 | #ifndef SQLITE_OMIT_DEPRECATED |
| 33521 | /* |
| 33522 | ** We added the xGetLastError() method with the intention of providing |
| 33523 | ** better low-level error messages when operating-system problems come up |
| 33524 | ** during SQLite operation. But so far, none of that has been implemented |
| 33525 | ** in the core. So this routine is never called. For now, it is merely |
| @@ -34053,11 +34197,11 @@ | |
| 34197 | strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); |
| 34198 | } |
| 34199 | writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); |
| 34200 | robust_ftruncate(conchFile->h, writeSize); |
| 34201 | rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); |
| 34202 | full_fsync(conchFile->h,0,0); |
| 34203 | /* If we created a new conch file (not just updated the contents of a |
| 34204 | ** valid conch file), try to match the permissions of the database |
| 34205 | */ |
| 34206 | if( rc==SQLITE_OK && createConch ){ |
| 34207 | struct stat buf; |
| @@ -34670,11 +34814,11 @@ | |
| 34814 | }; |
| 34815 | unsigned int i; /* Loop counter */ |
| 34816 | |
| 34817 | /* Double-check that the aSyscall[] array has been constructed |
| 34818 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 34819 | assert( ArraySize(aSyscall)==28 ); |
| 34820 | |
| 34821 | /* Register all VFSes defined in the aVfs[] array */ |
| 34822 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 34823 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 34824 | } |
| @@ -34970,10 +35114,14 @@ | |
| 35114 | |
| 35115 | #ifndef NTDDI_WINBLUE |
| 35116 | # define NTDDI_WINBLUE 0x06030000 |
| 35117 | #endif |
| 35118 | |
| 35119 | #ifndef NTDDI_WINTHRESHOLD |
| 35120 | # define NTDDI_WINTHRESHOLD 0x06040000 |
| 35121 | #endif |
| 35122 | |
| 35123 | /* |
| 35124 | ** Check to see if the GetVersionEx[AW] functions are deprecated on the |
| 35125 | ** target system. GetVersionEx was first deprecated in Win8.1. |
| 35126 | */ |
| 35127 | #ifndef SQLITE_WIN32_GETVERSIONEX |
| @@ -34982,10 +35130,23 @@ | |
| 35130 | # else |
| 35131 | # define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ |
| 35132 | # endif |
| 35133 | #endif |
| 35134 | |
| 35135 | /* |
| 35136 | ** Check to see if the CreateFileMappingA function is supported on the |
| 35137 | ** target system. It is unavailable when using "mincore.lib" on Win10. |
| 35138 | ** When compiling for Windows 10, always assume "mincore.lib" is in use. |
| 35139 | */ |
| 35140 | #ifndef SQLITE_WIN32_CREATEFILEMAPPINGA |
| 35141 | # if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD |
| 35142 | # define SQLITE_WIN32_CREATEFILEMAPPINGA 0 |
| 35143 | # else |
| 35144 | # define SQLITE_WIN32_CREATEFILEMAPPINGA 1 |
| 35145 | # endif |
| 35146 | #endif |
| 35147 | |
| 35148 | /* |
| 35149 | ** This constant should already be defined (in the "WinDef.h" SDK file). |
| 35150 | */ |
| 35151 | #ifndef MAX_PATH |
| 35152 | # define MAX_PATH (260) |
| @@ -35388,12 +35549,13 @@ | |
| 35549 | #endif |
| 35550 | |
| 35551 | #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ |
| 35552 | LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) |
| 35553 | |
| 35554 | #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ |
| 35555 | (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ |
| 35556 | SQLITE_WIN32_CREATEFILEMAPPINGA |
| 35557 | { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, |
| 35558 | #else |
| 35559 | { "CreateFileMappingA", (SYSCALL)0, 0 }, |
| 35560 | #endif |
| 35561 | |
| @@ -35619,22 +35781,21 @@ | |
| 35781 | { "GetTickCount", (SYSCALL)0, 0 }, |
| 35782 | #endif |
| 35783 | |
| 35784 | #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) |
| 35785 | |
| 35786 | #if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX |
| 35787 | { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, |
| 35788 | #else |
| 35789 | { "GetVersionExA", (SYSCALL)0, 0 }, |
| 35790 | #endif |
| 35791 | |
| 35792 | #define osGetVersionExA ((BOOL(WINAPI*)( \ |
| 35793 | LPOSVERSIONINFOA))aSyscall[34].pCurrent) |
| 35794 | |
| 35795 | #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ |
| 35796 | SQLITE_WIN32_GETVERSIONEX |
| 35797 | { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, |
| 35798 | #else |
| 35799 | { "GetVersionExW", (SYSCALL)0, 0 }, |
| 35800 | #endif |
| 35801 | |
| @@ -36241,11 +36402,11 @@ | |
| 36402 | ** this routine is used to determine if the host is Win95/98/ME or |
| 36403 | ** WinNT/2K/XP so that we will know whether or not we can safely call |
| 36404 | ** the LockFileEx() API. |
| 36405 | */ |
| 36406 | |
| 36407 | #if !SQLITE_WIN32_GETVERSIONEX |
| 36408 | # define osIsNT() (1) |
| 36409 | #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) |
| 36410 | # define osIsNT() (1) |
| 36411 | #elif !defined(SQLITE_WIN32_HAS_WIDE) |
| 36412 | # define osIsNT() (0) |
| @@ -36262,11 +36423,11 @@ | |
| 36423 | /* |
| 36424 | ** NOTE: The WinRT sub-platform is always assumed to be based on the NT |
| 36425 | ** kernel. |
| 36426 | */ |
| 36427 | return 1; |
| 36428 | #elif SQLITE_WIN32_GETVERSIONEX |
| 36429 | if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ |
| 36430 | #if defined(SQLITE_WIN32_HAS_ANSI) |
| 36431 | OSVERSIONINFOA sInfo; |
| 36432 | sInfo.dwOSVersionInfoSize = sizeof(sInfo); |
| 36433 | osGetVersionExA(&sInfo); |
| @@ -38846,11 +39007,11 @@ | |
| 39007 | ); |
| 39008 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 39009 | hMap = osCreateFileMappingW(pShmNode->hFile.h, |
| 39010 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 39011 | ); |
| 39012 | #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA |
| 39013 | hMap = osCreateFileMappingA(pShmNode->hFile.h, |
| 39014 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 39015 | ); |
| 39016 | #endif |
| 39017 | OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", |
| @@ -39002,11 +39163,11 @@ | |
| 39163 | pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); |
| 39164 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 39165 | pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, |
| 39166 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39167 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39168 | #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA |
| 39169 | pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, |
| 39170 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39171 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39172 | #endif |
| 39173 | if( pFd->hMap==NULL ){ |
| @@ -43066,11 +43227,11 @@ | |
| 43227 | */ |
| 43228 | static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ |
| 43229 | assert( p!=0 ); |
| 43230 | if( p->nFresh==0 ){ |
| 43231 | struct RowSetChunk *pNew; |
| 43232 | pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew)); |
| 43233 | if( pNew==0 ){ |
| 43234 | return 0; |
| 43235 | } |
| 43236 | pNew->pNextChunk = p->pChunk; |
| 43237 | p->pChunk = pNew; |
| @@ -43973,10 +44134,24 @@ | |
| 44134 | ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. |
| 44135 | ** This could conceivably cause corruption following a power failure on |
| 44136 | ** such a system. This is currently an undocumented limit. |
| 44137 | */ |
| 44138 | #define MAX_SECTOR_SIZE 0x10000 |
| 44139 | |
| 44140 | /* |
| 44141 | ** If the option SQLITE_EXTRA_DURABLE option is set at compile-time, then |
| 44142 | ** SQLite will do extra fsync() operations when synchronous==FULL to help |
| 44143 | ** ensure that transactions are durable across a power failure. Most |
| 44144 | ** applications are happy as long as transactions are consistent across |
| 44145 | ** a power failure, and are perfectly willing to lose the last transaction |
| 44146 | ** in exchange for the extra performance of avoiding directory syncs. |
| 44147 | ** And so the default SQLITE_EXTRA_DURABLE setting is off. |
| 44148 | */ |
| 44149 | #ifndef SQLITE_EXTRA_DURABLE |
| 44150 | # define SQLITE_EXTRA_DURABLE 0 |
| 44151 | #endif |
| 44152 | |
| 44153 | |
| 44154 | /* |
| 44155 | ** An instance of the following structure is allocated for each active |
| 44156 | ** savepoint and statement transaction in the system. All such structures |
| 44157 | ** are stored in the Pager.aSavepoint[] array, which is allocated and |
| @@ -44169,10 +44344,11 @@ | |
| 44344 | u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ |
| 44345 | u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
| 44346 | u8 useJournal; /* Use a rollback journal on this file */ |
| 44347 | u8 noSync; /* Do not sync the journal if true */ |
| 44348 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 44349 | u8 extraSync; /* sync directory after journal delete */ |
| 44350 | u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ |
| 44351 | u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ |
| 44352 | u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ |
| 44353 | u8 tempFile; /* zFilename is a temporary or immutable file */ |
| 44354 | u8 noLock; /* Do not lock (except in WAL mode) */ |
| @@ -45529,11 +45705,11 @@ | |
| 45705 | || pPager->journalMode==PAGER_JOURNALMODE_MEMORY |
| 45706 | || pPager->journalMode==PAGER_JOURNALMODE_WAL |
| 45707 | ); |
| 45708 | sqlite3OsClose(pPager->jfd); |
| 45709 | if( bDelete ){ |
| 45710 | rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync); |
| 45711 | } |
| 45712 | } |
| 45713 | } |
| 45714 | |
| 45715 | #ifdef SQLITE_CHECK_PAGES |
| @@ -47035,13 +47211,19 @@ | |
| 47211 | SQLITE_PRIVATE void sqlite3PagerSetFlags( |
| 47212 | Pager *pPager, /* The pager to set safety level for */ |
| 47213 | unsigned pgFlags /* Various flags */ |
| 47214 | ){ |
| 47215 | unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; |
| 47216 | if( pPager->tempFile ){ |
| 47217 | pPager->noSync = 1; |
| 47218 | pPager->fullSync = 0; |
| 47219 | pPager->extraSync = 0; |
| 47220 | }else{ |
| 47221 | pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; |
| 47222 | pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; |
| 47223 | pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; |
| 47224 | } |
| 47225 | if( pPager->noSync ){ |
| 47226 | pPager->syncFlags = 0; |
| 47227 | pPager->ckptSyncFlags = 0; |
| 47228 | }else if( pgFlags & PAGER_FULLFSYNC ){ |
| 47229 | pPager->syncFlags = SQLITE_SYNC_FULL; |
| @@ -48342,15 +48524,21 @@ | |
| 48524 | pPager->readOnly = (u8)readOnly; |
| 48525 | assert( useJournal || pPager->tempFile ); |
| 48526 | pPager->noSync = pPager->tempFile; |
| 48527 | if( pPager->noSync ){ |
| 48528 | assert( pPager->fullSync==0 ); |
| 48529 | assert( pPager->extraSync==0 ); |
| 48530 | assert( pPager->syncFlags==0 ); |
| 48531 | assert( pPager->walSyncFlags==0 ); |
| 48532 | assert( pPager->ckptSyncFlags==0 ); |
| 48533 | }else{ |
| 48534 | pPager->fullSync = 1; |
| 48535 | #if SQLITE_EXTRA_DURABLE |
| 48536 | pPager->extraSync = 1; |
| 48537 | #else |
| 48538 | pPager->extraSync = 0; |
| 48539 | #endif |
| 48540 | pPager->syncFlags = SQLITE_SYNC_NORMAL; |
| 48541 | pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; |
| 48542 | pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; |
| 48543 | } |
| 48544 | /* pPager->pFirst = 0; */ |
| @@ -57680,11 +57868,10 @@ | |
| 57868 | MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) |
| 57869 | if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ |
| 57870 | pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); |
| 57871 | if( pBt->mutex==0 ){ |
| 57872 | rc = SQLITE_NOMEM; |
| 57873 | goto btree_open_out; |
| 57874 | } |
| 57875 | } |
| 57876 | sqlite3_mutex_enter(mutexShared); |
| 57877 | pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList); |
| @@ -59391,17 +59578,17 @@ | |
| 59578 | ** iTable. If a read-only cursor is requested, it is assumed that |
| 59579 | ** the caller already has at least a read-only transaction open |
| 59580 | ** on the database already. If a write-cursor is requested, then |
| 59581 | ** the caller is assumed to have an open write transaction. |
| 59582 | ** |
| 59583 | ** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only |
| 59584 | ** be used for reading. If the BTREE_WRCSR bit is set, then the cursor |
| 59585 | ** can be used for reading or for writing if other conditions for writing |
| 59586 | ** are also met. These are the conditions that must be met in order |
| 59587 | ** for writing to be allowed: |
| 59588 | ** |
| 59589 | ** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR |
| 59590 | ** |
| 59591 | ** 2: Other database connections that share the same pager cache |
| 59592 | ** but which are not in the READ_UNCOMMITTED state may not have |
| 59593 | ** cursors open with wrFlag==0 on the same table. Otherwise |
| 59594 | ** the changes made by this write cursor would be visible to |
| @@ -59408,10 +59595,20 @@ | |
| 59595 | ** the read cursors in the other database connection. |
| 59596 | ** |
| 59597 | ** 3: The database must be writable (not on read-only media) |
| 59598 | ** |
| 59599 | ** 4: There must be an active transaction. |
| 59600 | ** |
| 59601 | ** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR |
| 59602 | ** is set. If FORDELETE is set, that is a hint to the implementation that |
| 59603 | ** this cursor will only be used to seek to and delete entries of an index |
| 59604 | ** as part of a larger DELETE statement. The FORDELETE hint is not used by |
| 59605 | ** this implementation. But in a hypothetical alternative storage engine |
| 59606 | ** in which index entries are automatically deleted when corresponding table |
| 59607 | ** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE |
| 59608 | ** operations on this cursor can be no-ops and all READ operations can |
| 59609 | ** return a null row (2-bytes: 0x01 0x00). |
| 59610 | ** |
| 59611 | ** No checking is done to make sure that page iTable really is the |
| 59612 | ** root page of a b-tree. If it is not, then the cursor acquired |
| 59613 | ** will not work correctly. |
| 59614 | ** |
| @@ -61481,11 +61678,11 @@ | |
| 61678 | */ |
| 61679 | #if SQLITE_DEBUG |
| 61680 | { |
| 61681 | CellInfo info; |
| 61682 | pPage->xParseCell(pPage, pCell, &info); |
| 61683 | assert( nHeader==(int)(info.pPayload - pCell) ); |
| 61684 | assert( info.nKey==nKey ); |
| 61685 | assert( *pnSize == info.nSize ); |
| 61686 | assert( spaceLeft == info.nLocal ); |
| 61687 | } |
| 61688 | #endif |
| @@ -63140,12 +63337,12 @@ | |
| 63337 | int rc = SQLITE_OK; |
| 63338 | const int nMin = pCur->pBt->usableSize * 2 / 3; |
| 63339 | u8 aBalanceQuickSpace[13]; |
| 63340 | u8 *pFree = 0; |
| 63341 | |
| 63342 | VVA_ONLY( int balance_quick_called = 0 ); |
| 63343 | VVA_ONLY( int balance_deeper_called = 0 ); |
| 63344 | |
| 63345 | do { |
| 63346 | int iPage = pCur->iPage; |
| 63347 | MemPage *pPage = pCur->apPage[iPage]; |
| 63348 | |
| @@ -63154,11 +63351,12 @@ | |
| 63351 | /* The root page of the b-tree is overfull. In this case call the |
| 63352 | ** balance_deeper() function to create a new child for the root-page |
| 63353 | ** and copy the current contents of the root-page to it. The |
| 63354 | ** next iteration of the do-loop will balance the child page. |
| 63355 | */ |
| 63356 | assert( balance_deeper_called==0 ); |
| 63357 | VVA_ONLY( balance_deeper_called++ ); |
| 63358 | rc = balance_deeper(pPage, &pCur->apPage[1]); |
| 63359 | if( rc==SQLITE_OK ){ |
| 63360 | pCur->iPage = 1; |
| 63361 | pCur->aiIdx[0] = 0; |
| 63362 | pCur->aiIdx[1] = 0; |
| @@ -63193,11 +63391,12 @@ | |
| 63391 | ** The purpose of the following assert() is to check that only a |
| 63392 | ** single call to balance_quick() is made for each call to this |
| 63393 | ** function. If this were not verified, a subtle bug involving reuse |
| 63394 | ** of the aBalanceQuickSpace[] might sneak in. |
| 63395 | */ |
| 63396 | assert( balance_quick_called==0 ); |
| 63397 | VVA_ONLY( balance_quick_called++ ); |
| 63398 | rc = balance_quick(pParent, pPage, aBalanceQuickSpace); |
| 63399 | }else |
| 63400 | #endif |
| 63401 | { |
| 63402 | /* In this case, call balance_nonroot() to redistribute cells |
| @@ -63424,35 +63623,45 @@ | |
| 63623 | } |
| 63624 | |
| 63625 | /* |
| 63626 | ** Delete the entry that the cursor is pointing to. |
| 63627 | ** |
| 63628 | ** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then |
| 63629 | ** the cursor is left pointing at an arbitrary location after the delete. |
| 63630 | ** But if that bit is set, then the cursor is left in a state such that |
| 63631 | ** the next call to BtreeNext() or BtreePrev() moves it to the same row |
| 63632 | ** as it would have been on if the call to BtreeDelete() had been omitted. |
| 63633 | ** |
| 63634 | ** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes |
| 63635 | ** associated with a single table entry and its indexes. Only one of those |
| 63636 | ** deletes is considered the "primary" delete. The primary delete occurs |
| 63637 | ** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete |
| 63638 | ** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag. |
| 63639 | ** The BTREE_AUXDELETE bit is a hint that is not used by this implementation, |
| 63640 | ** but which might be used by alternative storage engines. |
| 63641 | */ |
| 63642 | SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ |
| 63643 | Btree *p = pCur->pBtree; |
| 63644 | BtShared *pBt = p->pBt; |
| 63645 | int rc; /* Return code */ |
| 63646 | MemPage *pPage; /* Page to delete cell from */ |
| 63647 | unsigned char *pCell; /* Pointer to cell to delete */ |
| 63648 | int iCellIdx; /* Index of cell to delete */ |
| 63649 | int iCellDepth; /* Depth of node containing pCell */ |
| 63650 | u16 szCell; /* Size of the cell being deleted */ |
| 63651 | int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ |
| 63652 | u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ |
| 63653 | |
| 63654 | assert( cursorOwnsBtShared(pCur) ); |
| 63655 | assert( pBt->inTransaction==TRANS_WRITE ); |
| 63656 | assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); |
| 63657 | assert( pCur->curFlags & BTCF_WriteFlag ); |
| 63658 | assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); |
| 63659 | assert( !hasReadConflicts(p, pCur->pgnoRoot) ); |
| 63660 | assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); |
| 63661 | assert( pCur->eState==CURSOR_VALID ); |
| 63662 | assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); |
| 63663 | |
| 63664 | iCellDepth = pCur->iPage; |
| 63665 | iCellIdx = pCur->aiIdx[iCellDepth]; |
| 63666 | pPage = pCur->apPage[iCellDepth]; |
| 63667 | pCell = findCell(pPage, iCellIdx); |
| @@ -63561,11 +63770,11 @@ | |
| 63770 | } |
| 63771 | |
| 63772 | if( rc==SQLITE_OK ){ |
| 63773 | if( bSkipnext ){ |
| 63774 | assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); |
| 63775 | assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB ); |
| 63776 | assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); |
| 63777 | pCur->eState = CURSOR_SKIPNEXT; |
| 63778 | if( iCellIdx>=pPage->nCell ){ |
| 63779 | pCur->skipNext = -1; |
| 63780 | pCur->aiIdx[iCellDepth] = pPage->nCell-1; |
| @@ -64147,13 +64356,13 @@ | |
| 64356 | va_start(ap, zFormat); |
| 64357 | if( pCheck->errMsg.nChar ){ |
| 64358 | sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); |
| 64359 | } |
| 64360 | if( pCheck->zPfx ){ |
| 64361 | sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); |
| 64362 | } |
| 64363 | sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); |
| 64364 | va_end(ap); |
| 64365 | if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ |
| 64366 | pCheck->mallocFailed = 1; |
| 64367 | } |
| 64368 | } |
| @@ -64650,11 +64859,12 @@ | |
| 64859 | char zErr[100]; |
| 64860 | VVA_ONLY( int nRef ); |
| 64861 | |
| 64862 | sqlite3BtreeEnter(p); |
| 64863 | assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); |
| 64864 | VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) ); |
| 64865 | assert( nRef>=0 ); |
| 64866 | sCheck.pBt = pBt; |
| 64867 | sCheck.pPager = pBt->pPager; |
| 64868 | sCheck.nPage = btreePagecount(sCheck.pBt); |
| 64869 | sCheck.mxErr = mxErr; |
| 64870 | sCheck.nErr = 0; |
| @@ -64663,10 +64873,11 @@ | |
| 64873 | sCheck.v1 = 0; |
| 64874 | sCheck.v2 = 0; |
| 64875 | sCheck.aPgRef = 0; |
| 64876 | sCheck.heap = 0; |
| 64877 | sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); |
| 64878 | sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; |
| 64879 | if( sCheck.nPage==0 ){ |
| 64880 | goto integrity_ck_cleanup; |
| 64881 | } |
| 64882 | |
| 64883 | sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); |
| @@ -65939,10 +66150,11 @@ | |
| 66150 | ** in pMem->z is discarded. |
| 66151 | */ |
| 66152 | SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ |
| 66153 | assert( sqlite3VdbeCheckMemInvariants(pMem) ); |
| 66154 | assert( (pMem->flags&MEM_RowSet)==0 ); |
| 66155 | testcase( pMem->db==0 ); |
| 66156 | |
| 66157 | /* If the bPreserve flag is set to true, then the memory cell must already |
| 66158 | ** contain a valid string or blob value. */ |
| 66159 | assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); |
| 66160 | testcase( bPreserve && pMem->z==0 ); |
| @@ -66542,11 +66754,11 @@ | |
| 66754 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ |
| 66755 | sqlite3 *db = pMem->db; |
| 66756 | assert( db!=0 ); |
| 66757 | assert( (pMem->flags & MEM_RowSet)==0 ); |
| 66758 | sqlite3VdbeMemRelease(pMem); |
| 66759 | pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); |
| 66760 | if( db->mallocFailed ){ |
| 66761 | pMem->flags = MEM_Null; |
| 66762 | pMem->szMalloc = 0; |
| 66763 | }else{ |
| 66764 | assert( pMem->zMalloc ); |
| @@ -67204,11 +67416,11 @@ | |
| 67416 | |
| 67417 | *ppVal = pVal; |
| 67418 | return rc; |
| 67419 | |
| 67420 | no_mem: |
| 67421 | sqlite3OomFault(db); |
| 67422 | sqlite3DbFree(db, zVal); |
| 67423 | assert( *ppVal==0 ); |
| 67424 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 67425 | if( pCtx==0 ) sqlite3ValueFree(pVal); |
| 67426 | #else |
| @@ -67263,11 +67475,11 @@ | |
| 67475 | iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); |
| 67476 | nSerial = sqlite3VarintLen(iSerial); |
| 67477 | db = sqlite3_context_db_handle(context); |
| 67478 | |
| 67479 | nRet = 1 + nSerial + nVal; |
| 67480 | aRet = sqlite3DbMallocRawNN(db, nRet); |
| 67481 | if( aRet==0 ){ |
| 67482 | sqlite3_result_error_nomem(context); |
| 67483 | }else{ |
| 67484 | aRet[0] = nSerial+1; |
| 67485 | putVarint32(&aRet[1], iSerial); |
| @@ -67715,11 +67927,11 @@ | |
| 67927 | int i; |
| 67928 | VdbeOp *pOp; |
| 67929 | |
| 67930 | i = p->nOp; |
| 67931 | assert( p->magic==VDBE_MAGIC_INIT ); |
| 67932 | assert( op>=0 && op<0xff ); |
| 67933 | if( p->pParse->nOpAlloc<=i ){ |
| 67934 | return growOp3(p, op, p1, p2, p3); |
| 67935 | } |
| 67936 | p->nOp++; |
| 67937 | pOp = &p->aOp[i]; |
| @@ -67833,11 +68045,11 @@ | |
| 68045 | int p2, /* The P2 operand */ |
| 68046 | int p3, /* The P3 operand */ |
| 68047 | const u8 *zP4, /* The P4 operand */ |
| 68048 | int p4type /* P4 operand type */ |
| 68049 | ){ |
| 68050 | char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8); |
| 68051 | if( p4copy ) memcpy(p4copy, zP4, 8); |
| 68052 | return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); |
| 68053 | } |
| 68054 | |
| 68055 | /* |
| @@ -67867,10 +68079,25 @@ | |
| 68079 | ){ |
| 68080 | int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); |
| 68081 | sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); |
| 68082 | return addr; |
| 68083 | } |
| 68084 | |
| 68085 | /* Insert the end of a co-routine |
| 68086 | */ |
| 68087 | SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ |
| 68088 | sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); |
| 68089 | |
| 68090 | /* Clear the temporary register cache, thereby ensuring that each |
| 68091 | ** co-routine has its own independent set of registers, because co-routines |
| 68092 | ** might expect their registers to be preserved across an OP_Yield, and |
| 68093 | ** that could cause problems if two or more co-routines are using the same |
| 68094 | ** temporary register. |
| 68095 | */ |
| 68096 | v->pParse->nTempReg = 0; |
| 68097 | v->pParse->nRangeReg = 0; |
| 68098 | } |
| 68099 | |
| 68100 | /* |
| 68101 | ** Create a new symbolic label for an instruction that has yet to be |
| 68102 | ** coded. The symbolic label is really just a negative number. The |
| 68103 | ** label can be used as the P2 value of an operation. Later, when |
| @@ -68078,11 +68305,11 @@ | |
| 68305 | p->readOnly = 1; |
| 68306 | p->bIsReader = 0; |
| 68307 | for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ |
| 68308 | u8 opcode = pOp->opcode; |
| 68309 | |
| 68310 | /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing |
| 68311 | ** cases from this switch! */ |
| 68312 | switch( opcode ){ |
| 68313 | case OP_Transaction: { |
| 68314 | if( pOp->p2!=0 ) p->readOnly = 0; |
| 68315 | /* fall thru */ |
| @@ -68190,10 +68417,13 @@ | |
| 68417 | } |
| 68418 | |
| 68419 | /* |
| 68420 | ** Add a whole list of operations to the operation stack. Return a |
| 68421 | ** pointer to the first operation inserted. |
| 68422 | ** |
| 68423 | ** Non-zero P2 arguments to jump instructions are automatically adjusted |
| 68424 | ** so that the jump target is relative to the first operation inserted. |
| 68425 | */ |
| 68426 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList( |
| 68427 | Vdbe *p, /* Add opcodes to the prepared statement */ |
| 68428 | int nOp, /* Number of opcodes to add */ |
| 68429 | VdbeOpList const *aOp, /* The opcodes to be added */ |
| @@ -68210,10 +68440,13 @@ | |
| 68440 | for(i=0; i<nOp; i++, aOp++, pOut++){ |
| 68441 | pOut->opcode = aOp->opcode; |
| 68442 | pOut->p1 = aOp->p1; |
| 68443 | pOut->p2 = aOp->p2; |
| 68444 | assert( aOp->p2>=0 ); |
| 68445 | if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){ |
| 68446 | pOut->p2 += p->nOp; |
| 68447 | } |
| 68448 | pOut->p3 = aOp->p3; |
| 68449 | pOut->p4type = P4_NOTUSED; |
| 68450 | pOut->p4.p = 0; |
| 68451 | pOut->p5 = 0; |
| 68452 | #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS |
| @@ -68661,32 +68894,31 @@ | |
| 68894 | #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) |
| 68895 | /* |
| 68896 | ** Translate the P4.pExpr value for an OP_CursorHint opcode into text |
| 68897 | ** that can be displayed in the P4 column of EXPLAIN output. |
| 68898 | */ |
| 68899 | static void displayP4Expr(StrAccum *p, Expr *pExpr){ |
| 68900 | const char *zOp = 0; |
| 68901 | switch( pExpr->op ){ |
| 68902 | case TK_STRING: |
| 68903 | sqlite3XPrintf(p, "%Q", pExpr->u.zToken); |
| 68904 | break; |
| 68905 | case TK_INTEGER: |
| 68906 | sqlite3XPrintf(p, "%d", pExpr->u.iValue); |
| 68907 | break; |
| 68908 | case TK_NULL: |
| 68909 | sqlite3XPrintf(p, "NULL"); |
| 68910 | break; |
| 68911 | case TK_REGISTER: { |
| 68912 | sqlite3XPrintf(p, "r[%d]", pExpr->iTable); |
| 68913 | break; |
| 68914 | } |
| 68915 | case TK_COLUMN: { |
| 68916 | if( pExpr->iColumn<0 ){ |
| 68917 | sqlite3XPrintf(p, "rowid"); |
| 68918 | }else{ |
| 68919 | sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); |
| 68920 | } |
| 68921 | break; |
| 68922 | } |
| 68923 | case TK_LT: zOp = "LT"; break; |
| 68924 | case TK_LE: zOp = "LE"; break; |
| @@ -68714,25 +68946,23 @@ | |
| 68946 | case TK_NOT: zOp = "NOT"; break; |
| 68947 | case TK_ISNULL: zOp = "ISNULL"; break; |
| 68948 | case TK_NOTNULL: zOp = "NOTNULL"; break; |
| 68949 | |
| 68950 | default: |
| 68951 | sqlite3XPrintf(p, "%s", "expr"); |
| 68952 | break; |
| 68953 | } |
| 68954 | |
| 68955 | if( zOp ){ |
| 68956 | sqlite3XPrintf(p, "%s(", zOp); |
| 68957 | displayP4Expr(p, pExpr->pLeft); |
| 68958 | if( pExpr->pRight ){ |
| 68959 | sqlite3StrAccumAppend(p, ",", 1); |
| 68960 | displayP4Expr(p, pExpr->pRight); |
| 68961 | } |
| 68962 | sqlite3StrAccumAppend(p, ")", 1); |
| 68963 | } |
| 68964 | } |
| 68965 | #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ |
| 68966 | |
| 68967 | |
| 68968 | #if VDBE_DISPLAY_P4 |
| @@ -68740,107 +68970,100 @@ | |
| 68970 | ** Compute a string that describes the P4 parameter for an opcode. |
| 68971 | ** Use zTemp for any required temporary buffer space. |
| 68972 | */ |
| 68973 | static char *displayP4(Op *pOp, char *zTemp, int nTemp){ |
| 68974 | char *zP4 = zTemp; |
| 68975 | StrAccum x; |
| 68976 | assert( nTemp>=20 ); |
| 68977 | sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0); |
| 68978 | switch( pOp->p4type ){ |
| 68979 | case P4_KEYINFO: { |
| 68980 | int j; |
| 68981 | KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; |
| 68982 | assert( pKeyInfo->aSortOrder!=0 ); |
| 68983 | sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField); |
| 68984 | for(j=0; j<pKeyInfo->nField; j++){ |
| 68985 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 68986 | const char *zColl = pColl ? pColl->zName : ""; |
| 68987 | if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; |
| 68988 | sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); |
| 68989 | } |
| 68990 | sqlite3StrAccumAppend(&x, ")", 1); |
| 68991 | break; |
| 68992 | } |
| 68993 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 68994 | case P4_EXPR: { |
| 68995 | displayP4Expr(&x, pOp->p4.pExpr); |
| 68996 | break; |
| 68997 | } |
| 68998 | #endif |
| 68999 | case P4_COLLSEQ: { |
| 69000 | CollSeq *pColl = pOp->p4.pColl; |
| 69001 | sqlite3XPrintf(&x, "(%.20s)", pColl->zName); |
| 69002 | break; |
| 69003 | } |
| 69004 | case P4_FUNCDEF: { |
| 69005 | FuncDef *pDef = pOp->p4.pFunc; |
| 69006 | sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); |
| 69007 | break; |
| 69008 | } |
| 69009 | #ifdef SQLITE_DEBUG |
| 69010 | case P4_FUNCCTX: { |
| 69011 | FuncDef *pDef = pOp->p4.pCtx->pFunc; |
| 69012 | sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); |
| 69013 | break; |
| 69014 | } |
| 69015 | #endif |
| 69016 | case P4_INT64: { |
| 69017 | sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); |
| 69018 | break; |
| 69019 | } |
| 69020 | case P4_INT32: { |
| 69021 | sqlite3XPrintf(&x, "%d", pOp->p4.i); |
| 69022 | break; |
| 69023 | } |
| 69024 | case P4_REAL: { |
| 69025 | sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); |
| 69026 | break; |
| 69027 | } |
| 69028 | case P4_MEM: { |
| 69029 | Mem *pMem = pOp->p4.pMem; |
| 69030 | if( pMem->flags & MEM_Str ){ |
| 69031 | zP4 = pMem->z; |
| 69032 | }else if( pMem->flags & MEM_Int ){ |
| 69033 | sqlite3XPrintf(&x, "%lld", pMem->u.i); |
| 69034 | }else if( pMem->flags & MEM_Real ){ |
| 69035 | sqlite3XPrintf(&x, "%.16g", pMem->u.r); |
| 69036 | }else if( pMem->flags & MEM_Null ){ |
| 69037 | zP4 = "NULL"; |
| 69038 | }else{ |
| 69039 | assert( pMem->flags & MEM_Blob ); |
| 69040 | zP4 = "(blob)"; |
| 69041 | } |
| 69042 | break; |
| 69043 | } |
| 69044 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 69045 | case P4_VTAB: { |
| 69046 | sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; |
| 69047 | sqlite3XPrintf(&x, "vtab:%p", pVtab); |
| 69048 | break; |
| 69049 | } |
| 69050 | #endif |
| 69051 | case P4_INTARRAY: { |
| 69052 | int i; |
| 69053 | int *ai = pOp->p4.ai; |
| 69054 | int n = ai[0]; /* The first element of an INTARRAY is always the |
| 69055 | ** count of the number of elements to follow */ |
| 69056 | for(i=1; i<n; i++){ |
| 69057 | sqlite3XPrintf(&x, ",%d", ai[i]); |
| 69058 | } |
| 69059 | zTemp[0] = '['; |
| 69060 | sqlite3StrAccumAppend(&x, "]", 1); |
| 69061 | break; |
| 69062 | } |
| 69063 | case P4_SUBPROGRAM: { |
| 69064 | sqlite3XPrintf(&x, "program"); |
| 69065 | break; |
| 69066 | } |
| 69067 | case P4_ADVANCE: { |
| 69068 | zTemp[0] = 0; |
| 69069 | break; |
| @@ -68851,10 +69074,11 @@ | |
| 69074 | zP4 = zTemp; |
| 69075 | zTemp[0] = 0; |
| 69076 | } |
| 69077 | } |
| 69078 | } |
| 69079 | sqlite3StrAccumFinish(&x); |
| 69080 | assert( zP4!=0 ); |
| 69081 | return zP4; |
| 69082 | } |
| 69083 | #endif /* VDBE_DISPLAY_P4 */ |
| 69084 | |
| @@ -68970,11 +69194,10 @@ | |
| 69194 | */ |
| 69195 | static void releaseMemArray(Mem *p, int N){ |
| 69196 | if( p && N ){ |
| 69197 | Mem *pEnd = &p[N]; |
| 69198 | sqlite3 *db = p->db; |
| 69199 | if( db->pnBytesFreed ){ |
| 69200 | do{ |
| 69201 | if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); |
| 69202 | }while( (++p)<pEnd ); |
| 69203 | return; |
| @@ -69006,11 +69229,10 @@ | |
| 69229 | p->szMalloc = 0; |
| 69230 | } |
| 69231 | |
| 69232 | p->flags = MEM_Undefined; |
| 69233 | }while( (++p)<pEnd ); |
| 69234 | } |
| 69235 | } |
| 69236 | |
| 69237 | /* |
| 69238 | ** Delete a VdbeFrame object and its contents. VdbeFrame objects are |
| @@ -69067,11 +69289,11 @@ | |
| 69289 | p->pResultSet = 0; |
| 69290 | |
| 69291 | if( p->rc==SQLITE_NOMEM ){ |
| 69292 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 69293 | ** sqlite3_column_text16() failed. */ |
| 69294 | sqlite3OomFault(db); |
| 69295 | return SQLITE_ERROR; |
| 69296 | } |
| 69297 | |
| 69298 | /* When the number of output rows reaches nRow, that means the |
| 69299 | ** listing has finished and sqlite3_step() should return SQLITE_DONE. |
| @@ -69265,45 +69487,47 @@ | |
| 69487 | sqlite3IoTrace("SQL %s\n", z); |
| 69488 | } |
| 69489 | } |
| 69490 | #endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ |
| 69491 | |
| 69492 | /* An instance of this object describes bulk memory available for use |
| 69493 | ** by subcomponents of a prepared statement. Space is allocated out |
| 69494 | ** of a ReusableSpace object by the allocSpace() routine below. |
| 69495 | */ |
| 69496 | struct ReusableSpace { |
| 69497 | u8 *pSpace; /* Available memory */ |
| 69498 | int nFree; /* Bytes of available memory */ |
| 69499 | int nNeeded; /* Total bytes that could not be allocated */ |
| 69500 | }; |
| 69501 | |
| 69502 | /* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf |
| 69503 | ** from the ReusableSpace object. Return a pointer to the allocated |
| 69504 | ** memory on success. If insufficient memory is available in the |
| 69505 | ** ReusableSpace object, increase the ReusableSpace.nNeeded |
| 69506 | ** value by the amount needed and return NULL. |
| 69507 | ** |
| 69508 | ** If pBuf is not initially NULL, that means that the memory has already |
| 69509 | ** been allocated by a prior call to this routine, so just return a copy |
| 69510 | ** of pBuf and leave ReusableSpace unchanged. |
| 69511 | ** |
| 69512 | ** This allocator is employed to repurpose unused slots at the end of the |
| 69513 | ** opcode array of prepared state for other memory needs of the prepared |
| 69514 | ** statement. |
| 69515 | */ |
| 69516 | static void *allocSpace( |
| 69517 | struct ReusableSpace *p, /* Bulk memory available for allocation */ |
| 69518 | void *pBuf, /* Pointer to a prior allocation */ |
| 69519 | int nByte /* Bytes of memory needed */ |
| 69520 | ){ |
| 69521 | assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); |
| 69522 | if( pBuf==0 ){ |
| 69523 | nByte = ROUND8(nByte); |
| 69524 | if( nByte <= p->nFree ){ |
| 69525 | p->nFree -= nByte; |
| 69526 | pBuf = &p->pSpace[p->nFree]; |
| 69527 | }else{ |
| 69528 | p->nNeeded += nByte; |
| 69529 | } |
| 69530 | } |
| 69531 | assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); |
| 69532 | return pBuf; |
| 69533 | } |
| @@ -69332,11 +69556,10 @@ | |
| 69556 | } |
| 69557 | #endif |
| 69558 | p->pc = -1; |
| 69559 | p->rc = SQLITE_OK; |
| 69560 | p->errorAction = OE_Abort; |
| 69561 | p->nChange = 0; |
| 69562 | p->cacheCtr = 1; |
| 69563 | p->minWriteFileFormat = 255; |
| 69564 | p->iStatement = 0; |
| 69565 | p->nFkConstraint = 0; |
| @@ -69375,13 +69598,11 @@ | |
| 69598 | int nMem; /* Number of VM memory registers */ |
| 69599 | int nCursor; /* Number of cursors required */ |
| 69600 | int nArg; /* Number of arguments in subprograms */ |
| 69601 | int nOnce; /* Number of OP_Once instructions */ |
| 69602 | int n; /* Loop counter */ |
| 69603 | struct ReusableSpace x; /* Reusable bulk memory */ |
| 69604 | |
| 69605 | assert( p!=0 ); |
| 69606 | assert( p->nOp>0 ); |
| 69607 | assert( pParse!=0 ); |
| 69608 | assert( p->magic==VDBE_MAGIC_INIT ); |
| @@ -69395,69 +69616,64 @@ | |
| 69616 | nOnce = pParse->nOnce; |
| 69617 | if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ |
| 69618 | |
| 69619 | /* For each cursor required, also allocate a memory cell. Memory |
| 69620 | ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by |
| 69621 | ** the vdbe program. Instead they are used to allocate memory for |
| 69622 | ** VdbeCursor/BtCursor structures. The blob of memory associated with |
| 69623 | ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) |
| 69624 | ** stores the blob of memory associated with cursor 1, etc. |
| 69625 | ** |
| 69626 | ** See also: allocateCursor(). |
| 69627 | */ |
| 69628 | nMem += nCursor; |
| 69629 | |
| 69630 | /* Figure out how much reusable memory is available at the end of the |
| 69631 | ** opcode array. This extra memory will be reallocated for other elements |
| 69632 | ** of the prepared statement. |
| 69633 | */ |
| 69634 | n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ |
| 69635 | x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ |
| 69636 | assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); |
| 69637 | x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ |
| 69638 | assert( x.nFree>=0 ); |
| 69639 | if( x.nFree>0 ){ |
| 69640 | memset(x.pSpace, 0, x.nFree); |
| 69641 | assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); |
| 69642 | } |
| 69643 | |
| 69644 | resolveP2Values(p, &nArg); |
| 69645 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| 69646 | if( pParse->explain && nMem<10 ){ |
| 69647 | nMem = 10; |
| 69648 | } |
| 69649 | p->expired = 0; |
| 69650 | |
| 69651 | /* Memory for registers, parameters, cursor, etc, is allocated in one or two |
| 69652 | ** passes. On the first pass, we try to reuse unused memory at the |
| 69653 | ** end of the opcode array. If we are unable to satisfy all memory |
| 69654 | ** requirements by reusing the opcode array tail, then the second |
| 69655 | ** pass will fill in the remainder using a fresh memory allocation. |
| 69656 | ** |
| 69657 | ** This two-pass approach that reuses as much memory as possible from |
| 69658 | ** the leftover memory at the end of the opcode array. This can significantly |
| 69659 | ** reduce the amount of memory held by a prepared statement. |
| 69660 | */ |
| 69661 | do { |
| 69662 | x.nNeeded = 0; |
| 69663 | p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem)); |
| 69664 | p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); |
| 69665 | p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); |
| 69666 | p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); |
| 69667 | p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce); |
| 69668 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 69669 | p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); |
| 69670 | #endif |
| 69671 | if( x.nNeeded==0 ) break; |
| 69672 | x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); |
| 69673 | x.nFree = x.nNeeded; |
| 69674 | }while( !db->mallocFailed ); |
| 69675 | |
| 69676 | p->nCursor = nCursor; |
| 69677 | p->nOnceFlag = nOnce; |
| 69678 | if( p->aVar ){ |
| 69679 | p->nVar = (ynVar)nVar; |
| @@ -70066,11 +70282,11 @@ | |
| 70282 | ** Then the internal cache might have been left in an inconsistent |
| 70283 | ** state. We need to rollback the statement transaction, if there is |
| 70284 | ** one, or the complete transaction if there is no statement transaction. |
| 70285 | */ |
| 70286 | |
| 70287 | if( db->mallocFailed ){ |
| 70288 | p->rc = SQLITE_NOMEM; |
| 70289 | } |
| 70290 | if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); |
| 70291 | closeAllCursors(p); |
| 70292 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| @@ -70227,11 +70443,11 @@ | |
| 70443 | assert( db->nVdbeRead>=db->nVdbeWrite ); |
| 70444 | assert( db->nVdbeWrite>=0 ); |
| 70445 | } |
| 70446 | p->magic = VDBE_MAGIC_HALT; |
| 70447 | checkActiveVdbeCnt(db); |
| 70448 | if( db->mallocFailed ){ |
| 70449 | p->rc = SQLITE_NOMEM; |
| 70450 | } |
| 70451 | |
| 70452 | /* If the auto-commit flag is set to true, then any locks that were held |
| 70453 | ** by connection db have now been released. Call sqlite3ConnectionUnlocked() |
| @@ -70264,16 +70480,16 @@ | |
| 70480 | */ |
| 70481 | SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ |
| 70482 | sqlite3 *db = p->db; |
| 70483 | int rc = p->rc; |
| 70484 | if( p->zErrMsg ){ |
| 70485 | db->bBenignMalloc++; |
| 70486 | sqlite3BeginBenignMalloc(); |
| 70487 | if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); |
| 70488 | sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); |
| 70489 | sqlite3EndBenignMalloc(); |
| 70490 | db->bBenignMalloc--; |
| 70491 | db->errCode = rc; |
| 70492 | }else{ |
| 70493 | sqlite3Error(db, rc); |
| 70494 | } |
| 70495 | return rc; |
| @@ -70558,13 +70774,20 @@ | |
| 70774 | ** a NULL row. |
| 70775 | ** |
| 70776 | ** If the cursor is already pointing to the correct row and that row has |
| 70777 | ** not been deleted out from under the cursor, then this routine is a no-op. |
| 70778 | */ |
| 70779 | SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ |
| 70780 | VdbeCursor *p = *pp; |
| 70781 | if( p->eCurType==CURTYPE_BTREE ){ |
| 70782 | if( p->deferredMoveto ){ |
| 70783 | int iMap; |
| 70784 | if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ |
| 70785 | *pp = p->pAltCursor; |
| 70786 | *piCol = iMap - 1; |
| 70787 | return SQLITE_OK; |
| 70788 | } |
| 70789 | return handleDeferredMoveto(p); |
| 70790 | } |
| 70791 | if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ |
| 70792 | return handleMovedCursor(p); |
| 70793 | } |
| @@ -72191,11 +72414,12 @@ | |
| 72414 | } |
| 72415 | SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ |
| 72416 | return sqlite3VdbeIntValue((Mem*)pVal); |
| 72417 | } |
| 72418 | SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){ |
| 72419 | Mem *pMem = (Mem*)pVal; |
| 72420 | return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); |
| 72421 | } |
| 72422 | SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ |
| 72423 | return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); |
| 72424 | } |
| 72425 | #ifndef SQLITE_OMIT_UTF16 |
| @@ -72372,12 +72596,14 @@ | |
| 72596 | SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ |
| 72597 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72598 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72599 | } |
| 72600 | SQLITE_API void SQLITE_STDCALL sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ |
| 72601 | Mem *pOut = pCtx->pOut; |
| 72602 | assert( sqlite3_mutex_held(pOut->db->mutex) ); |
| 72603 | pOut->eSubtype = eSubtype & 0xff; |
| 72604 | pOut->flags |= MEM_Subtype; |
| 72605 | } |
| 72606 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text( |
| 72607 | sqlite3_context *pCtx, |
| 72608 | const char *z, |
| 72609 | int n, |
| @@ -72473,11 +72699,11 @@ | |
| 72699 | SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ |
| 72700 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72701 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72702 | pCtx->isError = SQLITE_NOMEM; |
| 72703 | pCtx->fErrorOrAux = 1; |
| 72704 | sqlite3OomFault(pCtx->pOut->db); |
| 72705 | } |
| 72706 | |
| 72707 | /* |
| 72708 | ** This function is called after a transaction has been committed. It |
| 72709 | ** invokes callbacks registered with sqlite3_wal_hook() as required. |
| @@ -73101,11 +73327,11 @@ | |
| 73327 | ret = xFunc(&p->aColName[N]); |
| 73328 | /* A malloc may have failed inside of the xFunc() call. If this |
| 73329 | ** is the case, clear the mallocFailed flag and return NULL. |
| 73330 | */ |
| 73331 | if( db->mallocFailed ){ |
| 73332 | sqlite3OomClear(db); |
| 73333 | ret = 0; |
| 73334 | } |
| 73335 | sqlite3_mutex_leave(db->mutex); |
| 73336 | } |
| 73337 | return ret; |
| @@ -73802,13 +74028,13 @@ | |
| 74028 | assert( idx>0 && idx<=p->nVar ); |
| 74029 | pVar = &p->aVar[idx-1]; |
| 74030 | if( pVar->flags & MEM_Null ){ |
| 74031 | sqlite3StrAccumAppend(&out, "NULL", 4); |
| 74032 | }else if( pVar->flags & MEM_Int ){ |
| 74033 | sqlite3XPrintf(&out, "%lld", pVar->u.i); |
| 74034 | }else if( pVar->flags & MEM_Real ){ |
| 74035 | sqlite3XPrintf(&out, "%!.15g", pVar->u.r); |
| 74036 | }else if( pVar->flags & MEM_Str ){ |
| 74037 | int nOut; /* Number of bytes of the string text to include in output */ |
| 74038 | #ifndef SQLITE_OMIT_UTF16 |
| 74039 | u8 enc = ENC(db); |
| 74040 | Mem utf8; |
| @@ -73825,36 +74051,36 @@ | |
| 74051 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ |
| 74052 | nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 74053 | while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } |
| 74054 | } |
| 74055 | #endif |
| 74056 | sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); |
| 74057 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 74058 | if( nOut<pVar->n ){ |
| 74059 | sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); |
| 74060 | } |
| 74061 | #endif |
| 74062 | #ifndef SQLITE_OMIT_UTF16 |
| 74063 | if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); |
| 74064 | #endif |
| 74065 | }else if( pVar->flags & MEM_Zero ){ |
| 74066 | sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); |
| 74067 | }else{ |
| 74068 | int nOut; /* Number of bytes of the blob to include in output */ |
| 74069 | assert( pVar->flags & MEM_Blob ); |
| 74070 | sqlite3StrAccumAppend(&out, "x'", 2); |
| 74071 | nOut = pVar->n; |
| 74072 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 74073 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 74074 | #endif |
| 74075 | for(i=0; i<nOut; i++){ |
| 74076 | sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); |
| 74077 | } |
| 74078 | sqlite3StrAccumAppend(&out, "'", 1); |
| 74079 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 74080 | if( nOut<pVar->n ){ |
| 74081 | sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); |
| 74082 | } |
| 74083 | #endif |
| 74084 | } |
| 74085 | } |
| 74086 | } |
| @@ -74336,10 +74562,11 @@ | |
| 74562 | }else{ |
| 74563 | char zBuf[200]; |
| 74564 | sqlite3VdbeMemPrettyPrint(p, zBuf); |
| 74565 | printf(" %s", zBuf); |
| 74566 | } |
| 74567 | if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); |
| 74568 | } |
| 74569 | static void registerTrace(int iReg, Mem *p){ |
| 74570 | printf("REG[%d] = ", iReg); |
| 74571 | memTracePrint(p); |
| 74572 | printf("\n"); |
| @@ -74506,10 +74733,13 @@ | |
| 74733 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 74734 | Op *pOp = aOp; /* Current operation */ |
| 74735 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 74736 | Op *pOrigOp; /* Value of pOp at the top of the loop */ |
| 74737 | #endif |
| 74738 | #ifdef SQLITE_DEBUG |
| 74739 | int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ |
| 74740 | #endif |
| 74741 | int rc = SQLITE_OK; /* Value to return */ |
| 74742 | sqlite3 *db = p->db; /* The database */ |
| 74743 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ |
| 74744 | u8 encoding = ENC(db); /* The database encoding */ |
| 74745 | int iCompare = 0; /* Result of last OP_Compare operation */ |
| @@ -74579,11 +74809,10 @@ | |
| 74809 | } |
| 74810 | sqlite3EndBenignMalloc(); |
| 74811 | #endif |
| 74812 | for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ |
| 74813 | assert( pOp>=aOp && pOp<&aOp[p->nOp]); |
| 74814 | #ifdef VDBE_PROFILE |
| 74815 | start = sqlite3Hwtime(); |
| 74816 | #endif |
| 74817 | nVmStep++; |
| 74818 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| @@ -75577,11 +75806,11 @@ | |
| 75806 | assert( pOp->p4type==P4_FUNCDEF ); |
| 75807 | n = pOp->p5; |
| 75808 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 75809 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 75810 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 75811 | pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 75812 | if( pCtx==0 ) goto no_mem; |
| 75813 | pCtx->pOut = 0; |
| 75814 | pCtx->pFunc = pOp->p4.pFunc; |
| 75815 | pCtx->iOp = (int)(pOp - aOp); |
| 75816 | pCtx->pVdbe = p; |
| @@ -76021,15 +76250,18 @@ | |
| 76250 | ** of integers in P4. |
| 76251 | ** |
| 76252 | ** The permutation is only valid until the next OP_Compare that has |
| 76253 | ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should |
| 76254 | ** occur immediately prior to the OP_Compare. |
| 76255 | ** |
| 76256 | ** The first integer in the P4 integer array is the length of the array |
| 76257 | ** and does not become part of the permutation. |
| 76258 | */ |
| 76259 | case OP_Permutation: { |
| 76260 | assert( pOp->p4type==P4_INTARRAY ); |
| 76261 | assert( pOp->p4.ai ); |
| 76262 | aPermute = pOp->p4.ai + 1; |
| 76263 | break; |
| 76264 | } |
| 76265 | |
| 76266 | /* Opcode: Compare P1 P2 P3 P4 P5 |
| 76267 | ** Synopsis: r[P1@P3] <-> r[P2@P3] |
| @@ -76330,26 +76562,28 @@ | |
| 76562 | u64 offset64; /* 64-bit offset */ |
| 76563 | u32 avail; /* Number of bytes of available data */ |
| 76564 | u32 t; /* A type code from the record header */ |
| 76565 | Mem *pReg; /* PseudoTable input register */ |
| 76566 | |
| 76567 | pC = p->apCsr[pOp->p1]; |
| 76568 | p2 = pOp->p2; |
| 76569 | |
| 76570 | /* If the cursor cache is stale, bring it up-to-date */ |
| 76571 | rc = sqlite3VdbeCursorMoveto(&pC, &p2); |
| 76572 | |
| 76573 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 76574 | pDest = &aMem[pOp->p3]; |
| 76575 | memAboutToChange(p, pDest); |
| 76576 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 76577 | assert( pC!=0 ); |
| 76578 | assert( p2<pC->nField ); |
| 76579 | aOffset = pC->aOffset; |
| 76580 | assert( pC->eCurType!=CURTYPE_VTAB ); |
| 76581 | assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); |
| 76582 | assert( pC->eCurType!=CURTYPE_SORTER ); |
| 76583 | pCrsr = pC->uc.pCursor; |
| 76584 | |
| 76585 | if( rc ) goto abort_due_to_error; |
| 76586 | if( pC->cacheStatus!=p->cacheCtr ){ |
| 76587 | if( pC->nullRow ){ |
| 76588 | if( pC->eCurType==CURTYPE_PSEUDO ){ |
| 76589 | assert( pC->uc.pseudoTableReg>0 ); |
| @@ -76816,11 +77050,11 @@ | |
| 77050 | db->nStatement+db->nSavepoint); |
| 77051 | if( rc!=SQLITE_OK ) goto abort_due_to_error; |
| 77052 | #endif |
| 77053 | |
| 77054 | /* Create a new savepoint structure. */ |
| 77055 | pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1); |
| 77056 | if( pNew ){ |
| 77057 | pNew->zName = (char *)&pNew[1]; |
| 77058 | memcpy(pNew->zName, zName, nName+1); |
| 77059 | |
| 77060 | /* If there is no open transaction, then mark this as a special |
| @@ -76953,32 +77187,31 @@ | |
| 77187 | ** This instruction causes the VM to halt. |
| 77188 | */ |
| 77189 | case OP_AutoCommit: { |
| 77190 | int desiredAutoCommit; |
| 77191 | int iRollback; |
| 77192 | |
| 77193 | desiredAutoCommit = pOp->p1; |
| 77194 | iRollback = pOp->p2; |
| 77195 | assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); |
| 77196 | assert( desiredAutoCommit==1 || iRollback==0 ); |
| 77197 | assert( db->nVdbeActive>0 ); /* At least this one VM is active */ |
| 77198 | assert( p->bIsReader ); |
| 77199 | |
| 77200 | if( desiredAutoCommit!=db->autoCommit ){ |
| 77201 | if( iRollback ){ |
| 77202 | assert( desiredAutoCommit==1 ); |
| 77203 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 77204 | db->autoCommit = 1; |
| 77205 | }else if( desiredAutoCommit && db->nVdbeWrite>0 ){ |
| 77206 | /* If this instruction implements a COMMIT and other VMs are writing |
| 77207 | ** return an error indicating that the other VMs must complete first. |
| 77208 | */ |
| 77209 | sqlite3VdbeError(p, "cannot commit transaction - " |
| 77210 | "SQL statements in progress"); |
| 77211 | rc = SQLITE_BUSY; |
| 77212 | break; |
| 77213 | }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ |
| 77214 | goto vdbe_return; |
| 77215 | }else{ |
| 77216 | db->autoCommit = (u8)desiredAutoCommit; |
| 77217 | } |
| @@ -77159,38 +77392,36 @@ | |
| 77392 | break; |
| 77393 | } |
| 77394 | |
| 77395 | /* Opcode: SetCookie P1 P2 P3 * * |
| 77396 | ** |
| 77397 | ** Write the integer value P3 into cookie number P2 of database P1. |
| 77398 | ** P2==1 is the schema version. P2==2 is the database format. |
| 77399 | ** P2==3 is the recommended pager cache |
| 77400 | ** size, and so forth. P1==0 is the main database file and P1==1 is the |
| 77401 | ** database file used to store temporary tables. |
| 77402 | ** |
| 77403 | ** A transaction must be started before executing this opcode. |
| 77404 | */ |
| 77405 | case OP_SetCookie: { |
| 77406 | Db *pDb; |
| 77407 | assert( pOp->p2<SQLITE_N_BTREE_META ); |
| 77408 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 77409 | assert( DbMaskTest(p->btreeMask, pOp->p1) ); |
| 77410 | assert( p->readOnly==0 ); |
| 77411 | pDb = &db->aDb[pOp->p1]; |
| 77412 | assert( pDb->pBt!=0 ); |
| 77413 | assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); |
| 77414 | /* See note about index shifting on OP_ReadCookie */ |
| 77415 | rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3); |
| 77416 | if( pOp->p2==BTREE_SCHEMA_VERSION ){ |
| 77417 | /* When the schema cookie changes, record the new cookie internally */ |
| 77418 | pDb->pSchema->schema_cookie = pOp->p3; |
| 77419 | db->flags |= SQLITE_InternChanges; |
| 77420 | }else if( pOp->p2==BTREE_FILE_FORMAT ){ |
| 77421 | /* Record changes in the file format */ |
| 77422 | pDb->pSchema->file_format = pOp->p3; |
| 77423 | } |
| 77424 | if( pOp->p1==1 ){ |
| 77425 | /* Invalidate all prepared statements whenever the TEMP database |
| 77426 | ** schema is changed. Ticket #1644 */ |
| 77427 | sqlite3ExpirePreparedStatements(db); |
| @@ -77346,10 +77577,13 @@ | |
| 77577 | pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); |
| 77578 | if( pCur==0 ) goto no_mem; |
| 77579 | pCur->nullRow = 1; |
| 77580 | pCur->isOrdered = 1; |
| 77581 | pCur->pgnoRoot = p2; |
| 77582 | #ifdef SQLITE_DEBUG |
| 77583 | pCur->wrFlag = wrFlag; |
| 77584 | #endif |
| 77585 | rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); |
| 77586 | pCur->pKeyInfo = pKeyInfo; |
| 77587 | /* Set the VdbeCursor.isTable variable. Previous versions of |
| 77588 | ** SQLite used to check if the root-page flags were sane at this point |
| 77589 | ** and report database corruption if they were not, but this check has |
| @@ -77799,36 +78033,10 @@ | |
| 78033 | assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); |
| 78034 | pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ |
| 78035 | } |
| 78036 | break; |
| 78037 | } |
| 78038 | |
| 78039 | |
| 78040 | /* Opcode: Found P1 P2 P3 P4 * |
| 78041 | ** Synopsis: key=r[P3@P4] |
| 78042 | ** |
| @@ -78295,18 +78503,26 @@ | |
| 78503 | |
| 78504 | /* Opcode: Delete P1 P2 * P4 P5 |
| 78505 | ** |
| 78506 | ** Delete the record at which the P1 cursor is currently pointing. |
| 78507 | ** |
| 78508 | ** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then |
| 78509 | ** the cursor will be left pointing at either the next or the previous |
| 78510 | ** record in the table. If it is left pointing at the next record, then |
| 78511 | ** the next Next instruction will be a no-op. As a result, in this case |
| 78512 | ** it is ok to delete a record from within a Next loop. If |
| 78513 | ** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be |
| 78514 | ** left in an undefined state. |
| 78515 | ** |
| 78516 | ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this |
| 78517 | ** delete one of several associated with deleting a table row and all its |
| 78518 | ** associated index entries. Exactly one of those deletes is the "primary" |
| 78519 | ** delete. The others are all on OPFLAG_FORDELETE cursors or else are |
| 78520 | ** marked with the AUXDELETE flag. |
| 78521 | ** |
| 78522 | ** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row |
| 78523 | ** change count is incremented (otherwise not). |
| 78524 | ** |
| 78525 | ** P1 must not be pseudo-table. It has to be a real table with |
| 78526 | ** multiple rows. |
| 78527 | ** |
| 78528 | ** If P4 is not NULL, then it is the name of the table that P1 is |
| @@ -78338,11 +78554,30 @@ | |
| 78554 | i64 iKey = 0; |
| 78555 | sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); |
| 78556 | assert( pC->movetoTarget==iKey ); |
| 78557 | } |
| 78558 | #endif |
| 78559 | |
| 78560 | /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ |
| 78561 | assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); |
| 78562 | assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); |
| 78563 | assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); |
| 78564 | |
| 78565 | #ifdef SQLITE_DEBUG |
| 78566 | if( p->pFrame==0 ){ |
| 78567 | if( pC->isEphemeral==0 |
| 78568 | && (pOp->p5 & OPFLAG_AUXDELETE)==0 |
| 78569 | && (pC->wrFlag & OPFLAG_FORDELETE)==0 |
| 78570 | ){ |
| 78571 | nExtraDelete++; |
| 78572 | } |
| 78573 | if( pOp->p2 & OPFLAG_NCHANGE ){ |
| 78574 | nExtraDelete--; |
| 78575 | } |
| 78576 | } |
| 78577 | #endif |
| 78578 | |
| 78579 | rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); |
| 78580 | pC->cacheStatus = CACHE_STALE; |
| 78581 | |
| 78582 | /* Invoke the update-hook if required. */ |
| 78583 | if( rc==SQLITE_OK && hasUpdateCallback ){ |
| @@ -78883,62 +79118,98 @@ | |
| 79118 | assert( pOp->p5==0 ); |
| 79119 | r.pKeyInfo = pC->pKeyInfo; |
| 79120 | r.nField = (u16)pOp->p3; |
| 79121 | r.default_rc = 0; |
| 79122 | r.aMem = &aMem[pOp->p2]; |
| 79123 | rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); |
| 79124 | if( rc==SQLITE_OK && res==0 ){ |
| 79125 | rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); |
| 79126 | } |
| 79127 | assert( pC->deferredMoveto==0 ); |
| 79128 | pC->cacheStatus = CACHE_STALE; |
| 79129 | break; |
| 79130 | } |
| 79131 | |
| 79132 | /* Opcode: Seek P1 * P3 P4 * |
| 79133 | ** Synopsis: Move P3 to P1.rowid |
| 79134 | ** |
| 79135 | ** P1 is an open index cursor and P3 is a cursor on the corresponding |
| 79136 | ** table. This opcode does a deferred seek of the P3 table cursor |
| 79137 | ** to the row that corresponds to the current row of P1. |
| 79138 | ** |
| 79139 | ** This is a deferred seek. Nothing actually happens until |
| 79140 | ** the cursor is used to read a record. That way, if no reads |
| 79141 | ** occur, no unnecessary I/O happens. |
| 79142 | ** |
| 79143 | ** P4 may be an array of integers (type P4_INTARRAY) containing |
| 79144 | ** one entry for each column in the P3 table. If array entry a(i) |
| 79145 | ** is non-zero, then reading column a(i)-1 from cursor P3 is |
| 79146 | ** equivalent to performing the deferred seek and then reading column i |
| 79147 | ** from P1. This information is stored in P3 and used to redirect |
| 79148 | ** reads against P3 over to P1, thus possibly avoiding the need to |
| 79149 | ** seek and read cursor P3. |
| 79150 | */ |
| 79151 | /* Opcode: IdxRowid P1 P2 * * * |
| 79152 | ** Synopsis: r[P2]=rowid |
| 79153 | ** |
| 79154 | ** Write into register P2 an integer which is the last entry in the record at |
| 79155 | ** the end of the index key pointed to by cursor P1. This integer should be |
| 79156 | ** the rowid of the table entry to which this index entry points. |
| 79157 | ** |
| 79158 | ** See also: Rowid, MakeRecord. |
| 79159 | */ |
| 79160 | case OP_Seek: |
| 79161 | case OP_IdxRowid: { /* out2 */ |
| 79162 | VdbeCursor *pC; /* The P1 index cursor */ |
| 79163 | VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */ |
| 79164 | i64 rowid; /* Rowid that P1 current points to */ |
| 79165 | |
| 79166 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 79167 | pC = p->apCsr[pOp->p1]; |
| 79168 | assert( pC!=0 ); |
| 79169 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 79170 | assert( pC->uc.pCursor!=0 ); |
| 79171 | assert( pC->isTable==0 ); |
| 79172 | assert( pC->deferredMoveto==0 ); |
| 79173 | assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); |
| 79174 | |
| 79175 | /* The IdxRowid and Seek opcodes are combined because of the commonality |
| 79176 | ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ |
| 79177 | rc = sqlite3VdbeCursorRestore(pC); |
| 79178 | |
| 79179 | /* sqlite3VbeCursorRestore() can only fail if the record has been deleted |
| 79180 | ** out from under the cursor. That will never happens for an IdxRowid |
| 79181 | ** or Seek opcode */ |
| 79182 | if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; |
| 79183 | |
| 79184 | if( !pC->nullRow ){ |
| 79185 | rowid = 0; /* Not needed. Only used to silence a warning. */ |
| 79186 | rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid); |
| 79187 | if( rc!=SQLITE_OK ){ |
| 79188 | goto abort_due_to_error; |
| 79189 | } |
| 79190 | if( pOp->opcode==OP_Seek ){ |
| 79191 | assert( pOp->p3>=0 && pOp->p3<p->nCursor ); |
| 79192 | pTabCur = p->apCsr[pOp->p3]; |
| 79193 | assert( pTabCur!=0 ); |
| 79194 | assert( pTabCur->eCurType==CURTYPE_BTREE ); |
| 79195 | assert( pTabCur->uc.pCursor!=0 ); |
| 79196 | assert( pTabCur->isTable ); |
| 79197 | pTabCur->nullRow = 0; |
| 79198 | pTabCur->movetoTarget = rowid; |
| 79199 | pTabCur->deferredMoveto = 1; |
| 79200 | assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); |
| 79201 | pTabCur->aAltMap = pOp->p4.ai; |
| 79202 | pTabCur->pAltCursor = pC; |
| 79203 | }else{ |
| 79204 | pOut = out2Prerelease(p, pOp); |
| 79205 | pOut->u.i = rowid; |
| 79206 | pOut->flags = MEM_Int; |
| 79207 | } |
| 79208 | }else{ |
| 79209 | assert( pOp->opcode==OP_IdxRowid ); |
| 79210 | sqlite3VdbeMemSetNull(&aMem[pOp->p2]); |
| 79211 | } |
| 79212 | break; |
| 79213 | } |
| 79214 | |
| 79215 | /* Opcode: IdxGE P1 P2 P3 P4 P5 |
| @@ -79329,11 +79600,11 @@ | |
| 79600 | Mem *pnErr; /* Register keeping track of errors remaining */ |
| 79601 | |
| 79602 | assert( p->bIsReader ); |
| 79603 | nRoot = pOp->p2; |
| 79604 | assert( nRoot>0 ); |
| 79605 | aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(nRoot+1) ); |
| 79606 | if( aRoot==0 ) goto no_mem; |
| 79607 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 79608 | pnErr = &aMem[pOp->p3]; |
| 79609 | assert( (pnErr->flags & MEM_Int)!=0 ); |
| 79610 | assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); |
| @@ -79711,24 +79982,35 @@ | |
| 79982 | goto jump_to_p2; |
| 79983 | } |
| 79984 | break; |
| 79985 | } |
| 79986 | |
| 79987 | /* Opcode: OffsetLimit P1 P2 P3 * * |
| 79988 | ** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) |
| 79989 | ** |
| 79990 | ** This opcode performs a commonly used computation associated with |
| 79991 | ** LIMIT and OFFSET process. r[P1] holds the limit counter. r[P3] |
| 79992 | ** holds the offset counter. The opcode computes the combined value |
| 79993 | ** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2] |
| 79994 | ** value computed is the total number of rows that will need to be |
| 79995 | ** visited in order to complete the query. |
| 79996 | ** |
| 79997 | ** If r[P3] is zero or negative, that means there is no OFFSET |
| 79998 | ** and r[P2] is set to be the value of the LIMIT, r[P1]. |
| 79999 | ** |
| 80000 | ** if r[P1] is zero or negative, that means there is no LIMIT |
| 80001 | ** and r[P2] is set to -1. |
| 80002 | ** |
| 80003 | ** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. |
| 80004 | */ |
| 80005 | case OP_OffsetLimit: { /* in1, out2, in3 */ |
| 80006 | pIn1 = &aMem[pOp->p1]; |
| 80007 | pIn3 = &aMem[pOp->p3]; |
| 80008 | pOut = out2Prerelease(p, pOp); |
| 80009 | assert( pIn1->flags & MEM_Int ); |
| 80010 | assert( pIn3->flags & MEM_Int ); |
| 80011 | pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0); |
| 80012 | break; |
| 80013 | } |
| 80014 | |
| 80015 | /* Opcode: IfNotZero P1 P2 P3 * * |
| 80016 | ** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 |
| @@ -79815,11 +80097,11 @@ | |
| 80097 | assert( pOp->p4type==P4_FUNCDEF ); |
| 80098 | n = pOp->p5; |
| 80099 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 80100 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 80101 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 80102 | pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 80103 | if( pCtx==0 ) goto no_mem; |
| 80104 | pCtx->pMem = 0; |
| 80105 | pCtx->pFunc = pOp->p4.pFunc; |
| 80106 | pCtx->iOp = (int)(pOp - aOp); |
| 80107 | pCtx->pVdbe = p; |
| @@ -80682,11 +80964,11 @@ | |
| 80964 | p->rc = rc; |
| 80965 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 80966 | sqlite3_log(rc, "statement aborts at %d: [%s] %s", |
| 80967 | (int)(pOp - aOp), p->zSql, p->zErrMsg); |
| 80968 | sqlite3VdbeHalt(p); |
| 80969 | if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); |
| 80970 | rc = SQLITE_ERROR; |
| 80971 | if( resetSchemaOnFault>0 ){ |
| 80972 | sqlite3ResetOneSchema(db, resetSchemaOnFault-1); |
| 80973 | } |
| 80974 | |
| @@ -80696,10 +80978,13 @@ | |
| 80978 | vdbe_return: |
| 80979 | db->lastRowid = lastRowid; |
| 80980 | testcase( nVmStep>0 ); |
| 80981 | p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; |
| 80982 | sqlite3VdbeLeave(p); |
| 80983 | assert( rc!=SQLITE_OK || nExtraDelete==0 |
| 80984 | || sqlite3_strlike("DELETE%",p->zSql,0)!=0 |
| 80985 | ); |
| 80986 | return rc; |
| 80987 | |
| 80988 | /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH |
| 80989 | ** is encountered. |
| 80990 | */ |
| @@ -80709,11 +80994,11 @@ | |
| 80994 | goto vdbe_error_halt; |
| 80995 | |
| 80996 | /* Jump to here if a malloc() fails. |
| 80997 | */ |
| 80998 | no_mem: |
| 80999 | sqlite3OomFault(db); |
| 81000 | sqlite3VdbeError(p, "out of memory"); |
| 81001 | rc = SQLITE_NOMEM; |
| 81002 | goto vdbe_error_halt; |
| 81003 | |
| 81004 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| @@ -80730,11 +81015,11 @@ | |
| 81015 | /* Jump to here if the sqlite3_interrupt() API sets the interrupt |
| 81016 | ** flag. |
| 81017 | */ |
| 81018 | abort_due_to_interrupt: |
| 81019 | assert( db->u1.isInterrupted ); |
| 81020 | rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_INTERRUPT; |
| 81021 | p->rc = rc; |
| 81022 | sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); |
| 81023 | goto vdbe_error_halt; |
| 81024 | } |
| 81025 | |
| @@ -80990,23 +81275,21 @@ | |
| 81275 | ** |
| 81276 | ** The sqlite3_blob_close() function finalizes the vdbe program, |
| 81277 | ** which closes the b-tree cursor and (possibly) commits the |
| 81278 | ** transaction. |
| 81279 | */ |
| 81280 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 81281 | static const VdbeOpList openBlob[] = { |
| 81282 | {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ |
| 81283 | {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ |
| 81284 | {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */ |
| 81285 | {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */ |
| 81286 | {OP_Column, 0, 0, 1}, /* 4 */ |
| 81287 | {OP_ResultRow, 1, 0, 0}, /* 5 */ |
| 81288 | {OP_Goto, 0, 2, 0}, /* 6 */ |
| 81289 | {OP_Close, 0, 0, 0}, /* 7 */ |
| 81290 | {OP_Halt, 0, 0, 0}, /* 8 */ |
| 81291 | }; |
| 81292 | Vdbe *v = (Vdbe *)pBlob->pStmt; |
| 81293 | int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 81294 | VdbeOp *aOp; |
| 81295 | |
| @@ -83044,27 +83327,28 @@ | |
| 83327 | if( pSorter->list.aMemory ){ |
| 83328 | int nMin = pSorter->iMemory + nReq; |
| 83329 | |
| 83330 | if( nMin>pSorter->nMemory ){ |
| 83331 | u8 *aNew; |
| 83332 | int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; |
| 83333 | int nNew = pSorter->nMemory * 2; |
| 83334 | while( nNew < nMin ) nNew = nNew*2; |
| 83335 | if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; |
| 83336 | if( nNew < nMin ) nNew = nMin; |
| 83337 | |
| 83338 | aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); |
| 83339 | if( !aNew ) return SQLITE_NOMEM; |
| 83340 | pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; |
| 83341 | pSorter->list.aMemory = aNew; |
| 83342 | pSorter->nMemory = nNew; |
| 83343 | } |
| 83344 | |
| 83345 | pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; |
| 83346 | pSorter->iMemory += ROUND8(nReq); |
| 83347 | if( pSorter->list.pList ){ |
| 83348 | pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); |
| 83349 | } |
| 83350 | }else{ |
| 83351 | pNew = (SorterRecord *)sqlite3Malloc(nReq); |
| 83352 | if( pNew==0 ){ |
| 83353 | return SQLITE_NOMEM; |
| 83354 | } |
| @@ -86230,12 +86514,11 @@ | |
| 86514 | return pExpr; |
| 86515 | } |
| 86516 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
| 86517 | Token s; |
| 86518 | assert( zC!=0 ); |
| 86519 | sqlite3TokenInit(&s, (char*)zC); |
| 86520 | return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); |
| 86521 | } |
| 86522 | |
| 86523 | /* |
| 86524 | ** Skip over any TK_COLLATE operators and any unlikely() |
| @@ -86599,18 +86882,19 @@ | |
| 86882 | ){ |
| 86883 | Expr *pNew; |
| 86884 | int nExtra = 0; |
| 86885 | int iValue = 0; |
| 86886 | |
| 86887 | assert( db!=0 ); |
| 86888 | if( pToken ){ |
| 86889 | if( op!=TK_INTEGER || pToken->z==0 |
| 86890 | || sqlite3GetInt32(pToken->z, &iValue)==0 ){ |
| 86891 | nExtra = pToken->n+1; |
| 86892 | assert( iValue>=0 ); |
| 86893 | } |
| 86894 | } |
| 86895 | pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); |
| 86896 | if( pNew ){ |
| 86897 | memset(pNew, 0, sizeof(Expr)); |
| 86898 | pNew->op = (u8)op; |
| 86899 | pNew->iAgg = -1; |
| 86900 | if( pToken ){ |
| @@ -86845,11 +87129,14 @@ | |
| 87129 | } |
| 87130 | if( x>0 ){ |
| 87131 | if( x>pParse->nzVar ){ |
| 87132 | char **a; |
| 87133 | a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); |
| 87134 | if( a==0 ){ |
| 87135 | assert( db->mallocFailed ); /* Error reported through mallocFailed */ |
| 87136 | return; |
| 87137 | } |
| 87138 | pParse->azVar = a; |
| 87139 | memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); |
| 87140 | pParse->nzVar = x; |
| 87141 | } |
| 87142 | if( z[0]!='?' || pParse->azVar[x-1]==0 ){ |
| @@ -87000,10 +87287,11 @@ | |
| 87287 | ** portion of the buffer copied into by this function. |
| 87288 | */ |
| 87289 | static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ |
| 87290 | Expr *pNew = 0; /* Value to return */ |
| 87291 | assert( flags==0 || flags==EXPRDUP_REDUCE ); |
| 87292 | assert( db!=0 ); |
| 87293 | if( p ){ |
| 87294 | const int isReduced = (flags&EXPRDUP_REDUCE); |
| 87295 | u8 *zAlloc; |
| 87296 | u32 staticFlag = 0; |
| 87297 | |
| @@ -87012,11 +87300,11 @@ | |
| 87300 | /* Figure out where to write the new Expr structure. */ |
| 87301 | if( pzBuffer ){ |
| 87302 | zAlloc = *pzBuffer; |
| 87303 | staticFlag = EP_Static; |
| 87304 | }else{ |
| 87305 | zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, flags)); |
| 87306 | } |
| 87307 | pNew = (Expr *)zAlloc; |
| 87308 | |
| 87309 | if( pNew ){ |
| 87310 | /* Set nNewSize to the size allocated for the structure pointed to |
| @@ -87135,16 +87423,17 @@ | |
| 87423 | } |
| 87424 | SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ |
| 87425 | ExprList *pNew; |
| 87426 | struct ExprList_item *pItem, *pOldItem; |
| 87427 | int i; |
| 87428 | assert( db!=0 ); |
| 87429 | if( p==0 ) return 0; |
| 87430 | pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); |
| 87431 | if( pNew==0 ) return 0; |
| 87432 | pNew->nExpr = i = p->nExpr; |
| 87433 | if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){} |
| 87434 | pNew->a = pItem = sqlite3DbMallocRawNN(db, i*sizeof(p->a[0]) ); |
| 87435 | if( pItem==0 ){ |
| 87436 | sqlite3DbFree(db, pNew); |
| 87437 | return 0; |
| 87438 | } |
| 87439 | pOldItem = p->a; |
| @@ -87171,13 +87460,14 @@ | |
| 87460 | || !defined(SQLITE_OMIT_SUBQUERY) |
| 87461 | SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ |
| 87462 | SrcList *pNew; |
| 87463 | int i; |
| 87464 | int nByte; |
| 87465 | assert( db!=0 ); |
| 87466 | if( p==0 ) return 0; |
| 87467 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); |
| 87468 | pNew = sqlite3DbMallocRawNN(db, nByte ); |
| 87469 | if( pNew==0 ) return 0; |
| 87470 | pNew->nSrc = pNew->nAlloc = p->nSrc; |
| 87471 | for(i=0; i<p->nSrc; i++){ |
| 87472 | struct SrcList_item *pNewItem = &pNew->a[i]; |
| 87473 | struct SrcList_item *pOldItem = &p->a[i]; |
| @@ -87210,15 +87500,16 @@ | |
| 87500 | return pNew; |
| 87501 | } |
| 87502 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ |
| 87503 | IdList *pNew; |
| 87504 | int i; |
| 87505 | assert( db!=0 ); |
| 87506 | if( p==0 ) return 0; |
| 87507 | pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); |
| 87508 | if( pNew==0 ) return 0; |
| 87509 | pNew->nId = p->nId; |
| 87510 | pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) ); |
| 87511 | if( pNew->a==0 ){ |
| 87512 | sqlite3DbFree(db, pNew); |
| 87513 | return 0; |
| 87514 | } |
| 87515 | /* Note that because the size of the allocation for p->a[] is not |
| @@ -87232,12 +87523,13 @@ | |
| 87523 | } |
| 87524 | return pNew; |
| 87525 | } |
| 87526 | SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ |
| 87527 | Select *pNew, *pPrior; |
| 87528 | assert( db!=0 ); |
| 87529 | if( p==0 ) return 0; |
| 87530 | pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); |
| 87531 | if( pNew==0 ) return 0; |
| 87532 | pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); |
| 87533 | pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); |
| 87534 | pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); |
| 87535 | pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); |
| @@ -87279,17 +87571,18 @@ | |
| 87571 | Parse *pParse, /* Parsing context */ |
| 87572 | ExprList *pList, /* List to which to append. Might be NULL */ |
| 87573 | Expr *pExpr /* Expression to be appended. Might be NULL */ |
| 87574 | ){ |
| 87575 | sqlite3 *db = pParse->db; |
| 87576 | assert( db!=0 ); |
| 87577 | if( pList==0 ){ |
| 87578 | pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) ); |
| 87579 | if( pList==0 ){ |
| 87580 | goto no_mem; |
| 87581 | } |
| 87582 | pList->nExpr = 0; |
| 87583 | pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0])); |
| 87584 | if( pList->a==0 ) goto no_mem; |
| 87585 | }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ |
| 87586 | struct ExprList_item *a; |
| 87587 | assert( pList->nExpr>0 ); |
| 87588 | a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0])); |
| @@ -91009,11 +91302,11 @@ | |
| 91302 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); |
| 91303 | sqlite3VdbeUsesBtree(v, iDb); |
| 91304 | sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); |
| 91305 | addr1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); |
| 91306 | sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); |
| 91307 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, minFormat); |
| 91308 | sqlite3VdbeJumpHere(v, addr1); |
| 91309 | sqlite3ReleaseTempReg(pParse, r1); |
| 91310 | sqlite3ReleaseTempReg(pParse, r2); |
| 91311 | } |
| 91312 | } |
| @@ -91096,11 +91389,11 @@ | |
| 91389 | sqlite3_value *pVal = 0; |
| 91390 | int rc; |
| 91391 | rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); |
| 91392 | assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); |
| 91393 | if( rc!=SQLITE_OK ){ |
| 91394 | assert( db->mallocFailed == 1 ); |
| 91395 | return; |
| 91396 | } |
| 91397 | if( !pVal ){ |
| 91398 | sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); |
| 91399 | return; |
| @@ -91204,11 +91497,11 @@ | |
| 91497 | nAlloc = (((pNew->nCol-1)/8)*8)+8; |
| 91498 | assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); |
| 91499 | pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); |
| 91500 | pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); |
| 91501 | if( !pNew->aCol || !pNew->zName ){ |
| 91502 | assert( db->mallocFailed ); |
| 91503 | goto exit_begin_add_column; |
| 91504 | } |
| 91505 | memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); |
| 91506 | for(i=0; i<pNew->nCol; i++){ |
| 91507 | Column *pCol = &pNew->aCol[i]; |
| @@ -91549,11 +91842,11 @@ | |
| 91842 | */ |
| 91843 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 91844 | static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ |
| 91845 | assert( db!=0 ); |
| 91846 | if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); |
| 91847 | p->u.aRowid = sqlite3DbMallocRawNN(db, n); |
| 91848 | if( p->u.aRowid ){ |
| 91849 | p->nRowid = n; |
| 91850 | memcpy(p->u.aRowid, pData, n); |
| 91851 | }else{ |
| 91852 | p->nRowid = 0; |
| @@ -92351,11 +92644,11 @@ | |
| 92644 | addrNextRow = sqlite3VdbeCurrentAddr(v); |
| 92645 | |
| 92646 | if( nColTest>0 ){ |
| 92647 | int endDistinctTest = sqlite3VdbeMakeLabel(v); |
| 92648 | int *aGotoChng; /* Array of jump instruction addresses */ |
| 92649 | aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest); |
| 92650 | if( aGotoChng==0 ) continue; |
| 92651 | |
| 92652 | /* |
| 92653 | ** next_row: |
| 92654 | ** regChng = 0 |
| @@ -92759,11 +93052,11 @@ | |
| 93052 | /* Index.aiRowEst may already be set here if there are duplicate |
| 93053 | ** sqlite_stat1 entries for this index. In that case just clobber |
| 93054 | ** the old data with the new instead of allocating a new array. */ |
| 93055 | if( pIndex->aiRowEst==0 ){ |
| 93056 | pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); |
| 93057 | if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db); |
| 93058 | } |
| 93059 | aiRowEst = pIndex->aiRowEst; |
| 93060 | #endif |
| 93061 | pIndex->bUnordered = 0; |
| 93062 | decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); |
| @@ -92906,11 +93199,11 @@ | |
| 93199 | sqlite3_stmt *pStmt = 0; /* An SQL statement being run */ |
| 93200 | char *zSql; /* Text of the SQL statement */ |
| 93201 | Index *pPrevIdx = 0; /* Previous index in the loop */ |
| 93202 | IndexSample *pSample; /* A slot in pIdx->aSample[] */ |
| 93203 | |
| 93204 | assert( db->lookaside.bDisable ); |
| 93205 | zSql = sqlite3MPrintf(db, zSql1, zDb); |
| 93206 | if( !zSql ){ |
| 93207 | return SQLITE_NOMEM; |
| 93208 | } |
| 93209 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| @@ -93020,11 +93313,11 @@ | |
| 93313 | ** the Index.aSample[] arrays of all indices. |
| 93314 | */ |
| 93315 | static int loadStat4(sqlite3 *db, const char *zDb){ |
| 93316 | int rc = SQLITE_OK; /* Result codes from subroutines */ |
| 93317 | |
| 93318 | assert( db->lookaside.bDisable ); |
| 93319 | if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ |
| 93320 | rc = loadStatTbl(db, 0, |
| 93321 | "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", |
| 93322 | "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", |
| 93323 | zDb |
| @@ -93102,24 +93395,23 @@ | |
| 93395 | |
| 93396 | |
| 93397 | /* Load the statistics from the sqlite_stat4 table. */ |
| 93398 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 93399 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 93400 | db->lookaside.bDisable++; |
| 93401 | rc = loadStat4(db, sInfo.zDatabase); |
| 93402 | db->lookaside.bDisable--; |
| 93403 | } |
| 93404 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 93405 | Index *pIdx = sqliteHashData(i); |
| 93406 | sqlite3_free(pIdx->aiRowEst); |
| 93407 | pIdx->aiRowEst = 0; |
| 93408 | } |
| 93409 | #endif |
| 93410 | |
| 93411 | if( rc==SQLITE_NOMEM ){ |
| 93412 | sqlite3OomFault(db); |
| 93413 | } |
| 93414 | return rc; |
| 93415 | } |
| 93416 | |
| 93417 | |
| @@ -93236,11 +93528,11 @@ | |
| 93528 | |
| 93529 | /* Allocate the new entry in the db->aDb[] array and initialize the schema |
| 93530 | ** hash tables. |
| 93531 | */ |
| 93532 | if( db->aDb==db->aDbStatic ){ |
| 93533 | aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); |
| 93534 | if( aNew==0 ) return; |
| 93535 | memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); |
| 93536 | }else{ |
| 93537 | aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); |
| 93538 | if( aNew==0 ) return; |
| @@ -93254,11 +93546,11 @@ | |
| 93546 | ** or may not be initialized. |
| 93547 | */ |
| 93548 | flags = db->openFlags; |
| 93549 | rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); |
| 93550 | if( rc!=SQLITE_OK ){ |
| 93551 | if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
| 93552 | sqlite3_result_error(context, zErr, -1); |
| 93553 | sqlite3_free(zErr); |
| 93554 | return; |
| 93555 | } |
| 93556 | assert( pVfs ); |
| @@ -93283,11 +93575,12 @@ | |
| 93575 | pPager = sqlite3BtreePager(aNew->pBt); |
| 93576 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 93577 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 93578 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 93579 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 93580 | sqlite3BtreeSetPagerFlags(aNew->pBt, |
| 93581 | PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); |
| 93582 | #endif |
| 93583 | sqlite3BtreeLeave(aNew->pBt); |
| 93584 | } |
| 93585 | aNew->safety_level = 3; |
| 93586 | aNew->zName = sqlite3DbStrDup(db, zName); |
| @@ -93356,11 +93649,11 @@ | |
| 93649 | db->aDb[iDb].pSchema = 0; |
| 93650 | } |
| 93651 | sqlite3ResetAllSchemasOfConnection(db); |
| 93652 | db->nDb = iDb; |
| 93653 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 93654 | sqlite3OomFault(db); |
| 93655 | sqlite3DbFree(db, zErrDyn); |
| 93656 | zErrDyn = sqlite3MPrintf(db, "out of memory"); |
| 93657 | }else if( zErrDyn==0 ){ |
| 93658 | zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); |
| 93659 | } |
| @@ -94053,11 +94346,11 @@ | |
| 94346 | p->iTab = iTab; |
| 94347 | p->isWriteLock = isWriteLock; |
| 94348 | p->zName = zName; |
| 94349 | }else{ |
| 94350 | pToplevel->nTableLock = 0; |
| 94351 | sqlite3OomFault(pToplevel->db); |
| 94352 | } |
| 94353 | } |
| 94354 | |
| 94355 | /* |
| 94356 | ** Code an OP_TableLock instruction for each table locked by the |
| @@ -94901,11 +95194,11 @@ | |
| 95194 | } |
| 95195 | } |
| 95196 | |
| 95197 | pTable = sqlite3DbMallocZero(db, sizeof(Table)); |
| 95198 | if( pTable==0 ){ |
| 95199 | assert( db->mallocFailed ); |
| 95200 | pParse->rc = SQLITE_NOMEM; |
| 95201 | pParse->nErr++; |
| 95202 | goto begin_table_error; |
| 95203 | } |
| 95204 | pTable->zName = zName; |
| @@ -94958,14 +95251,12 @@ | |
| 95251 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); |
| 95252 | sqlite3VdbeUsesBtree(v, iDb); |
| 95253 | addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); |
| 95254 | fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? |
| 95255 | 1 : SQLITE_MAX_FILE_FORMAT; |
| 95256 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat); |
| 95257 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db)); |
| 95258 | sqlite3VdbeJumpHere(v, addr1); |
| 95259 | |
| 95260 | /* This just creates a place-holder record in the sqlite_master table. |
| 95261 | ** The record created does not contain anything yet. It will be replaced |
| 95262 | ** by the real entry in code generated at sqlite3EndTable(). |
| @@ -95446,17 +95737,15 @@ | |
| 95737 | ** set back to prior value. But schema changes are infrequent |
| 95738 | ** and the probability of hitting the same cookie value is only |
| 95739 | ** 1 chance in 2^32. So we're safe enough. |
| 95740 | */ |
| 95741 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ |
| 95742 | sqlite3 *db = pParse->db; |
| 95743 | Vdbe *v = pParse->pVdbe; |
| 95744 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 95745 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, |
| 95746 | db->aDb[iDb].pSchema->schema_cookie+1); |
| 95747 | } |
| 95748 | |
| 95749 | /* |
| 95750 | ** Measure the number of characters needed to output the given |
| 95751 | ** identifier. The number returned includes any quotes used |
| @@ -95534,11 +95823,11 @@ | |
| 95823 | zEnd = "\n)"; |
| 95824 | } |
| 95825 | n += 35 + 6*p->nCol; |
| 95826 | zStmt = sqlite3DbMallocRaw(0, n); |
| 95827 | if( zStmt==0 ){ |
| 95828 | sqlite3OomFault(db); |
| 95829 | return 0; |
| 95830 | } |
| 95831 | sqlite3_snprintf(n, zStmt, "CREATE TABLE "); |
| 95832 | k = sqlite3Strlen30(zStmt); |
| 95833 | identPut(zStmt, &k, p->zName); |
| @@ -95683,12 +95972,11 @@ | |
| 95972 | ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. |
| 95973 | */ |
| 95974 | if( pTab->iPKey>=0 ){ |
| 95975 | ExprList *pList; |
| 95976 | Token ipkToken; |
| 95977 | sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName); |
| 95978 | pList = sqlite3ExprListAppend(pParse, 0, |
| 95979 | sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); |
| 95980 | if( pList==0 ) return; |
| 95981 | pList->a[0].sortOrder = pParse->iPkSortOrder; |
| 95982 | assert( pParse->pNewTable==pTab ); |
| @@ -95934,11 +96222,11 @@ | |
| 96222 | pParse->nTab = 2; |
| 96223 | addrTop = sqlite3VdbeCurrentAddr(v) + 1; |
| 96224 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); |
| 96225 | sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); |
| 96226 | sqlite3Select(pParse, pSelect, &dest); |
| 96227 | sqlite3VdbeEndCoroutine(v, regYield); |
| 96228 | sqlite3VdbeJumpHere(v, addrTop - 1); |
| 96229 | if( pParse->nErr ) return; |
| 96230 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); |
| 96231 | if( pSelTab==0 ) return; |
| 96232 | assert( p->aCol==0 ); |
| @@ -96018,11 +96306,11 @@ | |
| 96306 | Schema *pSchema = p->pSchema; |
| 96307 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 96308 | pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); |
| 96309 | if( pOld ){ |
| 96310 | assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 96311 | sqlite3OomFault(db); |
| 96312 | return; |
| 96313 | } |
| 96314 | pParse->pNewTable = 0; |
| 96315 | db->flags |= SQLITE_InternChanges; |
| 96316 | |
| @@ -96122,11 +96410,10 @@ | |
| 96410 | Select *pSel; /* Copy of the SELECT that implements the view */ |
| 96411 | int nErr = 0; /* Number of errors encountered */ |
| 96412 | int n; /* Temporarily holds the number of cursors assigned */ |
| 96413 | sqlite3 *db = pParse->db; /* Database connection for malloc errors */ |
| 96414 | sqlite3_xauth xAuth; /* Saved xAuth pointer */ |
| 96415 | |
| 96416 | assert( pTable ); |
| 96417 | |
| 96418 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 96419 | if( sqlite3VtabCallConnect(pParse, pTable) ){ |
| @@ -96168,30 +96455,31 @@ | |
| 96455 | ** to the elements of the FROM clause. But we do not want these changes |
| 96456 | ** to be permanent. So the computation is done on a copy of the SELECT |
| 96457 | ** statement that defines the view. |
| 96458 | */ |
| 96459 | assert( pTable->pSelect ); |
| 96460 | if( pTable->pCheck ){ |
| 96461 | db->lookaside.bDisable++; |
| 96462 | sqlite3ColumnsFromExprList(pParse, pTable->pCheck, |
| 96463 | &pTable->nCol, &pTable->aCol); |
| 96464 | db->lookaside.bDisable--; |
| 96465 | }else{ |
| 96466 | pSel = sqlite3SelectDup(db, pTable->pSelect, 0); |
| 96467 | if( pSel ){ |
| 96468 | n = pParse->nTab; |
| 96469 | sqlite3SrcListAssignCursors(pParse, pSel->pSrc); |
| 96470 | pTable->nCol = -1; |
| 96471 | db->lookaside.bDisable++; |
| 96472 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 96473 | xAuth = db->xAuth; |
| 96474 | db->xAuth = 0; |
| 96475 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96476 | db->xAuth = xAuth; |
| 96477 | #else |
| 96478 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96479 | #endif |
| 96480 | db->lookaside.bDisable--; |
| 96481 | pParse->nTab = n; |
| 96482 | if( pSelTab ){ |
| 96483 | assert( pTable->aCol==0 ); |
| 96484 | pTable->nCol = pSelTab->nCol; |
| 96485 | pTable->aCol = pSelTab->aCol; |
| @@ -96206,11 +96494,10 @@ | |
| 96494 | sqlite3SelectDelete(db, pSel); |
| 96495 | } else { |
| 96496 | nErr++; |
| 96497 | } |
| 96498 | } |
| 96499 | pTable->pSchema->schemaFlags |= DB_UnresetViews; |
| 96500 | #endif /* SQLITE_OMIT_VIEW */ |
| 96501 | return nErr; |
| 96502 | } |
| 96503 | #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ |
| @@ -96672,11 +96959,11 @@ | |
| 96959 | assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); |
| 96960 | pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, |
| 96961 | pFKey->zTo, (void *)pFKey |
| 96962 | ); |
| 96963 | if( pNextTo==pFKey ){ |
| 96964 | sqlite3OomFault(db); |
| 96965 | goto fk_end; |
| 96966 | } |
| 96967 | if( pNextTo ){ |
| 96968 | assert( pNextTo->pPrevTo==0 ); |
| 96969 | pFKey->pNextTo = pNextTo; |
| @@ -97032,12 +97319,11 @@ | |
| 97319 | ** key out of the last column added to the table under construction. |
| 97320 | ** So create a fake list to simulate this. |
| 97321 | */ |
| 97322 | if( pList==0 ){ |
| 97323 | Token prevCol; |
| 97324 | sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName); |
| 97325 | pList = sqlite3ExprListAppend(pParse, 0, |
| 97326 | sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); |
| 97327 | if( pList==0 ) goto exit_create_index; |
| 97328 | assert( pList->nExpr==1 ); |
| 97329 | sqlite3ExprListSetSortOrder(pList, sortOrder); |
| @@ -97255,11 +97541,11 @@ | |
| 97541 | assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); |
| 97542 | p = sqlite3HashInsert(&pIndex->pSchema->idxHash, |
| 97543 | pIndex->zName, pIndex); |
| 97544 | if( p ){ |
| 97545 | assert( p==pIndex ); /* Malloc must have failed */ |
| 97546 | sqlite3OomFault(db); |
| 97547 | goto exit_create_index; |
| 97548 | } |
| 97549 | db->flags |= SQLITE_InternChanges; |
| 97550 | if( pTblName!=0 ){ |
| 97551 | pIndex->tnum = db->init.newTnum; |
| @@ -97684,12 +97970,13 @@ | |
| 97970 | Token *pTable, /* Table to append */ |
| 97971 | Token *pDatabase /* Database of the table */ |
| 97972 | ){ |
| 97973 | struct SrcList_item *pItem; |
| 97974 | assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ |
| 97975 | assert( db!=0 ); |
| 97976 | if( pList==0 ){ |
| 97977 | pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) ); |
| 97978 | if( pList==0 ) return 0; |
| 97979 | pList->nAlloc = 1; |
| 97980 | pList->nSrc = 0; |
| 97981 | } |
| 97982 | pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); |
| @@ -97869,21 +98156,20 @@ | |
| 98156 | p->a[0].fg.jointype = 0; |
| 98157 | } |
| 98158 | } |
| 98159 | |
| 98160 | /* |
| 98161 | ** Generate VDBE code for a BEGIN statement. |
| 98162 | */ |
| 98163 | SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ |
| 98164 | sqlite3 *db; |
| 98165 | Vdbe *v; |
| 98166 | int i; |
| 98167 | |
| 98168 | assert( pParse!=0 ); |
| 98169 | db = pParse->db; |
| 98170 | assert( db!=0 ); |
| 98171 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ |
| 98172 | return; |
| 98173 | } |
| 98174 | v = sqlite3GetVdbe(pParse); |
| 98175 | if( !v ) return; |
| @@ -97891,15 +98177,15 @@ | |
| 98177 | for(i=0; i<db->nDb; i++){ |
| 98178 | sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); |
| 98179 | sqlite3VdbeUsesBtree(v, i); |
| 98180 | } |
| 98181 | } |
| 98182 | sqlite3VdbeAddOp0(v, OP_AutoCommit); |
| 98183 | } |
| 98184 | |
| 98185 | /* |
| 98186 | ** Generate VDBE code for a COMMIT statement. |
| 98187 | */ |
| 98188 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){ |
| 98189 | Vdbe *v; |
| 98190 | |
| 98191 | assert( pParse!=0 ); |
| @@ -97907,16 +98193,16 @@ | |
| 98193 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ |
| 98194 | return; |
| 98195 | } |
| 98196 | v = sqlite3GetVdbe(pParse); |
| 98197 | if( v ){ |
| 98198 | sqlite3VdbeAddOp1(v, OP_AutoCommit, 1); |
| 98199 | } |
| 98200 | } |
| 98201 | |
| 98202 | /* |
| 98203 | ** Generate VDBE code for a ROLLBACK statement. |
| 98204 | */ |
| 98205 | SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){ |
| 98206 | Vdbe *v; |
| 98207 | |
| 98208 | assert( pParse!=0 ); |
| @@ -97974,11 +98260,11 @@ | |
| 98260 | return 1; |
| 98261 | } |
| 98262 | db->aDb[1].pBt = pBt; |
| 98263 | assert( db->aDb[1].pSchema ); |
| 98264 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 98265 | sqlite3OomFault(db); |
| 98266 | return 1; |
| 98267 | } |
| 98268 | } |
| 98269 | return 0; |
| 98270 | } |
| @@ -98109,18 +98395,18 @@ | |
| 98395 | StrAccum errMsg; |
| 98396 | Table *pTab = pIdx->pTable; |
| 98397 | |
| 98398 | sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); |
| 98399 | if( pIdx->aColExpr ){ |
| 98400 | sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); |
| 98401 | }else{ |
| 98402 | for(j=0; j<pIdx->nKeyCol; j++){ |
| 98403 | char *zCol; |
| 98404 | assert( pIdx->aiColumn[j]>=0 ); |
| 98405 | zCol = pTab->aCol[pIdx->aiColumn[j]].zName; |
| 98406 | if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); |
| 98407 | sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol); |
| 98408 | } |
| 98409 | } |
| 98410 | zErr = sqlite3StrAccumFinish(&errMsg); |
| 98411 | sqlite3HaltConstraint(pParse, |
| 98412 | IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY |
| @@ -98349,14 +98635,13 @@ | |
| 98635 | int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); |
| 98636 | pNew = sqlite3DbRealloc(db, pWith, nByte); |
| 98637 | }else{ |
| 98638 | pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); |
| 98639 | } |
| 98640 | assert( (pNew!=0 && zName!=0) || db->mallocFailed ); |
| 98641 | |
| 98642 | if( db->mallocFailed ){ |
| 98643 | sqlite3ExprListDelete(db, pArglist); |
| 98644 | sqlite3SelectDelete(db, pQuery); |
| 98645 | sqlite3DbFree(db, zName); |
| 98646 | pNew = pWith; |
| 98647 | }else{ |
| @@ -98566,11 +98851,11 @@ | |
| 98851 | ** return the pColl pointer to be deleted (because it wasn't added |
| 98852 | ** to the hash table). |
| 98853 | */ |
| 98854 | assert( pDel==0 || pDel==pColl ); |
| 98855 | if( pDel!=0 ){ |
| 98856 | sqlite3OomFault(db); |
| 98857 | sqlite3DbFree(db, pDel); |
| 98858 | pColl = 0; |
| 98859 | } |
| 98860 | } |
| 98861 | } |
| @@ -98854,11 +99139,11 @@ | |
| 99139 | p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); |
| 99140 | }else{ |
| 99141 | p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); |
| 99142 | } |
| 99143 | if( !p ){ |
| 99144 | sqlite3OomFault(db); |
| 99145 | }else if ( 0==p->file_format ){ |
| 99146 | sqlite3HashInit(&p->tblHash); |
| 99147 | sqlite3HashInit(&p->idxHash); |
| 99148 | sqlite3HashInit(&p->trigHash); |
| 99149 | sqlite3HashInit(&p->fkeyHash); |
| @@ -99308,11 +99593,11 @@ | |
| 99593 | if( eOnePass!=ONEPASS_OFF ){ |
| 99594 | /* For ONEPASS, no need to store the rowid/primary-key. There is only |
| 99595 | ** one, so just keep it in its register(s) and fall through to the |
| 99596 | ** delete code. */ |
| 99597 | nKey = nPk; /* OP_Found will use an unpacked key */ |
| 99598 | aToOpen = sqlite3DbMallocRawNN(db, nIdx+2); |
| 99599 | if( aToOpen==0 ){ |
| 99600 | sqlite3WhereEnd(pWInfo); |
| 99601 | goto delete_from_cleanup; |
| 99602 | } |
| 99603 | memset(aToOpen, 1, nIdx+1); |
| @@ -99348,17 +99633,16 @@ | |
| 99633 | ** only effect this statement has is to fire the INSTEAD OF |
| 99634 | ** triggers. |
| 99635 | */ |
| 99636 | if( !isView ){ |
| 99637 | int iAddrOnce = 0; |
| 99638 | if( eOnePass==ONEPASS_MULTI ){ |
| 99639 | iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); |
| 99640 | } |
| 99641 | testcase( IsVirtual(pTab) ); |
| 99642 | sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, |
| 99643 | iTabCur, aToOpen, &iDataCur, &iIdxCur); |
| 99644 | assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); |
| 99645 | assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); |
| 99646 | if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); |
| 99647 | } |
| 99648 | |
| @@ -99587,19 +99871,24 @@ | |
| 99871 | |
| 99872 | /* Delete the index and table entries. Skip this step if pTab is really |
| 99873 | ** a view (in which case the only effect of the DELETE statement is to |
| 99874 | ** fire the INSTEAD OF triggers). */ |
| 99875 | if( pTab->pSelect==0 ){ |
| 99876 | u8 p5 = 0; |
| 99877 | sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); |
| 99878 | sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); |
| 99879 | if( count ){ |
| 99880 | sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); |
| 99881 | } |
| 99882 | if( eMode!=ONEPASS_OFF ){ |
| 99883 | sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); |
| 99884 | } |
| 99885 | if( iIdxNoSeek>=0 ){ |
| 99886 | sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); |
| 99887 | } |
| 99888 | if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; |
| 99889 | sqlite3VdbeChangeP5(v, p5); |
| 99890 | } |
| 99891 | |
| 99892 | /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
| 99893 | ** handle rows (possibly in other tables) that refer via a foreign key |
| 99894 | ** to the row just deleted. */ |
| @@ -100005,11 +100294,12 @@ | |
| 100294 | if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
| 100295 | x.nArg = argc-1; |
| 100296 | x.nUsed = 0; |
| 100297 | x.apArg = argv+1; |
| 100298 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 100299 | str.printfFlags = SQLITE_PRINTF_SQLFUNC; |
| 100300 | sqlite3XPrintf(&str, zFormat, &x); |
| 100301 | n = str.nChar; |
| 100302 | sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, |
| 100303 | SQLITE_DYNAMIC); |
| 100304 | } |
| 100305 | } |
| @@ -101380,11 +101670,11 @@ | |
| 101670 | */ |
| 101671 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ |
| 101672 | int rc = sqlite3_overload_function(db, "MATCH", 2); |
| 101673 | assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); |
| 101674 | if( rc==SQLITE_NOMEM ){ |
| 101675 | sqlite3OomFault(db); |
| 101676 | } |
| 101677 | } |
| 101678 | |
| 101679 | /* |
| 101680 | ** Set the LIKEOPT flag on the 2-argument function with the given name. |
| @@ -101795,11 +102085,11 @@ | |
| 102085 | if( !zKey ) return 0; |
| 102086 | if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; |
| 102087 | } |
| 102088 | }else if( paiCol ){ |
| 102089 | assert( nCol>1 ); |
| 102090 | aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); |
| 102091 | if( !aiCol ) return 1; |
| 102092 | *paiCol = aiCol; |
| 102093 | } |
| 102094 | |
| 102095 | for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ |
| @@ -102741,11 +103031,10 @@ | |
| 103031 | |
| 103032 | action = pFKey->aAction[iAction]; |
| 103033 | pTrigger = pFKey->apTrigger[iAction]; |
| 103034 | |
| 103035 | if( action!=OE_None && !pTrigger ){ |
| 103036 | char const *zFrom; /* Name of child table */ |
| 103037 | int nFrom; /* Length in bytes of zFrom */ |
| 103038 | Index *pIdx = 0; /* Parent key index for this FK */ |
| 103039 | int *aiCol = 0; /* child table cols -> parent key cols */ |
| 103040 | TriggerStep *pStep = 0; /* First (only) step of trigger program */ |
| @@ -102768,15 +103057,13 @@ | |
| 103057 | |
| 103058 | iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 103059 | assert( iFromCol>=0 ); |
| 103060 | assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 103061 | assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
| 103062 | sqlite3TokenInit(&tToCol, |
| 103063 | pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName); |
| 103064 | sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName); |
| 103065 | |
| 103066 | /* Create the expression "OLD.zToCol = zFromCol". It is important |
| 103067 | ** that the "OLD.zToCol" term is on the LHS of the = operator, so |
| 103068 | ** that the affinity and collation sequence associated with the |
| 103069 | ** parent table are used for the comparison. */ |
| @@ -102852,12 +103139,11 @@ | |
| 103139 | ); |
| 103140 | pWhere = 0; |
| 103141 | } |
| 103142 | |
| 103143 | /* Disable lookaside memory allocation */ |
| 103144 | db->lookaside.bDisable++; |
| 103145 | |
| 103146 | pTrigger = (Trigger *)sqlite3DbMallocZero(db, |
| 103147 | sizeof(Trigger) + /* struct Trigger */ |
| 103148 | sizeof(TriggerStep) + /* Single step in trigger program */ |
| 103149 | nFrom + 1 /* Space for pStep->zTarget */ |
| @@ -102875,11 +103161,11 @@ | |
| 103161 | pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
| 103162 | } |
| 103163 | } |
| 103164 | |
| 103165 | /* Re-enable the lookaside buffer, if it was disabled earlier. */ |
| 103166 | db->lookaside.bDisable--; |
| 103167 | |
| 103168 | sqlite3ExprDelete(db, pWhere); |
| 103169 | sqlite3ExprDelete(db, pWhen); |
| 103170 | sqlite3ExprListDelete(db, pList); |
| 103171 | sqlite3SelectDelete(db, pSelect); |
| @@ -103070,11 +103356,11 @@ | |
| 103356 | */ |
| 103357 | int n; |
| 103358 | Table *pTab = pIdx->pTable; |
| 103359 | pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); |
| 103360 | if( !pIdx->zColAff ){ |
| 103361 | sqlite3OomFault(db); |
| 103362 | return 0; |
| 103363 | } |
| 103364 | for(n=0; n<pIdx->nColumn; n++){ |
| 103365 | i16 x = pIdx->aiColumn[n]; |
| 103366 | if( x>=0 ){ |
| @@ -103121,11 +103407,11 @@ | |
| 103407 | char *zColAff = pTab->zColAff; |
| 103408 | if( zColAff==0 ){ |
| 103409 | sqlite3 *db = sqlite3VdbeDb(v); |
| 103410 | zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); |
| 103411 | if( !zColAff ){ |
| 103412 | sqlite3OomFault(db); |
| 103413 | return; |
| 103414 | } |
| 103415 | |
| 103416 | for(i=0; i<pTab->nCol; i++){ |
| 103417 | zColAff[i] = pTab->aCol[i].affinity; |
| @@ -103217,11 +103503,11 @@ | |
| 103503 | AutoincInfo *pInfo; |
| 103504 | |
| 103505 | pInfo = pToplevel->pAinc; |
| 103506 | while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } |
| 103507 | if( pInfo==0 ){ |
| 103508 | pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); |
| 103509 | if( pInfo==0 ) return 0; |
| 103510 | pInfo->pNext = pToplevel->pAinc; |
| 103511 | pToplevel->pAinc = pInfo; |
| 103512 | pInfo->pTab = pTab; |
| 103513 | pInfo->iDb = iDb; |
| @@ -103241,47 +103527,59 @@ | |
| 103527 | SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ |
| 103528 | AutoincInfo *p; /* Information about an AUTOINCREMENT */ |
| 103529 | sqlite3 *db = pParse->db; /* The database connection */ |
| 103530 | Db *pDb; /* Database only autoinc table */ |
| 103531 | int memId; /* Register holding max rowid */ |
| 103532 | Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
| 103533 | |
| 103534 | /* This routine is never called during trigger-generation. It is |
| 103535 | ** only called from the top-level */ |
| 103536 | assert( pParse->pTriggerTab==0 ); |
| 103537 | assert( sqlite3IsToplevel(pParse) ); |
| 103538 | |
| 103539 | assert( v ); /* We failed long ago if this is not so */ |
| 103540 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103541 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 103542 | static const VdbeOpList autoInc[] = { |
| 103543 | /* 0 */ {OP_Null, 0, 0, 0}, |
| 103544 | /* 1 */ {OP_Rewind, 0, 9, 0}, |
| 103545 | /* 2 */ {OP_Column, 0, 0, 0}, |
| 103546 | /* 3 */ {OP_Ne, 0, 7, 0}, |
| 103547 | /* 4 */ {OP_Rowid, 0, 0, 0}, |
| 103548 | /* 5 */ {OP_Column, 0, 1, 0}, |
| 103549 | /* 6 */ {OP_Goto, 0, 9, 0}, |
| 103550 | /* 7 */ {OP_Next, 0, 2, 0}, |
| 103551 | /* 8 */ {OP_Integer, 0, 0, 0}, |
| 103552 | /* 9 */ {OP_Close, 0, 0, 0} |
| 103553 | }; |
| 103554 | VdbeOp *aOp; |
| 103555 | pDb = &db->aDb[p->iDb]; |
| 103556 | memId = p->regCtr; |
| 103557 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103558 | sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); |
| 103559 | sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); |
| 103560 | aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); |
| 103561 | if( aOp==0 ) break; |
| 103562 | aOp[0].p2 = memId; |
| 103563 | aOp[0].p3 = memId+1; |
| 103564 | aOp[2].p3 = memId; |
| 103565 | aOp[3].p1 = memId-1; |
| 103566 | aOp[3].p3 = memId; |
| 103567 | aOp[3].p5 = SQLITE_JUMPIFNULL; |
| 103568 | aOp[4].p2 = memId+1; |
| 103569 | aOp[5].p3 = memId; |
| 103570 | aOp[8].p2 = memId; |
| 103571 | } |
| 103572 | } |
| 103573 | |
| 103574 | /* |
| 103575 | ** Update the maximum rowid for an autoincrement calculation. |
| 103576 | ** |
| 103577 | ** This routine should be called when the regRowid register holds a |
| 103578 | ** new rowid that is about to be inserted. If that new rowid is |
| 103579 | ** larger than the maximum rowid in the memId memory cell, then the |
| 103580 | ** memory cell is updated. |
| 103581 | */ |
| 103582 | static void autoIncStep(Parse *pParse, int memId, int regRowid){ |
| 103583 | if( memId>0 ){ |
| 103584 | sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); |
| 103585 | } |
| @@ -103292,34 +103590,47 @@ | |
| 103590 | ** maximum rowid values back into the sqlite_sequence register. |
| 103591 | ** Every statement that might do an INSERT into an autoincrement |
| 103592 | ** table (either directly or through triggers) needs to call this |
| 103593 | ** routine just before the "exit" code. |
| 103594 | */ |
| 103595 | static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ |
| 103596 | AutoincInfo *p; |
| 103597 | Vdbe *v = pParse->pVdbe; |
| 103598 | sqlite3 *db = pParse->db; |
| 103599 | |
| 103600 | assert( v ); |
| 103601 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103602 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 103603 | static const VdbeOpList autoIncEnd[] = { |
| 103604 | /* 0 */ {OP_NotNull, 0, 2, 0}, |
| 103605 | /* 1 */ {OP_NewRowid, 0, 0, 0}, |
| 103606 | /* 2 */ {OP_MakeRecord, 0, 2, 0}, |
| 103607 | /* 3 */ {OP_Insert, 0, 0, 0}, |
| 103608 | /* 4 */ {OP_Close, 0, 0, 0} |
| 103609 | }; |
| 103610 | VdbeOp *aOp; |
| 103611 | Db *pDb = &db->aDb[p->iDb]; |
| 103612 | int iRec; |
| 103613 | int memId = p->regCtr; |
| 103614 | |
| 103615 | iRec = sqlite3GetTempReg(pParse); |
| 103616 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103617 | sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); |
| 103618 | aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); |
| 103619 | if( aOp==0 ) break; |
| 103620 | aOp[0].p1 = memId+1; |
| 103621 | aOp[1].p2 = memId+1; |
| 103622 | aOp[2].p1 = memId-1; |
| 103623 | aOp[2].p3 = iRec; |
| 103624 | aOp[3].p2 = iRec; |
| 103625 | aOp[3].p3 = memId+1; |
| 103626 | aOp[3].p5 = OPFLAG_APPEND; |
| 103627 | sqlite3ReleaseTempReg(pParse, iRec); |
| 103628 | } |
| 103629 | } |
| 103630 | SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ |
| 103631 | if( pParse->pAinc ) autoIncrementEnd(pParse); |
| 103632 | } |
| 103633 | #else |
| 103634 | /* |
| 103635 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines |
| 103636 | ** above are all no-ops |
| @@ -103647,11 +103958,11 @@ | |
| 103958 | dest.iSdst = bIdListInOrder ? regData : 0; |
| 103959 | dest.nSdst = pTab->nCol; |
| 103960 | rc = sqlite3Select(pParse, pSelect, &dest); |
| 103961 | regFromSelect = dest.iSdst; |
| 103962 | if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; |
| 103963 | sqlite3VdbeEndCoroutine(v, regYield); |
| 103964 | sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ |
| 103965 | assert( pSelect->pEList ); |
| 103966 | nColumn = pSelect->pEList->nExpr; |
| 103967 | |
| 103968 | /* Set useTempTable to TRUE if the result of the SELECT statement |
| @@ -103749,11 +104060,11 @@ | |
| 104060 | /* If this is not a view, open the table and and all indices */ |
| 104061 | if( !isView ){ |
| 104062 | int nIdx; |
| 104063 | nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, |
| 104064 | &iDataCur, &iIdxCur); |
| 104065 | aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); |
| 104066 | if( aRegIdx==0 ){ |
| 104067 | goto insert_cleanup; |
| 104068 | } |
| 104069 | for(i=0; i<nIdx; i++){ |
| 104070 | aRegIdx[i] = ++pParse->nMem; |
| @@ -104634,11 +104945,11 @@ | |
| 104945 | */ |
| 104946 | SQLITE_PRIVATE int sqlite3OpenTableAndIndices( |
| 104947 | Parse *pParse, /* Parsing context */ |
| 104948 | Table *pTab, /* Table to be opened */ |
| 104949 | int op, /* OP_OpenRead or OP_OpenWrite */ |
| 104950 | u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ |
| 104951 | int iBase, /* Use this for the table cursor, if there is one */ |
| 104952 | u8 *aToOpen, /* If not NULL: boolean for each table and index */ |
| 104953 | int *piDataCur, /* Write the database source cursor number here */ |
| 104954 | int *piIdxCur /* Write the first index cursor number here */ |
| 104955 | ){ |
| @@ -104669,18 +104980,19 @@ | |
| 104980 | } |
| 104981 | if( piIdxCur ) *piIdxCur = iBase; |
| 104982 | for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ |
| 104983 | int iIdxCur = iBase++; |
| 104984 | assert( pIdx->pSchema==pTab->pSchema ); |
| 104985 | if( aToOpen==0 || aToOpen[i+1] ){ |
| 104986 | sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); |
| 104987 | sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
| 104988 | VdbeComment((v, "%s", pIdx->zName)); |
| 104989 | } |
| 104990 | if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ |
| 104991 | if( piDataCur ) *piDataCur = iIdxCur; |
| 104992 | }else{ |
| 104993 | sqlite3VdbeChangeP5(v, p5); |
| 104994 | } |
| 104995 | } |
| 104996 | if( iBase>pParse->nTab ) pParse->nTab = iBase; |
| 104997 | return i; |
| 104998 | } |
| @@ -105167,11 +105479,11 @@ | |
| 105479 | if( rc==SQLITE_ROW ){ |
| 105480 | azVals = &azCols[nCol]; |
| 105481 | for(i=0; i<nCol; i++){ |
| 105482 | azVals[i] = (char *)sqlite3_column_text(pStmt, i); |
| 105483 | if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 105484 | sqlite3OomFault(db); |
| 105485 | goto exec_out; |
| 105486 | } |
| 105487 | } |
| 105488 | } |
| 105489 | if( xCallback(pArg, nCol, azVals, azCols) ){ |
| @@ -107055,32 +107367,35 @@ | |
| 107367 | /************** End of pragma.h **********************************************/ |
| 107368 | /************** Continuing where we left off in pragma.c *********************/ |
| 107369 | |
| 107370 | /* |
| 107371 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| 107372 | ** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or |
| 107373 | ** unrecognized string argument. The FULL and EXTRA option is disallowed |
| 107374 | ** if the omitFull parameter it 1. |
| 107375 | ** |
| 107376 | ** Note that the values returned are one less that the values that |
| 107377 | ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done |
| 107378 | ** to support legacy SQL code. The safety level used to be boolean |
| 107379 | ** and older scripts may have used numbers 0 for OFF and 1 for ON. |
| 107380 | */ |
| 107381 | static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ |
| 107382 | /* 123456789 123456789 123 */ |
| 107383 | static const char zText[] = "onoffalseyestruextrafull"; |
| 107384 | static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 15, 20}; |
| 107385 | static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 5, 4}; |
| 107386 | static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 3, 2}; |
| 107387 | /* on no off false yes true extra full */ |
| 107388 | int i, n; |
| 107389 | if( sqlite3Isdigit(*z) ){ |
| 107390 | return (u8)sqlite3Atoi(z); |
| 107391 | } |
| 107392 | n = sqlite3Strlen30(z); |
| 107393 | for(i=0; i<ArraySize(iLength); i++){ |
| 107394 | if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 |
| 107395 | && (!omitFull || iValue[i]<=1) |
| 107396 | ){ |
| 107397 | return iValue[i]; |
| 107398 | } |
| 107399 | } |
| 107400 | return dflt; |
| 107401 | } |
| @@ -107467,12 +107782,11 @@ | |
| 107782 | aOp[1].p1 = iDb; |
| 107783 | aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE; |
| 107784 | }else{ |
| 107785 | int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); |
| 107786 | sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 107787 | sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, size); |
| 107788 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 107789 | pDb->pSchema->cache_size = size; |
| 107790 | sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
| 107791 | } |
| 107792 | break; |
| @@ -107499,11 +107813,11 @@ | |
| 107813 | /* Malloc may fail when setting the page-size, as there is an internal |
| 107814 | ** buffer that the pager module resizes using sqlite3_realloc(). |
| 107815 | */ |
| 107816 | db->nextPagesize = sqlite3Atoi(zRight); |
| 107817 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ |
| 107818 | sqlite3OomFault(db); |
| 107819 | } |
| 107820 | } |
| 107821 | break; |
| 107822 | } |
| 107823 | |
| @@ -107706,23 +108020,22 @@ | |
| 108020 | static const VdbeOpList setMeta6[] = { |
| 108021 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 108022 | { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, |
| 108023 | { OP_If, 1, 0, 0}, /* 2 */ |
| 108024 | { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ |
| 108025 | { OP_SetCookie, 0, BTREE_INCR_VACUUM, 0}, /* 4 */ |
| 108026 | }; |
| 108027 | VdbeOp *aOp; |
| 108028 | int iAddr = sqlite3VdbeCurrentAddr(v); |
| 108029 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setMeta6)); |
| 108030 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); |
| 108031 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 108032 | aOp[0].p1 = iDb; |
| 108033 | aOp[1].p1 = iDb; |
| 108034 | aOp[2].p2 = iAddr+4; |
| 108035 | aOp[4].p1 = iDb; |
| 108036 | aOp[4].p3 = eAuto - 1; |
| 108037 | sqlite3VdbeUsesBtree(v, iDb); |
| 108038 | } |
| 108039 | } |
| 108040 | break; |
| 108041 | } |
| @@ -107997,11 +108310,11 @@ | |
| 108310 | } |
| 108311 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 108312 | |
| 108313 | /* |
| 108314 | ** PRAGMA [schema.]synchronous |
| 108315 | ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA |
| 108316 | ** |
| 108317 | ** Return or set the local value of the synchronous flag. Changing |
| 108318 | ** the local value does not make changes to the disk file and the |
| 108319 | ** default value will be restored the next time the database is |
| 108320 | ** opened. |
| @@ -108624,20 +108937,19 @@ | |
| 108937 | } |
| 108938 | { |
| 108939 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 108940 | static const VdbeOpList endCode[] = { |
| 108941 | { OP_AddImm, 1, 0, 0}, /* 0 */ |
| 108942 | { OP_If, 1, 4, 0}, /* 1 */ |
| 108943 | { OP_String8, 0, 3, 0}, /* 2 */ |
| 108944 | { OP_ResultRow, 3, 1, 0}, /* 3 */ |
| 108945 | }; |
| 108946 | VdbeOp *aOp; |
| 108947 | |
| 108948 | aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
| 108949 | if( aOp ){ |
| 108950 | aOp[0].p2 = -mxErr; |
| 108951 | aOp[2].p4type = P4_STATIC; |
| 108952 | aOp[2].p4.z = "ok"; |
| 108953 | } |
| 108954 | } |
| 108955 | } |
| @@ -108751,21 +109063,20 @@ | |
| 109063 | sqlite3VdbeUsesBtree(v, iDb); |
| 109064 | if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ |
| 109065 | /* Write the specified cookie value */ |
| 109066 | static const VdbeOpList setCookie[] = { |
| 109067 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 109068 | { OP_SetCookie, 0, 0, 0}, /* 1 */ |
| 109069 | }; |
| 109070 | VdbeOp *aOp; |
| 109071 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); |
| 109072 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); |
| 109073 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 109074 | aOp[0].p1 = iDb; |
| 109075 | aOp[1].p1 = iDb; |
| 109076 | aOp[1].p2 = iCookie; |
| 109077 | aOp[1].p3 = sqlite3Atoi(zRight); |
| 109078 | }else{ |
| 109079 | /* Read the specified cookie value */ |
| 109080 | static const VdbeOpList readCookie[] = { |
| 109081 | { OP_Transaction, 0, 0, 0}, /* 0 */ |
| 109082 | { OP_ReadCookie, 0, 1, 0}, /* 1 */ |
| @@ -109033,15 +109344,14 @@ | |
| 109344 | ){ |
| 109345 | sqlite3 *db = pData->db; |
| 109346 | if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ |
| 109347 | char *z; |
| 109348 | if( zObj==0 ) zObj = "?"; |
| 109349 | z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); |
| 109350 | if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); |
| 109351 | sqlite3DbFree(db, *pData->pzErrMsg); |
| 109352 | *pData->pzErrMsg = z; |
| 109353 | } |
| 109354 | pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; |
| 109355 | } |
| 109356 | |
| 109357 | /* |
| @@ -109096,11 +109406,11 @@ | |
| 109406 | if( db->init.orphanTrigger ){ |
| 109407 | assert( iDb==1 ); |
| 109408 | }else{ |
| 109409 | pData->rc = rc; |
| 109410 | if( rc==SQLITE_NOMEM ){ |
| 109411 | sqlite3OomFault(db); |
| 109412 | }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ |
| 109413 | corruptSchema(pData, argv[0], sqlite3_errmsg(db)); |
| 109414 | } |
| 109415 | } |
| 109416 | } |
| @@ -109341,11 +109651,11 @@ | |
| 109651 | } |
| 109652 | sqlite3BtreeLeave(pDb->pBt); |
| 109653 | |
| 109654 | error_out: |
| 109655 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109656 | sqlite3OomFault(db); |
| 109657 | } |
| 109658 | return rc; |
| 109659 | } |
| 109660 | |
| 109661 | /* |
| @@ -109439,11 +109749,11 @@ | |
| 109749 | ** on the b-tree database, open one now. If a transaction is opened, it |
| 109750 | ** will be closed immediately after reading the meta-value. */ |
| 109751 | if( !sqlite3BtreeIsInReadTrans(pBt) ){ |
| 109752 | rc = sqlite3BtreeBeginTrans(pBt, 0); |
| 109753 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109754 | sqlite3OomFault(db); |
| 109755 | } |
| 109756 | if( rc!=SQLITE_OK ) return; |
| 109757 | openedTransaction = 1; |
| 109758 | } |
| 109759 | |
| @@ -109502,10 +109812,15 @@ | |
| 109812 | SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ |
| 109813 | if( pParse ){ |
| 109814 | sqlite3 *db = pParse->db; |
| 109815 | sqlite3DbFree(db, pParse->aLabel); |
| 109816 | sqlite3ExprListDelete(db, pParse->pConstExpr); |
| 109817 | if( db ){ |
| 109818 | assert( db->lookaside.bDisable >= pParse->disableLookaside ); |
| 109819 | db->lookaside.bDisable -= pParse->disableLookaside; |
| 109820 | } |
| 109821 | pParse->disableLookaside = 0; |
| 109822 | } |
| 109823 | } |
| 109824 | |
| 109825 | /* |
| 109826 | ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. |
| @@ -109530,11 +109845,11 @@ | |
| 109845 | rc = SQLITE_NOMEM; |
| 109846 | goto end_prepare; |
| 109847 | } |
| 109848 | pParse->pReprepare = pReprepare; |
| 109849 | assert( ppStmt && *ppStmt==0 ); |
| 109850 | /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ |
| 109851 | assert( sqlite3_mutex_held(db->mutex) ); |
| 109852 | |
| 109853 | /* Check to verify that it is possible to get a read lock on all |
| 109854 | ** database schemas. The inability to get a read lock indicates that |
| 109855 | ** some other database connection is holding a write-lock, which in |
| @@ -109587,23 +109902,20 @@ | |
| 109902 | goto end_prepare; |
| 109903 | } |
| 109904 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 109905 | if( zSqlCopy ){ |
| 109906 | sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); |
| 109907 | pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; |
| 109908 | sqlite3DbFree(db, zSqlCopy); |
| 109909 | }else{ |
| 109910 | pParse->zTail = &zSql[nBytes]; |
| 109911 | } |
| 109912 | }else{ |
| 109913 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 109914 | } |
| 109915 | assert( 0==pParse->nQueryLoop ); |
| 109916 | |
| 109917 | if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; |
| 109918 | if( pParse->checkSchema ){ |
| 109919 | schemaIsValid(pParse); |
| 109920 | } |
| 109921 | if( db->mallocFailed ){ |
| @@ -109721,11 +110033,11 @@ | |
| 110033 | db = sqlite3VdbeDb(p); |
| 110034 | assert( sqlite3_mutex_held(db->mutex) ); |
| 110035 | rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0); |
| 110036 | if( rc ){ |
| 110037 | if( rc==SQLITE_NOMEM ){ |
| 110038 | sqlite3OomFault(db); |
| 110039 | } |
| 110040 | assert( pNew==0 ); |
| 110041 | return rc; |
| 110042 | }else{ |
| 110043 | assert( pNew!=0 ); |
| @@ -109975,11 +110287,11 @@ | |
| 110287 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 110288 | ){ |
| 110289 | Select *pNew; |
| 110290 | Select standin; |
| 110291 | sqlite3 *db = pParse->db; |
| 110292 | pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); |
| 110293 | if( pNew==0 ){ |
| 110294 | assert( db->mallocFailed ); |
| 110295 | pNew = &standin; |
| 110296 | } |
| 110297 | if( pEList==0 ){ |
| @@ -110879,11 +111191,11 @@ | |
| 111191 | p->enc = ENC(db); |
| 111192 | p->db = db; |
| 111193 | p->nRef = 1; |
| 111194 | memset(&p[1], 0, nExtra); |
| 111195 | }else{ |
| 111196 | sqlite3OomFault(db); |
| 111197 | } |
| 111198 | return p; |
| 111199 | } |
| 111200 | |
| 111201 | /* |
| @@ -111540,11 +111852,11 @@ | |
| 111852 | if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); |
| 111853 | } |
| 111854 | pCol->zName = zName; |
| 111855 | sqlite3ColumnPropertiesFromName(0, pCol); |
| 111856 | if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ |
| 111857 | sqlite3OomFault(db); |
| 111858 | } |
| 111859 | } |
| 111860 | sqlite3HashClear(&ht); |
| 111861 | if( db->mallocFailed ){ |
| 111862 | for(j=0; j<i; j++){ |
| @@ -111627,11 +111939,11 @@ | |
| 111939 | if( pTab==0 ){ |
| 111940 | return 0; |
| 111941 | } |
| 111942 | /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside |
| 111943 | ** is disabled */ |
| 111944 | assert( db->lookaside.bDisable ); |
| 111945 | pTab->nRef = 1; |
| 111946 | pTab->zName = 0; |
| 111947 | pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 111948 | sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
| 111949 | selectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
| @@ -111723,14 +112035,12 @@ | |
| 112035 | p->iOffset = iOffset = ++pParse->nMem; |
| 112036 | pParse->nMem++; /* Allocate an extra register for limit+offset */ |
| 112037 | sqlite3ExprCode(pParse, p->pOffset, iOffset); |
| 112038 | sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); |
| 112039 | VdbeComment((v, "OFFSET counter")); |
| 112040 | sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); |
| 112041 | VdbeComment((v, "LIMIT+OFFSET")); |
| 112042 | } |
| 112043 | } |
| 112044 | } |
| 112045 | |
| 112046 | #ifndef SQLITE_OMIT_COMPOUND_SELECT |
| @@ -112143,13 +112453,12 @@ | |
| 112453 | p->iOffset = pPrior->iOffset; |
| 112454 | if( p->iLimit ){ |
| 112455 | addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); |
| 112456 | VdbeComment((v, "Jump ahead if LIMIT reached")); |
| 112457 | if( p->iOffset ){ |
| 112458 | sqlite3VdbeAddOp3(v, OP_OffsetLimit, |
| 112459 | p->iLimit, p->iOffset+1, p->iOffset); |
| 112460 | } |
| 112461 | } |
| 112462 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 112463 | rc = sqlite3Select(pParse, p, &dest); |
| 112464 | testcase( rc!=SQLITE_OK ); |
| @@ -112736,14 +113045,15 @@ | |
| 113045 | ** row of results comes from selectA or selectB. Also add explicit |
| 113046 | ** collations to the ORDER BY clause terms so that when the subqueries |
| 113047 | ** to the right and the left are evaluated, they use the correct |
| 113048 | ** collation. |
| 113049 | */ |
| 113050 | aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1)); |
| 113051 | if( aPermute ){ |
| 113052 | struct ExprList_item *pItem; |
| 113053 | aPermute[0] = nOrderBy; |
| 113054 | for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ |
| 113055 | assert( pItem->u.x.iOrderByCol>0 ); |
| 113056 | assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
| 113057 | aPermute[i] = pItem->u.x.iOrderByCol - 1; |
| 113058 | } |
| 113059 | pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); |
| @@ -112817,11 +113127,11 @@ | |
| 113127 | addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
| 113128 | VdbeComment((v, "left SELECT")); |
| 113129 | pPrior->iLimit = regLimitA; |
| 113130 | explainSetInteger(iSub1, pParse->iNextSelectId); |
| 113131 | sqlite3Select(pParse, pPrior, &destA); |
| 113132 | sqlite3VdbeEndCoroutine(v, regAddrA); |
| 113133 | sqlite3VdbeJumpHere(v, addr1); |
| 113134 | |
| 113135 | /* Generate a coroutine to evaluate the SELECT statement on |
| 113136 | ** the right - the "B" select |
| 113137 | */ |
| @@ -112834,11 +113144,11 @@ | |
| 113144 | p->iOffset = 0; |
| 113145 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 113146 | sqlite3Select(pParse, p, &destB); |
| 113147 | p->iLimit = savedLimit; |
| 113148 | p->iOffset = savedOffset; |
| 113149 | sqlite3VdbeEndCoroutine(v, regAddrB); |
| 113150 | |
| 113151 | /* Generate a subroutine that outputs the current row of the A |
| 113152 | ** select as the next output row of the compound select. |
| 113153 | */ |
| 113154 | VdbeNoopComment((v, "Output routine for A")); |
| @@ -114301,12 +114611,11 @@ | |
| 114611 | } |
| 114612 | }else{ |
| 114613 | pExpr = pRight; |
| 114614 | } |
| 114615 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 114616 | sqlite3TokenInit(&sColname, zColname); |
| 114617 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 114618 | if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ |
| 114619 | struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; |
| 114620 | if( pSub ){ |
| 114621 | pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); |
| @@ -114856,11 +115165,11 @@ | |
| 115165 | explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
| 115166 | sqlite3Select(pParse, pSub, &dest); |
| 115167 | pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); |
| 115168 | pItem->fg.viaCoroutine = 1; |
| 115169 | pItem->regResult = dest.iSdst; |
| 115170 | sqlite3VdbeEndCoroutine(v, pItem->regReturn); |
| 115171 | sqlite3VdbeJumpHere(v, addrTop-1); |
| 115172 | sqlite3ClearTempRegCache(pParse); |
| 115173 | }else{ |
| 115174 | /* Generate a subroutine that will fill an ephemeral table with |
| 115175 | ** the content of this subquery. pItem->addrFillSub will point |
| @@ -115428,11 +115737,12 @@ | |
| 115737 | assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); |
| 115738 | |
| 115739 | if( flag ){ |
| 115740 | pMinMax = sqlite3ExprListDup(db, pMinMax, 0); |
| 115741 | pDel = pMinMax; |
| 115742 | assert( db->mallocFailed || pMinMax!=0 ); |
| 115743 | if( !db->mallocFailed ){ |
| 115744 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 115745 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 115746 | } |
| 115747 | } |
| 115748 | |
| @@ -116001,12 +116311,11 @@ | |
| 116311 | pTrig->step_list = pStepList; |
| 116312 | while( pStepList ){ |
| 116313 | pStepList->pTrig = pTrig; |
| 116314 | pStepList = pStepList->pNext; |
| 116315 | } |
| 116316 | sqlite3TokenInit(&nameToken, pTrig->zName); |
| 116317 | sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
| 116318 | if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) |
| 116319 | || sqlite3FixExpr(&sFix, pTrig->pWhen) |
| 116320 | ){ |
| 116321 | goto triggerfinish_cleanup; |
| @@ -116038,11 +116347,11 @@ | |
| 116347 | Trigger *pLink = pTrig; |
| 116348 | Hash *pHash = &db->aDb[iDb].pSchema->trigHash; |
| 116349 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 116350 | pTrig = sqlite3HashInsert(pHash, zName, pTrig); |
| 116351 | if( pTrig ){ |
| 116352 | sqlite3OomFault(db); |
| 116353 | }else if( pLink->pSchema==pLink->pTabSchema ){ |
| 116354 | Table *pTab; |
| 116355 | pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); |
| 116356 | assert( pTab!=0 ); |
| 116357 | pLink->pNext = pTab->pTrigger; |
| @@ -117014,11 +117323,11 @@ | |
| 117323 | } |
| 117324 | |
| 117325 | /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. |
| 117326 | ** Initialize aXRef[] and aToOpen[] to their default values. |
| 117327 | */ |
| 117328 | aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); |
| 117329 | if( aXRef==0 ) goto update_cleanup; |
| 117330 | aRegIdx = aXRef+pTab->nCol; |
| 117331 | aToOpen = (u8*)(aRegIdx+nIdx); |
| 117332 | memset(aToOpen, 1, nIdx+1); |
| 117333 | aToOpen[nIdx+1] = 0; |
| @@ -118054,11 +118363,11 @@ | |
| 118363 | nName = sqlite3Strlen30(zName); |
| 118364 | if( sqlite3HashFind(&db->aModule, zName) ){ |
| 118365 | rc = SQLITE_MISUSE_BKPT; |
| 118366 | }else{ |
| 118367 | Module *pMod; |
| 118368 | pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); |
| 118369 | if( pMod ){ |
| 118370 | Module *pDel; |
| 118371 | char *zCopy = (char *)(&pMod[1]); |
| 118372 | memcpy(zCopy, zName, nName+1); |
| 118373 | pMod->zName = zCopy; |
| @@ -118067,11 +118376,11 @@ | |
| 118376 | pMod->xDestroy = xDestroy; |
| 118377 | pMod->pEpoTab = 0; |
| 118378 | pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); |
| 118379 | assert( pDel==0 || pDel==pMod ); |
| 118380 | if( pDel ){ |
| 118381 | sqlite3OomFault(db); |
| 118382 | sqlite3DbFree(db, pDel); |
| 118383 | } |
| 118384 | } |
| 118385 | } |
| 118386 | rc = sqlite3ApiExit(db, rc); |
| @@ -118444,11 +118753,11 @@ | |
| 118753 | Schema *pSchema = pTab->pSchema; |
| 118754 | const char *zName = pTab->zName; |
| 118755 | assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); |
| 118756 | pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); |
| 118757 | if( pOld ){ |
| 118758 | sqlite3OomFault(db); |
| 118759 | assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 118760 | return; |
| 118761 | } |
| 118762 | pParse->pNewTable = 0; |
| 118763 | } |
| @@ -118535,11 +118844,11 @@ | |
| 118844 | sCtx.pPrior = db->pVtabCtx; |
| 118845 | sCtx.bDeclared = 0; |
| 118846 | db->pVtabCtx = &sCtx; |
| 118847 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 118848 | db->pVtabCtx = sCtx.pPrior; |
| 118849 | if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
| 118850 | assert( sCtx.pTab==pTab ); |
| 118851 | |
| 118852 | if( SQLITE_OK!=rc ){ |
| 118853 | if( zErr==0 ){ |
| 118854 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| @@ -119093,11 +119402,11 @@ | |
| 119402 | apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); |
| 119403 | if( apVtabLock ){ |
| 119404 | pToplevel->apVtabLock = apVtabLock; |
| 119405 | pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; |
| 119406 | }else{ |
| 119407 | sqlite3OomFault(pToplevel->db); |
| 119408 | } |
| 119409 | } |
| 119410 | |
| 119411 | /* |
| 119412 | ** Check to see if virtual tale module pMod can be have an eponymous |
| @@ -119835,11 +120144,11 @@ | |
| 120144 | if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; |
| 120145 | sqlite3StrAccumAppend(pStr, " (", 2); |
| 120146 | for(i=0; i<nEq; i++){ |
| 120147 | const char *z = explainIndexColumnName(pIndex, i); |
| 120148 | if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5); |
| 120149 | sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); |
| 120150 | } |
| 120151 | |
| 120152 | j = i; |
| 120153 | if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ |
| 120154 | const char *z = explainIndexColumnName(pIndex, i); |
| @@ -119894,17 +120203,17 @@ | |
| 120203 | || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); |
| 120204 | |
| 120205 | sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); |
| 120206 | sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); |
| 120207 | if( pItem->pSelect ){ |
| 120208 | sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); |
| 120209 | }else{ |
| 120210 | sqlite3XPrintf(&str, " TABLE %s", pItem->zName); |
| 120211 | } |
| 120212 | |
| 120213 | if( pItem->zAlias ){ |
| 120214 | sqlite3XPrintf(&str, " AS %s", pItem->zAlias); |
| 120215 | } |
| 120216 | if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ |
| 120217 | const char *zFmt = 0; |
| 120218 | Index *pIdx; |
| 120219 | |
| @@ -119924,11 +120233,11 @@ | |
| 120233 | }else{ |
| 120234 | zFmt = "INDEX %s"; |
| 120235 | } |
| 120236 | if( zFmt ){ |
| 120237 | sqlite3StrAccumAppend(&str, " USING ", 7); |
| 120238 | sqlite3XPrintf(&str, zFmt, pIdx->zName); |
| 120239 | explainIndexRange(&str, pLoop); |
| 120240 | } |
| 120241 | }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ |
| 120242 | const char *zRangeOp; |
| 120243 | if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ |
| @@ -119939,21 +120248,21 @@ | |
| 120248 | zRangeOp = ">"; |
| 120249 | }else{ |
| 120250 | assert( flags&WHERE_TOP_LIMIT); |
| 120251 | zRangeOp = "<"; |
| 120252 | } |
| 120253 | sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); |
| 120254 | } |
| 120255 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 120256 | else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ |
| 120257 | sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", |
| 120258 | pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); |
| 120259 | } |
| 120260 | #endif |
| 120261 | #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS |
| 120262 | if( pLoop->nOut>=10 ){ |
| 120263 | sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); |
| 120264 | }else{ |
| 120265 | sqlite3StrAccumAppend(&str, " (~1 row)", 9); |
| 120266 | } |
| 120267 | #endif |
| 120268 | zMsg = sqlite3StrAccumFinish(&str); |
| @@ -120254,13 +120563,11 @@ | |
| 120563 | regBase = pParse->nMem + 1; |
| 120564 | nReg = pLoop->u.btree.nEq + nExtraReg; |
| 120565 | pParse->nMem += nReg; |
| 120566 | |
| 120567 | zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); |
| 120568 | assert( zAff!=0 || pParse->db->mallocFailed ); |
| 120569 | |
| 120570 | if( nSkip ){ |
| 120571 | int iIdxCur = pLevel->iIdxCur; |
| 120572 | sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); |
| 120573 | VdbeCoverageIf(v, bRev==0); |
| @@ -120504,10 +120811,58 @@ | |
| 120811 | } |
| 120812 | } |
| 120813 | #else |
| 120814 | # define codeCursorHint(A,B,C) /* No-op */ |
| 120815 | #endif /* SQLITE_ENABLE_CURSOR_HINTS */ |
| 120816 | |
| 120817 | /* |
| 120818 | ** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains |
| 120819 | ** a rowid value just read from cursor iIdxCur, open on index pIdx. This |
| 120820 | ** function generates code to do a deferred seek of cursor iCur to the |
| 120821 | ** rowid stored in register iRowid. |
| 120822 | ** |
| 120823 | ** Normally, this is just: |
| 120824 | ** |
| 120825 | ** OP_Seek $iCur $iRowid |
| 120826 | ** |
| 120827 | ** However, if the scan currently being coded is a branch of an OR-loop and |
| 120828 | ** the statement currently being coded is a SELECT, then P3 of the OP_Seek |
| 120829 | ** is set to iIdxCur and P4 is set to point to an array of integers |
| 120830 | ** containing one entry for each column of the table cursor iCur is open |
| 120831 | ** on. For each table column, if the column is the i'th column of the |
| 120832 | ** index, then the corresponding array entry is set to (i+1). If the column |
| 120833 | ** does not appear in the index at all, the array entry is set to 0. |
| 120834 | */ |
| 120835 | static void codeDeferredSeek( |
| 120836 | WhereInfo *pWInfo, /* Where clause context */ |
| 120837 | Index *pIdx, /* Index scan is using */ |
| 120838 | int iCur, /* Cursor for IPK b-tree */ |
| 120839 | int iIdxCur /* Index cursor */ |
| 120840 | ){ |
| 120841 | Parse *pParse = pWInfo->pParse; /* Parse context */ |
| 120842 | Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ |
| 120843 | |
| 120844 | assert( iIdxCur>0 ); |
| 120845 | assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); |
| 120846 | |
| 120847 | sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur); |
| 120848 | if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE) |
| 120849 | && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) |
| 120850 | ){ |
| 120851 | int i; |
| 120852 | Table *pTab = pIdx->pTable; |
| 120853 | int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1)); |
| 120854 | if( ai ){ |
| 120855 | ai[0] = pTab->nCol; |
| 120856 | for(i=0; i<pIdx->nColumn-1; i++){ |
| 120857 | assert( pIdx->aiColumn[i]<pTab->nCol ); |
| 120858 | if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1; |
| 120859 | } |
| 120860 | sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); |
| 120861 | } |
| 120862 | } |
| 120863 | } |
| 120864 | |
| 120865 | /* |
| 120866 | ** Generate code for the start of the iLevel-th loop in the WHERE clause |
| 120867 | ** implementation described by pWInfo. |
| 120868 | */ |
| @@ -120984,18 +121339,18 @@ | |
| 121339 | disableTerm(pLevel, pRangeStart); |
| 121340 | disableTerm(pLevel, pRangeEnd); |
| 121341 | if( omitTable ){ |
| 121342 | /* pIdx is a covering index. No need to access the main table. */ |
| 121343 | }else if( HasRowid(pIdx->pTable) ){ |
| 121344 | if( pWInfo->eOnePass!=ONEPASS_OFF ){ |
| 121345 | iRowidReg = ++pParse->nMem; |
| 121346 | sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); |
| 121347 | sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); |
| 121348 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); |
| 121349 | VdbeCoverage(v); |
| 121350 | }else{ |
| 121351 | codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); |
| 121352 | } |
| 121353 | }else if( iCur!=iIdxCur ){ |
| 121354 | Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); |
| 121355 | iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); |
| 121356 | for(j=0; j<pPk->nKeyCol; j++){ |
| @@ -121160,11 +121515,13 @@ | |
| 121515 | int iTerm; |
| 121516 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 121517 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 121518 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 121519 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 121520 | testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); |
| 121521 | testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); |
| 121522 | if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; |
| 121523 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 121524 | testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); |
| 121525 | pExpr = sqlite3ExprDup(db, pExpr, 0); |
| 121526 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
| 121527 | } |
| @@ -121500,11 +121857,11 @@ | |
| 121857 | int idx; |
| 121858 | testcase( wtFlags & TERM_VIRTUAL ); |
| 121859 | if( pWC->nTerm>=pWC->nSlot ){ |
| 121860 | WhereTerm *pOld = pWC->a; |
| 121861 | sqlite3 *db = pWC->pWInfo->pParse->db; |
| 121862 | pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); |
| 121863 | if( pWC->a==0 ){ |
| 121864 | if( wtFlags & TERM_DYNAMIC ){ |
| 121865 | sqlite3ExprDelete(db, p); |
| 121866 | } |
| 121867 | pWC->a = pOld; |
| @@ -121985,11 +122342,11 @@ | |
| 122342 | for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ |
| 122343 | if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ |
| 122344 | WhereAndInfo *pAndInfo; |
| 122345 | assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); |
| 122346 | chngToIN = 0; |
| 122347 | pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo)); |
| 122348 | if( pAndInfo ){ |
| 122349 | WhereClause *pAndWC; |
| 122350 | WhereTerm *pAndTerm; |
| 122351 | int j; |
| 122352 | Bitmask b = 0; |
| @@ -121999,11 +122356,10 @@ | |
| 122356 | pAndWC = &pAndInfo->wc; |
| 122357 | sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); |
| 122358 | sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); |
| 122359 | sqlite3WhereExprAnalyze(pSrc, pAndWC); |
| 122360 | pAndWC->pOuter = pWC; |
| 122361 | if( !db->mallocFailed ){ |
| 122362 | for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ |
| 122363 | assert( pAndTerm->pExpr ); |
| 122364 | if( allowedOp(pAndTerm->pExpr->op) ){ |
| 122365 | b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); |
| @@ -123742,11 +124098,11 @@ | |
| 124098 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 124099 | TRACE_IDX_OUTPUTS(p); |
| 124100 | |
| 124101 | if( rc!=SQLITE_OK ){ |
| 124102 | if( rc==SQLITE_NOMEM ){ |
| 124103 | sqlite3OomFault(pParse->db); |
| 124104 | }else if( !pVtab->zErrMsg ){ |
| 124105 | sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); |
| 124106 | }else{ |
| 124107 | sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); |
| 124108 | } |
| @@ -124534,11 +124890,11 @@ | |
| 124890 | */ |
| 124891 | static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ |
| 124892 | WhereTerm **paNew; |
| 124893 | if( p->nLSlot>=n ) return SQLITE_OK; |
| 124894 | n = (n+7)&~7; |
| 124895 | paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); |
| 124896 | if( paNew==0 ) return SQLITE_NOMEM; |
| 124897 | memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); |
| 124898 | if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm); |
| 124899 | p->aLTerm = paNew; |
| 124900 | p->nLSlot = n; |
| @@ -124831,11 +125187,11 @@ | |
| 125187 | whereLoopPrint(pTemplate, pBuilder->pWC); |
| 125188 | } |
| 125189 | #endif |
| 125190 | if( p==0 ){ |
| 125191 | /* Allocate a new WhereLoop to add to the end of the list */ |
| 125192 | *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); |
| 125193 | if( p==0 ) return SQLITE_NOMEM; |
| 125194 | whereLoopInit(p); |
| 125195 | p->pNextLoop = 0; |
| 125196 | }else{ |
| 125197 | /* We will be overwriting WhereLoop p[]. But before we do, first |
| @@ -126328,11 +126684,11 @@ | |
| 126684 | } |
| 126685 | |
| 126686 | /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ |
| 126687 | nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; |
| 126688 | nSpace += sizeof(LogEst) * nOrderBy; |
| 126689 | pSpace = sqlite3DbMallocRawNN(db, nSpace); |
| 126690 | if( pSpace==0 ) return SQLITE_NOMEM; |
| 126691 | aTo = (WherePath*)pSpace; |
| 126692 | aFrom = aTo+mxChoice; |
| 126693 | memset(aFrom, 0, sizeof(aFrom[0])); |
| 126694 | pX = (WhereLoop**)(aFrom+mxChoice); |
| @@ -126813,11 +127169,11 @@ | |
| 127169 | WhereLevel *pLevel; /* A single level in pWInfo->a[] */ |
| 127170 | WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ |
| 127171 | int ii; /* Loop counter */ |
| 127172 | sqlite3 *db; /* Database connection */ |
| 127173 | int rc; /* Return code */ |
| 127174 | u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */ |
| 127175 | |
| 127176 | assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( |
| 127177 | (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 |
| 127178 | && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 |
| 127179 | )); |
| @@ -127058,20 +127414,19 @@ | |
| 127414 | WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); |
| 127415 | pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; |
| 127416 | |
| 127417 | /* If the caller is an UPDATE or DELETE statement that is requesting |
| 127418 | ** to use a one-pass algorithm, determine if this is appropriate. |
| 127419 | */ |
| 127420 | assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); |
| 127421 | if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ |
| 127422 | int wsFlags = pWInfo->a[0].pWLoop->wsFlags; |
| 127423 | int bOnerow = (wsFlags & WHERE_ONEROW)!=0; |
| 127424 | if( bOnerow |
| 127425 | || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0 |
| 127426 | && 0==(wsFlags & WHERE_VIRTUALTABLE)) |
| 127427 | ){ |
| 127428 | pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; |
| 127429 | if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ |
| 127430 | if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ |
| 127431 | bFordelete = OPFLAG_FORDELETE; |
| 127432 | } |
| @@ -127511,10 +127866,19 @@ | |
| 127866 | /* |
| 127867 | ** An instance of this structure holds the ATTACH key and the key type. |
| 127868 | */ |
| 127869 | struct AttachKey { int type; Token key; }; |
| 127870 | |
| 127871 | /* |
| 127872 | ** Disable lookaside memory allocation for objects that might be |
| 127873 | ** shared across database connections. |
| 127874 | */ |
| 127875 | static void disableLookaside(Parse *pParse){ |
| 127876 | pParse->disableLookaside++; |
| 127877 | pParse->db->lookaside.bDisable++; |
| 127878 | } |
| 127879 | |
| 127880 | |
| 127881 | /* |
| 127882 | ** For a compound SELECT statement, make sure p->pPrior->pNext==p for |
| 127883 | ** all elements in the list. And make sure list length does not exceed |
| 127884 | ** SQLITE_LIMIT_COMPOUND_SELECT. |
| @@ -127593,11 +127957,11 @@ | |
| 127957 | |
| 127958 | /* A routine to convert a binary TK_IS or TK_ISNOT expression into a |
| 127959 | ** unary TK_ISNULL or TK_NOTNULL expression. */ |
| 127960 | static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ |
| 127961 | sqlite3 *db = pParse->db; |
| 127962 | if( pA && pY && pY->op==TK_NULL ){ |
| 127963 | pA->op = (u8)op; |
| 127964 | sqlite3ExprDelete(db, pA->pRight); |
| 127965 | pA->pRight = 0; |
| 127966 | } |
| 127967 | } |
| @@ -129635,11 +129999,11 @@ | |
| 129999 | sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); |
| 130000 | } |
| 130001 | break; |
| 130002 | case 27: /* createkw ::= CREATE */ |
| 130003 | { |
| 130004 | disableLookaside(pParse); |
| 130005 | yygotominor.yy0 = yymsp[0].minor.yy0; |
| 130006 | } |
| 130007 | break; |
| 130008 | case 28: /* ifnotexists ::= */ |
| 130009 | case 31: /* temp ::= */ yytestcase(yyruleno==31); |
| @@ -130717,11 +131081,11 @@ | |
| 131081 | sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); |
| 131082 | } |
| 131083 | break; |
| 131084 | case 307: /* add_column_fullname ::= fullname */ |
| 131085 | { |
| 131086 | disableLookaside(pParse); |
| 131087 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); |
| 131088 | } |
| 131089 | break; |
| 131090 | case 310: /* cmd ::= create_vtab */ |
| 131091 | {sqlite3VtabFinishParse(pParse,0);} |
| @@ -131097,16 +131461,96 @@ | |
| 131461 | ** parser for analysis. |
| 131462 | */ |
| 131463 | /* #include "sqliteInt.h" */ |
| 131464 | /* #include <stdlib.h> */ |
| 131465 | |
| 131466 | /* Character classes for tokenizing |
| 131467 | ** |
| 131468 | ** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented |
| 131469 | ** using a lookup table, whereas a switch() directly on c uses a binary search. |
| 131470 | ** The lookup table is much faster. To maximize speed, and to ensure that |
| 131471 | ** a lookup table is used, all of the classes need to be small integers and |
| 131472 | ** all of them need to be used within the switch. |
| 131473 | */ |
| 131474 | #define CC_X 0 /* The letter 'x', or start of BLOB literal */ |
| 131475 | #define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */ |
| 131476 | #define CC_ID 2 /* unicode characters usable in IDs */ |
| 131477 | #define CC_DIGIT 3 /* Digits */ |
| 131478 | #define CC_DOLLAR 4 /* '$' */ |
| 131479 | #define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */ |
| 131480 | #define CC_VARNUM 6 /* '?'. Numeric SQL variables */ |
| 131481 | #define CC_SPACE 7 /* Space characters */ |
| 131482 | #define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */ |
| 131483 | #define CC_QUOTE2 9 /* '['. [...] style quoted ids */ |
| 131484 | #define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */ |
| 131485 | #define CC_MINUS 11 /* '-'. Minus or SQL-style comment */ |
| 131486 | #define CC_LT 12 /* '<'. Part of < or <= or <> */ |
| 131487 | #define CC_GT 13 /* '>'. Part of > or >= */ |
| 131488 | #define CC_EQ 14 /* '='. Part of = or == */ |
| 131489 | #define CC_BANG 15 /* '!'. Part of != */ |
| 131490 | #define CC_SLASH 16 /* '/'. / or c-style comment */ |
| 131491 | #define CC_LP 17 /* '(' */ |
| 131492 | #define CC_RP 18 /* ')' */ |
| 131493 | #define CC_SEMI 19 /* ';' */ |
| 131494 | #define CC_PLUS 20 /* '+' */ |
| 131495 | #define CC_STAR 21 /* '*' */ |
| 131496 | #define CC_PERCENT 22 /* '%' */ |
| 131497 | #define CC_COMMA 23 /* ',' */ |
| 131498 | #define CC_AND 24 /* '&' */ |
| 131499 | #define CC_TILDA 25 /* '~' */ |
| 131500 | #define CC_DOT 26 /* '.' */ |
| 131501 | #define CC_ILLEGAL 27 /* Illegal character */ |
| 131502 | |
| 131503 | static const unsigned char aiClass[] = { |
| 131504 | #ifdef SQLITE_ASCII |
| 131505 | /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ |
| 131506 | /* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, |
| 131507 | /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131508 | /* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, |
| 131509 | /* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, |
| 131510 | /* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 131511 | /* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1, |
| 131512 | /* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 131513 | /* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27, |
| 131514 | /* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131515 | /* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131516 | /* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131517 | /* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131518 | /* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131519 | /* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131520 | /* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131521 | /* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 |
| 131522 | #endif |
| 131523 | #ifdef SQLITE_EBCDIC |
| 131524 | /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ |
| 131525 | /* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27, |
| 131526 | /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131527 | /* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131528 | /* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131529 | /* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 12, 17, 20, 10, |
| 131530 | /* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27, |
| 131531 | /* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 7, |
| 131532 | /* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8, |
| 131533 | /* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131534 | /* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131535 | /* 9x */ 25, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131536 | /* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, |
| 131537 | /* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131538 | /* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131539 | /* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131540 | /* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, |
| 131541 | #endif |
| 131542 | }; |
| 131543 | |
| 131544 | /* |
| 131545 | ** The charMap() macro maps alphabetic characters (only) into their |
| 131546 | ** lower-case ASCII equivalent. On ASCII machines, this is just |
| 131547 | ** an upper-to-lower case map. On EBCDIC machines we also need |
| 131548 | ** to adjust the encoding. The mapping is only valid for alphabetics |
| 131549 | ** which are the only characters for which this feature is used. |
| 131550 | ** |
| 131551 | ** Used by keywordhash.h |
| 131552 | */ |
| 131553 | #ifdef SQLITE_ASCII |
| 131554 | # define charMap(X) sqlite3UpperToLower[(unsigned char)X] |
| 131555 | #endif |
| 131556 | #ifdef SQLITE_EBCDIC |
| @@ -131136,11 +131580,11 @@ | |
| 131580 | ** The sqlite3KeywordCode function looks up an identifier to determine if |
| 131581 | ** it is a keyword. If it is a keyword, the token code of that keyword is |
| 131582 | ** returned. If the input is not a keyword, TK_ID is returned. |
| 131583 | ** |
| 131584 | ** The implementation of this routine was generated by a program, |
| 131585 | ** mkkeywordhash.c, located in the tool subdirectory of the distribution. |
| 131586 | ** The output of the mkkeywordhash.c program is written into a file |
| 131587 | ** named keywordhash.h and then included into this source file by |
| 131588 | ** the #include below. |
| 131589 | */ |
| 131590 | /************** Include keywordhash.h in the middle of tokenize.c ************/ |
| @@ -131277,142 +131721,151 @@ | |
| 131721 | TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, |
| 131722 | TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, |
| 131723 | TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, |
| 131724 | TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, |
| 131725 | }; |
| 131726 | int i, j; |
| 131727 | const char *zKW; |
| 131728 | if( n>=2 ){ |
| 131729 | i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; |
| 131730 | for(i=((int)aHash[i])-1; i>=0; i=((int)aNext[i])-1){ |
| 131731 | if( aLen[i]!=n ) continue; |
| 131732 | j = 0; |
| 131733 | zKW = &zText[aOffset[i]]; |
| 131734 | #ifdef SQLITE_ASCII |
| 131735 | while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; } |
| 131736 | #endif |
| 131737 | #ifdef SQLITE_EBCDIC |
| 131738 | while( j<n && toupper(z[j])==zKW[j] ){ j++; } |
| 131739 | #endif |
| 131740 | if( j<n ) continue; |
| 131741 | testcase( i==0 ); /* REINDEX */ |
| 131742 | testcase( i==1 ); /* INDEXED */ |
| 131743 | testcase( i==2 ); /* INDEX */ |
| 131744 | testcase( i==3 ); /* DESC */ |
| 131745 | testcase( i==4 ); /* ESCAPE */ |
| 131746 | testcase( i==5 ); /* EACH */ |
| 131747 | testcase( i==6 ); /* CHECK */ |
| 131748 | testcase( i==7 ); /* KEY */ |
| 131749 | testcase( i==8 ); /* BEFORE */ |
| 131750 | testcase( i==9 ); /* FOREIGN */ |
| 131751 | testcase( i==10 ); /* FOR */ |
| 131752 | testcase( i==11 ); /* IGNORE */ |
| 131753 | testcase( i==12 ); /* REGEXP */ |
| 131754 | testcase( i==13 ); /* EXPLAIN */ |
| 131755 | testcase( i==14 ); /* INSTEAD */ |
| 131756 | testcase( i==15 ); /* ADD */ |
| 131757 | testcase( i==16 ); /* DATABASE */ |
| 131758 | testcase( i==17 ); /* AS */ |
| 131759 | testcase( i==18 ); /* SELECT */ |
| 131760 | testcase( i==19 ); /* TABLE */ |
| 131761 | testcase( i==20 ); /* LEFT */ |
| 131762 | testcase( i==21 ); /* THEN */ |
| 131763 | testcase( i==22 ); /* END */ |
| 131764 | testcase( i==23 ); /* DEFERRABLE */ |
| 131765 | testcase( i==24 ); /* ELSE */ |
| 131766 | testcase( i==25 ); /* EXCEPT */ |
| 131767 | testcase( i==26 ); /* TRANSACTION */ |
| 131768 | testcase( i==27 ); /* ACTION */ |
| 131769 | testcase( i==28 ); /* ON */ |
| 131770 | testcase( i==29 ); /* NATURAL */ |
| 131771 | testcase( i==30 ); /* ALTER */ |
| 131772 | testcase( i==31 ); /* RAISE */ |
| 131773 | testcase( i==32 ); /* EXCLUSIVE */ |
| 131774 | testcase( i==33 ); /* EXISTS */ |
| 131775 | testcase( i==34 ); /* SAVEPOINT */ |
| 131776 | testcase( i==35 ); /* INTERSECT */ |
| 131777 | testcase( i==36 ); /* TRIGGER */ |
| 131778 | testcase( i==37 ); /* REFERENCES */ |
| 131779 | testcase( i==38 ); /* CONSTRAINT */ |
| 131780 | testcase( i==39 ); /* INTO */ |
| 131781 | testcase( i==40 ); /* OFFSET */ |
| 131782 | testcase( i==41 ); /* OF */ |
| 131783 | testcase( i==42 ); /* SET */ |
| 131784 | testcase( i==43 ); /* TEMPORARY */ |
| 131785 | testcase( i==44 ); /* TEMP */ |
| 131786 | testcase( i==45 ); /* OR */ |
| 131787 | testcase( i==46 ); /* UNIQUE */ |
| 131788 | testcase( i==47 ); /* QUERY */ |
| 131789 | testcase( i==48 ); /* WITHOUT */ |
| 131790 | testcase( i==49 ); /* WITH */ |
| 131791 | testcase( i==50 ); /* OUTER */ |
| 131792 | testcase( i==51 ); /* RELEASE */ |
| 131793 | testcase( i==52 ); /* ATTACH */ |
| 131794 | testcase( i==53 ); /* HAVING */ |
| 131795 | testcase( i==54 ); /* GROUP */ |
| 131796 | testcase( i==55 ); /* UPDATE */ |
| 131797 | testcase( i==56 ); /* BEGIN */ |
| 131798 | testcase( i==57 ); /* INNER */ |
| 131799 | testcase( i==58 ); /* RECURSIVE */ |
| 131800 | testcase( i==59 ); /* BETWEEN */ |
| 131801 | testcase( i==60 ); /* NOTNULL */ |
| 131802 | testcase( i==61 ); /* NOT */ |
| 131803 | testcase( i==62 ); /* NO */ |
| 131804 | testcase( i==63 ); /* NULL */ |
| 131805 | testcase( i==64 ); /* LIKE */ |
| 131806 | testcase( i==65 ); /* CASCADE */ |
| 131807 | testcase( i==66 ); /* ASC */ |
| 131808 | testcase( i==67 ); /* DELETE */ |
| 131809 | testcase( i==68 ); /* CASE */ |
| 131810 | testcase( i==69 ); /* COLLATE */ |
| 131811 | testcase( i==70 ); /* CREATE */ |
| 131812 | testcase( i==71 ); /* CURRENT_DATE */ |
| 131813 | testcase( i==72 ); /* DETACH */ |
| 131814 | testcase( i==73 ); /* IMMEDIATE */ |
| 131815 | testcase( i==74 ); /* JOIN */ |
| 131816 | testcase( i==75 ); /* INSERT */ |
| 131817 | testcase( i==76 ); /* MATCH */ |
| 131818 | testcase( i==77 ); /* PLAN */ |
| 131819 | testcase( i==78 ); /* ANALYZE */ |
| 131820 | testcase( i==79 ); /* PRAGMA */ |
| 131821 | testcase( i==80 ); /* ABORT */ |
| 131822 | testcase( i==81 ); /* VALUES */ |
| 131823 | testcase( i==82 ); /* VIRTUAL */ |
| 131824 | testcase( i==83 ); /* LIMIT */ |
| 131825 | testcase( i==84 ); /* WHEN */ |
| 131826 | testcase( i==85 ); /* WHERE */ |
| 131827 | testcase( i==86 ); /* RENAME */ |
| 131828 | testcase( i==87 ); /* AFTER */ |
| 131829 | testcase( i==88 ); /* REPLACE */ |
| 131830 | testcase( i==89 ); /* AND */ |
| 131831 | testcase( i==90 ); /* DEFAULT */ |
| 131832 | testcase( i==91 ); /* AUTOINCREMENT */ |
| 131833 | testcase( i==92 ); /* TO */ |
| 131834 | testcase( i==93 ); /* IN */ |
| 131835 | testcase( i==94 ); /* CAST */ |
| 131836 | testcase( i==95 ); /* COLUMN */ |
| 131837 | testcase( i==96 ); /* COMMIT */ |
| 131838 | testcase( i==97 ); /* CONFLICT */ |
| 131839 | testcase( i==98 ); /* CROSS */ |
| 131840 | testcase( i==99 ); /* CURRENT_TIMESTAMP */ |
| 131841 | testcase( i==100 ); /* CURRENT_TIME */ |
| 131842 | testcase( i==101 ); /* PRIMARY */ |
| 131843 | testcase( i==102 ); /* DEFERRED */ |
| 131844 | testcase( i==103 ); /* DISTINCT */ |
| 131845 | testcase( i==104 ); /* IS */ |
| 131846 | testcase( i==105 ); /* DROP */ |
| 131847 | testcase( i==106 ); /* FAIL */ |
| 131848 | testcase( i==107 ); /* FROM */ |
| 131849 | testcase( i==108 ); /* FULL */ |
| 131850 | testcase( i==109 ); /* GLOB */ |
| 131851 | testcase( i==110 ); /* BY */ |
| 131852 | testcase( i==111 ); /* IF */ |
| 131853 | testcase( i==112 ); /* ISNULL */ |
| 131854 | testcase( i==113 ); /* ORDER */ |
| 131855 | testcase( i==114 ); /* RESTRICT */ |
| 131856 | testcase( i==115 ); /* RIGHT */ |
| 131857 | testcase( i==116 ); /* ROLLBACK */ |
| 131858 | testcase( i==117 ); /* ROW */ |
| 131859 | testcase( i==118 ); /* UNION */ |
| 131860 | testcase( i==119 ); /* USING */ |
| 131861 | testcase( i==120 ); /* VACUUM */ |
| 131862 | testcase( i==121 ); /* VIEW */ |
| 131863 | testcase( i==122 ); /* INITIALLY */ |
| 131864 | testcase( i==123 ); /* ALL */ |
| 131865 | *pType = aCode[i]; |
| 131866 | break; |
| 131867 | } |
| 131868 | } |
| 131869 | return n; |
| 131870 | } |
| 131871 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ |
| @@ -131469,74 +131922,76 @@ | |
| 131922 | SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } |
| 131923 | #endif |
| 131924 | |
| 131925 | |
| 131926 | /* |
| 131927 | ** Return the length (in bytes) of the token that begins at z[0]. |
| 131928 | ** Store the token type in *tokenType before returning. |
| 131929 | */ |
| 131930 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ |
| 131931 | int i, c; |
| 131932 | switch( aiClass[*z] ){ /* Switch on the character-class of the first byte |
| 131933 | ** of the token. See the comment on the CC_ defines |
| 131934 | ** above. */ |
| 131935 | case CC_SPACE: { |
| 131936 | testcase( z[0]==' ' ); |
| 131937 | testcase( z[0]=='\t' ); |
| 131938 | testcase( z[0]=='\n' ); |
| 131939 | testcase( z[0]=='\f' ); |
| 131940 | testcase( z[0]=='\r' ); |
| 131941 | for(i=1; sqlite3Isspace(z[i]); i++){} |
| 131942 | *tokenType = TK_SPACE; |
| 131943 | return i; |
| 131944 | } |
| 131945 | case CC_MINUS: { |
| 131946 | if( z[1]=='-' ){ |
| 131947 | for(i=2; (c=z[i])!=0 && c!='\n'; i++){} |
| 131948 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131949 | return i; |
| 131950 | } |
| 131951 | *tokenType = TK_MINUS; |
| 131952 | return 1; |
| 131953 | } |
| 131954 | case CC_LP: { |
| 131955 | *tokenType = TK_LP; |
| 131956 | return 1; |
| 131957 | } |
| 131958 | case CC_RP: { |
| 131959 | *tokenType = TK_RP; |
| 131960 | return 1; |
| 131961 | } |
| 131962 | case CC_SEMI: { |
| 131963 | *tokenType = TK_SEMI; |
| 131964 | return 1; |
| 131965 | } |
| 131966 | case CC_PLUS: { |
| 131967 | *tokenType = TK_PLUS; |
| 131968 | return 1; |
| 131969 | } |
| 131970 | case CC_STAR: { |
| 131971 | *tokenType = TK_STAR; |
| 131972 | return 1; |
| 131973 | } |
| 131974 | case CC_SLASH: { |
| 131975 | if( z[1]!='*' || z[2]==0 ){ |
| 131976 | *tokenType = TK_SLASH; |
| 131977 | return 1; |
| 131978 | } |
| 131979 | for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} |
| 131980 | if( c ) i++; |
| 131981 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131982 | return i; |
| 131983 | } |
| 131984 | case CC_PERCENT: { |
| 131985 | *tokenType = TK_REM; |
| 131986 | return 1; |
| 131987 | } |
| 131988 | case CC_EQ: { |
| 131989 | *tokenType = TK_EQ; |
| 131990 | return 1 + (z[1]=='='); |
| 131991 | } |
| 131992 | case CC_LT: { |
| 131993 | if( (c=z[1])=='=' ){ |
| 131994 | *tokenType = TK_LE; |
| 131995 | return 2; |
| 131996 | }else if( c=='>' ){ |
| 131997 | *tokenType = TK_NE; |
| @@ -131547,11 +132002,11 @@ | |
| 132002 | }else{ |
| 132003 | *tokenType = TK_LT; |
| 132004 | return 1; |
| 132005 | } |
| 132006 | } |
| 132007 | case CC_GT: { |
| 132008 | if( (c=z[1])=='=' ){ |
| 132009 | *tokenType = TK_GE; |
| 132010 | return 2; |
| 132011 | }else if( c=='>' ){ |
| 132012 | *tokenType = TK_RSHIFT; |
| @@ -131559,43 +132014,41 @@ | |
| 132014 | }else{ |
| 132015 | *tokenType = TK_GT; |
| 132016 | return 1; |
| 132017 | } |
| 132018 | } |
| 132019 | case CC_BANG: { |
| 132020 | if( z[1]!='=' ){ |
| 132021 | *tokenType = TK_ILLEGAL; |
| 132022 | return 2; |
| 132023 | }else{ |
| 132024 | *tokenType = TK_NE; |
| 132025 | return 2; |
| 132026 | } |
| 132027 | } |
| 132028 | case CC_PIPE: { |
| 132029 | if( z[1]!='|' ){ |
| 132030 | *tokenType = TK_BITOR; |
| 132031 | return 1; |
| 132032 | }else{ |
| 132033 | *tokenType = TK_CONCAT; |
| 132034 | return 2; |
| 132035 | } |
| 132036 | } |
| 132037 | case CC_COMMA: { |
| 132038 | *tokenType = TK_COMMA; |
| 132039 | return 1; |
| 132040 | } |
| 132041 | case CC_AND: { |
| 132042 | *tokenType = TK_BITAND; |
| 132043 | return 1; |
| 132044 | } |
| 132045 | case CC_TILDA: { |
| 132046 | *tokenType = TK_BITNOT; |
| 132047 | return 1; |
| 132048 | } |
| 132049 | case CC_QUOTE: { |
| 132050 | int delim = z[0]; |
| 132051 | testcase( delim=='`' ); |
| 132052 | testcase( delim=='\'' ); |
| 132053 | testcase( delim=='"' ); |
| 132054 | for(i=1; (c=z[i])!=0; i++){ |
| @@ -131616,11 +132069,11 @@ | |
| 132069 | }else{ |
| 132070 | *tokenType = TK_ILLEGAL; |
| 132071 | return i; |
| 132072 | } |
| 132073 | } |
| 132074 | case CC_DOT: { |
| 132075 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 132076 | if( !sqlite3Isdigit(z[1]) ) |
| 132077 | #endif |
| 132078 | { |
| 132079 | *tokenType = TK_DOT; |
| @@ -131627,12 +132080,11 @@ | |
| 132080 | return 1; |
| 132081 | } |
| 132082 | /* If the next character is a digit, this is a floating point |
| 132083 | ** number that begins with ".". Fall thru into the next case */ |
| 132084 | } |
| 132085 | case CC_DIGIT: { |
| 132086 | testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); |
| 132087 | testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); |
| 132088 | testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); |
| 132089 | testcase( z[0]=='9' ); |
| 132090 | *tokenType = TK_INTEGER; |
| @@ -131663,26 +132115,22 @@ | |
| 132115 | *tokenType = TK_ILLEGAL; |
| 132116 | i++; |
| 132117 | } |
| 132118 | return i; |
| 132119 | } |
| 132120 | case CC_QUOTE2: { |
| 132121 | for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} |
| 132122 | *tokenType = c==']' ? TK_ID : TK_ILLEGAL; |
| 132123 | return i; |
| 132124 | } |
| 132125 | case CC_VARNUM: { |
| 132126 | *tokenType = TK_VARIABLE; |
| 132127 | for(i=1; sqlite3Isdigit(z[i]); i++){} |
| 132128 | return i; |
| 132129 | } |
| 132130 | case CC_DOLLAR: |
| 132131 | case CC_VARALPHA: { |
| 132132 | int n = 0; |
| 132133 | testcase( z[0]=='$' ); testcase( z[0]=='@' ); |
| 132134 | testcase( z[0]==':' ); testcase( z[0]=='#' ); |
| 132135 | *tokenType = TK_VARIABLE; |
| 132136 | for(i=1; (c=z[i])!=0; i++){ |
| @@ -131707,12 +132155,24 @@ | |
| 132155 | } |
| 132156 | } |
| 132157 | if( n==0 ) *tokenType = TK_ILLEGAL; |
| 132158 | return i; |
| 132159 | } |
| 132160 | case CC_KYWD: { |
| 132161 | for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} |
| 132162 | if( IdChar(z[i]) ){ |
| 132163 | /* This token started out using characters that can appear in keywords, |
| 132164 | ** but z[i] is a character not allowed within keywords, so this must |
| 132165 | ** be an identifier instead */ |
| 132166 | i++; |
| 132167 | break; |
| 132168 | } |
| 132169 | *tokenType = TK_ID; |
| 132170 | return keywordCode((char*)z, i, tokenType); |
| 132171 | } |
| 132172 | #ifndef SQLITE_OMIT_BLOB_LITERAL |
| 132173 | case CC_X: { |
| 132174 | testcase( z[0]=='x' ); testcase( z[0]=='X' ); |
| 132175 | if( z[1]=='\'' ){ |
| 132176 | *tokenType = TK_BLOB; |
| 132177 | for(i=2; sqlite3Isxdigit(z[i]); i++){} |
| 132178 | if( z[i]!='\'' || i%2 ){ |
| @@ -131720,24 +132180,26 @@ | |
| 132180 | while( z[i] && z[i]!='\'' ){ i++; } |
| 132181 | } |
| 132182 | if( z[i] ) i++; |
| 132183 | return i; |
| 132184 | } |
| 132185 | /* If it is not a BLOB literal, then it must be an ID, since no |
| 132186 | ** SQL keywords start with the letter 'x'. Fall through */ |
| 132187 | } |
| 132188 | #endif |
| 132189 | case CC_ID: { |
| 132190 | i = 1; |
| 132191 | break; |
| 132192 | } |
| 132193 | default: { |
| 132194 | *tokenType = TK_ILLEGAL; |
| 132195 | return 1; |
| 132196 | } |
| 132197 | } |
| 132198 | while( IdChar(z[i]) ){ i++; } |
| 132199 | *tokenType = TK_ID; |
| 132200 | return i; |
| 132201 | } |
| 132202 | |
| 132203 | /* |
| 132204 | ** Run the parser on the given SQL string. The parser structure is |
| 132205 | ** passed in. An SQLITE_ status code is returned. If an error occurs |
| @@ -131749,11 +132211,10 @@ | |
| 132211 | int nErr = 0; /* Number of errors encountered */ |
| 132212 | int i; /* Loop counter */ |
| 132213 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 132214 | int tokenType; /* type of the next token */ |
| 132215 | int lastTokenParsed = -1; /* type of the previous token */ |
| 132216 | sqlite3 *db = pParse->db; /* The database connection */ |
| 132217 | int mxSqlLen; /* Max length of an SQL string */ |
| 132218 | |
| 132219 | assert( zSql!=0 ); |
| 132220 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| @@ -131765,20 +132226,18 @@ | |
| 132226 | i = 0; |
| 132227 | assert( pzErrMsg!=0 ); |
| 132228 | /* sqlite3ParserTrace(stdout, "parser: "); */ |
| 132229 | pEngine = sqlite3ParserAlloc(sqlite3Malloc); |
| 132230 | if( pEngine==0 ){ |
| 132231 | sqlite3OomFault(db); |
| 132232 | return SQLITE_NOMEM; |
| 132233 | } |
| 132234 | assert( pParse->pNewTable==0 ); |
| 132235 | assert( pParse->pNewTrigger==0 ); |
| 132236 | assert( pParse->nVar==0 ); |
| 132237 | assert( pParse->nzVar==0 ); |
| 132238 | assert( pParse->azVar==0 ); |
| 132239 | while( zSql[i]!=0 ){ |
| 132240 | assert( i>=0 ); |
| 132241 | pParse->sLastToken.z = &zSql[i]; |
| 132242 | pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); |
| 132243 | i += pParse->sLastToken.n; |
| @@ -131787,11 +132246,10 @@ | |
| 132246 | break; |
| 132247 | } |
| 132248 | if( tokenType>=TK_SPACE ){ |
| 132249 | assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); |
| 132250 | if( db->u1.isInterrupted ){ |
| 132251 | pParse->rc = SQLITE_INTERRUPT; |
| 132252 | break; |
| 132253 | } |
| 132254 | if( tokenType==TK_ILLEGAL ){ |
| 132255 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", |
| @@ -131822,11 +132280,10 @@ | |
| 132280 | sqlite3ParserStackPeak(pEngine) |
| 132281 | ); |
| 132282 | sqlite3_mutex_leave(sqlite3MallocMutex()); |
| 132283 | #endif /* YYDEBUG */ |
| 132284 | sqlite3ParserFree(pEngine, sqlite3_free); |
| 132285 | if( db->mallocFailed ){ |
| 132286 | pParse->rc = SQLITE_NOMEM; |
| 132287 | } |
| 132288 | if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ |
| 132289 | pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); |
| @@ -132963,16 +133420,16 @@ | |
| 133420 | p->pNext = db->lookaside.pFree; |
| 133421 | db->lookaside.pFree = p; |
| 133422 | p = (LookasideSlot*)&((u8*)p)[sz]; |
| 133423 | } |
| 133424 | db->lookaside.pEnd = p; |
| 133425 | db->lookaside.bDisable = 0; |
| 133426 | db->lookaside.bMalloced = pBuf==0 ?1:0; |
| 133427 | }else{ |
| 133428 | db->lookaside.pStart = db; |
| 133429 | db->lookaside.pEnd = db; |
| 133430 | db->lookaside.bDisable = 1; |
| 133431 | db->lookaside.bMalloced = 0; |
| 133432 | } |
| 133433 | #endif /* SQLITE_OMIT_LOOKASIDE */ |
| 133434 | return SQLITE_OK; |
| 133435 | } |
| @@ -134473,11 +134930,11 @@ | |
| 134930 | /* A malloc() may have failed within the call to sqlite3_value_text16() |
| 134931 | ** above. If this is the case, then the db->mallocFailed flag needs to |
| 134932 | ** be cleared before returning. Do this directly, instead of via |
| 134933 | ** sqlite3ApiExit(), to avoid setting the database handle error message. |
| 134934 | */ |
| 134935 | sqlite3OomClear(db); |
| 134936 | } |
| 134937 | sqlite3_mutex_leave(db->mutex); |
| 134938 | return z; |
| 134939 | } |
| 134940 | #endif /* SQLITE_OMIT_UTF16 */ |
| @@ -135111,11 +135568,11 @@ | |
| 135568 | |
| 135569 | /* Parse the filename/URI argument. */ |
| 135570 | db->openFlags = flags; |
| 135571 | rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); |
| 135572 | if( rc!=SQLITE_OK ){ |
| 135573 | if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
| 135574 | sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); |
| 135575 | sqlite3_free(zErrMsg); |
| 135576 | goto opendb_out; |
| 135577 | } |
| 135578 | |
| @@ -135831,11 +136288,11 @@ | |
| 136288 | ** process aborts. If X is false and assert() is disabled, then the |
| 136289 | ** return value is zero. |
| 136290 | */ |
| 136291 | case SQLITE_TESTCTRL_ASSERT: { |
| 136292 | volatile int x = 0; |
| 136293 | assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 ); |
| 136294 | rc = x; |
| 136295 | break; |
| 136296 | } |
| 136297 | |
| 136298 | |
| @@ -146361,10 +146818,11 @@ | |
| 146818 | |
| 146819 | zName = sqlite3_value_text(argv[0]); |
| 146820 | nName = sqlite3_value_bytes(argv[0])+1; |
| 146821 | |
| 146822 | if( argc==2 ){ |
| 146823 | #ifdef SQLITE_ENABLE_FTS3_TOKENIZER |
| 146824 | void *pOld; |
| 146825 | int n = sqlite3_value_bytes(argv[1]); |
| 146826 | if( zName==0 || n!=sizeof(pPtr) ){ |
| 146827 | sqlite3_result_error(context, "argument type mismatch", -1); |
| 146828 | return; |
| @@ -146373,11 +146831,18 @@ | |
| 146831 | pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); |
| 146832 | if( pOld==pPtr ){ |
| 146833 | sqlite3_result_error(context, "out of memory", -1); |
| 146834 | return; |
| 146835 | } |
| 146836 | #else |
| 146837 | sqlite3_result_error(context, "fts3tokenize: " |
| 146838 | "disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER", -1 |
| 146839 | ); |
| 146840 | return; |
| 146841 | #endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ |
| 146842 | }else |
| 146843 | { |
| 146844 | if( zName ){ |
| 146845 | pPtr = sqlite3Fts3HashFind(pHash, zName, nName); |
| 146846 | } |
| 146847 | if( !pPtr ){ |
| 146848 | char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); |
| @@ -146622,10 +147087,11 @@ | |
| 147087 | sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); |
| 147088 | } |
| 147089 | Tcl_DecrRefCount(pRet); |
| 147090 | } |
| 147091 | |
| 147092 | #ifdef SQLITE_ENABLE_FTS3_TOKENIZER |
| 147093 | static |
| 147094 | int registerTokenizer( |
| 147095 | sqlite3 *db, |
| 147096 | char *zName, |
| 147097 | const sqlite3_tokenizer_module *p |
| @@ -146643,10 +147109,12 @@ | |
| 147109 | sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); |
| 147110 | sqlite3_step(pStmt); |
| 147111 | |
| 147112 | return sqlite3_finalize(pStmt); |
| 147113 | } |
| 147114 | #endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ |
| 147115 | |
| 147116 | |
| 147117 | static |
| 147118 | int queryTokenizer( |
| 147119 | sqlite3 *db, |
| 147120 | char *zName, |
| @@ -146714,15 +147182,17 @@ | |
| 147182 | assert( rc==SQLITE_ERROR ); |
| 147183 | assert( p2==0 ); |
| 147184 | assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); |
| 147185 | |
| 147186 | /* Test the storage function */ |
| 147187 | #ifdef SQLITE_ENABLE_FTS3_TOKENIZER |
| 147188 | rc = registerTokenizer(db, "nosuchtokenizer", p1); |
| 147189 | assert( rc==SQLITE_OK ); |
| 147190 | rc = queryTokenizer(db, "nosuchtokenizer", &p2); |
| 147191 | assert( rc==SQLITE_OK ); |
| 147192 | assert( p2==p1 ); |
| 147193 | #endif |
| 147194 | |
| 147195 | sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); |
| 147196 | } |
| 147197 | |
| 147198 | #endif |
| @@ -164601,11 +165071,13 @@ | |
| 165071 | StatTable *pTab = 0; |
| 165072 | int rc = SQLITE_OK; |
| 165073 | int iDb; |
| 165074 | |
| 165075 | if( argc>=4 ){ |
| 165076 | Token nm; |
| 165077 | sqlite3TokenInit(&nm, (char*)argv[3]); |
| 165078 | iDb = sqlite3FindDb(db, &nm); |
| 165079 | if( iDb<0 ){ |
| 165080 | *pzErr = sqlite3_mprintf("no such database: %s", argv[3]); |
| 165081 | return SQLITE_ERROR; |
| 165082 | } |
| 165083 | }else{ |
| @@ -165431,14 +165903,37 @@ | |
| 165903 | static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ |
| 165904 | u32 i; |
| 165905 | if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; |
| 165906 | p->zBuf[p->nUsed++] = '"'; |
| 165907 | for(i=0; i<N; i++){ |
| 165908 | unsigned char c = ((unsigned const char*)zIn)[i]; |
| 165909 | if( c=='"' || c=='\\' ){ |
| 165910 | json_simple_escape: |
| 165911 | if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; |
| 165912 | p->zBuf[p->nUsed++] = '\\'; |
| 165913 | }else if( c<=0x1f ){ |
| 165914 | static const char aSpecial[] = { |
| 165915 | 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, |
| 165916 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 165917 | }; |
| 165918 | assert( sizeof(aSpecial)==32 ); |
| 165919 | assert( aSpecial['\b']=='b' ); |
| 165920 | assert( aSpecial['\f']=='f' ); |
| 165921 | assert( aSpecial['\n']=='n' ); |
| 165922 | assert( aSpecial['\r']=='r' ); |
| 165923 | assert( aSpecial['\t']=='t' ); |
| 165924 | if( aSpecial[c] ){ |
| 165925 | c = aSpecial[c]; |
| 165926 | goto json_simple_escape; |
| 165927 | } |
| 165928 | if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; |
| 165929 | p->zBuf[p->nUsed++] = '\\'; |
| 165930 | p->zBuf[p->nUsed++] = 'u'; |
| 165931 | p->zBuf[p->nUsed++] = '0'; |
| 165932 | p->zBuf[p->nUsed++] = '0'; |
| 165933 | p->zBuf[p->nUsed++] = '0' + (c>>4); |
| 165934 | c = "0123456789abcdef"[c&0xf]; |
| 165935 | } |
| 165936 | p->zBuf[p->nUsed++] = c; |
| 165937 | } |
| 165938 | p->zBuf[p->nUsed++] = '"'; |
| 165939 | assert( p->nUsed<p->nAlloc ); |
| @@ -165475,11 +165970,11 @@ | |
| 165970 | break; |
| 165971 | } |
| 165972 | default: { |
| 165973 | if( p->bErr==0 ){ |
| 165974 | sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); |
| 165975 | p->bErr = 2; |
| 165976 | jsonReset(p); |
| 165977 | } |
| 165978 | break; |
| 165979 | } |
| 165980 | } |
| @@ -166703,11 +167198,11 @@ | |
| 167198 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 167199 | if( pStr ){ |
| 167200 | pStr->pCtx = ctx; |
| 167201 | jsonAppendChar(pStr, ']'); |
| 167202 | if( pStr->bErr ){ |
| 167203 | if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); |
| 167204 | assert( pStr->bStatic ); |
| 167205 | }else{ |
| 167206 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 167207 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 167208 | pStr->bStatic = 1; |
| @@ -166751,11 +167246,11 @@ | |
| 167246 | JsonString *pStr; |
| 167247 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 167248 | if( pStr ){ |
| 167249 | jsonAppendChar(pStr, '}'); |
| 167250 | if( pStr->bErr ){ |
| 167251 | if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); |
| 167252 | assert( pStr->bStatic ); |
| 167253 | }else{ |
| 167254 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 167255 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 167256 | pStr->bStatic = 1; |
| @@ -167940,11 +168435,11 @@ | |
| 168435 | typedef unsigned int u32; |
| 168436 | typedef unsigned short u16; |
| 168437 | typedef sqlite3_int64 i64; |
| 168438 | typedef sqlite3_uint64 u64; |
| 168439 | |
| 168440 | #define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) |
| 168441 | |
| 168442 | #define testcase(x) |
| 168443 | #define ALWAYS(x) 1 |
| 168444 | #define NEVER(x) 0 |
| 168445 | |
| @@ -168136,12 +168631,12 @@ | |
| 168631 | ** Buffer object for the incremental building of string data. |
| 168632 | */ |
| 168633 | typedef struct Fts5Buffer Fts5Buffer; |
| 168634 | struct Fts5Buffer { |
| 168635 | u8 *p; |
| 168636 | int n; |
| 168637 | int nSpace; |
| 168638 | }; |
| 168639 | |
| 168640 | static int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32); |
| 168641 | static void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64); |
| 168642 | static void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, u32, const u8*); |
| @@ -168158,11 +168653,11 @@ | |
| 168653 | #define fts5BufferFree(a) sqlite3Fts5BufferFree(a) |
| 168654 | #define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d) |
| 168655 | #define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) |
| 168656 | |
| 168657 | #define fts5BufferGrow(pRc,pBuf,nn) ( \ |
| 168658 | (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \ |
| 168659 | sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \ |
| 168660 | ) |
| 168661 | |
| 168662 | /* Write and decode big-endian 32-bit integer values */ |
| 168663 | static void sqlite3Fts5Put32(u8*, int); |
| @@ -168193,10 +168688,11 @@ | |
| 168688 | typedef struct Fts5PoslistWriter Fts5PoslistWriter; |
| 168689 | struct Fts5PoslistWriter { |
| 168690 | i64 iPrev; |
| 168691 | }; |
| 168692 | static int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); |
| 168693 | static void sqlite3Fts5PoslistSafeAppend(Fts5Buffer*, i64*, i64); |
| 168694 | |
| 168695 | static int sqlite3Fts5PoslistNext64( |
| 168696 | const u8 *a, int n, /* Buffer containing poslist */ |
| 168697 | int *pi, /* IN/OUT: Offset within a[] */ |
| 168698 | i64 *piOff /* IN/OUT: Current offset */ |
| @@ -168226,17 +168722,32 @@ | |
| 168722 | */ |
| 168723 | |
| 168724 | typedef struct Fts5Index Fts5Index; |
| 168725 | typedef struct Fts5IndexIter Fts5IndexIter; |
| 168726 | |
| 168727 | struct Fts5IndexIter { |
| 168728 | i64 iRowid; |
| 168729 | const u8 *pData; |
| 168730 | int nData; |
| 168731 | u8 bEof; |
| 168732 | }; |
| 168733 | |
| 168734 | #define sqlite3Fts5IterEof(x) ((x)->bEof) |
| 168735 | |
| 168736 | /* |
| 168737 | ** Values used as part of the flags argument passed to IndexQuery(). |
| 168738 | */ |
| 168739 | #define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ |
| 168740 | #define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ |
| 168741 | #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ |
| 168742 | #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ |
| 168743 | |
| 168744 | /* The following are used internally by the fts5_index.c module. They are |
| 168745 | ** defined here only to make it easier to avoid clashes with the flags |
| 168746 | ** above. */ |
| 168747 | #define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 |
| 168748 | #define FTS5INDEX_QUERY_NOOUTPUT 0x0020 |
| 168749 | |
| 168750 | /* |
| 168751 | ** Create/destroy an Fts5Index object. |
| 168752 | */ |
| 168753 | static int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); |
| @@ -168289,16 +168800,13 @@ | |
| 168800 | |
| 168801 | /* |
| 168802 | ** The various operations on open token or token prefix iterators opened |
| 168803 | ** using sqlite3Fts5IndexQuery(). |
| 168804 | */ |
| 168805 | static int sqlite3Fts5IterNext(Fts5IndexIter*); |
| 168806 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); |
| 168807 | static i64 sqlite3Fts5IterRowid(Fts5IndexIter*); |
| 168808 | |
| 168809 | /* |
| 168810 | ** Close an iterator opened by sqlite3Fts5IndexQuery(). |
| 168811 | */ |
| 168812 | static void sqlite3Fts5IterClose(Fts5IndexIter*); |
| @@ -168380,12 +168888,10 @@ | |
| 168888 | static int sqlite3Fts5IndexOptimize(Fts5Index *p); |
| 168889 | static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); |
| 168890 | |
| 168891 | static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); |
| 168892 | |
| 168893 | /* |
| 168894 | ** End of interface to code in fts5_index.c. |
| 168895 | **************************************************************************/ |
| 168896 | |
| 168897 | /************************************************************************** |
| @@ -170432,11 +170938,11 @@ | |
| 170938 | { "bm25", 0, fts5Bm25Function, 0 }, |
| 170939 | }; |
| 170940 | int rc = SQLITE_OK; /* Return code */ |
| 170941 | int i; /* To iterate through builtin functions */ |
| 170942 | |
| 170943 | for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){ |
| 170944 | rc = pApi->xCreateFunction(pApi, |
| 170945 | aBuiltin[i].zFunc, |
| 170946 | aBuiltin[i].pUserData, |
| 170947 | aBuiltin[i].xFunc, |
| 170948 | aBuiltin[i].xDestroy |
| @@ -170464,22 +170970,24 @@ | |
| 170970 | |
| 170971 | |
| 170972 | /* #include "fts5Int.h" */ |
| 170973 | |
| 170974 | static int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){ |
| 170975 | if( (u32)pBuf->nSpace<nByte ){ |
| 170976 | u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64; |
| 170977 | u8 *pNew; |
| 170978 | while( nNew<nByte ){ |
| 170979 | nNew = nNew * 2; |
| 170980 | } |
| 170981 | pNew = sqlite3_realloc(pBuf->p, nNew); |
| 170982 | if( pNew==0 ){ |
| 170983 | *pRc = SQLITE_NOMEM; |
| 170984 | return 1; |
| 170985 | }else{ |
| 170986 | pBuf->nSpace = nNew; |
| 170987 | pBuf->p = pNew; |
| 170988 | } |
| 170989 | } |
| 170990 | return 0; |
| 170991 | } |
| 170992 | |
| 170993 | |
| @@ -170655,28 +171163,41 @@ | |
| 171163 | pIter->a = a; |
| 171164 | pIter->n = n; |
| 171165 | sqlite3Fts5PoslistReaderNext(pIter); |
| 171166 | return pIter->bEof; |
| 171167 | } |
| 171168 | |
| 171169 | /* |
| 171170 | ** Append position iPos to the position list being accumulated in buffer |
| 171171 | ** pBuf, which must be already be large enough to hold the new data. |
| 171172 | ** The previous position written to this list is *piPrev. *piPrev is set |
| 171173 | ** to iPos before returning. |
| 171174 | */ |
| 171175 | static void sqlite3Fts5PoslistSafeAppend( |
| 171176 | Fts5Buffer *pBuf, |
| 171177 | i64 *piPrev, |
| 171178 | i64 iPos |
| 171179 | ){ |
| 171180 | static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; |
| 171181 | if( (iPos & colmask) != (*piPrev & colmask) ){ |
| 171182 | pBuf->p[pBuf->n++] = 1; |
| 171183 | pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); |
| 171184 | *piPrev = (iPos & colmask); |
| 171185 | } |
| 171186 | pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); |
| 171187 | *piPrev = iPos; |
| 171188 | } |
| 171189 | |
| 171190 | static int sqlite3Fts5PoslistWriterAppend( |
| 171191 | Fts5Buffer *pBuf, |
| 171192 | Fts5PoslistWriter *pWriter, |
| 171193 | i64 iPos |
| 171194 | ){ |
| 171195 | int rc; |
| 171196 | if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; |
| 171197 | sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); |
| 171198 | return SQLITE_OK; |
| 171199 | } |
| 171200 | |
| 171201 | static void *sqlite3Fts5MallocZero(int *pRc, int nByte){ |
| 171202 | void *pRet = 0; |
| 171203 | if( *pRc==SQLITE_OK ){ |
| @@ -170770,11 +171291,11 @@ | |
| 171291 | ){ |
| 171292 | int rc = SQLITE_OK; |
| 171293 | *pbPresent = 0; |
| 171294 | if( p ){ |
| 171295 | int i; |
| 171296 | u32 hash = 13; |
| 171297 | Fts5TermsetEntry *pEntry; |
| 171298 | |
| 171299 | /* Calculate a hash value for this term. This is the same hash checksum |
| 171300 | ** used by the fts5_hash.c module. This is not important for correct |
| 171301 | ** operation of the module, but is necessary to ensure that some tests |
| @@ -170787,11 +171308,11 @@ | |
| 171308 | |
| 171309 | for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){ |
| 171310 | if( pEntry->iIdx==iIdx |
| 171311 | && pEntry->nTerm==nTerm |
| 171312 | && memcmp(pEntry->pTerm, pTerm, nTerm)==0 |
| 171313 | ){ |
| 171314 | *pbPresent = 1; |
| 171315 | break; |
| 171316 | } |
| 171317 | } |
| 171318 | |
| @@ -170811,11 +171332,11 @@ | |
| 171332 | return rc; |
| 171333 | } |
| 171334 | |
| 171335 | static void sqlite3Fts5TermsetFree(Fts5Termset *p){ |
| 171336 | if( p ){ |
| 171337 | u32 i; |
| 171338 | for(i=0; i<ArraySize(p->apHash); i++){ |
| 171339 | Fts5TermsetEntry *pEntry = p->apHash[i]; |
| 171340 | while( pEntry ){ |
| 171341 | Fts5TermsetEntry *pDel = pEntry; |
| 171342 | pEntry = pEntry->pNext; |
| @@ -171838,10 +172359,13 @@ | |
| 172359 | struct Fts5ExprNode { |
| 172360 | int eType; /* Node type */ |
| 172361 | int bEof; /* True at EOF */ |
| 172362 | int bNomatch; /* True if entry is not a match */ |
| 172363 | |
| 172364 | /* Next method for this node. */ |
| 172365 | int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64); |
| 172366 | |
| 172367 | i64 iRowid; /* Current rowid */ |
| 172368 | Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ |
| 172369 | |
| 172370 | /* Child nodes. For a NOT node, this array always contains 2 entries. For |
| 172371 | ** AND or OR nodes, it contains 2 or more entries. */ |
| @@ -171849,10 +172373,16 @@ | |
| 172373 | Fts5ExprNode *apChild[1]; /* Array of child nodes */ |
| 172374 | }; |
| 172375 | |
| 172376 | #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) |
| 172377 | |
| 172378 | /* |
| 172379 | ** Invoke the xNext method of an Fts5ExprNode object. This macro should be |
| 172380 | ** used as if it has the same signature as the xNext() methods themselves. |
| 172381 | */ |
| 172382 | #define fts5ExprNodeNext(a,b,c,d) (b)->xNext((a), (b), (c), (d)) |
| 172383 | |
| 172384 | /* |
| 172385 | ** An instance of the following structure represents a single search term |
| 172386 | ** or term prefix. |
| 172387 | */ |
| 172388 | struct Fts5ExprTerm { |
| @@ -172010,11 +172540,19 @@ | |
| 172540 | *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); |
| 172541 | if( pNew==0 ){ |
| 172542 | sParse.rc = SQLITE_NOMEM; |
| 172543 | sqlite3Fts5ParseNodeFree(sParse.pExpr); |
| 172544 | }else{ |
| 172545 | if( !sParse.pExpr ){ |
| 172546 | const int nByte = sizeof(Fts5ExprNode); |
| 172547 | pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte); |
| 172548 | if( pNew->pRoot ){ |
| 172549 | pNew->pRoot->bEof = 1; |
| 172550 | } |
| 172551 | }else{ |
| 172552 | pNew->pRoot = sParse.pExpr; |
| 172553 | } |
| 172554 | pNew->pIndex = 0; |
| 172555 | pNew->pConfig = pConfig; |
| 172556 | pNew->apExprPhrase = sParse.apPhrase; |
| 172557 | pNew->nPhrase = sParse.nPhrase; |
| 172558 | sParse.apPhrase = 0; |
| @@ -172062,11 +172600,11 @@ | |
| 172600 | |
| 172601 | assert( pTerm->pSynonym ); |
| 172602 | assert( bDesc==0 || bDesc==1 ); |
| 172603 | for(p=pTerm; p; p=p->pSynonym){ |
| 172604 | if( 0==sqlite3Fts5IterEof(p->pIter) ){ |
| 172605 | i64 iRowid = p->pIter->iRowid; |
| 172606 | if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){ |
| 172607 | iRet = iRowid; |
| 172608 | bRetValid = 1; |
| 172609 | } |
| 172610 | } |
| @@ -172082,11 +172620,11 @@ | |
| 172620 | static int fts5ExprSynonymList( |
| 172621 | Fts5ExprTerm *pTerm, |
| 172622 | int bCollist, |
| 172623 | Fts5Colset *pColset, |
| 172624 | i64 iRowid, |
| 172625 | Fts5Buffer *pBuf, /* Use this buffer for space if required */ |
| 172626 | u8 **pa, int *pn |
| 172627 | ){ |
| 172628 | Fts5PoslistReader aStatic[4]; |
| 172629 | Fts5PoslistReader *aIter = aStatic; |
| 172630 | int nIter = 0; |
| @@ -172095,23 +172633,12 @@ | |
| 172633 | Fts5ExprTerm *p; |
| 172634 | |
| 172635 | assert( pTerm->pSynonym ); |
| 172636 | for(p=pTerm; p; p=p->pSynonym){ |
| 172637 | Fts5IndexIter *pIter = p->pIter; |
| 172638 | if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){ |
| 172639 | if( pIter->nData==0 ) continue; |
| 172640 | if( nIter==nAlloc ){ |
| 172641 | int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; |
| 172642 | Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172643 | if( aNew==0 ){ |
| 172644 | rc = SQLITE_NOMEM; |
| @@ -172120,24 +172647,23 @@ | |
| 172647 | memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); |
| 172648 | nAlloc = nAlloc*2; |
| 172649 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| 172650 | aIter = aNew; |
| 172651 | } |
| 172652 | sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &aIter[nIter]); |
| 172653 | assert( aIter[nIter].bEof==0 ); |
| 172654 | nIter++; |
| 172655 | } |
| 172656 | } |
| 172657 | |
| 172658 | if( nIter==1 ){ |
| 172659 | *pa = (u8*)aIter[0].a; |
| 172660 | *pn = aIter[0].n; |
| 172661 | }else{ |
| 172662 | Fts5PoslistWriter writer = {0}; |
| 172663 | i64 iPrev = -1; |
| 172664 | fts5BufferZero(pBuf); |
| 172665 | while( 1 ){ |
| 172666 | int i; |
| 172667 | i64 iMin = FTS5_LARGEST_INT64; |
| 172668 | for(i=0; i<nIter; i++){ |
| 172669 | if( aIter[i].bEof==0 ){ |
| @@ -172148,19 +172674,16 @@ | |
| 172674 | iMin = aIter[i].iPos; |
| 172675 | } |
| 172676 | } |
| 172677 | } |
| 172678 | if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break; |
| 172679 | rc = sqlite3Fts5PoslistWriterAppend(pBuf, &writer, iMin); |
| 172680 | iPrev = iMin; |
| 172681 | } |
| 172682 | if( rc==SQLITE_OK ){ |
| 172683 | *pa = pBuf->p; |
| 172684 | *pn = pBuf->n; |
| 172685 | } |
| 172686 | } |
| 172687 | |
| 172688 | synonym_poslist_out: |
| 172689 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| @@ -172193,32 +172716,37 @@ | |
| 172716 | |
| 172717 | fts5BufferZero(&pPhrase->poslist); |
| 172718 | |
| 172719 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172720 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172721 | if( pPhrase->nTerm>ArraySize(aStatic) ){ |
| 172722 | int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; |
| 172723 | aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172724 | if( !aIter ) return SQLITE_NOMEM; |
| 172725 | } |
| 172726 | memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm); |
| 172727 | |
| 172728 | /* Initialize a term iterator for each term in the phrase */ |
| 172729 | for(i=0; i<pPhrase->nTerm; i++){ |
| 172730 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 172731 | int n = 0; |
| 172732 | int bFlag = 0; |
| 172733 | u8 *a = 0; |
| 172734 | if( pTerm->pSynonym ){ |
| 172735 | Fts5Buffer buf = {0, 0, 0}; |
| 172736 | rc = fts5ExprSynonymList( |
| 172737 | pTerm, 0, pColset, pNode->iRowid, &buf, &a, &n |
| 172738 | ); |
| 172739 | if( rc ){ |
| 172740 | sqlite3_free(a); |
| 172741 | goto ismatch_out; |
| 172742 | } |
| 172743 | if( a==buf.p ) bFlag = 1; |
| 172744 | }else{ |
| 172745 | a = (u8*)pTerm->pIter->pData; |
| 172746 | n = pTerm->pIter->nData; |
| 172747 | } |
| 172748 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); |
| 172749 | aIter[i].bFlag = (u8)bFlag; |
| 172750 | if( aIter[i].bEof ) goto ismatch_out; |
| 172751 | } |
| 172752 | |
| @@ -172286,16 +172814,10 @@ | |
| 172814 | p->n = n; |
| 172815 | fts5LookaheadReaderNext(p); |
| 172816 | return fts5LookaheadReaderNext(p); |
| 172817 | } |
| 172818 | |
| 172819 | typedef struct Fts5NearTrimmer Fts5NearTrimmer; |
| 172820 | struct Fts5NearTrimmer { |
| 172821 | Fts5LookaheadReader reader; /* Input iterator */ |
| 172822 | Fts5PoslistWriter writer; /* Writer context */ |
| 172823 | Fts5Buffer *pOut; /* Output poslist */ |
| @@ -172329,11 +172851,11 @@ | |
| 172851 | |
| 172852 | assert( pNear->nPhrase>1 ); |
| 172853 | |
| 172854 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172855 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172856 | if( pNear->nPhrase>ArraySize(aStatic) ){ |
| 172857 | int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; |
| 172858 | a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); |
| 172859 | }else{ |
| 172860 | memset(aStatic, 0, sizeof(aStatic)); |
| 172861 | } |
| @@ -172406,75 +172928,10 @@ | |
| 172928 | if( a!=aStatic ) sqlite3_free(a); |
| 172929 | return bRet; |
| 172930 | } |
| 172931 | } |
| 172932 | |
| 172933 | /* |
| 172934 | ** Advance iterator pIter until it points to a value equal to or laster |
| 172935 | ** than the initial value of *piLast. If this means the iterator points |
| 172936 | ** to a value laster than *piLast, update *piLast to the new lastest value. |
| 172937 | ** |
| @@ -172490,19 +172947,19 @@ | |
| 172947 | int *pbEof /* OUT: Set to true if EOF */ |
| 172948 | ){ |
| 172949 | i64 iLast = *piLast; |
| 172950 | i64 iRowid; |
| 172951 | |
| 172952 | iRowid = pIter->iRowid; |
| 172953 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172954 | int rc = sqlite3Fts5IterNextFrom(pIter, iLast); |
| 172955 | if( rc || sqlite3Fts5IterEof(pIter) ){ |
| 172956 | *pRc = rc; |
| 172957 | *pbEof = 1; |
| 172958 | return 1; |
| 172959 | } |
| 172960 | iRowid = pIter->iRowid; |
| 172961 | assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) ); |
| 172962 | } |
| 172963 | *piLast = iRowid; |
| 172964 | |
| 172965 | return 0; |
| @@ -172519,11 +172976,11 @@ | |
| 172976 | Fts5ExprTerm *p; |
| 172977 | int bEof = 0; |
| 172978 | |
| 172979 | for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){ |
| 172980 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 172981 | i64 iRowid = p->pIter->iRowid; |
| 172982 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172983 | rc = sqlite3Fts5IterNextFrom(p->pIter, iLast); |
| 172984 | } |
| 172985 | } |
| 172986 | } |
| @@ -172551,17 +173008,11 @@ | |
| 173008 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 173009 | pPhrase->poslist.n = 0; |
| 173010 | for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ |
| 173011 | Fts5IndexIter *pIter = pTerm->pIter; |
| 173012 | if( sqlite3Fts5IterEof(pIter)==0 ){ |
| 173013 | if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){ |
| 173014 | pPhrase->poslist.n = 1; |
| 173015 | } |
| 173016 | } |
| 173017 | } |
| 173018 | return pPhrase->poslist.n; |
| @@ -172576,13 +173027,12 @@ | |
| 173027 | if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ |
| 173028 | int bMatch = 0; |
| 173029 | rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch); |
| 173030 | if( bMatch==0 ) break; |
| 173031 | }else{ |
| 173032 | Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 173033 | fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData); |
| 173034 | } |
| 173035 | } |
| 173036 | |
| 173037 | *pRc = rc; |
| 173038 | if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){ |
| @@ -172590,107 +173040,10 @@ | |
| 173040 | } |
| 173041 | return 0; |
| 173042 | } |
| 173043 | } |
| 173044 | |
| 173045 | |
| 173046 | /* |
| 173047 | ** Initialize all term iterators in the pNear object. If any term is found |
| 173048 | ** to match no documents at all, return immediately without initializing any |
| 173049 | ** further iterators. |
| @@ -172701,10 +173054,11 @@ | |
| 173054 | ){ |
| 173055 | Fts5ExprNearset *pNear = pNode->pNear; |
| 173056 | int i, j; |
| 173057 | int rc = SQLITE_OK; |
| 173058 | |
| 173059 | assert( pNode->bNomatch==0 ); |
| 173060 | for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){ |
| 173061 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 173062 | for(j=0; j<pPhrase->nTerm; j++){ |
| 173063 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; |
| 173064 | Fts5ExprTerm *p; |
| @@ -172735,14 +173089,10 @@ | |
| 173089 | } |
| 173090 | } |
| 173091 | |
| 173092 | return rc; |
| 173093 | } |
| 173094 | |
| 173095 | /* |
| 173096 | ** If pExpr is an ASC iterator, this function returns a value with the |
| 173097 | ** same sign as: |
| 173098 | ** |
| @@ -172768,10 +173118,11 @@ | |
| 173118 | } |
| 173119 | |
| 173120 | static void fts5ExprSetEof(Fts5ExprNode *pNode){ |
| 173121 | int i; |
| 173122 | pNode->bEof = 1; |
| 173123 | pNode->bNomatch = 0; |
| 173124 | for(i=0; i<pNode->nChild; i++){ |
| 173125 | fts5ExprSetEof(pNode->apChild[i]); |
| 173126 | } |
| 173127 | } |
| 173128 | |
| @@ -172790,16 +173141,279 @@ | |
| 173141 | } |
| 173142 | } |
| 173143 | } |
| 173144 | |
| 173145 | |
| 173146 | |
| 173147 | /* |
| 173148 | ** Compare the values currently indicated by the two nodes as follows: |
| 173149 | ** |
| 173150 | ** res = (*p1) - (*p2) |
| 173151 | ** |
| 173152 | ** Nodes that point to values that come later in the iteration order are |
| 173153 | ** considered to be larger. Nodes at EOF are the largest of all. |
| 173154 | ** |
| 173155 | ** This means that if the iteration order is ASC, then numerically larger |
| 173156 | ** rowids are considered larger. Or if it is the default DESC, numerically |
| 173157 | ** smaller rowids are larger. |
| 173158 | */ |
| 173159 | static int fts5NodeCompare( |
| 173160 | Fts5Expr *pExpr, |
| 173161 | Fts5ExprNode *p1, |
| 173162 | Fts5ExprNode *p2 |
| 173163 | ){ |
| 173164 | if( p2->bEof ) return -1; |
| 173165 | if( p1->bEof ) return +1; |
| 173166 | return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); |
| 173167 | } |
| 173168 | |
| 173169 | /* |
| 173170 | ** All individual term iterators in pNear are guaranteed to be valid when |
| 173171 | ** this function is called. This function checks if all term iterators |
| 173172 | ** point to the same rowid, and if not, advances them until they do. |
| 173173 | ** If an EOF is reached before this happens, *pbEof is set to true before |
| 173174 | ** returning. |
| 173175 | ** |
| 173176 | ** SQLITE_OK is returned if an error occurs, or an SQLite error code |
| 173177 | ** otherwise. It is not considered an error code if an iterator reaches |
| 173178 | ** EOF. |
| 173179 | */ |
| 173180 | static int fts5ExprNodeTest_STRING( |
| 173181 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 173182 | Fts5ExprNode *pNode |
| 173183 | ){ |
| 173184 | Fts5ExprNearset *pNear = pNode->pNear; |
| 173185 | Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; |
| 173186 | int rc = SQLITE_OK; |
| 173187 | i64 iLast; /* Lastest rowid any iterator points to */ |
| 173188 | int i, j; /* Phrase and token index, respectively */ |
| 173189 | int bMatch; /* True if all terms are at the same rowid */ |
| 173190 | const int bDesc = pExpr->bDesc; |
| 173191 | |
| 173192 | /* Check that this node should not be FTS5_TERM */ |
| 173193 | assert( pNear->nPhrase>1 |
| 173194 | || pNear->apPhrase[0]->nTerm>1 |
| 173195 | || pNear->apPhrase[0]->aTerm[0].pSynonym |
| 173196 | ); |
| 173197 | |
| 173198 | /* Initialize iLast, the "lastest" rowid any iterator points to. If the |
| 173199 | ** iterator skips through rowids in the default ascending order, this means |
| 173200 | ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it |
| 173201 | ** means the minimum rowid. */ |
| 173202 | if( pLeft->aTerm[0].pSynonym ){ |
| 173203 | iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); |
| 173204 | }else{ |
| 173205 | iLast = pLeft->aTerm[0].pIter->iRowid; |
| 173206 | } |
| 173207 | |
| 173208 | do { |
| 173209 | bMatch = 1; |
| 173210 | for(i=0; i<pNear->nPhrase; i++){ |
| 173211 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 173212 | for(j=0; j<pPhrase->nTerm; j++){ |
| 173213 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; |
| 173214 | if( pTerm->pSynonym ){ |
| 173215 | i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); |
| 173216 | if( iRowid==iLast ) continue; |
| 173217 | bMatch = 0; |
| 173218 | if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ |
| 173219 | pNode->bNomatch = 0; |
| 173220 | pNode->bEof = 1; |
| 173221 | return rc; |
| 173222 | } |
| 173223 | }else{ |
| 173224 | Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; |
| 173225 | if( pIter->iRowid==iLast ) continue; |
| 173226 | bMatch = 0; |
| 173227 | if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ |
| 173228 | return rc; |
| 173229 | } |
| 173230 | } |
| 173231 | } |
| 173232 | } |
| 173233 | }while( bMatch==0 ); |
| 173234 | |
| 173235 | pNode->iRowid = iLast; |
| 173236 | pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK); |
| 173237 | assert( pNode->bEof==0 || pNode->bNomatch==0 ); |
| 173238 | |
| 173239 | return rc; |
| 173240 | } |
| 173241 | |
| 173242 | /* |
| 173243 | ** Advance the first term iterator in the first phrase of pNear. Set output |
| 173244 | ** variable *pbEof to true if it reaches EOF or if an error occurs. |
| 173245 | ** |
| 173246 | ** Return SQLITE_OK if successful, or an SQLite error code if an error |
| 173247 | ** occurs. |
| 173248 | */ |
| 173249 | static int fts5ExprNodeNext_STRING( |
| 173250 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 173251 | Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ |
| 173252 | int bFromValid, |
| 173253 | i64 iFrom |
| 173254 | ){ |
| 173255 | Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; |
| 173256 | int rc = SQLITE_OK; |
| 173257 | |
| 173258 | pNode->bNomatch = 0; |
| 173259 | if( pTerm->pSynonym ){ |
| 173260 | int bEof = 1; |
| 173261 | Fts5ExprTerm *p; |
| 173262 | |
| 173263 | /* Find the firstest rowid any synonym points to. */ |
| 173264 | i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); |
| 173265 | |
| 173266 | /* Advance each iterator that currently points to iRowid. Or, if iFrom |
| 173267 | ** is valid - each iterator that points to a rowid before iFrom. */ |
| 173268 | for(p=pTerm; p; p=p->pSynonym){ |
| 173269 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 173270 | i64 ii = p->pIter->iRowid; |
| 173271 | if( ii==iRowid |
| 173272 | || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) |
| 173273 | ){ |
| 173274 | if( bFromValid ){ |
| 173275 | rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); |
| 173276 | }else{ |
| 173277 | rc = sqlite3Fts5IterNext(p->pIter); |
| 173278 | } |
| 173279 | if( rc!=SQLITE_OK ) break; |
| 173280 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 173281 | bEof = 0; |
| 173282 | } |
| 173283 | }else{ |
| 173284 | bEof = 0; |
| 173285 | } |
| 173286 | } |
| 173287 | } |
| 173288 | |
| 173289 | /* Set the EOF flag if either all synonym iterators are at EOF or an |
| 173290 | ** error has occurred. */ |
| 173291 | pNode->bEof = (rc || bEof); |
| 173292 | }else{ |
| 173293 | Fts5IndexIter *pIter = pTerm->pIter; |
| 173294 | |
| 173295 | assert( Fts5NodeIsString(pNode) ); |
| 173296 | if( bFromValid ){ |
| 173297 | rc = sqlite3Fts5IterNextFrom(pIter, iFrom); |
| 173298 | }else{ |
| 173299 | rc = sqlite3Fts5IterNext(pIter); |
| 173300 | } |
| 173301 | |
| 173302 | pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); |
| 173303 | } |
| 173304 | |
| 173305 | if( pNode->bEof==0 ){ |
| 173306 | assert( rc==SQLITE_OK ); |
| 173307 | rc = fts5ExprNodeTest_STRING(pExpr, pNode); |
| 173308 | } |
| 173309 | |
| 173310 | return rc; |
| 173311 | } |
| 173312 | |
| 173313 | |
| 173314 | static int fts5ExprNodeTest_TERM( |
| 173315 | Fts5Expr *pExpr, /* Expression that pNear is a part of */ |
| 173316 | Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ |
| 173317 | ){ |
| 173318 | /* As this "NEAR" object is actually a single phrase that consists |
| 173319 | ** of a single term only, grab pointers into the poslist managed by the |
| 173320 | ** fts5_index.c iterator object. This is much faster than synthesizing |
| 173321 | ** a new poslist the way we have to for more complicated phrase or NEAR |
| 173322 | ** expressions. */ |
| 173323 | Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; |
| 173324 | Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 173325 | |
| 173326 | assert( pNode->eType==FTS5_TERM ); |
| 173327 | assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 ); |
| 173328 | assert( pPhrase->aTerm[0].pSynonym==0 ); |
| 173329 | |
| 173330 | pPhrase->poslist.n = pIter->nData; |
| 173331 | if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 173332 | pPhrase->poslist.p = (u8*)pIter->pData; |
| 173333 | } |
| 173334 | pNode->iRowid = pIter->iRowid; |
| 173335 | pNode->bNomatch = (pPhrase->poslist.n==0); |
| 173336 | return SQLITE_OK; |
| 173337 | } |
| 173338 | |
| 173339 | /* |
| 173340 | ** xNext() method for a node of type FTS5_TERM. |
| 173341 | */ |
| 173342 | static int fts5ExprNodeNext_TERM( |
| 173343 | Fts5Expr *pExpr, |
| 173344 | Fts5ExprNode *pNode, |
| 173345 | int bFromValid, |
| 173346 | i64 iFrom |
| 173347 | ){ |
| 173348 | int rc; |
| 173349 | Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; |
| 173350 | |
| 173351 | assert( pNode->bEof==0 ); |
| 173352 | if( bFromValid ){ |
| 173353 | rc = sqlite3Fts5IterNextFrom(pIter, iFrom); |
| 173354 | }else{ |
| 173355 | rc = sqlite3Fts5IterNext(pIter); |
| 173356 | } |
| 173357 | if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ |
| 173358 | rc = fts5ExprNodeTest_TERM(pExpr, pNode); |
| 173359 | }else{ |
| 173360 | pNode->bEof = 1; |
| 173361 | pNode->bNomatch = 0; |
| 173362 | } |
| 173363 | return rc; |
| 173364 | } |
| 173365 | |
| 173366 | static void fts5ExprNodeTest_OR( |
| 173367 | Fts5Expr *pExpr, /* Expression of which pNode is a part */ |
| 173368 | Fts5ExprNode *pNode /* Expression node to test */ |
| 173369 | ){ |
| 173370 | Fts5ExprNode *pNext = pNode->apChild[0]; |
| 173371 | int i; |
| 173372 | |
| 173373 | for(i=1; i<pNode->nChild; i++){ |
| 173374 | Fts5ExprNode *pChild = pNode->apChild[i]; |
| 173375 | int cmp = fts5NodeCompare(pExpr, pNext, pChild); |
| 173376 | if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ |
| 173377 | pNext = pChild; |
| 173378 | } |
| 173379 | } |
| 173380 | pNode->iRowid = pNext->iRowid; |
| 173381 | pNode->bEof = pNext->bEof; |
| 173382 | pNode->bNomatch = pNext->bNomatch; |
| 173383 | } |
| 173384 | |
| 173385 | static int fts5ExprNodeNext_OR( |
| 173386 | Fts5Expr *pExpr, |
| 173387 | Fts5ExprNode *pNode, |
| 173388 | int bFromValid, |
| 173389 | i64 iFrom |
| 173390 | ){ |
| 173391 | int i; |
| 173392 | i64 iLast = pNode->iRowid; |
| 173393 | |
| 173394 | for(i=0; i<pNode->nChild; i++){ |
| 173395 | Fts5ExprNode *p1 = pNode->apChild[i]; |
| 173396 | assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); |
| 173397 | if( p1->bEof==0 ){ |
| 173398 | if( (p1->iRowid==iLast) |
| 173399 | || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) |
| 173400 | ){ |
| 173401 | int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); |
| 173402 | if( rc!=SQLITE_OK ) return rc; |
| 173403 | } |
| 173404 | } |
| 173405 | } |
| 173406 | |
| 173407 | fts5ExprNodeTest_OR(pExpr, pNode); |
| 173408 | return SQLITE_OK; |
| 173409 | } |
| 173410 | |
| 173411 | /* |
| 173412 | ** Argument pNode is an FTS5_AND node. |
| 173413 | */ |
| 173414 | static int fts5ExprNodeTest_AND( |
| 173415 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 173416 | Fts5ExprNode *pAnd /* FTS5_AND node to advance */ |
| 173417 | ){ |
| 173418 | int iChild; |
| 173419 | i64 iLast = pAnd->iRowid; |
| @@ -172810,19 +173424,15 @@ | |
| 173424 | do { |
| 173425 | pAnd->bNomatch = 0; |
| 173426 | bMatch = 1; |
| 173427 | for(iChild=0; iChild<pAnd->nChild; iChild++){ |
| 173428 | Fts5ExprNode *pChild = pAnd->apChild[iChild]; |
| 173429 | int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); |
| 173430 | if( cmp>0 ){ |
| 173431 | /* Advance pChild until it points to iLast or laster */ |
| 173432 | rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); |
| 173433 | if( rc!=SQLITE_OK ) return rc; |
| 173434 | } |
| 173435 | |
| 173436 | /* If the child node is now at EOF, so is the parent AND node. Otherwise, |
| 173437 | ** the child node is guaranteed to have advanced at least as far as |
| 173438 | ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the |
| @@ -172848,190 +173458,99 @@ | |
| 173458 | } |
| 173459 | pAnd->iRowid = iLast; |
| 173460 | return SQLITE_OK; |
| 173461 | } |
| 173462 | |
| 173463 | static int fts5ExprNodeNext_AND( |
| 173464 | Fts5Expr *pExpr, |
| 173465 | Fts5ExprNode *pNode, |
| 173466 | int bFromValid, |
| 173467 | i64 iFrom |
| 173468 | ){ |
| 173469 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 173470 | if( rc==SQLITE_OK ){ |
| 173471 | rc = fts5ExprNodeTest_AND(pExpr, pNode); |
| 173472 | } |
| 173473 | return rc; |
| 173474 | } |
| 173475 | |
| 173476 | static int fts5ExprNodeTest_NOT( |
| 173477 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 173478 | Fts5ExprNode *pNode /* FTS5_NOT node to advance */ |
| 173479 | ){ |
| 173480 | int rc = SQLITE_OK; |
| 173481 | Fts5ExprNode *p1 = pNode->apChild[0]; |
| 173482 | Fts5ExprNode *p2 = pNode->apChild[1]; |
| 173483 | assert( pNode->nChild==2 ); |
| 173484 | |
| 173485 | while( rc==SQLITE_OK && p1->bEof==0 ){ |
| 173486 | int cmp = fts5NodeCompare(pExpr, p1, p2); |
| 173487 | if( cmp>0 ){ |
| 173488 | rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); |
| 173489 | cmp = fts5NodeCompare(pExpr, p1, p2); |
| 173490 | } |
| 173491 | assert( rc!=SQLITE_OK || cmp<=0 ); |
| 173492 | if( cmp || p2->bNomatch ) break; |
| 173493 | rc = fts5ExprNodeNext(pExpr, p1, 0, 0); |
| 173494 | } |
| 173495 | pNode->bEof = p1->bEof; |
| 173496 | pNode->bNomatch = p1->bNomatch; |
| 173497 | pNode->iRowid = p1->iRowid; |
| 173498 | if( p1->bEof ){ |
| 173499 | fts5ExprNodeZeroPoslist(p2); |
| 173500 | } |
| 173501 | return rc; |
| 173502 | } |
| 173503 | |
| 173504 | static int fts5ExprNodeNext_NOT( |
| 173505 | Fts5Expr *pExpr, |
| 173506 | Fts5ExprNode *pNode, |
| 173507 | int bFromValid, |
| 173508 | i64 iFrom |
| 173509 | ){ |
| 173510 | int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 173511 | if( rc==SQLITE_OK ){ |
| 173512 | rc = fts5ExprNodeTest_NOT(pExpr, pNode); |
| 173513 | } |
| 173514 | return rc; |
| 173515 | } |
| 173516 | |
| 173517 | /* |
| 173518 | ** If pNode currently points to a match, this function returns SQLITE_OK |
| 173519 | ** without modifying it. Otherwise, pNode is advanced until it does point |
| 173520 | ** to a match or EOF is reached. |
| 173521 | */ |
| 173522 | static int fts5ExprNodeTest( |
| 173523 | Fts5Expr *pExpr, /* Expression of which pNode is a part */ |
| 173524 | Fts5ExprNode *pNode /* Expression node to test */ |
| 173525 | ){ |
| 173526 | int rc = SQLITE_OK; |
| 173527 | if( pNode->bEof==0 ){ |
| 173528 | switch( pNode->eType ){ |
| 173529 | |
| 173530 | case FTS5_STRING: { |
| 173531 | rc = fts5ExprNodeTest_STRING(pExpr, pNode); |
| 173532 | break; |
| 173533 | } |
| 173534 | |
| 173535 | case FTS5_TERM: { |
| 173536 | rc = fts5ExprNodeTest_TERM(pExpr, pNode); |
| 173537 | break; |
| 173538 | } |
| 173539 | |
| 173540 | case FTS5_AND: { |
| 173541 | rc = fts5ExprNodeTest_AND(pExpr, pNode); |
| 173542 | break; |
| 173543 | } |
| 173544 | |
| 173545 | case FTS5_OR: { |
| 173546 | fts5ExprNodeTest_OR(pExpr, pNode); |
| 173547 | break; |
| 173548 | } |
| 173549 | |
| 173550 | default: assert( pNode->eType==FTS5_NOT ); { |
| 173551 | rc = fts5ExprNodeTest_NOT(pExpr, pNode); |
| 173552 | break; |
| 173553 | } |
| 173554 | } |
| 173555 | } |
| 173556 | return rc; |
| @@ -173046,24 +173565,44 @@ | |
| 173565 | ** It is not an error if there are no matches. |
| 173566 | */ |
| 173567 | static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ |
| 173568 | int rc = SQLITE_OK; |
| 173569 | pNode->bEof = 0; |
| 173570 | pNode->bNomatch = 0; |
| 173571 | |
| 173572 | if( Fts5NodeIsString(pNode) ){ |
| 173573 | /* Initialize all term iterators in the NEAR object. */ |
| 173574 | rc = fts5ExprNearInitAll(pExpr, pNode); |
| 173575 | }else{ |
| 173576 | int i; |
| 173577 | int nEof = 0; |
| 173578 | for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){ |
| 173579 | Fts5ExprNode *pChild = pNode->apChild[i]; |
| 173580 | rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]); |
| 173581 | assert( pChild->bEof==0 || pChild->bEof==1 ); |
| 173582 | nEof += pChild->bEof; |
| 173583 | } |
| 173584 | pNode->iRowid = pNode->apChild[0]->iRowid; |
| 173585 | |
| 173586 | switch( pNode->eType ){ |
| 173587 | case FTS5_AND: |
| 173588 | if( nEof>0 ) fts5ExprSetEof(pNode); |
| 173589 | break; |
| 173590 | |
| 173591 | case FTS5_OR: |
| 173592 | if( pNode->nChild==nEof ) fts5ExprSetEof(pNode); |
| 173593 | break; |
| 173594 | |
| 173595 | default: |
| 173596 | assert( pNode->eType==FTS5_NOT ); |
| 173597 | pNode->bEof = pNode->apChild[0]->bEof; |
| 173598 | break; |
| 173599 | } |
| 173600 | } |
| 173601 | |
| 173602 | if( rc==SQLITE_OK ){ |
| 173603 | rc = fts5ExprNodeTest(pExpr, pNode); |
| 173604 | } |
| 173605 | return rc; |
| 173606 | } |
| 173607 | |
| 173608 | |
| @@ -173083,11 +173622,11 @@ | |
| 173622 | ** is not considered an error if the query does not match any documents. |
| 173623 | */ |
| 173624 | static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ |
| 173625 | Fts5ExprNode *pRoot = p->pRoot; |
| 173626 | int rc = SQLITE_OK; |
| 173627 | if( pRoot->xNext ){ |
| 173628 | p->pIndex = pIdx; |
| 173629 | p->bDesc = bDesc; |
| 173630 | rc = fts5ExprNodeFirst(p, pRoot); |
| 173631 | |
| 173632 | /* If not at EOF but the current rowid occurs earlier than iFirst in |
| @@ -173095,11 +173634,12 @@ | |
| 173634 | if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ |
| 173635 | rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); |
| 173636 | } |
| 173637 | |
| 173638 | /* If the iterator is not at a real match, skip forward until it is. */ |
| 173639 | while( pRoot->bNomatch ){ |
| 173640 | assert( pRoot->bEof==0 && rc==SQLITE_OK ); |
| 173641 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173642 | } |
| 173643 | } |
| 173644 | return rc; |
| 173645 | } |
| @@ -173111,21 +173651,23 @@ | |
| 173651 | ** is not considered an error if the query does not match any documents. |
| 173652 | */ |
| 173653 | static int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ |
| 173654 | int rc; |
| 173655 | Fts5ExprNode *pRoot = p->pRoot; |
| 173656 | assert( pRoot->bEof==0 && pRoot->bNomatch==0 ); |
| 173657 | do { |
| 173658 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173659 | assert( pRoot->bNomatch==0 || (rc==SQLITE_OK && pRoot->bEof==0) ); |
| 173660 | }while( pRoot->bNomatch ); |
| 173661 | if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ |
| 173662 | pRoot->bEof = 1; |
| 173663 | } |
| 173664 | return rc; |
| 173665 | } |
| 173666 | |
| 173667 | static int sqlite3Fts5ExprEof(Fts5Expr *p){ |
| 173668 | return p->pRoot->bEof; |
| 173669 | } |
| 173670 | |
| 173671 | static i64 sqlite3Fts5ExprRowid(Fts5Expr *p){ |
| 173672 | return p->pRoot->iRowid; |
| 173673 | } |
| @@ -173146,14 +173688,14 @@ | |
| 173688 | Fts5ExprTerm *pSyn; |
| 173689 | Fts5ExprTerm *pNext; |
| 173690 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 173691 | sqlite3_free(pTerm->zTerm); |
| 173692 | sqlite3Fts5IterClose(pTerm->pIter); |
| 173693 | for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ |
| 173694 | pNext = pSyn->pSynonym; |
| 173695 | sqlite3Fts5IterClose(pSyn->pIter); |
| 173696 | fts5BufferFree((Fts5Buffer*)&pSyn[1]); |
| 173697 | sqlite3_free(pSyn); |
| 173698 | } |
| 173699 | } |
| 173700 | if( pPhrase->poslist.nSpace>0 ) fts5BufferFree(&pPhrase->poslist); |
| 173701 | sqlite3_free(pPhrase); |
| @@ -173237,17 +173779,17 @@ | |
| 173779 | if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; |
| 173780 | |
| 173781 | assert( pPhrase==0 || pPhrase->nTerm>0 ); |
| 173782 | if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ |
| 173783 | Fts5ExprTerm *pSyn; |
| 173784 | int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; |
| 173785 | pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); |
| 173786 | if( pSyn==0 ){ |
| 173787 | rc = SQLITE_NOMEM; |
| 173788 | }else{ |
| 173789 | memset(pSyn, 0, nByte); |
| 173790 | pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); |
| 173791 | memcpy(pSyn->zTerm, pToken, nToken); |
| 173792 | pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; |
| 173793 | pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; |
| 173794 | } |
| 173795 | }else{ |
| @@ -173422,12 +173964,14 @@ | |
| 173964 | pNew->pRoot->pNear->nPhrase = 1; |
| 173965 | sCtx.pPhrase->pNode = pNew->pRoot; |
| 173966 | |
| 173967 | if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ |
| 173968 | pNew->pRoot->eType = FTS5_TERM; |
| 173969 | pNew->pRoot->xNext = fts5ExprNodeNext_TERM; |
| 173970 | }else{ |
| 173971 | pNew->pRoot->eType = FTS5_STRING; |
| 173972 | pNew->pRoot->xNext = fts5ExprNodeNext_STRING; |
| 173973 | } |
| 173974 | }else{ |
| 173975 | sqlite3Fts5ExprFree(pNew); |
| 173976 | fts5ExprPhraseFree(sCtx.pPhrase); |
| 173977 | pNew = 0; |
| @@ -173570,10 +174114,42 @@ | |
| 174114 | pNear->pColset = pColset; |
| 174115 | }else{ |
| 174116 | sqlite3_free(pColset); |
| 174117 | } |
| 174118 | } |
| 174119 | |
| 174120 | static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ |
| 174121 | switch( pNode->eType ){ |
| 174122 | case FTS5_STRING: { |
| 174123 | Fts5ExprNearset *pNear = pNode->pNear; |
| 174124 | if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 |
| 174125 | && pNear->apPhrase[0]->aTerm[0].pSynonym==0 |
| 174126 | ){ |
| 174127 | pNode->eType = FTS5_TERM; |
| 174128 | pNode->xNext = fts5ExprNodeNext_TERM; |
| 174129 | }else{ |
| 174130 | pNode->xNext = fts5ExprNodeNext_STRING; |
| 174131 | } |
| 174132 | break; |
| 174133 | }; |
| 174134 | |
| 174135 | case FTS5_OR: { |
| 174136 | pNode->xNext = fts5ExprNodeNext_OR; |
| 174137 | break; |
| 174138 | }; |
| 174139 | |
| 174140 | case FTS5_AND: { |
| 174141 | pNode->xNext = fts5ExprNodeNext_AND; |
| 174142 | break; |
| 174143 | }; |
| 174144 | |
| 174145 | default: assert( pNode->eType==FTS5_NOT ); { |
| 174146 | pNode->xNext = fts5ExprNodeNext_NOT; |
| 174147 | break; |
| 174148 | }; |
| 174149 | } |
| 174150 | } |
| 174151 | |
| 174152 | static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ |
| 174153 | if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){ |
| 174154 | int nByte = sizeof(Fts5ExprNode*) * pSub->nChild; |
| 174155 | memcpy(&p->apChild[p->nChild], pSub->apChild, nByte); |
| @@ -173620,20 +174196,20 @@ | |
| 174196 | pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); |
| 174197 | |
| 174198 | if( pRet ){ |
| 174199 | pRet->eType = eType; |
| 174200 | pRet->pNear = pNear; |
| 174201 | fts5ExprAssignXNext(pRet); |
| 174202 | if( eType==FTS5_STRING ){ |
| 174203 | int iPhrase; |
| 174204 | for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){ |
| 174205 | pNear->apPhrase[iPhrase]->pNode = pRet; |
| 174206 | } |
| 174207 | |
| 174208 | if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL |
| 174209 | && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1) |
| 174210 | ){ |
| 174211 | assert( pParse->rc==SQLITE_OK ); |
| 174212 | pParse->rc = SQLITE_ERROR; |
| 174213 | assert( pParse->zErr==0 ); |
| 174214 | pParse->zErr = sqlite3_mprintf( |
| 174215 | "fts5: %s queries are not supported (detail!=full)", |
| @@ -173640,10 +174216,11 @@ | |
| 174216 | pNear->nPhrase==1 ? "phrase": "NEAR" |
| 174217 | ); |
| 174218 | sqlite3_free(pRet); |
| 174219 | pRet = 0; |
| 174220 | } |
| 174221 | |
| 174222 | }else{ |
| 174223 | fts5ExprAddChildren(pRet, pLeft); |
| 174224 | fts5ExprAddChildren(pRet, pRight); |
| 174225 | } |
| 174226 | } |
| @@ -173922,11 +174499,11 @@ | |
| 174499 | if( rc==SQLITE_OK ){ |
| 174500 | rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr); |
| 174501 | } |
| 174502 | if( rc==SQLITE_OK ){ |
| 174503 | char *zText; |
| 174504 | if( pExpr->pRoot->xNext==0 ){ |
| 174505 | zText = sqlite3_mprintf(""); |
| 174506 | }else if( bTcl ){ |
| 174507 | zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot); |
| 174508 | }else{ |
| 174509 | zText = fts5ExprPrint(pConfig, pExpr->pRoot); |
| @@ -174022,11 +174599,11 @@ | |
| 174599 | }; |
| 174600 | int i; |
| 174601 | int rc = SQLITE_OK; |
| 174602 | void *pCtx = (void*)pGlobal; |
| 174603 | |
| 174604 | for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){ |
| 174605 | struct Fts5ExprFunc *p = &aFunc[i]; |
| 174606 | rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); |
| 174607 | } |
| 174608 | |
| 174609 | /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ |
| @@ -174260,30 +174837,25 @@ | |
| 174837 | Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase]; |
| 174838 | Fts5ExprNode *pNode = pPhrase->pNode; |
| 174839 | int rc = SQLITE_OK; |
| 174840 | |
| 174841 | assert( iPhrase>=0 && iPhrase<pExpr->nPhrase ); |
| 174842 | assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); |
| 174843 | |
| 174844 | if( pNode->bEof==0 |
| 174845 | && pNode->iRowid==pExpr->pRoot->iRowid |
| 174846 | && pPhrase->poslist.n>0 |
| 174847 | ){ |
| 174848 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; |
| 174849 | if( pTerm->pSynonym ){ |
| 174850 | Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1]; |
| 174851 | rc = fts5ExprSynonymList( |
| 174852 | pTerm, 1, 0, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist |
| 174853 | ); |
| 174854 | }else{ |
| 174855 | *ppCollist = pPhrase->aTerm[0].pIter->pData; |
| 174856 | *pnCollist = pPhrase->aTerm[0].pIter->nData; |
| 174857 | } |
| 174858 | }else{ |
| 174859 | *ppCollist = 0; |
| 174860 | *pnCollist = 0; |
| 174861 | } |
| @@ -175080,10 +175652,11 @@ | |
| 175652 | |
| 175653 | typedef struct Fts5Data Fts5Data; |
| 175654 | typedef struct Fts5DlidxIter Fts5DlidxIter; |
| 175655 | typedef struct Fts5DlidxLvl Fts5DlidxLvl; |
| 175656 | typedef struct Fts5DlidxWriter Fts5DlidxWriter; |
| 175657 | typedef struct Fts5Iter Fts5Iter; |
| 175658 | typedef struct Fts5PageWriter Fts5PageWriter; |
| 175659 | typedef struct Fts5SegIter Fts5SegIter; |
| 175660 | typedef struct Fts5DoclistIter Fts5DoclistIter; |
| 175661 | typedef struct Fts5SegWriter Fts5SegWriter; |
| 175662 | typedef struct Fts5Structure Fts5Structure; |
| @@ -175322,20 +175895,24 @@ | |
| 175895 | ** |
| 175896 | ** poslist: |
| 175897 | ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. |
| 175898 | ** There is no way to tell if this is populated or not. |
| 175899 | */ |
| 175900 | struct Fts5Iter { |
| 175901 | Fts5IndexIter base; /* Base class containing output vars */ |
| 175902 | |
| 175903 | Fts5Index *pIndex; /* Index that owns this iterator */ |
| 175904 | Fts5Structure *pStruct; /* Database structure for this iterator */ |
| 175905 | Fts5Buffer poslist; /* Buffer containing current poslist */ |
| 175906 | Fts5Colset *pColset; /* Restrict matches to these columns */ |
| 175907 | |
| 175908 | /* Invoked to set output variables. */ |
| 175909 | void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*); |
| 175910 | |
| 175911 | int nSeg; /* Size of aSeg[] array */ |
| 175912 | int bRev; /* True to iterate in reverse order */ |
| 175913 | u8 bSkipEmpty; /* True to skip deleted entries */ |
| 175914 | |
| 175915 | i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ |
| 175916 | Fts5CResult *aFirst; /* Current merge state (see above) */ |
| 175917 | Fts5SegIter aSeg[1]; /* Array of segment iterators */ |
| 175918 | }; |
| @@ -176571,11 +177148,11 @@ | |
| 177148 | /* |
| 177149 | ** Return true if the iterator passed as the second argument currently |
| 177150 | ** points to a delete marker. A delete marker is an entry with a 0 byte |
| 177151 | ** position-list. |
| 177152 | */ |
| 177153 | static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){ |
| 177154 | Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; |
| 177155 | return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0); |
| 177156 | } |
| 177157 | |
| 177158 | /* |
| @@ -176843,13 +177420,10 @@ | |
| 177420 | iPoslist = pIter->iTermLeafOffset; |
| 177421 | }else{ |
| 177422 | iPoslist = 4; |
| 177423 | } |
| 177424 | fts5IndexSkipVarint(pLeaf->p, iPoslist); |
| 177425 | pIter->iLeafOffset = iPoslist; |
| 177426 | |
| 177427 | /* If this condition is true then the largest rowid for the current |
| 177428 | ** term may not be stored on the current page. So search forward to |
| 177429 | ** see where said rowid really is. */ |
| @@ -177077,13 +177651,10 @@ | |
| 177651 | ){ |
| 177652 | int iPg = 1; |
| 177653 | int bGe = (flags & FTS5INDEX_QUERY_SCAN); |
| 177654 | int bDlidx = 0; /* True if there is a doclist-index */ |
| 177655 | |
| 177656 | assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); |
| 177657 | assert( pTerm && nTerm ); |
| 177658 | memset(pIter, 0, sizeof(*pIter)); |
| 177659 | pIter->pSeg = pSeg; |
| 177660 | |
| @@ -177225,11 +177796,11 @@ | |
| 177796 | ** fts5AssertMultiIterSetup(). It ensures that the result currently stored |
| 177797 | ** in *pRes is the correct result of comparing the current positions of the |
| 177798 | ** two iterators. |
| 177799 | */ |
| 177800 | static void fts5AssertComparisonResult( |
| 177801 | Fts5Iter *pIter, |
| 177802 | Fts5SegIter *p1, |
| 177803 | Fts5SegIter *p2, |
| 177804 | Fts5CResult *pRes |
| 177805 | ){ |
| 177806 | int i1 = p1 - pIter->aSeg; |
| @@ -177266,16 +177837,16 @@ | |
| 177837 | ** This function is a no-op unless SQLITE_DEBUG is defined when this module |
| 177838 | ** is compiled. In that case, this function is essentially an assert() |
| 177839 | ** statement used to verify that the contents of the pIter->aFirst[] array |
| 177840 | ** are correct. |
| 177841 | */ |
| 177842 | static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){ |
| 177843 | if( p->rc==SQLITE_OK ){ |
| 177844 | Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177845 | int i; |
| 177846 | |
| 177847 | assert( (pFirst->pLeaf==0)==pIter->base.bEof ); |
| 177848 | |
| 177849 | /* Check that pIter->iSwitchRowid is set correctly. */ |
| 177850 | for(i=0; i<pIter->nSeg; i++){ |
| 177851 | Fts5SegIter *p1 = &pIter->aSeg[i]; |
| 177852 | assert( p1==pFirst |
| @@ -177311,11 +177882,11 @@ | |
| 177882 | ** If the returned value is non-zero, then it is the index of an entry |
| 177883 | ** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing |
| 177884 | ** to a key that is a duplicate of another, higher priority, |
| 177885 | ** segment-iterator in the pSeg->aSeg[] array. |
| 177886 | */ |
| 177887 | static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ |
| 177888 | int i1; /* Index of left-hand Fts5SegIter */ |
| 177889 | int i2; /* Index of right-hand Fts5SegIter */ |
| 177890 | int iRes; |
| 177891 | Fts5SegIter *p1; /* Left-hand Fts5SegIter */ |
| 177892 | Fts5SegIter *p2; /* Right-hand Fts5SegIter */ |
| @@ -177457,11 +178028,11 @@ | |
| 178028 | |
| 178029 | |
| 178030 | /* |
| 178031 | ** Free the iterator object passed as the second argument. |
| 178032 | */ |
| 178033 | static void fts5MultiIterFree(Fts5Index *p, Fts5Iter *pIter){ |
| 178034 | if( pIter ){ |
| 178035 | int i; |
| 178036 | for(i=0; i<pIter->nSeg; i++){ |
| 178037 | fts5SegIterClear(&pIter->aSeg[i]); |
| 178038 | } |
| @@ -177471,11 +178042,11 @@ | |
| 178042 | } |
| 178043 | } |
| 178044 | |
| 178045 | static void fts5MultiIterAdvanced( |
| 178046 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 178047 | Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ |
| 178048 | int iChanged, /* Index of sub-iterator just advanced */ |
| 178049 | int iMinset /* Minimum entry in aFirst[] to set */ |
| 178050 | ){ |
| 178051 | int i; |
| 178052 | for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){ |
| @@ -177499,12 +178070,13 @@ | |
| 178070 | ** on the iterator instead. That function does the same as this one, except |
| 178071 | ** that it deals with more complicated cases as well. |
| 178072 | */ |
| 178073 | static int fts5MultiIterAdvanceRowid( |
| 178074 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 178075 | Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ |
| 178076 | int iChanged, /* Index of sub-iterator just advanced */ |
| 178077 | Fts5SegIter **ppFirst |
| 178078 | ){ |
| 178079 | Fts5SegIter *pNew = &pIter->aSeg[iChanged]; |
| 178080 | |
| 178081 | if( pNew->iRowid==pIter->iSwitchRowid |
| 178082 | || (pNew->iRowid<pIter->iSwitchRowid)==pIter->bRev |
| @@ -177533,19 +178105,20 @@ | |
| 178105 | |
| 178106 | pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ]; |
| 178107 | } |
| 178108 | } |
| 178109 | |
| 178110 | *ppFirst = pNew; |
| 178111 | return 0; |
| 178112 | } |
| 178113 | |
| 178114 | /* |
| 178115 | ** Set the pIter->bEof variable based on the state of the sub-iterators. |
| 178116 | */ |
| 178117 | static void fts5MultiIterSetEof(Fts5Iter *pIter){ |
| 178118 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 178119 | pIter->base.bEof = pSeg->pLeaf==0; |
| 178120 | pIter->iSwitchRowid = pSeg->iRowid; |
| 178121 | } |
| 178122 | |
| 178123 | /* |
| 178124 | ** Move the iterator to the next entry. |
| @@ -177554,43 +178127,48 @@ | |
| 178127 | ** considered an error if the iterator reaches EOF, or if it is already at |
| 178128 | ** EOF when this function is called. |
| 178129 | */ |
| 178130 | static void fts5MultiIterNext( |
| 178131 | Fts5Index *p, |
| 178132 | Fts5Iter *pIter, |
| 178133 | int bFrom, /* True if argument iFrom is valid */ |
| 178134 | i64 iFrom /* Advance at least as far as this */ |
| 178135 | ){ |
| 178136 | int bUseFrom = bFrom; |
| 178137 | while( p->rc==SQLITE_OK ){ |
| 178138 | int iFirst = pIter->aFirst[1].iFirst; |
| 178139 | int bNewTerm = 0; |
| 178140 | Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; |
| 178141 | assert( p->rc==SQLITE_OK ); |
| 178142 | if( bUseFrom && pSeg->pDlidx ){ |
| 178143 | fts5SegIterNextFrom(p, pSeg, iFrom); |
| 178144 | }else{ |
| 178145 | pSeg->xNext(p, pSeg, &bNewTerm); |
| 178146 | } |
| 178147 | |
| 178148 | if( pSeg->pLeaf==0 || bNewTerm |
| 178149 | || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) |
| 178150 | ){ |
| 178151 | fts5MultiIterAdvanced(p, pIter, iFirst, 1); |
| 178152 | fts5MultiIterSetEof(pIter); |
| 178153 | pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; |
| 178154 | if( pSeg->pLeaf==0 ) return; |
| 178155 | } |
| 178156 | |
| 178157 | fts5AssertMultiIterSetup(p, pIter); |
| 178158 | assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); |
| 178159 | if( pIter->bSkipEmpty==0 || pSeg->nPos ){ |
| 178160 | pIter->xSetOutputs(pIter, pSeg); |
| 178161 | return; |
| 178162 | } |
| 178163 | bUseFrom = 0; |
| 178164 | } |
| 178165 | } |
| 178166 | |
| 178167 | static void fts5MultiIterNext2( |
| 178168 | Fts5Index *p, |
| 178169 | Fts5Iter *pIter, |
| 178170 | int *pbNewTerm /* OUT: True if *might* be new term */ |
| 178171 | ){ |
| 178172 | assert( pIter->bSkipEmpty ); |
| 178173 | if( p->rc==SQLITE_OK ){ |
| 178174 | do { |
| @@ -177599,11 +178177,11 @@ | |
| 178177 | int bNewTerm = 0; |
| 178178 | |
| 178179 | assert( p->rc==SQLITE_OK ); |
| 178180 | pSeg->xNext(p, pSeg, &bNewTerm); |
| 178181 | if( pSeg->pLeaf==0 || bNewTerm |
| 178182 | || fts5MultiIterAdvanceRowid(p, pIter, iFirst, &pSeg) |
| 178183 | ){ |
| 178184 | fts5MultiIterAdvanced(p, pIter, iFirst, 1); |
| 178185 | fts5MultiIterSetEof(pIter); |
| 178186 | *pbNewTerm = 1; |
| 178187 | }else{ |
| @@ -177613,220 +178191,143 @@ | |
| 178191 | |
| 178192 | }while( fts5MultiIterIsEmpty(p, pIter) ); |
| 178193 | } |
| 178194 | } |
| 178195 | |
| 178196 | static void fts5IterSetOutputs_Noop(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178197 | } |
| 178198 | |
| 178199 | static Fts5Iter *fts5MultiIterAlloc( |
| 178200 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 178201 | int nSeg |
| 178202 | ){ |
| 178203 | Fts5Iter *pNew; |
| 178204 | int nSlot; /* Power of two >= nSeg */ |
| 178205 | |
| 178206 | for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2); |
| 178207 | pNew = fts5IdxMalloc(p, |
| 178208 | sizeof(Fts5Iter) + /* pNew */ |
| 178209 | sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */ |
| 178210 | sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ |
| 178211 | ); |
| 178212 | if( pNew ){ |
| 178213 | pNew->nSeg = nSlot; |
| 178214 | pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; |
| 178215 | pNew->pIndex = p; |
| 178216 | pNew->xSetOutputs = fts5IterSetOutputs_Noop; |
| 178217 | } |
| 178218 | return pNew; |
| 178219 | } |
| 178220 | |
| 178221 | static void fts5PoslistCallback( |
| 178222 | Fts5Index *p, |
| 178223 | void *pContext, |
| 178224 | const u8 *pChunk, int nChunk |
| 178225 | ){ |
| 178226 | assert_nc( nChunk>=0 ); |
| 178227 | if( nChunk>0 ){ |
| 178228 | fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); |
| 178229 | } |
| 178230 | } |
| 178231 | |
| 178232 | typedef struct PoslistCallbackCtx PoslistCallbackCtx; |
| 178233 | struct PoslistCallbackCtx { |
| 178234 | Fts5Buffer *pBuf; /* Append to this buffer */ |
| 178235 | Fts5Colset *pColset; /* Restrict matches to this column */ |
| 178236 | int eState; /* See above */ |
| 178237 | }; |
| 178238 | |
| 178239 | typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; |
| 178240 | struct PoslistOffsetsCtx { |
| 178241 | Fts5Buffer *pBuf; /* Append to this buffer */ |
| 178242 | Fts5Colset *pColset; /* Restrict matches to this column */ |
| 178243 | int iRead; |
| 178244 | int iWrite; |
| 178245 | }; |
| 178246 | |
| 178247 | /* |
| 178248 | ** TODO: Make this more efficient! |
| 178249 | */ |
| 178250 | static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ |
| 178251 | int i; |
| 178252 | for(i=0; i<pColset->nCol; i++){ |
| 178253 | if( pColset->aiCol[i]==iCol ) return 1; |
| 178254 | } |
| 178255 | return 0; |
| 178256 | } |
| 178257 | |
| 178258 | static void fts5PoslistOffsetsCallback( |
| 178259 | Fts5Index *p, |
| 178260 | void *pContext, |
| 178261 | const u8 *pChunk, int nChunk |
| 178262 | ){ |
| 178263 | PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; |
| 178264 | assert_nc( nChunk>=0 ); |
| 178265 | if( nChunk>0 ){ |
| 178266 | int i = 0; |
| 178267 | while( i<nChunk ){ |
| 178268 | int iVal; |
| 178269 | i += fts5GetVarint32(&pChunk[i], iVal); |
| 178270 | iVal += pCtx->iRead - 2; |
| 178271 | pCtx->iRead = iVal; |
| 178272 | if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ |
| 178273 | fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); |
| 178274 | pCtx->iWrite = iVal; |
| 178275 | } |
| 178276 | } |
| 178277 | } |
| 178278 | } |
| 178279 | |
| 178280 | static void fts5PoslistFilterCallback( |
| 178281 | Fts5Index *p, |
| 178282 | void *pContext, |
| 178283 | const u8 *pChunk, int nChunk |
| 178284 | ){ |
| 178285 | PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; |
| 178286 | assert_nc( nChunk>=0 ); |
| 178287 | if( nChunk>0 ){ |
| 178288 | /* Search through to find the first varint with value 1. This is the |
| 178289 | ** start of the next columns hits. */ |
| 178290 | int i = 0; |
| 178291 | int iStart = 0; |
| 178292 | |
| 178293 | if( pCtx->eState==2 ){ |
| 178294 | int iCol; |
| 178295 | fts5FastGetVarint32(pChunk, i, iCol); |
| 178296 | if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ |
| 178297 | pCtx->eState = 1; |
| 178298 | fts5BufferSafeAppendVarint(pCtx->pBuf, 1); |
| 178299 | }else{ |
| 178300 | pCtx->eState = 0; |
| 178301 | } |
| 178302 | } |
| 178303 | |
| 178304 | do { |
| 178305 | while( i<nChunk && pChunk[i]!=0x01 ){ |
| 178306 | while( pChunk[i] & 0x80 ) i++; |
| 178307 | i++; |
| 178308 | } |
| 178309 | if( pCtx->eState ){ |
| 178310 | fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 178311 | } |
| 178312 | if( i<nChunk ){ |
| 178313 | int iCol; |
| 178314 | iStart = i; |
| 178315 | i++; |
| 178316 | if( i>=nChunk ){ |
| 178317 | pCtx->eState = 2; |
| 178318 | }else{ |
| 178319 | fts5FastGetVarint32(pChunk, i, iCol); |
| 178320 | pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); |
| 178321 | if( pCtx->eState ){ |
| 178322 | fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 178323 | iStart = i; |
| 178324 | } |
| 178325 | } |
| 178326 | } |
| 178327 | }while( i<nChunk ); |
| 178328 | } |
| 178329 | } |
| 178330 | |
| 178331 | static void fts5ChunkIterate( |
| 178332 | Fts5Index *p, /* Index object */ |
| 178333 | Fts5SegIter *pSeg, /* Poslist of this iterator */ |
| @@ -177866,11 +178367,462 @@ | |
| 178367 | } |
| 178368 | } |
| 178369 | } |
| 178370 | } |
| 178371 | |
| 178372 | /* |
| 178373 | ** Iterator pIter currently points to a valid entry (not EOF). This |
| 178374 | ** function appends the position list data for the current entry to |
| 178375 | ** buffer pBuf. It does not make a copy of the position-list size |
| 178376 | ** field. |
| 178377 | */ |
| 178378 | static void fts5SegiterPoslist( |
| 178379 | Fts5Index *p, |
| 178380 | Fts5SegIter *pSeg, |
| 178381 | Fts5Colset *pColset, |
| 178382 | Fts5Buffer *pBuf |
| 178383 | ){ |
| 178384 | if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ |
| 178385 | if( pColset==0 ){ |
| 178386 | fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); |
| 178387 | }else{ |
| 178388 | if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 178389 | PoslistCallbackCtx sCtx; |
| 178390 | sCtx.pBuf = pBuf; |
| 178391 | sCtx.pColset = pColset; |
| 178392 | sCtx.eState = fts5IndexColsetTest(pColset, 0); |
| 178393 | assert( sCtx.eState==0 || sCtx.eState==1 ); |
| 178394 | fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); |
| 178395 | }else{ |
| 178396 | PoslistOffsetsCtx sCtx; |
| 178397 | memset(&sCtx, 0, sizeof(sCtx)); |
| 178398 | sCtx.pBuf = pBuf; |
| 178399 | sCtx.pColset = pColset; |
| 178400 | fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); |
| 178401 | } |
| 178402 | } |
| 178403 | } |
| 178404 | } |
| 178405 | |
| 178406 | /* |
| 178407 | ** IN/OUT parameter (*pa) points to a position list n bytes in size. If |
| 178408 | ** the position list contains entries for column iCol, then (*pa) is set |
| 178409 | ** to point to the sub-position-list for that column and the number of |
| 178410 | ** bytes in it returned. Or, if the argument position list does not |
| 178411 | ** contain any entries for column iCol, return 0. |
| 178412 | */ |
| 178413 | static int fts5IndexExtractCol( |
| 178414 | const u8 **pa, /* IN/OUT: Pointer to poslist */ |
| 178415 | int n, /* IN: Size of poslist in bytes */ |
| 178416 | int iCol /* Column to extract from poslist */ |
| 178417 | ){ |
| 178418 | int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ |
| 178419 | const u8 *p = *pa; |
| 178420 | const u8 *pEnd = &p[n]; /* One byte past end of position list */ |
| 178421 | |
| 178422 | while( iCol>iCurrent ){ |
| 178423 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 178424 | ** not part of a varint. Note that it is not possible for a negative |
| 178425 | ** or extremely large varint to occur within an uncorrupted position |
| 178426 | ** list. So the last byte of each varint may be assumed to have a clear |
| 178427 | ** 0x80 bit. */ |
| 178428 | while( *p!=0x01 ){ |
| 178429 | while( *p++ & 0x80 ); |
| 178430 | if( p>=pEnd ) return 0; |
| 178431 | } |
| 178432 | *pa = p++; |
| 178433 | iCurrent = *p++; |
| 178434 | if( iCurrent & 0x80 ){ |
| 178435 | p--; |
| 178436 | p += fts5GetVarint32(p, iCurrent); |
| 178437 | } |
| 178438 | } |
| 178439 | if( iCol!=iCurrent ) return 0; |
| 178440 | |
| 178441 | /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 178442 | ** not part of a varint */ |
| 178443 | while( p<pEnd && *p!=0x01 ){ |
| 178444 | while( *p++ & 0x80 ); |
| 178445 | } |
| 178446 | |
| 178447 | return p - (*pa); |
| 178448 | } |
| 178449 | |
| 178450 | static int fts5IndexExtractColset ( |
| 178451 | Fts5Colset *pColset, /* Colset to filter on */ |
| 178452 | const u8 *pPos, int nPos, /* Position list */ |
| 178453 | Fts5Buffer *pBuf /* Output buffer */ |
| 178454 | ){ |
| 178455 | int rc = SQLITE_OK; |
| 178456 | int i; |
| 178457 | |
| 178458 | fts5BufferZero(pBuf); |
| 178459 | for(i=0; i<pColset->nCol; i++){ |
| 178460 | const u8 *pSub = pPos; |
| 178461 | int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); |
| 178462 | if( nSub ){ |
| 178463 | fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); |
| 178464 | } |
| 178465 | } |
| 178466 | return rc; |
| 178467 | } |
| 178468 | |
| 178469 | /* |
| 178470 | ** xSetOutputs callback used by detail=none tables. |
| 178471 | */ |
| 178472 | static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178473 | assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE ); |
| 178474 | pIter->base.iRowid = pSeg->iRowid; |
| 178475 | pIter->base.nData = pSeg->nPos; |
| 178476 | } |
| 178477 | |
| 178478 | /* |
| 178479 | ** xSetOutputs callback used by detail=full and detail=col tables when no |
| 178480 | ** column filters are specified. |
| 178481 | */ |
| 178482 | static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178483 | pIter->base.iRowid = pSeg->iRowid; |
| 178484 | pIter->base.nData = pSeg->nPos; |
| 178485 | |
| 178486 | assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); |
| 178487 | assert( pIter->pColset==0 ); |
| 178488 | |
| 178489 | if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ |
| 178490 | /* All data is stored on the current page. Populate the output |
| 178491 | ** variables to point into the body of the page object. */ |
| 178492 | pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 178493 | }else{ |
| 178494 | /* The data is distributed over two or more pages. Copy it into the |
| 178495 | ** Fts5Iter.poslist buffer and then set the output pointer to point |
| 178496 | ** to this buffer. */ |
| 178497 | fts5BufferZero(&pIter->poslist); |
| 178498 | fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); |
| 178499 | pIter->base.pData = pIter->poslist.p; |
| 178500 | } |
| 178501 | } |
| 178502 | |
| 178503 | /* |
| 178504 | ** xSetOutputs callback used by detail=col when there is a column filter |
| 178505 | ** and there are 100 or more columns. Also called as a fallback from |
| 178506 | ** fts5IterSetOutputs_Col100 if the column-list spans more than one page. |
| 178507 | */ |
| 178508 | static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178509 | fts5BufferZero(&pIter->poslist); |
| 178510 | fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist); |
| 178511 | pIter->base.iRowid = pSeg->iRowid; |
| 178512 | pIter->base.pData = pIter->poslist.p; |
| 178513 | pIter->base.nData = pIter->poslist.n; |
| 178514 | } |
| 178515 | |
| 178516 | /* |
| 178517 | ** xSetOutputs callback used when: |
| 178518 | ** |
| 178519 | ** * detail=col, |
| 178520 | ** * there is a column filter, and |
| 178521 | ** * the table contains 100 or fewer columns. |
| 178522 | ** |
| 178523 | ** The last point is to ensure all column numbers are stored as |
| 178524 | ** single-byte varints. |
| 178525 | */ |
| 178526 | static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178527 | |
| 178528 | assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); |
| 178529 | assert( pIter->pColset ); |
| 178530 | |
| 178531 | if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ |
| 178532 | fts5IterSetOutputs_Col(pIter, pSeg); |
| 178533 | }else{ |
| 178534 | u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 178535 | u8 *pEnd = (u8*)&a[pSeg->nPos]; |
| 178536 | int iPrev = 0; |
| 178537 | int *aiCol = pIter->pColset->aiCol; |
| 178538 | int *aiColEnd = &aiCol[pIter->pColset->nCol]; |
| 178539 | |
| 178540 | u8 *aOut = pIter->poslist.p; |
| 178541 | int iPrevOut = 0; |
| 178542 | |
| 178543 | pIter->base.iRowid = pSeg->iRowid; |
| 178544 | |
| 178545 | while( a<pEnd ){ |
| 178546 | iPrev += (int)a++[0] - 2; |
| 178547 | while( *aiCol<iPrev ){ |
| 178548 | aiCol++; |
| 178549 | if( aiCol==aiColEnd ) goto setoutputs_col_out; |
| 178550 | } |
| 178551 | if( *aiCol==iPrev ){ |
| 178552 | *aOut++ = (iPrev - iPrevOut) + 2; |
| 178553 | iPrevOut = iPrev; |
| 178554 | } |
| 178555 | } |
| 178556 | |
| 178557 | setoutputs_col_out: |
| 178558 | pIter->base.pData = pIter->poslist.p; |
| 178559 | pIter->base.nData = aOut - pIter->poslist.p; |
| 178560 | } |
| 178561 | } |
| 178562 | |
| 178563 | /* |
| 178564 | ** xSetOutputs callback used by detail=full when there is a column filter. |
| 178565 | */ |
| 178566 | static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178567 | Fts5Colset *pColset = pIter->pColset; |
| 178568 | pIter->base.iRowid = pSeg->iRowid; |
| 178569 | |
| 178570 | assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); |
| 178571 | assert( pColset ); |
| 178572 | |
| 178573 | if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ |
| 178574 | /* All data is stored on the current page. Populate the output |
| 178575 | ** variables to point into the body of the page object. */ |
| 178576 | const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 178577 | if( pColset->nCol==1 ){ |
| 178578 | pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); |
| 178579 | pIter->base.pData = a; |
| 178580 | }else{ |
| 178581 | fts5BufferZero(&pIter->poslist); |
| 178582 | fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist); |
| 178583 | pIter->base.pData = pIter->poslist.p; |
| 178584 | pIter->base.nData = pIter->poslist.n; |
| 178585 | } |
| 178586 | }else{ |
| 178587 | /* The data is distributed over two or more pages. Copy it into the |
| 178588 | ** Fts5Iter.poslist buffer and then set the output pointer to point |
| 178589 | ** to this buffer. */ |
| 178590 | fts5BufferZero(&pIter->poslist); |
| 178591 | fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); |
| 178592 | pIter->base.pData = pIter->poslist.p; |
| 178593 | pIter->base.nData = pIter->poslist.n; |
| 178594 | } |
| 178595 | } |
| 178596 | |
| 178597 | static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ |
| 178598 | if( *pRc==SQLITE_OK ){ |
| 178599 | Fts5Config *pConfig = pIter->pIndex->pConfig; |
| 178600 | if( pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 178601 | pIter->xSetOutputs = fts5IterSetOutputs_None; |
| 178602 | } |
| 178603 | |
| 178604 | else if( pIter->pColset==0 ){ |
| 178605 | pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; |
| 178606 | } |
| 178607 | |
| 178608 | else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 178609 | pIter->xSetOutputs = fts5IterSetOutputs_Full; |
| 178610 | } |
| 178611 | |
| 178612 | else{ |
| 178613 | assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); |
| 178614 | if( pConfig->nCol<=100 ){ |
| 178615 | pIter->xSetOutputs = fts5IterSetOutputs_Col100; |
| 178616 | sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); |
| 178617 | }else{ |
| 178618 | pIter->xSetOutputs = fts5IterSetOutputs_Col; |
| 178619 | } |
| 178620 | } |
| 178621 | } |
| 178622 | } |
| 178623 | |
| 178624 | |
| 178625 | /* |
| 178626 | ** Allocate a new Fts5Iter object. |
| 178627 | ** |
| 178628 | ** The new object will be used to iterate through data in structure pStruct. |
| 178629 | ** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel |
| 178630 | ** is zero or greater, data from the first nSegment segments on level iLevel |
| 178631 | ** is merged. |
| 178632 | ** |
| 178633 | ** The iterator initially points to the first term/rowid entry in the |
| 178634 | ** iterated data. |
| 178635 | */ |
| 178636 | static void fts5MultiIterNew( |
| 178637 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 178638 | Fts5Structure *pStruct, /* Structure of specific index */ |
| 178639 | int flags, /* FTS5INDEX_QUERY_XXX flags */ |
| 178640 | Fts5Colset *pColset, /* Colset to filter on (or NULL) */ |
| 178641 | const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ |
| 178642 | int iLevel, /* Level to iterate (-1 for all) */ |
| 178643 | int nSegment, /* Number of segments to merge (iLevel>=0) */ |
| 178644 | Fts5Iter **ppOut /* New object */ |
| 178645 | ){ |
| 178646 | int nSeg = 0; /* Number of segment-iters in use */ |
| 178647 | int iIter = 0; /* */ |
| 178648 | int iSeg; /* Used to iterate through segments */ |
| 178649 | Fts5Buffer buf = {0,0,0}; /* Buffer used by fts5SegIterSeekInit() */ |
| 178650 | Fts5StructureLevel *pLvl; |
| 178651 | Fts5Iter *pNew; |
| 178652 | |
| 178653 | assert( (pTerm==0 && nTerm==0) || iLevel<0 ); |
| 178654 | |
| 178655 | /* Allocate space for the new multi-seg-iterator. */ |
| 178656 | if( p->rc==SQLITE_OK ){ |
| 178657 | if( iLevel<0 ){ |
| 178658 | assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); |
| 178659 | nSeg = pStruct->nSegment; |
| 178660 | nSeg += (p->pHash ? 1 : 0); |
| 178661 | }else{ |
| 178662 | nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); |
| 178663 | } |
| 178664 | } |
| 178665 | *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); |
| 178666 | if( pNew==0 ) return; |
| 178667 | pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); |
| 178668 | pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY)); |
| 178669 | pNew->pStruct = pStruct; |
| 178670 | pNew->pColset = pColset; |
| 178671 | fts5StructureRef(pStruct); |
| 178672 | if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){ |
| 178673 | fts5IterSetOutputCb(&p->rc, pNew); |
| 178674 | } |
| 178675 | |
| 178676 | /* Initialize each of the component segment iterators. */ |
| 178677 | if( p->rc==SQLITE_OK ){ |
| 178678 | if( iLevel<0 ){ |
| 178679 | Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; |
| 178680 | if( p->pHash ){ |
| 178681 | /* Add a segment iterator for the current contents of the hash table. */ |
| 178682 | Fts5SegIter *pIter = &pNew->aSeg[iIter++]; |
| 178683 | fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); |
| 178684 | } |
| 178685 | for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){ |
| 178686 | for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){ |
| 178687 | Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; |
| 178688 | Fts5SegIter *pIter = &pNew->aSeg[iIter++]; |
| 178689 | if( pTerm==0 ){ |
| 178690 | fts5SegIterInit(p, pSeg, pIter); |
| 178691 | }else{ |
| 178692 | fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter); |
| 178693 | } |
| 178694 | } |
| 178695 | } |
| 178696 | }else{ |
| 178697 | pLvl = &pStruct->aLevel[iLevel]; |
| 178698 | for(iSeg=nSeg-1; iSeg>=0; iSeg--){ |
| 178699 | fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); |
| 178700 | } |
| 178701 | } |
| 178702 | assert( iIter==nSeg ); |
| 178703 | } |
| 178704 | |
| 178705 | /* If the above was successful, each component iterators now points |
| 178706 | ** to the first entry in its segment. In this case initialize the |
| 178707 | ** aFirst[] array. Or, if an error has occurred, free the iterator |
| 178708 | ** object and set the output variable to NULL. */ |
| 178709 | if( p->rc==SQLITE_OK ){ |
| 178710 | for(iIter=pNew->nSeg-1; iIter>0; iIter--){ |
| 178711 | int iEq; |
| 178712 | if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ |
| 178713 | Fts5SegIter *pSeg = &pNew->aSeg[iEq]; |
| 178714 | if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); |
| 178715 | fts5MultiIterAdvanced(p, pNew, iEq, iIter); |
| 178716 | } |
| 178717 | } |
| 178718 | fts5MultiIterSetEof(pNew); |
| 178719 | fts5AssertMultiIterSetup(p, pNew); |
| 178720 | |
| 178721 | if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ |
| 178722 | fts5MultiIterNext(p, pNew, 0, 0); |
| 178723 | }else if( pNew->base.bEof==0 ){ |
| 178724 | Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; |
| 178725 | pNew->xSetOutputs(pNew, pSeg); |
| 178726 | } |
| 178727 | |
| 178728 | }else{ |
| 178729 | fts5MultiIterFree(p, pNew); |
| 178730 | *ppOut = 0; |
| 178731 | } |
| 178732 | fts5BufferFree(&buf); |
| 178733 | |
| 178734 | } |
| 178735 | |
| 178736 | /* |
| 178737 | ** Create an Fts5Iter that iterates through the doclist provided |
| 178738 | ** as the second argument. |
| 178739 | */ |
| 178740 | static void fts5MultiIterNew2( |
| 178741 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 178742 | Fts5Data *pData, /* Doclist to iterate through */ |
| 178743 | int bDesc, /* True for descending rowid order */ |
| 178744 | Fts5Iter **ppOut /* New object */ |
| 178745 | ){ |
| 178746 | Fts5Iter *pNew; |
| 178747 | pNew = fts5MultiIterAlloc(p, 2); |
| 178748 | if( pNew ){ |
| 178749 | Fts5SegIter *pIter = &pNew->aSeg[1]; |
| 178750 | |
| 178751 | pIter->flags = FTS5_SEGITER_ONETERM; |
| 178752 | if( pData->szLeaf>0 ){ |
| 178753 | pIter->pLeaf = pData; |
| 178754 | pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); |
| 178755 | pIter->iEndofDoclist = pData->nn; |
| 178756 | pNew->aFirst[1].iFirst = 1; |
| 178757 | if( bDesc ){ |
| 178758 | pNew->bRev = 1; |
| 178759 | pIter->flags |= FTS5_SEGITER_REVERSE; |
| 178760 | fts5SegIterReverseInitPage(p, pIter); |
| 178761 | }else{ |
| 178762 | fts5SegIterLoadNPos(p, pIter); |
| 178763 | } |
| 178764 | pData = 0; |
| 178765 | }else{ |
| 178766 | pNew->base.bEof = 1; |
| 178767 | } |
| 178768 | fts5SegIterSetNext(p, pIter); |
| 178769 | |
| 178770 | *ppOut = pNew; |
| 178771 | } |
| 178772 | |
| 178773 | fts5DataRelease(pData); |
| 178774 | } |
| 178775 | |
| 178776 | /* |
| 178777 | ** Return true if the iterator is at EOF or if an error has occurred. |
| 178778 | ** False otherwise. |
| 178779 | */ |
| 178780 | static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){ |
| 178781 | assert( p->rc |
| 178782 | || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof |
| 178783 | ); |
| 178784 | return (p->rc || pIter->base.bEof); |
| 178785 | } |
| 178786 | |
| 178787 | /* |
| 178788 | ** Return the rowid of the entry that the iterator currently points |
| 178789 | ** to. If the iterator points to EOF when this function is called the |
| 178790 | ** results are undefined. |
| 178791 | */ |
| 178792 | static i64 fts5MultiIterRowid(Fts5Iter *pIter){ |
| 178793 | assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); |
| 178794 | return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; |
| 178795 | } |
| 178796 | |
| 178797 | /* |
| 178798 | ** Move the iterator to the next entry at or following iMatch. |
| 178799 | */ |
| 178800 | static void fts5MultiIterNextFrom( |
| 178801 | Fts5Index *p, |
| 178802 | Fts5Iter *pIter, |
| 178803 | i64 iMatch |
| 178804 | ){ |
| 178805 | while( 1 ){ |
| 178806 | i64 iRowid; |
| 178807 | fts5MultiIterNext(p, pIter, 1, iMatch); |
| 178808 | if( fts5MultiIterEof(p, pIter) ) break; |
| 178809 | iRowid = fts5MultiIterRowid(pIter); |
| 178810 | if( pIter->bRev==0 && iRowid>=iMatch ) break; |
| 178811 | if( pIter->bRev!=0 && iRowid<=iMatch ) break; |
| 178812 | } |
| 178813 | } |
| 178814 | |
| 178815 | /* |
| 178816 | ** Return a pointer to a buffer containing the term associated with the |
| 178817 | ** entry that the iterator currently points to. |
| 178818 | */ |
| 178819 | static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){ |
| 178820 | Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 178821 | *pn = p->term.n; |
| 178822 | return p->term.p; |
| 178823 | } |
| 178824 | |
| 178825 | /* |
| 178826 | ** Allocate a new segment-id for the structure pStruct. The new segment |
| 178827 | ** id must be between 1 and 65335 inclusive, and must not be used by |
| 178828 | ** any currently existing segment. If a free segment id cannot be found, |
| @@ -178401,11 +179353,11 @@ | |
| 179353 | /* |
| 179354 | ** Iterator pIter was used to iterate through the input segments of on an |
| 179355 | ** incremental merge operation. This function is called if the incremental |
| 179356 | ** merge step has finished but the input has not been completely exhausted. |
| 179357 | */ |
| 179358 | static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ |
| 179359 | int i; |
| 179360 | Fts5Buffer buf; |
| 179361 | memset(&buf, 0, sizeof(Fts5Buffer)); |
| 179362 | for(i=0; i<pIter->nSeg; i++){ |
| 179363 | Fts5SegIter *pSeg = &pIter->aSeg[i]; |
| @@ -178479,18 +179431,19 @@ | |
| 179431 | int *pnRem /* Write up to this many output leaves */ |
| 179432 | ){ |
| 179433 | Fts5Structure *pStruct = *ppStruct; |
| 179434 | Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; |
| 179435 | Fts5StructureLevel *pLvlOut; |
| 179436 | Fts5Iter *pIter = 0; /* Iterator to read input data */ |
| 179437 | int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */ |
| 179438 | int nInput; /* Number of input segments */ |
| 179439 | Fts5SegWriter writer; /* Writer object */ |
| 179440 | Fts5StructureSegment *pSeg; /* Output segment */ |
| 179441 | Fts5Buffer term; |
| 179442 | int bOldest; /* True if the output segment is the oldest */ |
| 179443 | int eDetail = p->pConfig->eDetail; |
| 179444 | const int flags = FTS5INDEX_QUERY_NOOUTPUT; |
| 179445 | |
| 179446 | assert( iLvl<pStruct->nLevel ); |
| 179447 | assert( pLvl->nMerge<=pLvl->nSeg ); |
| 179448 | |
| 179449 | memset(&writer, 0, sizeof(Fts5SegWriter)); |
| @@ -178531,11 +179484,11 @@ | |
| 179484 | nInput = pLvl->nSeg; |
| 179485 | } |
| 179486 | bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); |
| 179487 | |
| 179488 | assert( iLvl>=0 ); |
| 179489 | for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter); |
| 179490 | fts5MultiIterEof(p, pIter)==0; |
| 179491 | fts5MultiIterNext(p, pIter, 0, 0) |
| 179492 | ){ |
| 179493 | Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 179494 | int nPos; /* position-list size field value */ |
| @@ -178976,279 +179929,32 @@ | |
| 179929 | fts5StructureRelease(pStruct); |
| 179930 | |
| 179931 | return fts5IndexReturn(p); |
| 179932 | } |
| 179933 | |
| 179934 | static void fts5AppendRowid( |
| 179935 | Fts5Index *p, |
| 179936 | i64 iDelta, |
| 179937 | Fts5Iter *pMulti, |
| 179938 | Fts5Buffer *pBuf |
| 179939 | ){ |
| 179940 | fts5BufferAppendVarint(&p->rc, pBuf, iDelta); |
| 179941 | } |
| 179942 | |
| 179943 | static void fts5AppendPoslist( |
| 179944 | Fts5Index *p, |
| 179945 | i64 iDelta, |
| 179946 | Fts5Iter *pMulti, |
| 179947 | Fts5Buffer *pBuf |
| 179948 | ){ |
| 179949 | int nData = pMulti->base.nData; |
| 179950 | assert( nData>0 ); |
| 179951 | if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){ |
| 179952 | fts5BufferSafeAppendVarint(pBuf, iDelta); |
| 179953 | fts5BufferSafeAppendVarint(pBuf, nData*2); |
| 179954 | fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData); |
| 179955 | } |
| 179956 | } |
| 179957 | |
| 179958 | |
| 179959 | static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ |
| 179960 | u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist; |
| @@ -179388,73 +180094,107 @@ | |
| 180094 | ){ |
| 180095 | if( p2->n ){ |
| 180096 | i64 iLastRowid = 0; |
| 180097 | Fts5DoclistIter i1; |
| 180098 | Fts5DoclistIter i2; |
| 180099 | Fts5Buffer out = {0, 0, 0}; |
| 180100 | Fts5Buffer tmp = {0, 0, 0}; |
| 180101 | |
| 180102 | if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; |
| 180103 | fts5DoclistIterInit(p1, &i1); |
| 180104 | fts5DoclistIterInit(p2, &i2); |
| 180105 | |
| 180106 | while( 1 ){ |
| 180107 | if( i1.iRowid<i2.iRowid ){ |
| 180108 | /* Copy entry from i1 */ |
| 180109 | fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); |
| 180110 | fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize); |
| 180111 | fts5DoclistIterNext(&i1); |
| 180112 | if( i1.aPoslist==0 ) break; |
| 180113 | } |
| 180114 | else if( i2.iRowid!=i1.iRowid ){ |
| 180115 | /* Copy entry from i2 */ |
| 180116 | fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 180117 | fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize); |
| 180118 | fts5DoclistIterNext(&i2); |
| 180119 | if( i2.aPoslist==0 ) break; |
| 180120 | } |
| 180121 | else{ |
| 180122 | /* Merge the two position lists. */ |
| 180123 | i64 iPos1 = 0; |
| 180124 | i64 iPos2 = 0; |
| 180125 | int iOff1 = 0; |
| 180126 | int iOff2 = 0; |
| 180127 | u8 *a1 = &i1.aPoslist[i1.nSize]; |
| 180128 | u8 *a2 = &i2.aPoslist[i2.nSize]; |
| 180129 | |
| 180130 | i64 iPrev = 0; |
| 180131 | Fts5PoslistWriter writer; |
| 180132 | memset(&writer, 0, sizeof(writer)); |
| 180133 | |
| 180134 | fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 180135 | fts5BufferZero(&tmp); |
| 180136 | sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist); |
| 180137 | if( p->rc ) break; |
| 180138 | |
| 180139 | sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 180140 | sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 180141 | assert( iPos1>=0 && iPos2>=0 ); |
| 180142 | |
| 180143 | if( iPos1<iPos2 ){ |
| 180144 | sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); |
| 180145 | sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 180146 | }else{ |
| 180147 | sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); |
| 180148 | sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 180149 | } |
| 180150 | |
| 180151 | if( iPos1>=0 && iPos2>=0 ){ |
| 180152 | while( 1 ){ |
| 180153 | if( iPos1<iPos2 ){ |
| 180154 | if( iPos1!=iPrev ){ |
| 180155 | sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); |
| 180156 | } |
| 180157 | sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 180158 | if( iPos1<0 ) break; |
| 180159 | }else{ |
| 180160 | assert( iPos2!=iPrev ); |
| 180161 | sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); |
| 180162 | sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 180163 | if( iPos2<0 ) break; |
| 180164 | } |
| 180165 | } |
| 180166 | } |
| 180167 | |
| 180168 | if( iPos1>=0 ){ |
| 180169 | if( iPos1!=iPrev ){ |
| 180170 | sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); |
| 180171 | } |
| 180172 | fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); |
| 180173 | }else{ |
| 180174 | assert( iPos2>=0 && iPos2!=iPrev ); |
| 180175 | sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); |
| 180176 | fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); |
| 180177 | } |
| 180178 | |
| 180179 | /* WRITEPOSLISTSIZE */ |
| 180180 | fts5BufferSafeAppendVarint(&out, tmp.n * 2); |
| 180181 | fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); |
| 180182 | fts5DoclistIterNext(&i1); |
| 180183 | fts5DoclistIterNext(&i2); |
| 180184 | if( i1.aPoslist==0 || i2.aPoslist==0 ) break; |
| 180185 | } |
| 180186 | } |
| 180187 | |
| 180188 | if( i1.aPoslist ){ |
| 180189 | fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); |
| 180190 | fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist); |
| 180191 | } |
| 180192 | else if( i2.aPoslist ){ |
| 180193 | fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 180194 | fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); |
| 180195 | } |
| 180196 | |
| 180197 | fts5BufferSet(&p->rc, p1, out.n, out.p); |
| 180198 | fts5BufferFree(&tmp); |
| 180199 | fts5BufferFree(&out); |
| 180200 | } |
| @@ -179464,18 +180204,18 @@ | |
| 180204 | Fts5Index *p, /* Index to read from */ |
| 180205 | int bDesc, /* True for "ORDER BY rowid DESC" */ |
| 180206 | const u8 *pToken, /* Buffer containing prefix to match */ |
| 180207 | int nToken, /* Size of buffer pToken in bytes */ |
| 180208 | Fts5Colset *pColset, /* Restrict matches to these columns */ |
| 180209 | Fts5Iter **ppIter /* OUT: New iterator */ |
| 180210 | ){ |
| 180211 | Fts5Structure *pStruct; |
| 180212 | Fts5Buffer *aBuf; |
| 180213 | const int nBuf = 32; |
| 180214 | |
| 180215 | void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); |
| 180216 | void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*); |
| 180217 | if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 180218 | xMerge = fts5MergeRowidLists; |
| 180219 | xAppend = fts5AppendRowid; |
| 180220 | }else{ |
| 180221 | xMerge = fts5MergePrefixLists; |
| @@ -179484,32 +180224,40 @@ | |
| 180224 | |
| 180225 | aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf); |
| 180226 | pStruct = fts5StructureRead(p); |
| 180227 | |
| 180228 | if( aBuf && pStruct ){ |
| 180229 | const int flags = FTS5INDEX_QUERY_SCAN |
| 180230 | | FTS5INDEX_QUERY_SKIPEMPTY |
| 180231 | | FTS5INDEX_QUERY_NOOUTPUT; |
| 180232 | int i; |
| 180233 | i64 iLastRowid = 0; |
| 180234 | Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ |
| 180235 | Fts5Data *pData; |
| 180236 | Fts5Buffer doclist; |
| 180237 | int bNewTerm = 1; |
| 180238 | |
| 180239 | memset(&doclist, 0, sizeof(doclist)); |
| 180240 | fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1); |
| 180241 | fts5IterSetOutputCb(&p->rc, p1); |
| 180242 | for( /* no-op */ ; |
| 180243 | fts5MultiIterEof(p, p1)==0; |
| 180244 | fts5MultiIterNext2(p, p1, &bNewTerm) |
| 180245 | ){ |
| 180246 | Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ]; |
| 180247 | int nTerm = pSeg->term.n; |
| 180248 | const u8 *pTerm = pSeg->term.p; |
| 180249 | p1->xSetOutputs(p1, pSeg); |
| 180250 | |
| 180251 | assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 ); |
| 180252 | if( bNewTerm ){ |
| 180253 | if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break; |
| 180254 | } |
| 180255 | |
| 180256 | if( p1->base.nData==0 ) continue; |
| 180257 | |
| 180258 | if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){ |
| 180259 | for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ |
| 180260 | assert( i<nBuf ); |
| 180261 | if( aBuf[i].n==0 ){ |
| 180262 | fts5BufferSwap(&doclist, &aBuf[i]); |
| 180263 | fts5BufferZero(&doclist); |
| @@ -179519,13 +180267,12 @@ | |
| 180267 | } |
| 180268 | } |
| 180269 | iLastRowid = 0; |
| 180270 | } |
| 180271 | |
| 180272 | xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist); |
| 180273 | iLastRowid = p1->base.iRowid; |
| 180274 | } |
| 180275 | |
| 180276 | for(i=0; i<nBuf; i++){ |
| 180277 | if( p->rc==SQLITE_OK ){ |
| 180278 | xMerge(p, &doclist, &aBuf[i]); |
| @@ -179591,11 +180338,11 @@ | |
| 180338 | ** records must be invalidated. |
| 180339 | */ |
| 180340 | static int sqlite3Fts5IndexRollback(Fts5Index *p){ |
| 180341 | fts5CloseReader(p); |
| 180342 | fts5IndexDiscardData(p); |
| 180343 | /* assert( p->rc==SQLITE_OK ); */ |
| 180344 | return SQLITE_OK; |
| 180345 | } |
| 180346 | |
| 180347 | /* |
| 180348 | ** The %_data table is completely empty when this function is called. This |
| @@ -179763,26 +180510,31 @@ | |
| 180510 | int flags, /* Mask of FTS5INDEX_QUERY_X flags */ |
| 180511 | Fts5Colset *pColset, /* Match these columns only */ |
| 180512 | Fts5IndexIter **ppIter /* OUT: New iterator object */ |
| 180513 | ){ |
| 180514 | Fts5Config *pConfig = p->pConfig; |
| 180515 | Fts5Iter *pRet = 0; |
| 180516 | Fts5Buffer buf = {0, 0, 0}; |
| 180517 | |
| 180518 | /* If the QUERY_SCAN flag is set, all other flags must be clear. */ |
| 180519 | assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); |
| 180520 | |
| 180521 | if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ |
| 180522 | int iIdx = 0; /* Index to search */ |
| 180523 | memcpy(&buf.p[1], pToken, nToken); |
| 180524 | |
| 180525 | /* Figure out which index to search and set iIdx accordingly. If this |
| 180526 | ** is a prefix query for which there is no prefix index, set iIdx to |
| 180527 | ** greater than pConfig->nPrefix to indicate that the query will be |
| 180528 | ** satisfied by scanning multiple terms in the main index. |
| 180529 | ** |
| 180530 | ** If the QUERY_TEST_NOIDX flag was specified, then this must be a |
| 180531 | ** prefix-query. Instead of using a prefix-index (if one exists), |
| 180532 | ** evaluate the prefix query using the main FTS index. This is used |
| 180533 | ** for internal sanity checking by the integrity-check in debug |
| 180534 | ** mode only. */ |
| 180535 | #ifdef SQLITE_DEBUG |
| 180536 | if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ |
| 180537 | assert( flags & FTS5INDEX_QUERY_PREFIX ); |
| 180538 | iIdx = 1+pConfig->nPrefix; |
| 180539 | }else |
| 180540 | #endif |
| @@ -179792,54 +180544,62 @@ | |
| 180544 | if( pConfig->aPrefix[iIdx-1]==nChar ) break; |
| 180545 | } |
| 180546 | } |
| 180547 | |
| 180548 | if( iIdx<=pConfig->nPrefix ){ |
| 180549 | /* Straight index lookup */ |
| 180550 | Fts5Structure *pStruct = fts5StructureRead(p); |
| 180551 | buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); |
| 180552 | if( pStruct ){ |
| 180553 | fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, |
| 180554 | pColset, buf.p, nToken+1, -1, 0, &pRet |
| 180555 | ); |
| 180556 | fts5StructureRelease(pStruct); |
| 180557 | } |
| 180558 | }else{ |
| 180559 | /* Scan multiple terms in the main index */ |
| 180560 | int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; |
| 180561 | buf.p[0] = FTS5_MAIN_PREFIX; |
| 180562 | fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); |
| 180563 | assert( pRet->pColset==0 ); |
| 180564 | fts5IterSetOutputCb(&p->rc, pRet); |
| 180565 | if( p->rc==SQLITE_OK ){ |
| 180566 | Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; |
| 180567 | if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); |
| 180568 | } |
| 180569 | } |
| 180570 | |
| 180571 | if( p->rc ){ |
| 180572 | sqlite3Fts5IterClose(&pRet->base); |
| 180573 | pRet = 0; |
| 180574 | fts5CloseReader(p); |
| 180575 | } |
| 180576 | |
| 180577 | *ppIter = &pRet->base; |
| 180578 | sqlite3Fts5BufferFree(&buf); |
| 180579 | } |
| 180580 | return fts5IndexReturn(p); |
| 180581 | } |
| 180582 | |
| 180583 | /* |
| 180584 | ** Return true if the iterator passed as the only argument is at EOF. |
| 180585 | */ |
| 180586 | /* |
| 180587 | ** Move to the next matching rowid. |
| 180588 | */ |
| 180589 | static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){ |
| 180590 | Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 180591 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 180592 | fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); |
| 180593 | return fts5IndexReturn(pIter->pIndex); |
| 180594 | } |
| 180595 | |
| 180596 | /* |
| 180597 | ** Move to the next matching term/rowid. Used by the fts5vocab module. |
| 180598 | */ |
| 180599 | static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){ |
| 180600 | Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 180601 | Fts5Index *p = pIter->pIndex; |
| 180602 | |
| 180603 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 180604 | |
| 180605 | fts5MultiIterNext(p, pIter, 0, 0); |
| @@ -179846,11 +180606,11 @@ | |
| 180606 | if( p->rc==SQLITE_OK ){ |
| 180607 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 180608 | if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){ |
| 180609 | fts5DataRelease(pSeg->pLeaf); |
| 180610 | pSeg->pLeaf = 0; |
| 180611 | pIter->base.bEof = 1; |
| 180612 | } |
| 180613 | } |
| 180614 | |
| 180615 | return fts5IndexReturn(pIter->pIndex); |
| 180616 | } |
| @@ -179858,133 +180618,32 @@ | |
| 180618 | /* |
| 180619 | ** Move to the next matching rowid that occurs at or after iMatch. The |
| 180620 | ** definition of "at or after" depends on whether this iterator iterates |
| 180621 | ** in ascending or descending rowid order. |
| 180622 | */ |
| 180623 | static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ |
| 180624 | Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 180625 | fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); |
| 180626 | return fts5IndexReturn(pIter->pIndex); |
| 180627 | } |
| 180628 | |
| 180629 | /* |
| 180630 | ** Return the current term. |
| 180631 | */ |
| 180632 | static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ |
| 180633 | int n; |
| 180634 | const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n); |
| 180635 | *pn = n-1; |
| 180636 | return &z[1]; |
| 180637 | } |
| 180638 | |
| 180639 | /* |
| 180640 | ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). |
| 180641 | */ |
| 180642 | static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ |
| 180643 | if( pIndexIter ){ |
| 180644 | Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 180645 | Fts5Index *pIndex = pIter->pIndex; |
| 180646 | fts5MultiIterFree(pIter->pIndex, pIter); |
| 180647 | fts5CloseReader(pIndex); |
| 180648 | } |
| 180649 | } |
| @@ -180147,39 +180806,34 @@ | |
| 180806 | int flags, /* Flags for Fts5IndexQuery */ |
| 180807 | u64 *pCksum /* IN/OUT: Checksum value */ |
| 180808 | ){ |
| 180809 | int eDetail = p->pConfig->eDetail; |
| 180810 | u64 cksum = *pCksum; |
| 180811 | Fts5IndexIter *pIter = 0; |
| 180812 | int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); |
| 180813 | |
| 180814 | while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){ |
| 180815 | i64 rowid = pIter->iRowid; |
| 180816 | |
| 180817 | if( eDetail==FTS5_DETAIL_NONE ){ |
| 180818 | cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); |
| 180819 | }else{ |
| 180820 | Fts5PoslistReader sReader; |
| 180821 | for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader); |
| 180822 | sReader.bEof==0; |
| 180823 | sqlite3Fts5PoslistReaderNext(&sReader) |
| 180824 | ){ |
| 180825 | int iCol = FTS5_POS2COLUMN(sReader.iPos); |
| 180826 | int iOff = FTS5_POS2OFFSET(sReader.iPos); |
| 180827 | cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); |
| 180828 | } |
| 180829 | } |
| 180830 | if( rc==SQLITE_OK ){ |
| 180831 | rc = sqlite3Fts5IterNext(pIter); |
| 180832 | } |
| 180833 | } |
| 180834 | sqlite3Fts5IterClose(pIter); |
| 180835 | |
| 180836 | *pCksum = cksum; |
| 180837 | return rc; |
| 180838 | } |
| 180839 | |
| @@ -180480,18 +181134,19 @@ | |
| 181134 | */ |
| 181135 | static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ |
| 181136 | int eDetail = p->pConfig->eDetail; |
| 181137 | u64 cksum2 = 0; /* Checksum based on contents of indexes */ |
| 181138 | Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ |
| 181139 | Fts5Iter *pIter; /* Used to iterate through entire index */ |
| 181140 | Fts5Structure *pStruct; /* Index structure */ |
| 181141 | |
| 181142 | #ifdef SQLITE_DEBUG |
| 181143 | /* Used by extra internal tests only run if NDEBUG is not defined */ |
| 181144 | u64 cksum3 = 0; /* Checksum based on contents of indexes */ |
| 181145 | Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ |
| 181146 | #endif |
| 181147 | const int flags = FTS5INDEX_QUERY_NOOUTPUT; |
| 181148 | |
| 181149 | /* Load the FTS index structure */ |
| 181150 | pStruct = fts5StructureRead(p); |
| 181151 | |
| 181152 | /* Check that the internal nodes of each segment match the leaves */ |
| @@ -180516,11 +181171,11 @@ | |
| 181171 | ** |
| 181172 | ** As each term visited by the linear scans, a separate query for the |
| 181173 | ** same term is performed. cksum3 is calculated based on the entries |
| 181174 | ** extracted by these queries. |
| 181175 | */ |
| 181176 | for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter); |
| 181177 | fts5MultiIterEof(p, pIter)==0; |
| 181178 | fts5MultiIterNext(p, pIter, 0, 0) |
| 181179 | ){ |
| 181180 | int n; /* Size of term in bytes */ |
| 181181 | i64 iPos = 0; /* Position read from poslist */ |
| @@ -181234,14 +181889,14 @@ | |
| 181889 | #define FTS5_BI_ORDER_DESC 0x0080 |
| 181890 | |
| 181891 | /* |
| 181892 | ** Values for Fts5Cursor.csrflags |
| 181893 | */ |
| 181894 | #define FTS5CSR_EOF 0x01 |
| 181895 | #define FTS5CSR_REQUIRE_CONTENT 0x02 |
| 181896 | #define FTS5CSR_REQUIRE_DOCSIZE 0x04 |
| 181897 | #define FTS5CSR_REQUIRE_INST 0x08 |
| 181898 | #define FTS5CSR_FREE_ZRANK 0x10 |
| 181899 | #define FTS5CSR_REQUIRE_RESEEK 0x20 |
| 181900 | #define FTS5CSR_REQUIRE_POSLIST 0x40 |
| 181901 | |
| 181902 | #define BitFlagAllTest(x,y) (((x) & (y))==(y)) |
| @@ -181552,11 +182207,11 @@ | |
| 182207 | |
| 182208 | /* Set idxFlags flags for all WHERE clause terms that will be used. */ |
| 182209 | for(i=0; i<pInfo->nConstraint; i++){ |
| 182210 | struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; |
| 182211 | int j; |
| 182212 | for(j=0; j<ArraySize(aConstraint); j++){ |
| 182213 | struct Constraint *pC = &aConstraint[j]; |
| 182214 | if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){ |
| 182215 | if( p->usable ){ |
| 182216 | pC->iConsIndex = i; |
| 182217 | idxFlags |= pC->fts5op; |
| @@ -181599,11 +182254,11 @@ | |
| 182254 | pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; |
| 182255 | } |
| 182256 | |
| 182257 | /* Assign argvIndex values to each constraint in use. */ |
| 182258 | iNext = 1; |
| 182259 | for(i=0; i<ArraySize(aConstraint); i++){ |
| 182260 | struct Constraint *pC = &aConstraint[i]; |
| 182261 | if( pC->iConsIndex>=0 ){ |
| 182262 | pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; |
| 182263 | pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; |
| 182264 | } |
| @@ -181792,18 +182447,19 @@ | |
| 182447 | Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); |
| 182448 | int bDesc = pCsr->bDesc; |
| 182449 | i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); |
| 182450 | |
| 182451 | rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); |
| 182452 | if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ |
| 182453 | *pbSkip = 1; |
| 182454 | } |
| 182455 | |
| 182456 | CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); |
| 182457 | fts5CsrNewrow(pCsr); |
| 182458 | if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ |
| 182459 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 182460 | *pbSkip = 1; |
| 182461 | } |
| 182462 | } |
| 182463 | return rc; |
| 182464 | } |
| 182465 | |
| @@ -181816,28 +182472,28 @@ | |
| 182472 | ** even if we reach end-of-file. The fts5EofMethod() will be called |
| 182473 | ** subsequently to determine whether or not an EOF was hit. |
| 182474 | */ |
| 182475 | static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ |
| 182476 | Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; |
| 182477 | int rc; |
| 182478 | |
| 182479 | assert( (pCsr->ePlan<3)== |
| 182480 | (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) |
| 182481 | ); |
| 182482 | assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) ); |
| 182483 | |
| 182484 | if( pCsr->ePlan<3 ){ |
| 182485 | int bSkip = 0; |
| 182486 | if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; |
| 182487 | rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); |
| 182488 | CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr)); |
| 182489 | fts5CsrNewrow(pCsr); |
| 182490 | }else{ |
| 182491 | switch( pCsr->ePlan ){ |
| 182492 | case FTS5_PLAN_SPECIAL: { |
| 182493 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 182494 | rc = SQLITE_OK; |
| 182495 | break; |
| 182496 | } |
| 182497 | |
| 182498 | case FTS5_PLAN_SORTED_MATCH: { |
| 182499 | rc = fts5SorterNext(pCsr); |
| @@ -183605,11 +184261,11 @@ | |
| 184261 | sqlite3_context *pCtx, /* Function call context */ |
| 184262 | int nArg, /* Number of args */ |
| 184263 | sqlite3_value **apVal /* Function arguments */ |
| 184264 | ){ |
| 184265 | assert( nArg==0 ); |
| 184266 | sqlite3_result_text(pCtx, "fts5: 2016-02-08 20:45:37 6eab74c9ae57676044b5bc82fa14e92fd2448008", -1, SQLITE_TRANSIENT); |
| 184267 | } |
| 184268 | |
| 184269 | static int fts5Init(sqlite3 *db){ |
| 184270 | static const sqlite3_module fts5Mod = { |
| 184271 | /* iVersion */ 2, |
| @@ -184050,11 +184706,11 @@ | |
| 184706 | int rc = SQLITE_OK; |
| 184707 | if( p ){ |
| 184708 | int i; |
| 184709 | |
| 184710 | /* Finalize all SQL statements */ |
| 184711 | for(i=0; i<ArraySize(p->aStmt); i++){ |
| 184712 | sqlite3_finalize(p->aStmt[i]); |
| 184713 | } |
| 184714 | |
| 184715 | sqlite3_free(p); |
| 184716 | } |
| @@ -186055,11 +186711,11 @@ | |
| 186711 | }; |
| 186712 | |
| 186713 | int rc = SQLITE_OK; /* Return code */ |
| 186714 | int i; /* To iterate through builtin functions */ |
| 186715 | |
| 186716 | for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){ |
| 186717 | rc = pApi->xCreateTokenizer(pApi, |
| 186718 | aBuiltin[i].zName, |
| 186719 | (void*)pApi, |
| 186720 | &aBuiltin[i].x, |
| 186721 | 0 |
| @@ -186765,11 +187421,14 @@ | |
| 187421 | return fts5PutVarint64(p,v); |
| 187422 | } |
| 187423 | |
| 187424 | |
| 187425 | static int sqlite3Fts5GetVarintLen(u32 iVal){ |
| 187426 | #if 0 |
| 187427 | if( iVal<(1 << 7 ) ) return 1; |
| 187428 | #endif |
| 187429 | assert( iVal>=(1 << 7) ); |
| 187430 | if( iVal<(1 << 14) ) return 2; |
| 187431 | if( iVal<(1 << 21) ) return 3; |
| 187432 | if( iVal<(1 << 28) ) return 4; |
| 187433 | return 5; |
| 187434 | } |
| @@ -186959,11 +187618,11 @@ | |
| 187618 | int nTab = (int)strlen(zTab)+1; |
| 187619 | int eType = 0; |
| 187620 | |
| 187621 | rc = fts5VocabTableType(zType, pzErr, &eType); |
| 187622 | if( rc==SQLITE_OK ){ |
| 187623 | assert( eType>=0 && eType<ArraySize(azSchema) ); |
| 187624 | rc = sqlite3_declare_vtab(db, azSchema[eType]); |
| 187625 | } |
| 187626 | |
| 187627 | nByte = sizeof(Fts5VocabTable) + nDb + nTab; |
| 187628 | pRet = sqlite3Fts5MallocZero(&rc, nByte); |
| @@ -187182,59 +187841,54 @@ | |
| 187841 | memset(pCsr->aDoc, 0, nCol * sizeof(i64)); |
| 187842 | pCsr->iCol = 0; |
| 187843 | |
| 187844 | assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); |
| 187845 | while( rc==SQLITE_OK ){ |
| 187846 | const u8 *pPos; int nPos; /* Position list */ |
| 187847 | i64 iPos = 0; /* 64-bit position read from poslist */ |
| 187848 | int iOff = 0; /* Current offset within position list */ |
| 187849 | |
| 187850 | pPos = pCsr->pIter->pData; |
| 187851 | nPos = pCsr->pIter->nData; |
| 187852 | switch( pCsr->pConfig->eDetail ){ |
| 187853 | case FTS5_DETAIL_FULL: |
| 187854 | pPos = pCsr->pIter->pData; |
| 187855 | nPos = pCsr->pIter->nData; |
| 187856 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 187857 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 187858 | pCsr->aCnt[0]++; |
| 187859 | } |
| 187860 | pCsr->aDoc[0]++; |
| 187861 | }else{ |
| 187862 | int iCol = -1; |
| 187863 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 187864 | int ii = FTS5_POS2COLUMN(iPos); |
| 187865 | pCsr->aCnt[ii]++; |
| 187866 | if( iCol!=ii ){ |
| 187867 | if( ii>=nCol ){ |
| 187868 | rc = FTS5_CORRUPT; |
| 187869 | break; |
| 187870 | } |
| 187871 | pCsr->aDoc[ii]++; |
| 187872 | iCol = ii; |
| 187873 | } |
| 187874 | } |
| 187875 | } |
| 187876 | break; |
| 187877 | |
| 187878 | case FTS5_DETAIL_COLUMNS: |
| 187879 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 187880 | pCsr->aDoc[0]++; |
| 187881 | }else{ |
| 187882 | while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ |
| 187883 | assert_nc( iPos>=0 && iPos<nCol ); |
| 187884 | if( iPos>=nCol ){ |
| 187885 | rc = FTS5_CORRUPT; |
| 187886 | break; |
| 187887 | } |
| 187888 | pCsr->aDoc[iPos]++; |
| 187889 | } |
| 187890 | } |
| 187891 | break; |
| 187892 | |
| 187893 | default: |
| 187894 | assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); |
| 187895 |
+2
-2
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -111,11 +111,11 @@ | ||
| 111 | 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | 113 | */ |
| 114 | 114 | #define SQLITE_VERSION "3.11.0" |
| 115 | 115 | #define SQLITE_VERSION_NUMBER 3011000 |
| 116 | -#define SQLITE_SOURCE_ID "2016-01-20 14:22:41 204432ee72fda8e82d244c4aa18de7ec4811b8e1" | |
| 116 | +#define SQLITE_SOURCE_ID "2016-02-09 02:12:20 ca72be8618e5d466d6f35819ca8bbd2b84269959" | |
| 117 | 117 | |
| 118 | 118 | /* |
| 119 | 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | 121 | ** |
| @@ -5695,11 +5695,11 @@ | ||
| 5695 | 5695 | */ |
| 5696 | 5696 | struct sqlite3_index_info { |
| 5697 | 5697 | /* Inputs */ |
| 5698 | 5698 | int nConstraint; /* Number of entries in aConstraint */ |
| 5699 | 5699 | struct sqlite3_index_constraint { |
| 5700 | - int iColumn; /* Column on left-hand side of constraint */ | |
| 5700 | + int iColumn; /* Column constrained. -1 for ROWID */ | |
| 5701 | 5701 | unsigned char op; /* Constraint operator */ |
| 5702 | 5702 | unsigned char usable; /* True if this constraint is usable */ |
| 5703 | 5703 | int iTermOffset; /* Used internally - xBestIndex should ignore */ |
| 5704 | 5704 | } *aConstraint; /* Table of WHERE clause constraints */ |
| 5705 | 5705 | int nOrderBy; /* Number of terms in the ORDER BY clause */ |
| 5706 | 5706 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -111,11 +111,11 @@ | |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.11.0" |
| 115 | #define SQLITE_VERSION_NUMBER 3011000 |
| 116 | #define SQLITE_SOURCE_ID "2016-01-20 14:22:41 204432ee72fda8e82d244c4aa18de7ec4811b8e1" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| @@ -5695,11 +5695,11 @@ | |
| 5695 | */ |
| 5696 | struct sqlite3_index_info { |
| 5697 | /* Inputs */ |
| 5698 | int nConstraint; /* Number of entries in aConstraint */ |
| 5699 | struct sqlite3_index_constraint { |
| 5700 | int iColumn; /* Column on left-hand side of constraint */ |
| 5701 | unsigned char op; /* Constraint operator */ |
| 5702 | unsigned char usable; /* True if this constraint is usable */ |
| 5703 | int iTermOffset; /* Used internally - xBestIndex should ignore */ |
| 5704 | } *aConstraint; /* Table of WHERE clause constraints */ |
| 5705 | int nOrderBy; /* Number of terms in the ORDER BY clause */ |
| 5706 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -111,11 +111,11 @@ | |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.11.0" |
| 115 | #define SQLITE_VERSION_NUMBER 3011000 |
| 116 | #define SQLITE_SOURCE_ID "2016-02-09 02:12:20 ca72be8618e5d466d6f35819ca8bbd2b84269959" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| @@ -5695,11 +5695,11 @@ | |
| 5695 | */ |
| 5696 | struct sqlite3_index_info { |
| 5697 | /* Inputs */ |
| 5698 | int nConstraint; /* Number of entries in aConstraint */ |
| 5699 | struct sqlite3_index_constraint { |
| 5700 | int iColumn; /* Column constrained. -1 for ROWID */ |
| 5701 | unsigned char op; /* Constraint operator */ |
| 5702 | unsigned char usable; /* True if this constraint is usable */ |
| 5703 | int iTermOffset; /* Used internally - xBestIndex should ignore */ |
| 5704 | } *aConstraint; /* Table of WHERE clause constraints */ |
| 5705 | int nOrderBy; /* Number of terms in the ORDER BY clause */ |
| 5706 |