| | @@ -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-15 17:29:24 3d862f207e3adc00f78066799ac5a8c282430a5f" |
| 333 | 334 | |
| 334 | 335 | /* |
| 335 | 336 | ** CAPI3REF: Run-Time Library Version Numbers |
| 336 | 337 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 337 | 338 | ** |
| | @@ -561,11 +562,11 @@ |
| 561 | 562 | ** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() |
| 562 | 563 | ** is not NULL then any error message is written into memory obtained |
| 563 | 564 | ** from [sqlite3_malloc()] and passed back through the 5th parameter. |
| 564 | 565 | ** To avoid memory leaks, the application should invoke [sqlite3_free()] |
| 565 | 566 | ** on error message strings returned through the 5th parameter of |
| 566 | | -** of sqlite3_exec() after the error message string is no longer needed. |
| 567 | +** sqlite3_exec() after the error message string is no longer needed. |
| 567 | 568 | ** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors |
| 568 | 569 | ** occur, then sqlite3_exec() sets the pointer in its 5th parameter to |
| 569 | 570 | ** NULL before returning. |
| 570 | 571 | ** |
| 571 | 572 | ** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() |
| | @@ -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 | */ |
| | @@ -13958,10 +13987,11 @@ |
| 13958 | 13987 | int n; /* A counter */ |
| 13959 | 13988 | int iCur; /* A cursor number */ |
| 13960 | 13989 | SrcList *pSrcList; /* FROM clause */ |
| 13961 | 13990 | struct SrcCount *pSrcCount; /* Counting column references */ |
| 13962 | 13991 | struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ |
| 13992 | + int *aiCol; /* array of column indexes */ |
| 13963 | 13993 | } u; |
| 13964 | 13994 | }; |
| 13965 | 13995 | |
| 13966 | 13996 | /* Forward declarations */ |
| 13967 | 13997 | SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*); |
| | @@ -14027,10 +14057,17 @@ |
| 14027 | 14057 | SQLITE_PRIVATE int sqlite3CantopenError(int); |
| 14028 | 14058 | #define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) |
| 14029 | 14059 | #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__) |
| 14030 | 14060 | #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__) |
| 14031 | 14061 | |
| 14062 | +/* |
| 14063 | +** FTS3 and FTS4 both require virtual table support |
| 14064 | +*/ |
| 14065 | +#if defined(SQLITE_OMIT_VIRTUALTABLE) |
| 14066 | +# undef SQLITE_ENABLE_FTS3 |
| 14067 | +# undef SQLITE_ENABLE_FTS4 |
| 14068 | +#endif |
| 14032 | 14069 | |
| 14033 | 14070 | /* |
| 14034 | 14071 | ** FTS4 is really an extension for FTS3. It is enabled using the |
| 14035 | 14072 | ** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call |
| 14036 | 14073 | ** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3. |
| | @@ -14085,10 +14122,11 @@ |
| 14085 | 14122 | SQLITE_PRIVATE void sqlite3MallocEnd(void); |
| 14086 | 14123 | SQLITE_PRIVATE void *sqlite3Malloc(u64); |
| 14087 | 14124 | SQLITE_PRIVATE void *sqlite3MallocZero(u64); |
| 14088 | 14125 | SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64); |
| 14089 | 14126 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64); |
| 14127 | +SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64); |
| 14090 | 14128 | SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); |
| 14091 | 14129 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); |
| 14092 | 14130 | SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); |
| 14093 | 14131 | SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); |
| 14094 | 14132 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); |
| | @@ -14167,14 +14205,12 @@ |
| 14167 | 14205 | int nArg; /* Total number of arguments */ |
| 14168 | 14206 | int nUsed; /* Number of arguments used so far */ |
| 14169 | 14207 | sqlite3_value **apArg; /* The argument values */ |
| 14170 | 14208 | }; |
| 14171 | 14209 | |
| 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*, ...); |
| 14210 | +SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, const char*, va_list); |
| 14211 | +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); |
| 14176 | 14212 | SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); |
| 14177 | 14213 | SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); |
| 14178 | 14214 | #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
| 14179 | 14215 | SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...); |
| 14180 | 14216 | #endif |
| | @@ -14191,10 +14227,11 @@ |
| 14191 | 14227 | |
| 14192 | 14228 | |
| 14193 | 14229 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); |
| 14194 | 14230 | SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); |
| 14195 | 14231 | SQLITE_PRIVATE int sqlite3Dequote(char*); |
| 14232 | +SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); |
| 14196 | 14233 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); |
| 14197 | 14234 | SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); |
| 14198 | 14235 | SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); |
| 14199 | 14236 | SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); |
| 14200 | 14237 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); |
| | @@ -14403,11 +14440,11 @@ |
| 14403 | 14440 | Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); |
| 14404 | 14441 | SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); |
| 14405 | 14442 | SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); |
| 14406 | 14443 | SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); |
| 14407 | 14444 | SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, |
| 14408 | | - u8,u8,int,int*); |
| 14445 | + u8,u8,int,int*,int*); |
| 14409 | 14446 | SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); |
| 14410 | 14447 | SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*); |
| 14411 | 14448 | SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); |
| 14412 | 14449 | SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); |
| 14413 | 14450 | SQLITE_PRIVATE void sqlite3MayAbort(Parse*); |
| | @@ -14622,11 +14659,10 @@ |
| 14622 | 14659 | SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); |
| 14623 | 14660 | SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*); |
| 14624 | 14661 | SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*); |
| 14625 | 14662 | SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int); |
| 14626 | 14663 | SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); |
| 14627 | | -SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int); |
| 14628 | 14664 | SQLITE_PRIVATE void sqlite3SchemaClear(void *); |
| 14629 | 14665 | SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *); |
| 14630 | 14666 | SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *); |
| 14631 | 14667 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int); |
| 14632 | 14668 | SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*); |
| | @@ -14638,10 +14674,12 @@ |
| 14638 | 14674 | SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, |
| 14639 | 14675 | void (*)(sqlite3_context*,int,sqlite3_value **), |
| 14640 | 14676 | void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), |
| 14641 | 14677 | FuncDestructor *pDestructor |
| 14642 | 14678 | ); |
| 14679 | +SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); |
| 14680 | +SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); |
| 14643 | 14681 | SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); |
| 14644 | 14682 | SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); |
| 14645 | 14683 | |
| 14646 | 14684 | SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); |
| 14647 | 14685 | SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); |
| | @@ -15734,18 +15772,20 @@ |
| 15734 | 15772 | ** - On either an index or a table |
| 15735 | 15773 | ** * A sorter |
| 15736 | 15774 | ** * A virtual table |
| 15737 | 15775 | ** * A one-row "pseudotable" stored in a single register |
| 15738 | 15776 | */ |
| 15777 | +typedef struct VdbeCursor VdbeCursor; |
| 15739 | 15778 | struct VdbeCursor { |
| 15740 | 15779 | u8 eCurType; /* One of the CURTYPE_* values above */ |
| 15741 | 15780 | i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ |
| 15742 | 15781 | u8 nullRow; /* True if pointing to a row with no data */ |
| 15743 | 15782 | u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ |
| 15744 | 15783 | u8 isTable; /* True for rowid tables. False for indexes */ |
| 15745 | 15784 | #ifdef SQLITE_DEBUG |
| 15746 | 15785 | u8 seekOp; /* Most recent seek operation on this cursor */ |
| 15786 | + u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ |
| 15747 | 15787 | #endif |
| 15748 | 15788 | Bool isEphemeral:1; /* True for an ephemeral table */ |
| 15749 | 15789 | Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ |
| 15750 | 15790 | Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */ |
| 15751 | 15791 | Pgno pgnoRoot; /* Root page of the open btree cursor */ |
| | @@ -15760,10 +15800,12 @@ |
| 15760 | 15800 | Btree *pBt; /* Separate file holding temporary table */ |
| 15761 | 15801 | KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ |
| 15762 | 15802 | int seekResult; /* Result of previous sqlite3BtreeMoveto() */ |
| 15763 | 15803 | i64 seqCount; /* Sequence counter */ |
| 15764 | 15804 | i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ |
| 15805 | + VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ |
| 15806 | + int *aAltMap; /* Mapping from table to index column numbers */ |
| 15765 | 15807 | #ifdef SQLITE_ENABLE_COLUMN_USED_MASK |
| 15766 | 15808 | u64 maskUsed; /* Mask of columns used by this cursor */ |
| 15767 | 15809 | #endif |
| 15768 | 15810 | |
| 15769 | 15811 | /* Cached information about the header for the data record that the |
| | @@ -15784,11 +15826,10 @@ |
| 15784 | 15826 | u32 aType[1]; /* Type values for all entries in the record */ |
| 15785 | 15827 | /* 2*nField extra array elements allocated for aType[], beyond the one |
| 15786 | 15828 | ** static element declared in the structure. nField total array slots for |
| 15787 | 15829 | ** aType[] and nField+1 array slots for aOffset[] */ |
| 15788 | 15830 | }; |
| 15789 | | -typedef struct VdbeCursor VdbeCursor; |
| 15790 | 15831 | |
| 15791 | 15832 | /* |
| 15792 | 15833 | ** When a sub-program is executed (OP_Program), a structure of this type |
| 15793 | 15834 | ** is allocated to store the current value of the program counter, as |
| 15794 | 15835 | ** well as the current memory cell array and various other frame specific |
| | @@ -15895,11 +15936,11 @@ |
| 15895 | 15936 | #define MEM_AffMask 0x001f /* Mask of affinity bits */ |
| 15896 | 15937 | #define MEM_RowSet 0x0020 /* Value is a RowSet object */ |
| 15897 | 15938 | #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ |
| 15898 | 15939 | #define MEM_Undefined 0x0080 /* Value is undefined */ |
| 15899 | 15940 | #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ |
| 15900 | | -#define MEM_TypeMask 0x01ff /* Mask of type bits */ |
| 15941 | +#define MEM_TypeMask 0x81ff /* Mask of type bits */ |
| 15901 | 15942 | |
| 15902 | 15943 | |
| 15903 | 15944 | /* Whenever Mem contains a valid string or blob representation, one of |
| 15904 | 15945 | ** the following flags must be set to determine the memory management |
| 15905 | 15946 | ** policy for Mem.z. The MEM_Term flag tells us whether or not the |
| | @@ -15909,14 +15950,21 @@ |
| 15909 | 15950 | #define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ |
| 15910 | 15951 | #define MEM_Static 0x0800 /* Mem.z points to a static string */ |
| 15911 | 15952 | #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ |
| 15912 | 15953 | #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ |
| 15913 | 15954 | #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ |
| 15955 | +#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */ |
| 15914 | 15956 | #ifdef SQLITE_OMIT_INCRBLOB |
| 15915 | 15957 | #undef MEM_Zero |
| 15916 | 15958 | #define MEM_Zero 0x0000 |
| 15917 | 15959 | #endif |
| 15960 | + |
| 15961 | +/* Return TRUE if Mem X contains dynamically allocated content - anything |
| 15962 | +** that needs to be deallocated to avoid a leak. |
| 15963 | +*/ |
| 15964 | +#define VdbeMemDynamic(X) \ |
| 15965 | + (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) |
| 15918 | 15966 | |
| 15919 | 15967 | /* |
| 15920 | 15968 | ** Clear any existing type flags from a Mem and replace them with f |
| 15921 | 15969 | */ |
| 15922 | 15970 | #define MemSetTypeFlag(p, f) \ |
| | @@ -16083,11 +16131,11 @@ |
| 16083 | 16131 | ** Function prototypes |
| 16084 | 16132 | */ |
| 16085 | 16133 | SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); |
| 16086 | 16134 | SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); |
| 16087 | 16135 | void sqliteVdbePopStack(Vdbe*,int); |
| 16088 | | -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); |
| 16136 | +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); |
| 16089 | 16137 | SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); |
| 16090 | 16138 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 16091 | 16139 | SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); |
| 16092 | 16140 | #endif |
| 16093 | 16141 | SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); |
| | @@ -16129,12 +16177,10 @@ |
| 16129 | 16177 | SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); |
| 16130 | 16178 | SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); |
| 16131 | 16179 | SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); |
| 16132 | 16180 | SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); |
| 16133 | 16181 | SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); |
| 16134 | | -#define VdbeMemDynamic(X) \ |
| 16135 | | - (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) |
| 16136 | 16182 | SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); |
| 16137 | 16183 | SQLITE_PRIVATE const char *sqlite3OpcodeName(int); |
| 16138 | 16184 | SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); |
| 16139 | 16185 | SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); |
| 16140 | 16186 | SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); |
| | @@ -17492,11 +17538,11 @@ |
| 17492 | 17538 | z = zBuf; |
| 17493 | 17539 | }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
| 17494 | 17540 | sqlite3_result_error_toobig(context); |
| 17495 | 17541 | return; |
| 17496 | 17542 | }else{ |
| 17497 | | - z = sqlite3DbMallocRaw(db, (int)n); |
| 17543 | + z = sqlite3DbMallocRawNN(db, (int)n); |
| 17498 | 17544 | if( z==0 ){ |
| 17499 | 17545 | sqlite3_result_error_nomem(context); |
| 17500 | 17546 | return; |
| 17501 | 17547 | } |
| 17502 | 17548 | } |
| | @@ -17707,18 +17753,40 @@ |
| 17707 | 17753 | */ |
| 17708 | 17754 | #define _SQLITE_OS_C_ 1 |
| 17709 | 17755 | /* #include "sqliteInt.h" */ |
| 17710 | 17756 | #undef _SQLITE_OS_C_ |
| 17711 | 17757 | |
| 17758 | +/* |
| 17759 | +** If we compile with the SQLITE_TEST macro set, then the following block |
| 17760 | +** of code will give us the ability to simulate a disk I/O error. This |
| 17761 | +** is used for testing the I/O recovery logic. |
| 17762 | +*/ |
| 17763 | +#if defined(SQLITE_TEST) |
| 17764 | +SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ |
| 17765 | +SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ |
| 17766 | +SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ |
| 17767 | +SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ |
| 17768 | +SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ |
| 17769 | +SQLITE_API int sqlite3_diskfull_pending = 0; |
| 17770 | +SQLITE_API int sqlite3_diskfull = 0; |
| 17771 | +#endif /* defined(SQLITE_TEST) */ |
| 17772 | + |
| 17773 | +/* |
| 17774 | +** When testing, also keep a count of the number of open files. |
| 17775 | +*/ |
| 17776 | +#if defined(SQLITE_TEST) |
| 17777 | +SQLITE_API int sqlite3_open_file_count = 0; |
| 17778 | +#endif /* defined(SQLITE_TEST) */ |
| 17779 | + |
| 17712 | 17780 | /* |
| 17713 | 17781 | ** The default SQLite sqlite3_vfs implementations do not allocate |
| 17714 | 17782 | ** memory (actually, os_unix.c allocates a small amount of memory |
| 17715 | 17783 | ** from within OsOpen()), but some third-party implementations may. |
| 17716 | 17784 | ** So we test the effects of a malloc() failing and the sqlite3OsXXX() |
| 17717 | 17785 | ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. |
| 17718 | 17786 | ** |
| 17719 | | -** The following functions are instrumented for malloc() failure |
| 17787 | +** The following functions are instrumented for malloc() failure |
| 17720 | 17788 | ** testing: |
| 17721 | 17789 | ** |
| 17722 | 17790 | ** sqlite3OsRead() |
| 17723 | 17791 | ** sqlite3OsWrite() |
| 17724 | 17792 | ** sqlite3OsSync() |
| | @@ -17800,12 +17868,12 @@ |
| 17800 | 17868 | */ |
| 17801 | 17869 | SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ |
| 17802 | 17870 | #ifdef SQLITE_TEST |
| 17803 | 17871 | if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ |
| 17804 | 17872 | /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite |
| 17805 | | - ** is using a regular VFS, it is called after the corresponding |
| 17806 | | - ** transaction has been committed. Injecting a fault at this point |
| 17873 | + ** is using a regular VFS, it is called after the corresponding |
| 17874 | + ** transaction has been committed. Injecting a fault at this point |
| 17807 | 17875 | ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM |
| 17808 | 17876 | ** but the transaction is committed anyway. |
| 17809 | 17877 | ** |
| 17810 | 17878 | ** The core must call OsFileControl() though, not OsFileControlHint(), |
| 17811 | 17879 | ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably |
| | @@ -17870,14 +17938,14 @@ |
| 17870 | 17938 | /* |
| 17871 | 17939 | ** The next group of routines are convenience wrappers around the |
| 17872 | 17940 | ** VFS methods. |
| 17873 | 17941 | */ |
| 17874 | 17942 | SQLITE_PRIVATE int sqlite3OsOpen( |
| 17875 | | - sqlite3_vfs *pVfs, |
| 17876 | | - const char *zPath, |
| 17877 | | - sqlite3_file *pFile, |
| 17878 | | - int flags, |
| 17943 | + sqlite3_vfs *pVfs, |
| 17944 | + const char *zPath, |
| 17945 | + sqlite3_file *pFile, |
| 17946 | + int flags, |
| 17879 | 17947 | int *pFlagsOut |
| 17880 | 17948 | ){ |
| 17881 | 17949 | int rc; |
| 17882 | 17950 | DO_OS_MALLOC_TEST(0); |
| 17883 | 17951 | /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed |
| | @@ -17892,22 +17960,22 @@ |
| 17892 | 17960 | DO_OS_MALLOC_TEST(0); |
| 17893 | 17961 | assert( dirSync==0 || dirSync==1 ); |
| 17894 | 17962 | return pVfs->xDelete(pVfs, zPath, dirSync); |
| 17895 | 17963 | } |
| 17896 | 17964 | SQLITE_PRIVATE int sqlite3OsAccess( |
| 17897 | | - sqlite3_vfs *pVfs, |
| 17898 | | - const char *zPath, |
| 17899 | | - int flags, |
| 17965 | + sqlite3_vfs *pVfs, |
| 17966 | + const char *zPath, |
| 17967 | + int flags, |
| 17900 | 17968 | int *pResOut |
| 17901 | 17969 | ){ |
| 17902 | 17970 | DO_OS_MALLOC_TEST(0); |
| 17903 | 17971 | return pVfs->xAccess(pVfs, zPath, flags, pResOut); |
| 17904 | 17972 | } |
| 17905 | 17973 | SQLITE_PRIVATE int sqlite3OsFullPathname( |
| 17906 | | - sqlite3_vfs *pVfs, |
| 17907 | | - const char *zPath, |
| 17908 | | - int nPathOut, |
| 17974 | + sqlite3_vfs *pVfs, |
| 17975 | + const char *zPath, |
| 17976 | + int nPathOut, |
| 17909 | 17977 | char *zPathOut |
| 17910 | 17978 | ){ |
| 17911 | 17979 | DO_OS_MALLOC_TEST(0); |
| 17912 | 17980 | zPathOut[0] = 0; |
| 17913 | 17981 | return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); |
| | @@ -17949,13 +18017,13 @@ |
| 17949 | 18017 | } |
| 17950 | 18018 | return rc; |
| 17951 | 18019 | } |
| 17952 | 18020 | |
| 17953 | 18021 | SQLITE_PRIVATE int sqlite3OsOpenMalloc( |
| 17954 | | - sqlite3_vfs *pVfs, |
| 17955 | | - const char *zFile, |
| 17956 | | - sqlite3_file **ppFile, |
| 18022 | + sqlite3_vfs *pVfs, |
| 18023 | + const char *zFile, |
| 18024 | + sqlite3_file **ppFile, |
| 17957 | 18025 | int flags, |
| 17958 | 18026 | int *pOutFlags |
| 17959 | 18027 | ){ |
| 17960 | 18028 | int rc = SQLITE_NOMEM; |
| 17961 | 18029 | sqlite3_file *pFile; |
| | @@ -20081,15 +20149,15 @@ |
| 20081 | 20149 | mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; |
| 20082 | 20150 | while( ALWAYS(iLogsize<LOGMAX) ){ |
| 20083 | 20151 | int iBuddy; |
| 20084 | 20152 | if( (iBlock>>iLogsize) & 1 ){ |
| 20085 | 20153 | iBuddy = iBlock - size; |
| 20154 | + assert( iBuddy>=0 ); |
| 20086 | 20155 | }else{ |
| 20087 | 20156 | iBuddy = iBlock + size; |
| 20157 | + if( iBuddy>=mem5.nBlock ) break; |
| 20088 | 20158 | } |
| 20089 | | - assert( iBuddy>=0 ); |
| 20090 | | - if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break; |
| 20091 | 20159 | if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; |
| 20092 | 20160 | memsys5Unlink(iBuddy, iLogsize); |
| 20093 | 20161 | iLogsize++; |
| 20094 | 20162 | if( iBuddy<iBlock ){ |
| 20095 | 20163 | mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize; |
| | @@ -21174,12 +21242,12 @@ |
| 21174 | 21242 | ** Macros for performance tracing. Normally turned off. Only works |
| 21175 | 21243 | ** on i486 hardware. |
| 21176 | 21244 | */ |
| 21177 | 21245 | #ifdef SQLITE_PERFORMANCE_TRACE |
| 21178 | 21246 | |
| 21179 | | -/* |
| 21180 | | -** hwtime.h contains inline assembler code for implementing |
| 21247 | +/* |
| 21248 | +** hwtime.h contains inline assembler code for implementing |
| 21181 | 21249 | ** high-performance timing routines. |
| 21182 | 21250 | */ |
| 21183 | 21251 | /************** Include hwtime.h in the middle of os_common.h ****************/ |
| 21184 | 21252 | /************** Begin file hwtime.h ******************************************/ |
| 21185 | 21253 | /* |
| | @@ -21285,18 +21353,18 @@ |
| 21285 | 21353 | /* |
| 21286 | 21354 | ** If we compile with the SQLITE_TEST macro set, then the following block |
| 21287 | 21355 | ** of code will give us the ability to simulate a disk I/O error. This |
| 21288 | 21356 | ** is used for testing the I/O recovery logic. |
| 21289 | 21357 | */ |
| 21290 | | -#ifdef SQLITE_TEST |
| 21291 | | -SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ |
| 21292 | | -SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ |
| 21293 | | -SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ |
| 21294 | | -SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ |
| 21295 | | -SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ |
| 21296 | | -SQLITE_API int sqlite3_diskfull_pending = 0; |
| 21297 | | -SQLITE_API int sqlite3_diskfull = 0; |
| 21358 | +#if defined(SQLITE_TEST) |
| 21359 | +SQLITE_API extern int sqlite3_io_error_hit; |
| 21360 | +SQLITE_API extern int sqlite3_io_error_hardhit; |
| 21361 | +SQLITE_API extern int sqlite3_io_error_pending; |
| 21362 | +SQLITE_API extern int sqlite3_io_error_persist; |
| 21363 | +SQLITE_API extern int sqlite3_io_error_benign; |
| 21364 | +SQLITE_API extern int sqlite3_diskfull_pending; |
| 21365 | +SQLITE_API extern int sqlite3_diskfull; |
| 21298 | 21366 | #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) |
| 21299 | 21367 | #define SimulateIOError(CODE) \ |
| 21300 | 21368 | if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ |
| 21301 | 21369 | || sqlite3_io_error_pending-- == 1 ) \ |
| 21302 | 21370 | { local_ioerr(); CODE; } |
| | @@ -21318,21 +21386,21 @@ |
| 21318 | 21386 | } |
| 21319 | 21387 | #else |
| 21320 | 21388 | #define SimulateIOErrorBenign(X) |
| 21321 | 21389 | #define SimulateIOError(A) |
| 21322 | 21390 | #define SimulateDiskfullError(A) |
| 21323 | | -#endif |
| 21391 | +#endif /* defined(SQLITE_TEST) */ |
| 21324 | 21392 | |
| 21325 | 21393 | /* |
| 21326 | 21394 | ** When testing, keep a count of the number of open files. |
| 21327 | 21395 | */ |
| 21328 | | -#ifdef SQLITE_TEST |
| 21329 | | -SQLITE_API int sqlite3_open_file_count = 0; |
| 21396 | +#if defined(SQLITE_TEST) |
| 21397 | +SQLITE_API extern int sqlite3_open_file_count; |
| 21330 | 21398 | #define OpenCounter(X) sqlite3_open_file_count+=(X) |
| 21331 | 21399 | #else |
| 21332 | 21400 | #define OpenCounter(X) |
| 21333 | | -#endif |
| 21401 | +#endif /* defined(SQLITE_TEST) */ |
| 21334 | 21402 | |
| 21335 | 21403 | #endif /* !defined(_OS_COMMON_H_) */ |
| 21336 | 21404 | |
| 21337 | 21405 | /************** End of os_common.h *******************************************/ |
| 21338 | 21406 | /************** Continuing where we left off in mutex_w32.c ******************/ |
| | @@ -22386,14 +22454,28 @@ |
| 22386 | 22454 | /* |
| 22387 | 22455 | ** Allocate and zero memory. If the allocation fails, make |
| 22388 | 22456 | ** the mallocFailed flag in the connection pointer. |
| 22389 | 22457 | */ |
| 22390 | 22458 | 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 | | - } |
| 22459 | + void *p; |
| 22460 | + testcase( db==0 ); |
| 22461 | + p = sqlite3DbMallocRaw(db, n); |
| 22462 | + if( p ) memset(p, 0, (size_t)n); |
| 22463 | + return p; |
| 22464 | +} |
| 22465 | + |
| 22466 | + |
| 22467 | +/* Finish the work of sqlite3DbMallocRawNN for the unusual and |
| 22468 | +** slower case when the allocation cannot be fulfilled using lookaside. |
| 22469 | +*/ |
| 22470 | +static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){ |
| 22471 | + void *p; |
| 22472 | + assert( db!=0 ); |
| 22473 | + p = sqlite3Malloc(n); |
| 22474 | + if( !p ) sqlite3OomFault(db); |
| 22475 | + sqlite3MemdebugSetType(p, |
| 22476 | + (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP); |
| 22395 | 22477 | return p; |
| 22396 | 22478 | } |
| 22397 | 22479 | |
| 22398 | 22480 | /* |
| 22399 | 22481 | ** Allocate memory, either lookaside (if possible) or heap. |
| | @@ -22411,71 +22493,77 @@ |
| 22411 | 22493 | ** int *b = (int*)sqlite3DbMallocRaw(db, 200); |
| 22412 | 22494 | ** if( b ) a[10] = 9; |
| 22413 | 22495 | ** |
| 22414 | 22496 | ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed |
| 22415 | 22497 | ** that all prior mallocs (ex: "a") worked too. |
| 22498 | +** |
| 22499 | +** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is |
| 22500 | +** not a NULL pointer. |
| 22416 | 22501 | */ |
| 22417 | | -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n); |
| 22418 | 22502 | SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){ |
| 22419 | | - assert( db==0 || sqlite3_mutex_held(db->mutex) ); |
| 22420 | | - assert( db==0 || db->pnBytesFreed==0 ); |
| 22503 | + void *p; |
| 22504 | + if( db ) return sqlite3DbMallocRawNN(db, n); |
| 22505 | + p = sqlite3Malloc(n); |
| 22506 | + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 22507 | + return p; |
| 22508 | +} |
| 22509 | +SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ |
| 22421 | 22510 | #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 | | - } |
| 22511 | + LookasideSlot *pBuf; |
| 22512 | + assert( db!=0 ); |
| 22513 | + assert( sqlite3_mutex_held(db->mutex) ); |
| 22514 | + assert( db->pnBytesFreed==0 ); |
| 22515 | + if( db->lookaside.bDisable==0 ){ |
| 22516 | + assert( db->mallocFailed==0 ); |
| 22517 | + if( n>db->lookaside.sz ){ |
| 22518 | + db->lookaside.anStat[1]++; |
| 22519 | + }else if( (pBuf = db->lookaside.pFree)==0 ){ |
| 22520 | + db->lookaside.anStat[2]++; |
| 22521 | + }else{ |
| 22522 | + db->lookaside.pFree = pBuf->pNext; |
| 22523 | + db->lookaside.nOut++; |
| 22524 | + db->lookaside.anStat[0]++; |
| 22525 | + if( db->lookaside.nOut>db->lookaside.mxOut ){ |
| 22526 | + db->lookaside.mxOut = db->lookaside.nOut; |
| 22527 | + } |
| 22528 | + return (void*)pBuf; |
| 22529 | + } |
| 22530 | + }else if( db->mallocFailed ){ |
| 22531 | + return 0; |
| 22442 | 22532 | } |
| 22443 | 22533 | #else |
| 22444 | | - if( db && db->mallocFailed ){ |
| 22534 | + assert( db!=0 ); |
| 22535 | + assert( sqlite3_mutex_held(db->mutex) ); |
| 22536 | + assert( db->pnBytesFreed==0 ); |
| 22537 | + if( db->mallocFailed ){ |
| 22445 | 22538 | return 0; |
| 22446 | 22539 | } |
| 22447 | 22540 | #endif |
| 22448 | 22541 | return dbMallocRawFinish(db, n); |
| 22449 | 22542 | } |
| 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 | | -} |
| 22543 | + |
| 22544 | +/* Forward declaration */ |
| 22545 | +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n); |
| 22459 | 22546 | |
| 22460 | 22547 | /* |
| 22461 | 22548 | ** Resize the block of memory pointed to by p to n bytes. If the |
| 22462 | 22549 | ** resize fails, set the mallocFailed flag in the connection object. |
| 22463 | 22550 | */ |
| 22464 | 22551 | SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ |
| 22552 | + assert( db!=0 ); |
| 22553 | + if( p==0 ) return sqlite3DbMallocRawNN(db, n); |
| 22554 | + assert( sqlite3_mutex_held(db->mutex) ); |
| 22555 | + if( isLookaside(db,p) && n<=db->lookaside.sz ) return p; |
| 22556 | + return dbReallocFinish(db, p, n); |
| 22557 | +} |
| 22558 | +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){ |
| 22465 | 22559 | void *pNew = 0; |
| 22466 | 22560 | assert( db!=0 ); |
| 22467 | | - assert( sqlite3_mutex_held(db->mutex) ); |
| 22561 | + assert( p!=0 ); |
| 22468 | 22562 | if( db->mallocFailed==0 ){ |
| 22469 | | - if( p==0 ){ |
| 22470 | | - return sqlite3DbMallocRaw(db, n); |
| 22471 | | - } |
| 22472 | 22563 | if( isLookaside(db, p) ){ |
| 22473 | | - if( n<=db->lookaside.sz ){ |
| 22474 | | - return p; |
| 22475 | | - } |
| 22476 | | - pNew = sqlite3DbMallocRaw(db, n); |
| 22564 | + pNew = sqlite3DbMallocRawNN(db, n); |
| 22477 | 22565 | if( pNew ){ |
| 22478 | 22566 | memcpy(pNew, p, db->lookaside.sz); |
| 22479 | 22567 | sqlite3DbFree(db, p); |
| 22480 | 22568 | } |
| 22481 | 22569 | }else{ |
| | @@ -22482,14 +22570,14 @@ |
| 22482 | 22570 | assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22483 | 22571 | assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); |
| 22484 | 22572 | sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
| 22485 | 22573 | pNew = sqlite3_realloc64(p, n); |
| 22486 | 22574 | if( !pNew ){ |
| 22487 | | - db->mallocFailed = 1; |
| 22575 | + sqlite3OomFault(db); |
| 22488 | 22576 | } |
| 22489 | 22577 | sqlite3MemdebugSetType(pNew, |
| 22490 | | - (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); |
| 22578 | + (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); |
| 22491 | 22579 | } |
| 22492 | 22580 | } |
| 22493 | 22581 | return pNew; |
| 22494 | 22582 | } |
| 22495 | 22583 | |
| | @@ -22527,15 +22615,16 @@ |
| 22527 | 22615 | } |
| 22528 | 22616 | return zNew; |
| 22529 | 22617 | } |
| 22530 | 22618 | SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ |
| 22531 | 22619 | char *zNew; |
| 22620 | + assert( db!=0 ); |
| 22532 | 22621 | if( z==0 ){ |
| 22533 | 22622 | return 0; |
| 22534 | 22623 | } |
| 22535 | 22624 | assert( (n&0x7fffffff)==n ); |
| 22536 | | - zNew = sqlite3DbMallocRaw(db, n+1); |
| 22625 | + zNew = sqlite3DbMallocRawNN(db, n+1); |
| 22537 | 22626 | if( zNew ){ |
| 22538 | 22627 | memcpy(zNew, z, (size_t)n); |
| 22539 | 22628 | zNew[n] = 0; |
| 22540 | 22629 | } |
| 22541 | 22630 | return zNew; |
| | @@ -22546,16 +22635,48 @@ |
| 22546 | 22635 | */ |
| 22547 | 22636 | SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ |
| 22548 | 22637 | sqlite3DbFree(db, *pz); |
| 22549 | 22638 | *pz = sqlite3DbStrDup(db, zNew); |
| 22550 | 22639 | } |
| 22640 | + |
| 22641 | +/* |
| 22642 | +** Call this routine to record the fact that an OOM (out-of-memory) error |
| 22643 | +** has happened. This routine will set db->mallocFailed, and also |
| 22644 | +** temporarily disable the lookaside memory allocator and interrupt |
| 22645 | +** any running VDBEs. |
| 22646 | +*/ |
| 22647 | +SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){ |
| 22648 | + if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ |
| 22649 | + db->mallocFailed = 1; |
| 22650 | + if( db->nVdbeExec>0 ){ |
| 22651 | + db->u1.isInterrupted = 1; |
| 22652 | + } |
| 22653 | + db->lookaside.bDisable++; |
| 22654 | + } |
| 22655 | +} |
| 22656 | + |
| 22657 | +/* |
| 22658 | +** This routine reactivates the memory allocator and clears the |
| 22659 | +** db->mallocFailed flag as necessary. |
| 22660 | +** |
| 22661 | +** The memory allocator is not restarted if there are running |
| 22662 | +** VDBEs. |
| 22663 | +*/ |
| 22664 | +SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){ |
| 22665 | + if( db->mallocFailed && db->nVdbeExec==0 ){ |
| 22666 | + db->mallocFailed = 0; |
| 22667 | + db->u1.isInterrupted = 0; |
| 22668 | + assert( db->lookaside.bDisable>0 ); |
| 22669 | + db->lookaside.bDisable--; |
| 22670 | + } |
| 22671 | +} |
| 22551 | 22672 | |
| 22552 | 22673 | /* |
| 22553 | 22674 | ** Take actions at the end of an API call to indicate an OOM error |
| 22554 | 22675 | */ |
| 22555 | 22676 | static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ |
| 22556 | | - db->mallocFailed = 0; |
| 22677 | + sqlite3OomClear(db); |
| 22557 | 22678 | sqlite3Error(db, SQLITE_NOMEM); |
| 22558 | 22679 | return SQLITE_NOMEM; |
| 22559 | 22680 | } |
| 22560 | 22681 | |
| 22561 | 22682 | /* |
| | @@ -22756,11 +22877,10 @@ |
| 22756 | 22877 | /* |
| 22757 | 22878 | ** Render a string given by "fmt" into the StrAccum object. |
| 22758 | 22879 | */ |
| 22759 | 22880 | SQLITE_PRIVATE void sqlite3VXPrintf( |
| 22760 | 22881 | StrAccum *pAccum, /* Accumulate results here */ |
| 22761 | | - u32 bFlags, /* SQLITE_PRINTF_* flags */ |
| 22762 | 22882 | const char *fmt, /* Format string */ |
| 22763 | 22883 | va_list ap /* arguments */ |
| 22764 | 22884 | ){ |
| 22765 | 22885 | int c; /* Next character in the format string */ |
| 22766 | 22886 | char *bufpt; /* Pointer to the conversion buffer */ |
| | @@ -22796,15 +22916,15 @@ |
| 22796 | 22916 | #endif |
| 22797 | 22917 | PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ |
| 22798 | 22918 | char buf[etBUFSIZE]; /* Conversion buffer */ |
| 22799 | 22919 | |
| 22800 | 22920 | bufpt = 0; |
| 22801 | | - if( bFlags ){ |
| 22802 | | - if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ |
| 22921 | + if( pAccum->printfFlags ){ |
| 22922 | + if( (bArgList = (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ |
| 22803 | 22923 | pArgList = va_arg(ap, PrintfArguments*); |
| 22804 | 22924 | } |
| 22805 | | - useIntern = bFlags & SQLITE_PRINTF_INTERNAL; |
| 22925 | + useIntern = pAccum->printfFlags & SQLITE_PRINTF_INTERNAL; |
| 22806 | 22926 | }else{ |
| 22807 | 22927 | bArgList = useIntern = 0; |
| 22808 | 22928 | } |
| 22809 | 22929 | for(; (c=(*fmt))!=0; ++fmt){ |
| 22810 | 22930 | if( c!='%' ){ |
| | @@ -23351,13 +23471,13 @@ |
| 23351 | 23471 | if( p->mxAlloc==0 ){ |
| 23352 | 23472 | N = p->nAlloc - p->nChar - 1; |
| 23353 | 23473 | setStrAccumError(p, STRACCUM_TOOBIG); |
| 23354 | 23474 | return N; |
| 23355 | 23475 | }else{ |
| 23356 | | - char *zOld = p->bMalloced ? p->zText : 0; |
| 23476 | + char *zOld = isMalloced(p) ? p->zText : 0; |
| 23357 | 23477 | i64 szNew = p->nChar; |
| 23358 | | - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23478 | + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
| 23359 | 23479 | szNew += N + 1; |
| 23360 | 23480 | if( szNew+p->nChar<=p->mxAlloc ){ |
| 23361 | 23481 | /* Force exponential buffer size growth as long as it does not overflow, |
| 23362 | 23482 | ** to avoid having to call this routine too often */ |
| 23363 | 23483 | szNew += p->nChar; |
| | @@ -23374,14 +23494,14 @@ |
| 23374 | 23494 | }else{ |
| 23375 | 23495 | zNew = sqlite3_realloc64(zOld, p->nAlloc); |
| 23376 | 23496 | } |
| 23377 | 23497 | if( zNew ){ |
| 23378 | 23498 | assert( p->zText!=0 || p->nChar==0 ); |
| 23379 | | - if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); |
| 23499 | + if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); |
| 23380 | 23500 | p->zText = zNew; |
| 23381 | 23501 | p->nAlloc = sqlite3DbMallocSize(p->db, zNew); |
| 23382 | | - p->bMalloced = 1; |
| 23502 | + p->printfFlags |= SQLITE_PRINTF_MALLOCED; |
| 23383 | 23503 | }else{ |
| 23384 | 23504 | sqlite3StrAccumReset(p); |
| 23385 | 23505 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23386 | 23506 | return 0; |
| 23387 | 23507 | } |
| | @@ -23395,11 +23515,11 @@ |
| 23395 | 23515 | SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ |
| 23396 | 23516 | testcase( p->nChar + (i64)N > 0x7fffffff ); |
| 23397 | 23517 | if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ |
| 23398 | 23518 | return; |
| 23399 | 23519 | } |
| 23400 | | - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23520 | + assert( (p->zText==p->zBase)==!isMalloced(p) ); |
| 23401 | 23521 | while( (N--)>0 ) p->zText[p->nChar++] = c; |
| 23402 | 23522 | } |
| 23403 | 23523 | |
| 23404 | 23524 | /* |
| 23405 | 23525 | ** The StrAccum "p" is not large enough to accept N new bytes of z[]. |
| | @@ -23413,11 +23533,11 @@ |
| 23413 | 23533 | N = sqlite3StrAccumEnlarge(p, N); |
| 23414 | 23534 | if( N>0 ){ |
| 23415 | 23535 | memcpy(&p->zText[p->nChar], z, N); |
| 23416 | 23536 | p->nChar += N; |
| 23417 | 23537 | } |
| 23418 | | - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23538 | + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
| 23419 | 23539 | } |
| 23420 | 23540 | |
| 23421 | 23541 | /* |
| 23422 | 23542 | ** Append N bytes of text from z to the StrAccum object. Increase the |
| 23423 | 23543 | ** size of the memory allocation for StrAccum if necessary. |
| | @@ -23449,17 +23569,17 @@ |
| 23449 | 23569 | ** Return a pointer to the resulting string. Return a NULL |
| 23450 | 23570 | ** pointer if any kind of error was encountered. |
| 23451 | 23571 | */ |
| 23452 | 23572 | SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ |
| 23453 | 23573 | if( p->zText ){ |
| 23454 | | - assert( (p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23574 | + assert( (p->zText==p->zBase)==!isMalloced(p) ); |
| 23455 | 23575 | p->zText[p->nChar] = 0; |
| 23456 | | - if( p->mxAlloc>0 && p->bMalloced==0 ){ |
| 23576 | + if( p->mxAlloc>0 && !isMalloced(p) ){ |
| 23457 | 23577 | p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
| 23458 | 23578 | if( p->zText ){ |
| 23459 | 23579 | memcpy(p->zText, p->zBase, p->nChar+1); |
| 23460 | | - p->bMalloced = 1; |
| 23580 | + p->printfFlags |= SQLITE_PRINTF_MALLOCED; |
| 23461 | 23581 | }else{ |
| 23462 | 23582 | setStrAccumError(p, STRACCUM_NOMEM); |
| 23463 | 23583 | } |
| 23464 | 23584 | } |
| 23465 | 23585 | } |
| | @@ -23468,14 +23588,14 @@ |
| 23468 | 23588 | |
| 23469 | 23589 | /* |
| 23470 | 23590 | ** Reset an StrAccum string. Reclaim all malloced memory. |
| 23471 | 23591 | */ |
| 23472 | 23592 | SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ |
| 23473 | | - assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
| 23474 | | - if( p->bMalloced ){ |
| 23593 | + assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
| 23594 | + if( isMalloced(p) ){ |
| 23475 | 23595 | sqlite3DbFree(p->db, p->zText); |
| 23476 | | - p->bMalloced = 0; |
| 23596 | + p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; |
| 23477 | 23597 | } |
| 23478 | 23598 | p->zText = 0; |
| 23479 | 23599 | } |
| 23480 | 23600 | |
| 23481 | 23601 | /* |
| | @@ -23497,11 +23617,11 @@ |
| 23497 | 23617 | p->db = db; |
| 23498 | 23618 | p->nChar = 0; |
| 23499 | 23619 | p->nAlloc = n; |
| 23500 | 23620 | p->mxAlloc = mx; |
| 23501 | 23621 | p->accError = 0; |
| 23502 | | - p->bMalloced = 0; |
| 23622 | + p->printfFlags = 0; |
| 23503 | 23623 | } |
| 23504 | 23624 | |
| 23505 | 23625 | /* |
| 23506 | 23626 | ** Print into memory obtained from sqliteMalloc(). Use the internal |
| 23507 | 23627 | ** %-conversion extensions. |
| | @@ -23511,14 +23631,15 @@ |
| 23511 | 23631 | char zBase[SQLITE_PRINT_BUF_SIZE]; |
| 23512 | 23632 | StrAccum acc; |
| 23513 | 23633 | assert( db!=0 ); |
| 23514 | 23634 | sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), |
| 23515 | 23635 | db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 23516 | | - sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); |
| 23636 | + acc.printfFlags = SQLITE_PRINTF_INTERNAL; |
| 23637 | + sqlite3VXPrintf(&acc, zFormat, ap); |
| 23517 | 23638 | z = sqlite3StrAccumFinish(&acc); |
| 23518 | 23639 | if( acc.accError==STRACCUM_NOMEM ){ |
| 23519 | | - db->mallocFailed = 1; |
| 23640 | + sqlite3OomFault(db); |
| 23520 | 23641 | } |
| 23521 | 23642 | return z; |
| 23522 | 23643 | } |
| 23523 | 23644 | |
| 23524 | 23645 | /* |
| | @@ -23551,11 +23672,11 @@ |
| 23551 | 23672 | #endif |
| 23552 | 23673 | #ifndef SQLITE_OMIT_AUTOINIT |
| 23553 | 23674 | if( sqlite3_initialize() ) return 0; |
| 23554 | 23675 | #endif |
| 23555 | 23676 | sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); |
| 23556 | | - sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23677 | + sqlite3VXPrintf(&acc, zFormat, ap); |
| 23557 | 23678 | z = sqlite3StrAccumFinish(&acc); |
| 23558 | 23679 | return z; |
| 23559 | 23680 | } |
| 23560 | 23681 | |
| 23561 | 23682 | /* |
| | @@ -23596,11 +23717,11 @@ |
| 23596 | 23717 | if( zBuf ) zBuf[0] = 0; |
| 23597 | 23718 | return zBuf; |
| 23598 | 23719 | } |
| 23599 | 23720 | #endif |
| 23600 | 23721 | sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); |
| 23601 | | - sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23722 | + sqlite3VXPrintf(&acc, zFormat, ap); |
| 23602 | 23723 | return sqlite3StrAccumFinish(&acc); |
| 23603 | 23724 | } |
| 23604 | 23725 | SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
| 23605 | 23726 | char *z; |
| 23606 | 23727 | va_list ap; |
| | @@ -23627,11 +23748,11 @@ |
| 23627 | 23748 | static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
| 23628 | 23749 | StrAccum acc; /* String accumulator */ |
| 23629 | 23750 | char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
| 23630 | 23751 | |
| 23631 | 23752 | sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); |
| 23632 | | - sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23753 | + sqlite3VXPrintf(&acc, zFormat, ap); |
| 23633 | 23754 | sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
| 23634 | 23755 | sqlite3StrAccumFinish(&acc)); |
| 23635 | 23756 | } |
| 23636 | 23757 | |
| 23637 | 23758 | /* |
| | @@ -23656,11 +23777,11 @@ |
| 23656 | 23777 | va_list ap; |
| 23657 | 23778 | StrAccum acc; |
| 23658 | 23779 | char zBuf[500]; |
| 23659 | 23780 | sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); |
| 23660 | 23781 | va_start(ap,zFormat); |
| 23661 | | - sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23782 | + sqlite3VXPrintf(&acc, zFormat, ap); |
| 23662 | 23783 | va_end(ap); |
| 23663 | 23784 | sqlite3StrAccumFinish(&acc); |
| 23664 | 23785 | fprintf(stdout,"%s", zBuf); |
| 23665 | 23786 | fflush(stdout); |
| 23666 | 23787 | } |
| | @@ -23669,14 +23790,14 @@ |
| 23669 | 23790 | |
| 23670 | 23791 | /* |
| 23671 | 23792 | ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument |
| 23672 | 23793 | ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. |
| 23673 | 23794 | */ |
| 23674 | | -SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ |
| 23795 | +SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ |
| 23675 | 23796 | va_list ap; |
| 23676 | 23797 | va_start(ap,zFormat); |
| 23677 | | - sqlite3VXPrintf(p, bFlags, zFormat, ap); |
| 23798 | + sqlite3VXPrintf(p, zFormat, ap); |
| 23678 | 23799 | va_end(ap); |
| 23679 | 23800 | } |
| 23680 | 23801 | |
| 23681 | 23802 | /************** End of printf.c **********************************************/ |
| 23682 | 23803 | /************** Begin file treeview.c ****************************************/ |
| | @@ -23743,11 +23864,11 @@ |
| 23743 | 23864 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); |
| 23744 | 23865 | } |
| 23745 | 23866 | sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); |
| 23746 | 23867 | } |
| 23747 | 23868 | va_start(ap, zFormat); |
| 23748 | | - sqlite3VXPrintf(&acc, 0, zFormat, ap); |
| 23869 | + sqlite3VXPrintf(&acc, zFormat, ap); |
| 23749 | 23870 | va_end(ap); |
| 23750 | 23871 | if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); |
| 23751 | 23872 | sqlite3StrAccumFinish(&acc); |
| 23752 | 23873 | fprintf(stdout,"%s", zBuf); |
| 23753 | 23874 | fflush(stdout); |
| | @@ -23778,21 +23899,21 @@ |
| 23778 | 23899 | for(i=0; i<pWith->nCte; i++){ |
| 23779 | 23900 | StrAccum x; |
| 23780 | 23901 | char zLine[1000]; |
| 23781 | 23902 | const struct Cte *pCte = &pWith->a[i]; |
| 23782 | 23903 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23783 | | - sqlite3XPrintf(&x, 0, "%s", pCte->zName); |
| 23904 | + sqlite3XPrintf(&x, "%s", pCte->zName); |
| 23784 | 23905 | if( pCte->pCols && pCte->pCols->nExpr>0 ){ |
| 23785 | 23906 | char cSep = '('; |
| 23786 | 23907 | int j; |
| 23787 | 23908 | for(j=0; j<pCte->pCols->nExpr; j++){ |
| 23788 | | - sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName); |
| 23909 | + sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); |
| 23789 | 23910 | cSep = ','; |
| 23790 | 23911 | } |
| 23791 | | - sqlite3XPrintf(&x, 0, ")"); |
| 23912 | + sqlite3XPrintf(&x, ")"); |
| 23792 | 23913 | } |
| 23793 | | - sqlite3XPrintf(&x, 0, " AS"); |
| 23914 | + sqlite3XPrintf(&x, " AS"); |
| 23794 | 23915 | sqlite3StrAccumFinish(&x); |
| 23795 | 23916 | sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1); |
| 23796 | 23917 | sqlite3TreeViewSelect(pView, pCte->pSelect, 0); |
| 23797 | 23918 | sqlite3TreeViewPop(pView); |
| 23798 | 23919 | } |
| | @@ -23839,24 +23960,24 @@ |
| 23839 | 23960 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 23840 | 23961 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 23841 | 23962 | StrAccum x; |
| 23842 | 23963 | char zLine[100]; |
| 23843 | 23964 | sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); |
| 23844 | | - sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); |
| 23965 | + sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); |
| 23845 | 23966 | if( pItem->zDatabase ){ |
| 23846 | | - sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); |
| 23967 | + sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); |
| 23847 | 23968 | }else if( pItem->zName ){ |
| 23848 | | - sqlite3XPrintf(&x, 0, " %s", pItem->zName); |
| 23969 | + sqlite3XPrintf(&x, " %s", pItem->zName); |
| 23849 | 23970 | } |
| 23850 | 23971 | if( pItem->pTab ){ |
| 23851 | | - sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); |
| 23972 | + sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); |
| 23852 | 23973 | } |
| 23853 | 23974 | if( pItem->zAlias ){ |
| 23854 | | - sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); |
| 23975 | + sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); |
| 23855 | 23976 | } |
| 23856 | 23977 | if( pItem->fg.jointype & JT_LEFT ){ |
| 23857 | | - sqlite3XPrintf(&x, 0, " LEFT-JOIN"); |
| 23978 | + sqlite3XPrintf(&x, " LEFT-JOIN"); |
| 23858 | 23979 | } |
| 23859 | 23980 | sqlite3StrAccumFinish(&x); |
| 23860 | 23981 | sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); |
| 23861 | 23982 | if( pItem->pSelect ){ |
| 23862 | 23983 | sqlite3TreeViewSelect(pView, pItem->pSelect, 0); |
| | @@ -24899,11 +25020,11 @@ |
| 24899 | 25020 | *z = 0; |
| 24900 | 25021 | assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); |
| 24901 | 25022 | |
| 24902 | 25023 | c = pMem->flags; |
| 24903 | 25024 | sqlite3VdbeMemRelease(pMem); |
| 24904 | | - pMem->flags = MEM_Str|MEM_Term|(c&MEM_AffMask); |
| 25025 | + pMem->flags = MEM_Str|MEM_Term|(c&(MEM_AffMask|MEM_Subtype)); |
| 24905 | 25026 | pMem->enc = desiredEnc; |
| 24906 | 25027 | pMem->z = (char*)zOut; |
| 24907 | 25028 | pMem->zMalloc = pMem->z; |
| 24908 | 25029 | pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z); |
| 24909 | 25030 | |
| | @@ -25349,10 +25470,18 @@ |
| 25349 | 25470 | } |
| 25350 | 25471 | } |
| 25351 | 25472 | z[j] = 0; |
| 25352 | 25473 | return j; |
| 25353 | 25474 | } |
| 25475 | + |
| 25476 | +/* |
| 25477 | +** Generate a Token object from a string |
| 25478 | +*/ |
| 25479 | +SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ |
| 25480 | + p->z = z; |
| 25481 | + p->n = sqlite3Strlen30(z); |
| 25482 | +} |
| 25354 | 25483 | |
| 25355 | 25484 | /* Convenient short-hand */ |
| 25356 | 25485 | #define UpperToLower sqlite3UpperToLower |
| 25357 | 25486 | |
| 25358 | 25487 | /* |
| | @@ -26258,11 +26387,11 @@ |
| 26258 | 26387 | */ |
| 26259 | 26388 | SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ |
| 26260 | 26389 | char *zBlob; |
| 26261 | 26390 | int i; |
| 26262 | 26391 | |
| 26263 | | - zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1); |
| 26392 | + zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1); |
| 26264 | 26393 | n--; |
| 26265 | 26394 | if( zBlob ){ |
| 26266 | 26395 | for(i=0; i<n; i+=2){ |
| 26267 | 26396 | zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]); |
| 26268 | 26397 | } |
| | @@ -26796,95 +26925,96 @@ |
| 26796 | 26925 | # define OpHelp(X) "\0" X |
| 26797 | 26926 | #else |
| 26798 | 26927 | # define OpHelp(X) |
| 26799 | 26928 | #endif |
| 26800 | 26929 | 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(""), |
| 26930 | + static const char *const azName[] = { |
| 26931 | + /* 0 */ "Savepoint" OpHelp(""), |
| 26932 | + /* 1 */ "AutoCommit" OpHelp(""), |
| 26933 | + /* 2 */ "Transaction" OpHelp(""), |
| 26934 | + /* 3 */ "SorterNext" OpHelp(""), |
| 26935 | + /* 4 */ "PrevIfOpen" OpHelp(""), |
| 26936 | + /* 5 */ "NextIfOpen" OpHelp(""), |
| 26937 | + /* 6 */ "Prev" OpHelp(""), |
| 26938 | + /* 7 */ "Next" OpHelp(""), |
| 26939 | + /* 8 */ "Checkpoint" OpHelp(""), |
| 26940 | + /* 9 */ "JournalMode" OpHelp(""), |
| 26941 | + /* 10 */ "Vacuum" OpHelp(""), |
| 26942 | + /* 11 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), |
| 26943 | + /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"), |
| 26944 | + /* 13 */ "Goto" OpHelp(""), |
| 26945 | + /* 14 */ "Gosub" OpHelp(""), |
| 26946 | + /* 15 */ "Return" OpHelp(""), |
| 26947 | + /* 16 */ "InitCoroutine" OpHelp(""), |
| 26948 | + /* 17 */ "EndCoroutine" OpHelp(""), |
| 26949 | + /* 18 */ "Yield" OpHelp(""), |
| 26820 | 26950 | /* 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]"), |
| 26951 | + /* 20 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), |
| 26952 | + /* 21 */ "Halt" OpHelp(""), |
| 26953 | + /* 22 */ "Integer" OpHelp("r[P2]=P1"), |
| 26954 | + /* 23 */ "Int64" OpHelp("r[P2]=P4"), |
| 26955 | + /* 24 */ "String" OpHelp("r[P2]='P4' (len=P1)"), |
| 26956 | + /* 25 */ "Null" OpHelp("r[P2..P3]=NULL"), |
| 26957 | + /* 26 */ "SoftNull" OpHelp("r[P1]=NULL"), |
| 26958 | + /* 27 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), |
| 26959 | + /* 28 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), |
| 26960 | + /* 29 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), |
| 26961 | + /* 30 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), |
| 26962 | + /* 31 */ "SCopy" OpHelp("r[P2]=r[P1]"), |
| 26963 | + /* 32 */ "IntCopy" OpHelp("r[P2]=r[P1]"), |
| 26964 | + /* 33 */ "ResultRow" OpHelp("output=r[P1@P2]"), |
| 26965 | + /* 34 */ "CollSeq" OpHelp(""), |
| 26966 | + /* 35 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), |
| 26967 | + /* 36 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), |
| 26968 | + /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), |
| 26969 | + /* 38 */ "MustBeInt" OpHelp(""), |
| 26970 | + /* 39 */ "RealAffinity" OpHelp(""), |
| 26971 | + /* 40 */ "Cast" OpHelp("affinity(r[P1])"), |
| 26972 | + /* 41 */ "Permutation" OpHelp(""), |
| 26973 | + /* 42 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), |
| 26974 | + /* 43 */ "Jump" OpHelp(""), |
| 26975 | + /* 44 */ "Once" OpHelp(""), |
| 26976 | + /* 45 */ "If" OpHelp(""), |
| 26977 | + /* 46 */ "IfNot" OpHelp(""), |
| 26978 | + /* 47 */ "Column" OpHelp("r[P3]=PX"), |
| 26979 | + /* 48 */ "Affinity" OpHelp("affinity(r[P1@P2])"), |
| 26980 | + /* 49 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), |
| 26981 | + /* 50 */ "Count" OpHelp("r[P2]=count()"), |
| 26982 | + /* 51 */ "ReadCookie" OpHelp(""), |
| 26983 | + /* 52 */ "SetCookie" OpHelp(""), |
| 26984 | + /* 53 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), |
| 26985 | + /* 54 */ "OpenRead" OpHelp("root=P2 iDb=P3"), |
| 26986 | + /* 55 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), |
| 26987 | + /* 56 */ "OpenAutoindex" OpHelp("nColumn=P2"), |
| 26988 | + /* 57 */ "OpenEphemeral" OpHelp("nColumn=P2"), |
| 26989 | + /* 58 */ "SorterOpen" OpHelp(""), |
| 26990 | + /* 59 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), |
| 26991 | + /* 60 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), |
| 26992 | + /* 61 */ "Close" OpHelp(""), |
| 26993 | + /* 62 */ "ColumnsUsed" OpHelp(""), |
| 26994 | + /* 63 */ "SeekLT" OpHelp("key=r[P3@P4]"), |
| 26995 | + /* 64 */ "SeekLE" OpHelp("key=r[P3@P4]"), |
| 26996 | + /* 65 */ "SeekGE" OpHelp("key=r[P3@P4]"), |
| 26997 | + /* 66 */ "SeekGT" OpHelp("key=r[P3@P4]"), |
| 26998 | + /* 67 */ "NoConflict" OpHelp("key=r[P3@P4]"), |
| 26999 | + /* 68 */ "NotFound" OpHelp("key=r[P3@P4]"), |
| 27000 | + /* 69 */ "Found" OpHelp("key=r[P3@P4]"), |
| 27001 | + /* 70 */ "NotExists" OpHelp("intkey=r[P3]"), |
| 26872 | 27002 | /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), |
| 26873 | 27003 | /* 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++"), |
| 27004 | + /* 73 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), |
| 27005 | + /* 74 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 27006 | + /* 75 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 26877 | 27007 | /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), |
| 26878 | 27008 | /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), |
| 26879 | 27009 | /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"), |
| 26880 | 27010 | /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"), |
| 26881 | 27011 | /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"), |
| 26882 | 27012 | /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"), |
| 26883 | 27013 | /* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"), |
| 26884 | 27014 | /* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"), |
| 26885 | | - /* 84 */ "NewRowid" OpHelp("r[P2]=rowid"), |
| 27015 | + /* 84 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), |
| 26886 | 27016 | /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), |
| 26887 | 27017 | /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), |
| 26888 | 27018 | /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), |
| 26889 | 27019 | /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), |
| 26890 | 27020 | /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), |
| | @@ -26891,78 +27021,77 @@ |
| 26891 | 27021 | /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), |
| 26892 | 27022 | /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), |
| 26893 | 27023 | /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), |
| 26894 | 27024 | /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), |
| 26895 | 27025 | /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), |
| 26896 | | - /* 95 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), |
| 27026 | + /* 95 */ "Delete" OpHelp(""), |
| 26897 | 27027 | /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), |
| 26898 | 27028 | /* 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"), |
| 27029 | + /* 98 */ "ResetCount" OpHelp(""), |
| 27030 | + /* 99 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), |
| 27031 | + /* 100 */ "SorterData" OpHelp("r[P2]=data"), |
| 27032 | + /* 101 */ "RowKey" OpHelp("r[P2]=key"), |
| 27033 | + /* 102 */ "RowData" OpHelp("r[P2]=data"), |
| 27034 | + /* 103 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 27035 | + /* 104 */ "NullRow" OpHelp(""), |
| 27036 | + /* 105 */ "Last" OpHelp(""), |
| 27037 | + /* 106 */ "SorterSort" OpHelp(""), |
| 27038 | + /* 107 */ "Sort" OpHelp(""), |
| 27039 | + /* 108 */ "Rewind" OpHelp(""), |
| 27040 | + /* 109 */ "SorterInsert" OpHelp(""), |
| 27041 | + /* 110 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 27042 | + /* 111 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 27043 | + /* 112 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 27044 | + /* 113 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 27045 | + /* 114 */ "IdxLE" OpHelp("key=r[P3@P4]"), |
| 27046 | + /* 115 */ "IdxGT" OpHelp("key=r[P3@P4]"), |
| 27047 | + /* 116 */ "IdxLT" OpHelp("key=r[P3@P4]"), |
| 27048 | + /* 117 */ "IdxGE" OpHelp("key=r[P3@P4]"), |
| 27049 | + /* 118 */ "Destroy" OpHelp(""), |
| 27050 | + /* 119 */ "Clear" OpHelp(""), |
| 27051 | + /* 120 */ "ResetSorter" OpHelp(""), |
| 27052 | + /* 121 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 27053 | + /* 122 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 27054 | + /* 123 */ "ParseSchema" OpHelp(""), |
| 27055 | + /* 124 */ "LoadAnalysis" OpHelp(""), |
| 27056 | + /* 125 */ "DropTable" OpHelp(""), |
| 27057 | + /* 126 */ "DropIndex" OpHelp(""), |
| 27058 | + /* 127 */ "DropTrigger" OpHelp(""), |
| 27059 | + /* 128 */ "IntegrityCk" OpHelp(""), |
| 27060 | + /* 129 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), |
| 27061 | + /* 130 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), |
| 27062 | + /* 131 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), |
| 27063 | + /* 132 */ "Program" OpHelp(""), |
| 26934 | 27064 | /* 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(""), |
| 27065 | + /* 134 */ "Param" OpHelp(""), |
| 27066 | + /* 135 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), |
| 27067 | + /* 136 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), |
| 27068 | + /* 137 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), |
| 27069 | + /* 138 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), |
| 27070 | + /* 139 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), |
| 27071 | + /* 140 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), |
| 27072 | + /* 141 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), |
| 27073 | + /* 142 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"), |
| 27074 | + /* 143 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 27075 | + /* 144 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), |
| 27076 | + /* 145 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), |
| 27077 | + /* 146 */ "IncrVacuum" OpHelp(""), |
| 27078 | + /* 147 */ "Expire" OpHelp(""), |
| 27079 | + /* 148 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), |
| 27080 | + /* 149 */ "VBegin" OpHelp(""), |
| 27081 | + /* 150 */ "VCreate" OpHelp(""), |
| 27082 | + /* 151 */ "VDestroy" OpHelp(""), |
| 27083 | + /* 152 */ "VOpen" OpHelp(""), |
| 27084 | + /* 153 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), |
| 27085 | + /* 154 */ "VNext" OpHelp(""), |
| 27086 | + /* 155 */ "VRename" OpHelp(""), |
| 27087 | + /* 156 */ "Pagecount" OpHelp(""), |
| 27088 | + /* 157 */ "MaxPgcnt" OpHelp(""), |
| 27089 | + /* 158 */ "Init" OpHelp("Start at P2"), |
| 27090 | + /* 159 */ "CursorHint" OpHelp(""), |
| 27091 | + /* 160 */ "Noop" OpHelp(""), |
| 27092 | + /* 161 */ "Explain" OpHelp(""), |
| 26964 | 27093 | }; |
| 26965 | 27094 | return azName[i]; |
| 26966 | 27095 | } |
| 26967 | 27096 | #endif |
| 26968 | 27097 | |
| | @@ -27117,10 +27246,15 @@ |
| 27117 | 27246 | /* |
| 27118 | 27247 | ** Maximum supported path-length. |
| 27119 | 27248 | */ |
| 27120 | 27249 | #define MAX_PATHNAME 512 |
| 27121 | 27250 | |
| 27251 | +/* |
| 27252 | +** Maximum supported symbolic links |
| 27253 | +*/ |
| 27254 | +#define SQLITE_MAX_SYMLINKS 100 |
| 27255 | + |
| 27122 | 27256 | /* Always cast the getpid() return type for compatibility with |
| 27123 | 27257 | ** kernel modules in VxWorks. */ |
| 27124 | 27258 | #define osGetpid(X) (pid_t)getpid() |
| 27125 | 27259 | |
| 27126 | 27260 | /* |
| | @@ -27269,12 +27403,12 @@ |
| 27269 | 27403 | ** Macros for performance tracing. Normally turned off. Only works |
| 27270 | 27404 | ** on i486 hardware. |
| 27271 | 27405 | */ |
| 27272 | 27406 | #ifdef SQLITE_PERFORMANCE_TRACE |
| 27273 | 27407 | |
| 27274 | | -/* |
| 27275 | | -** hwtime.h contains inline assembler code for implementing |
| 27408 | +/* |
| 27409 | +** hwtime.h contains inline assembler code for implementing |
| 27276 | 27410 | ** high-performance timing routines. |
| 27277 | 27411 | */ |
| 27278 | 27412 | /************** Include hwtime.h in the middle of os_common.h ****************/ |
| 27279 | 27413 | /************** Begin file hwtime.h ******************************************/ |
| 27280 | 27414 | /* |
| | @@ -27380,18 +27514,18 @@ |
| 27380 | 27514 | /* |
| 27381 | 27515 | ** If we compile with the SQLITE_TEST macro set, then the following block |
| 27382 | 27516 | ** of code will give us the ability to simulate a disk I/O error. This |
| 27383 | 27517 | ** is used for testing the I/O recovery logic. |
| 27384 | 27518 | */ |
| 27385 | | -#ifdef SQLITE_TEST |
| 27386 | | -SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ |
| 27387 | | -SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ |
| 27388 | | -SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ |
| 27389 | | -SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ |
| 27390 | | -SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ |
| 27391 | | -SQLITE_API int sqlite3_diskfull_pending = 0; |
| 27392 | | -SQLITE_API int sqlite3_diskfull = 0; |
| 27519 | +#if defined(SQLITE_TEST) |
| 27520 | +SQLITE_API extern int sqlite3_io_error_hit; |
| 27521 | +SQLITE_API extern int sqlite3_io_error_hardhit; |
| 27522 | +SQLITE_API extern int sqlite3_io_error_pending; |
| 27523 | +SQLITE_API extern int sqlite3_io_error_persist; |
| 27524 | +SQLITE_API extern int sqlite3_io_error_benign; |
| 27525 | +SQLITE_API extern int sqlite3_diskfull_pending; |
| 27526 | +SQLITE_API extern int sqlite3_diskfull; |
| 27393 | 27527 | #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) |
| 27394 | 27528 | #define SimulateIOError(CODE) \ |
| 27395 | 27529 | if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ |
| 27396 | 27530 | || sqlite3_io_error_pending-- == 1 ) \ |
| 27397 | 27531 | { local_ioerr(); CODE; } |
| | @@ -27413,21 +27547,21 @@ |
| 27413 | 27547 | } |
| 27414 | 27548 | #else |
| 27415 | 27549 | #define SimulateIOErrorBenign(X) |
| 27416 | 27550 | #define SimulateIOError(A) |
| 27417 | 27551 | #define SimulateDiskfullError(A) |
| 27418 | | -#endif |
| 27552 | +#endif /* defined(SQLITE_TEST) */ |
| 27419 | 27553 | |
| 27420 | 27554 | /* |
| 27421 | 27555 | ** When testing, keep a count of the number of open files. |
| 27422 | 27556 | */ |
| 27423 | | -#ifdef SQLITE_TEST |
| 27424 | | -SQLITE_API int sqlite3_open_file_count = 0; |
| 27557 | +#if defined(SQLITE_TEST) |
| 27558 | +SQLITE_API extern int sqlite3_open_file_count; |
| 27425 | 27559 | #define OpenCounter(X) sqlite3_open_file_count+=(X) |
| 27426 | 27560 | #else |
| 27427 | 27561 | #define OpenCounter(X) |
| 27428 | | -#endif |
| 27562 | +#endif /* defined(SQLITE_TEST) */ |
| 27429 | 27563 | |
| 27430 | 27564 | #endif /* !defined(_OS_COMMON_H_) */ |
| 27431 | 27565 | |
| 27432 | 27566 | /************** End of os_common.h *******************************************/ |
| 27433 | 27567 | /************** Continuing where we left off in os_unix.c ********************/ |
| | @@ -27641,10 +27775,16 @@ |
| 27641 | 27775 | #else |
| 27642 | 27776 | { "readlink", (sqlite3_syscall_ptr)0, 0 }, |
| 27643 | 27777 | #endif |
| 27644 | 27778 | #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent) |
| 27645 | 27779 | |
| 27780 | +#if defined(HAVE_LSTAT) |
| 27781 | + { "lstat", (sqlite3_syscall_ptr)lstat, 0 }, |
| 27782 | +#else |
| 27783 | + { "lstat", (sqlite3_syscall_ptr)0, 0 }, |
| 27784 | +#endif |
| 27785 | +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) |
| 27646 | 27786 | |
| 27647 | 27787 | }; /* End of the overrideable system calls */ |
| 27648 | 27788 | |
| 27649 | 27789 | |
| 27650 | 27790 | /* |
| | @@ -33042,16 +33182,11 @@ |
| 33042 | 33182 | #ifndef SQLITE_DISABLE_DIRSYNC |
| 33043 | 33183 | if( (dirSync & 1)!=0 ){ |
| 33044 | 33184 | int fd; |
| 33045 | 33185 | rc = osOpenDirectory(zPath, &fd); |
| 33046 | 33186 | if( rc==SQLITE_OK ){ |
| 33047 | | -#if OS_VXWORKS |
| 33048 | | - if( fsync(fd)==-1 ) |
| 33049 | | -#else |
| 33050 | | - if( fsync(fd) ) |
| 33051 | | -#endif |
| 33052 | | - { |
| 33187 | + if( full_fsync(fd,0,0) ){ |
| 33053 | 33188 | rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath); |
| 33054 | 33189 | } |
| 33055 | 33190 | robust_close(0, fd, __LINE__); |
| 33056 | 33191 | }else{ |
| 33057 | 33192 | assert( rc==SQLITE_CANTOPEN ); |
| | @@ -33093,10 +33228,36 @@ |
| 33093 | 33228 | *pResOut = osAccess(zPath, W_OK|R_OK)==0; |
| 33094 | 33229 | } |
| 33095 | 33230 | return SQLITE_OK; |
| 33096 | 33231 | } |
| 33097 | 33232 | |
| 33233 | +/* |
| 33234 | +** |
| 33235 | +*/ |
| 33236 | +static int mkFullPathname( |
| 33237 | + const char *zPath, /* Input path */ |
| 33238 | + char *zOut, /* Output buffer */ |
| 33239 | + int nOut /* Allocated size of buffer zOut */ |
| 33240 | +){ |
| 33241 | + int nPath = sqlite3Strlen30(zPath); |
| 33242 | + int iOff = 0; |
| 33243 | + if( zPath[0]!='/' ){ |
| 33244 | + if( osGetcwd(zOut, nOut-2)==0 ){ |
| 33245 | + return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); |
| 33246 | + } |
| 33247 | + iOff = sqlite3Strlen30(zOut); |
| 33248 | + zOut[iOff++] = '/'; |
| 33249 | + } |
| 33250 | + if( (iOff+nPath+1)>nOut ){ |
| 33251 | + /* SQLite assumes that xFullPathname() nul-terminates the output buffer |
| 33252 | + ** even if it returns an error. */ |
| 33253 | + zOut[iOff] = '\0'; |
| 33254 | + return SQLITE_CANTOPEN_BKPT; |
| 33255 | + } |
| 33256 | + sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); |
| 33257 | + return SQLITE_OK; |
| 33258 | +} |
| 33098 | 33259 | |
| 33099 | 33260 | /* |
| 33100 | 33261 | ** Turn a relative pathname into a full pathname. The relative path |
| 33101 | 33262 | ** is stored as a nul-terminated string in the buffer pointed to by |
| 33102 | 33263 | ** zPath. |
| | @@ -33109,73 +33270,85 @@ |
| 33109 | 33270 | sqlite3_vfs *pVfs, /* Pointer to vfs object */ |
| 33110 | 33271 | const char *zPath, /* Possibly relative input path */ |
| 33111 | 33272 | int nOut, /* Size of output buffer in bytes */ |
| 33112 | 33273 | char *zOut /* Output buffer */ |
| 33113 | 33274 | ){ |
| 33275 | +#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT) |
| 33276 | + return mkFullPathname(zPath, zOut, nOut); |
| 33277 | +#else |
| 33278 | + int rc = SQLITE_OK; |
| 33114 | 33279 | int nByte; |
| 33280 | + int nLink = 1; /* Number of symbolic links followed so far */ |
| 33281 | + const char *zIn = zPath; /* Input path for each iteration of loop */ |
| 33282 | + char *zDel = 0; |
| 33283 | + |
| 33284 | + assert( pVfs->mxPathname==MAX_PATHNAME ); |
| 33285 | + UNUSED_PARAMETER(pVfs); |
| 33115 | 33286 | |
| 33116 | 33287 | /* It's odd to simulate an io-error here, but really this is just |
| 33117 | 33288 | ** using the io-error infrastructure to test that SQLite handles this |
| 33118 | 33289 | ** function failing. This function could fail if, for example, the |
| 33119 | 33290 | ** current working directory has been unlinked. |
| 33120 | 33291 | */ |
| 33121 | 33292 | SimulateIOError( return SQLITE_ERROR ); |
| 33122 | 33293 | |
| 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; |
| 33294 | + do { |
| 33295 | + |
| 33296 | + /* Call stat() on path zIn. Set bLink to true if the path is a symbolic |
| 33297 | + ** link, or false otherwise. */ |
| 33298 | + int bLink = 0; |
| 33299 | + struct stat buf; |
| 33300 | + if( osLstat(zIn, &buf)!=0 ){ |
| 33301 | + if( errno!=ENOENT ){ |
| 33302 | + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); |
| 33303 | + } |
| 33304 | + }else{ |
| 33305 | + bLink = S_ISLNK(buf.st_mode); |
| 33306 | + } |
| 33307 | + |
| 33308 | + if( bLink ){ |
| 33309 | + if( zDel==0 ){ |
| 33310 | + zDel = sqlite3_malloc(nOut); |
| 33311 | + if( zDel==0 ) rc = SQLITE_NOMEM; |
| 33312 | + }else if( ++nLink>SQLITE_MAX_SYMLINKS ){ |
| 33313 | + rc = SQLITE_CANTOPEN_BKPT; |
| 33314 | + } |
| 33315 | + |
| 33316 | + if( rc==SQLITE_OK ){ |
| 33317 | + nByte = osReadlink(zIn, zDel, nOut-1); |
| 33318 | + if( nByte<0 ){ |
| 33319 | + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); |
| 33320 | + }else{ |
| 33321 | + if( zDel[0]!='/' ){ |
| 33322 | + int n; |
| 33323 | + for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); |
| 33324 | + if( nByte+n+1>nOut ){ |
| 33325 | + rc = SQLITE_CANTOPEN_BKPT; |
| 33326 | + }else{ |
| 33327 | + memmove(&zDel[n], zDel, nByte+1); |
| 33328 | + memcpy(zDel, zIn, n); |
| 33329 | + nByte += n; |
| 33330 | + } |
| 33331 | + } |
| 33332 | + zDel[nByte] = '\0'; |
| 33333 | + } |
| 33334 | + } |
| 33335 | + |
| 33336 | + zIn = zDel; |
| 33337 | + } |
| 33338 | + |
| 33339 | + assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' ); |
| 33340 | + if( rc==SQLITE_OK && zIn!=zOut ){ |
| 33341 | + rc = mkFullPathname(zIn, zOut, nOut); |
| 33342 | + } |
| 33343 | + if( bLink==0 ) break; |
| 33344 | + zIn = zOut; |
| 33345 | + }while( rc==SQLITE_OK ); |
| 33346 | + |
| 33347 | + sqlite3_free(zDel); |
| 33348 | + return rc; |
| 33349 | +#endif /* HAVE_READLINK && HAVE_LSTAT */ |
| 33177 | 33350 | } |
| 33178 | 33351 | |
| 33179 | 33352 | |
| 33180 | 33353 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 33181 | 33354 | /* |
| | @@ -33353,11 +33526,11 @@ |
| 33353 | 33526 | #endif |
| 33354 | 33527 | UNUSED_PARAMETER(NotUsed); |
| 33355 | 33528 | return rc; |
| 33356 | 33529 | } |
| 33357 | 33530 | |
| 33358 | | -#if 0 /* Not used */ |
| 33531 | +#ifndef SQLITE_OMIT_DEPRECATED |
| 33359 | 33532 | /* |
| 33360 | 33533 | ** Find the current time (in Universal Coordinated Time). Write the |
| 33361 | 33534 | ** current time and date as a Julian Day number into *prNow and |
| 33362 | 33535 | ** return 0. Return 1 if the time and date cannot be found. |
| 33363 | 33536 | */ |
| | @@ -33371,11 +33544,11 @@ |
| 33371 | 33544 | } |
| 33372 | 33545 | #else |
| 33373 | 33546 | # define unixCurrentTime 0 |
| 33374 | 33547 | #endif |
| 33375 | 33548 | |
| 33376 | | -#if 0 /* Not used */ |
| 33549 | +#ifndef SQLITE_OMIT_DEPRECATED |
| 33377 | 33550 | /* |
| 33378 | 33551 | ** We added the xGetLastError() method with the intention of providing |
| 33379 | 33552 | ** better low-level error messages when operating-system problems come up |
| 33380 | 33553 | ** during SQLite operation. But so far, none of that has been implemented |
| 33381 | 33554 | ** in the core. So this routine is never called. For now, it is merely |
| | @@ -34053,11 +34226,11 @@ |
| 34053 | 34226 | strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); |
| 34054 | 34227 | } |
| 34055 | 34228 | writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]); |
| 34056 | 34229 | robust_ftruncate(conchFile->h, writeSize); |
| 34057 | 34230 | rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0); |
| 34058 | | - fsync(conchFile->h); |
| 34231 | + full_fsync(conchFile->h,0,0); |
| 34059 | 34232 | /* If we created a new conch file (not just updated the contents of a |
| 34060 | 34233 | ** valid conch file), try to match the permissions of the database |
| 34061 | 34234 | */ |
| 34062 | 34235 | if( rc==SQLITE_OK && createConch ){ |
| 34063 | 34236 | struct stat buf; |
| | @@ -34670,11 +34843,11 @@ |
| 34670 | 34843 | }; |
| 34671 | 34844 | unsigned int i; /* Loop counter */ |
| 34672 | 34845 | |
| 34673 | 34846 | /* Double-check that the aSyscall[] array has been constructed |
| 34674 | 34847 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 34675 | | - assert( ArraySize(aSyscall)==27 ); |
| 34848 | + assert( ArraySize(aSyscall)==28 ); |
| 34676 | 34849 | |
| 34677 | 34850 | /* Register all VFSes defined in the aVfs[] array */ |
| 34678 | 34851 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 34679 | 34852 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 34680 | 34853 | } |
| | @@ -34753,12 +34926,12 @@ |
| 34753 | 34926 | ** Macros for performance tracing. Normally turned off. Only works |
| 34754 | 34927 | ** on i486 hardware. |
| 34755 | 34928 | */ |
| 34756 | 34929 | #ifdef SQLITE_PERFORMANCE_TRACE |
| 34757 | 34930 | |
| 34758 | | -/* |
| 34759 | | -** hwtime.h contains inline assembler code for implementing |
| 34931 | +/* |
| 34932 | +** hwtime.h contains inline assembler code for implementing |
| 34760 | 34933 | ** high-performance timing routines. |
| 34761 | 34934 | */ |
| 34762 | 34935 | /************** Include hwtime.h in the middle of os_common.h ****************/ |
| 34763 | 34936 | /************** Begin file hwtime.h ******************************************/ |
| 34764 | 34937 | /* |
| | @@ -34864,18 +35037,18 @@ |
| 34864 | 35037 | /* |
| 34865 | 35038 | ** If we compile with the SQLITE_TEST macro set, then the following block |
| 34866 | 35039 | ** of code will give us the ability to simulate a disk I/O error. This |
| 34867 | 35040 | ** is used for testing the I/O recovery logic. |
| 34868 | 35041 | */ |
| 34869 | | -#ifdef SQLITE_TEST |
| 34870 | | -SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ |
| 34871 | | -SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ |
| 34872 | | -SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ |
| 34873 | | -SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ |
| 34874 | | -SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */ |
| 34875 | | -SQLITE_API int sqlite3_diskfull_pending = 0; |
| 34876 | | -SQLITE_API int sqlite3_diskfull = 0; |
| 35042 | +#if defined(SQLITE_TEST) |
| 35043 | +SQLITE_API extern int sqlite3_io_error_hit; |
| 35044 | +SQLITE_API extern int sqlite3_io_error_hardhit; |
| 35045 | +SQLITE_API extern int sqlite3_io_error_pending; |
| 35046 | +SQLITE_API extern int sqlite3_io_error_persist; |
| 35047 | +SQLITE_API extern int sqlite3_io_error_benign; |
| 35048 | +SQLITE_API extern int sqlite3_diskfull_pending; |
| 35049 | +SQLITE_API extern int sqlite3_diskfull; |
| 34877 | 35050 | #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) |
| 34878 | 35051 | #define SimulateIOError(CODE) \ |
| 34879 | 35052 | if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ |
| 34880 | 35053 | || sqlite3_io_error_pending-- == 1 ) \ |
| 34881 | 35054 | { local_ioerr(); CODE; } |
| | @@ -34897,21 +35070,21 @@ |
| 34897 | 35070 | } |
| 34898 | 35071 | #else |
| 34899 | 35072 | #define SimulateIOErrorBenign(X) |
| 34900 | 35073 | #define SimulateIOError(A) |
| 34901 | 35074 | #define SimulateDiskfullError(A) |
| 34902 | | -#endif |
| 35075 | +#endif /* defined(SQLITE_TEST) */ |
| 34903 | 35076 | |
| 34904 | 35077 | /* |
| 34905 | 35078 | ** When testing, keep a count of the number of open files. |
| 34906 | 35079 | */ |
| 34907 | | -#ifdef SQLITE_TEST |
| 34908 | | -SQLITE_API int sqlite3_open_file_count = 0; |
| 35080 | +#if defined(SQLITE_TEST) |
| 35081 | +SQLITE_API extern int sqlite3_open_file_count; |
| 34909 | 35082 | #define OpenCounter(X) sqlite3_open_file_count+=(X) |
| 34910 | 35083 | #else |
| 34911 | 35084 | #define OpenCounter(X) |
| 34912 | | -#endif |
| 35085 | +#endif /* defined(SQLITE_TEST) */ |
| 34913 | 35086 | |
| 34914 | 35087 | #endif /* !defined(_OS_COMMON_H_) */ |
| 34915 | 35088 | |
| 34916 | 35089 | /************** End of os_common.h *******************************************/ |
| 34917 | 35090 | /************** Continuing where we left off in os_win.c *********************/ |
| | @@ -34970,10 +35143,14 @@ |
| 34970 | 35143 | |
| 34971 | 35144 | #ifndef NTDDI_WINBLUE |
| 34972 | 35145 | # define NTDDI_WINBLUE 0x06030000 |
| 34973 | 35146 | #endif |
| 34974 | 35147 | |
| 35148 | +#ifndef NTDDI_WINTHRESHOLD |
| 35149 | +# define NTDDI_WINTHRESHOLD 0x06040000 |
| 35150 | +#endif |
| 35151 | + |
| 34975 | 35152 | /* |
| 34976 | 35153 | ** Check to see if the GetVersionEx[AW] functions are deprecated on the |
| 34977 | 35154 | ** target system. GetVersionEx was first deprecated in Win8.1. |
| 34978 | 35155 | */ |
| 34979 | 35156 | #ifndef SQLITE_WIN32_GETVERSIONEX |
| | @@ -34982,10 +35159,23 @@ |
| 34982 | 35159 | # else |
| 34983 | 35160 | # define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ |
| 34984 | 35161 | # endif |
| 34985 | 35162 | #endif |
| 34986 | 35163 | |
| 35164 | +/* |
| 35165 | +** Check to see if the CreateFileMappingA function is supported on the |
| 35166 | +** target system. It is unavailable when using "mincore.lib" on Win10. |
| 35167 | +** When compiling for Windows 10, always assume "mincore.lib" is in use. |
| 35168 | +*/ |
| 35169 | +#ifndef SQLITE_WIN32_CREATEFILEMAPPINGA |
| 35170 | +# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD |
| 35171 | +# define SQLITE_WIN32_CREATEFILEMAPPINGA 0 |
| 35172 | +# else |
| 35173 | +# define SQLITE_WIN32_CREATEFILEMAPPINGA 1 |
| 35174 | +# endif |
| 35175 | +#endif |
| 35176 | + |
| 34987 | 35177 | /* |
| 34988 | 35178 | ** This constant should already be defined (in the "WinDef.h" SDK file). |
| 34989 | 35179 | */ |
| 34990 | 35180 | #ifndef MAX_PATH |
| 34991 | 35181 | # define MAX_PATH (260) |
| | @@ -35388,12 +35578,13 @@ |
| 35388 | 35578 | #endif |
| 35389 | 35579 | |
| 35390 | 35580 | #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ |
| 35391 | 35581 | LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) |
| 35392 | 35582 | |
| 35393 | | -#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ |
| 35394 | | - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) |
| 35583 | +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ |
| 35584 | + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ |
| 35585 | + SQLITE_WIN32_CREATEFILEMAPPINGA |
| 35395 | 35586 | { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, |
| 35396 | 35587 | #else |
| 35397 | 35588 | { "CreateFileMappingA", (SYSCALL)0, 0 }, |
| 35398 | 35589 | #endif |
| 35399 | 35590 | |
| | @@ -35619,22 +35810,21 @@ |
| 35619 | 35810 | { "GetTickCount", (SYSCALL)0, 0 }, |
| 35620 | 35811 | #endif |
| 35621 | 35812 | |
| 35622 | 35813 | #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) |
| 35623 | 35814 | |
| 35624 | | -#if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \ |
| 35625 | | - SQLITE_WIN32_GETVERSIONEX |
| 35815 | +#if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX |
| 35626 | 35816 | { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, |
| 35627 | 35817 | #else |
| 35628 | 35818 | { "GetVersionExA", (SYSCALL)0, 0 }, |
| 35629 | 35819 | #endif |
| 35630 | 35820 | |
| 35631 | 35821 | #define osGetVersionExA ((BOOL(WINAPI*)( \ |
| 35632 | 35822 | LPOSVERSIONINFOA))aSyscall[34].pCurrent) |
| 35633 | 35823 | |
| 35634 | 35824 | #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ |
| 35635 | | - defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX |
| 35825 | + SQLITE_WIN32_GETVERSIONEX |
| 35636 | 35826 | { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, |
| 35637 | 35827 | #else |
| 35638 | 35828 | { "GetVersionExW", (SYSCALL)0, 0 }, |
| 35639 | 35829 | #endif |
| 35640 | 35830 | |
| | @@ -36241,11 +36431,11 @@ |
| 36241 | 36431 | ** this routine is used to determine if the host is Win95/98/ME or |
| 36242 | 36432 | ** WinNT/2K/XP so that we will know whether or not we can safely call |
| 36243 | 36433 | ** the LockFileEx() API. |
| 36244 | 36434 | */ |
| 36245 | 36435 | |
| 36246 | | -#if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX |
| 36436 | +#if !SQLITE_WIN32_GETVERSIONEX |
| 36247 | 36437 | # define osIsNT() (1) |
| 36248 | 36438 | #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) |
| 36249 | 36439 | # define osIsNT() (1) |
| 36250 | 36440 | #elif !defined(SQLITE_WIN32_HAS_WIDE) |
| 36251 | 36441 | # define osIsNT() (0) |
| | @@ -36262,11 +36452,11 @@ |
| 36262 | 36452 | /* |
| 36263 | 36453 | ** NOTE: The WinRT sub-platform is always assumed to be based on the NT |
| 36264 | 36454 | ** kernel. |
| 36265 | 36455 | */ |
| 36266 | 36456 | return 1; |
| 36267 | | -#elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX |
| 36457 | +#elif SQLITE_WIN32_GETVERSIONEX |
| 36268 | 36458 | if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ |
| 36269 | 36459 | #if defined(SQLITE_WIN32_HAS_ANSI) |
| 36270 | 36460 | OSVERSIONINFOA sInfo; |
| 36271 | 36461 | sInfo.dwOSVersionInfoSize = sizeof(sInfo); |
| 36272 | 36462 | osGetVersionExA(&sInfo); |
| | @@ -38846,11 +39036,11 @@ |
| 38846 | 39036 | ); |
| 38847 | 39037 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 38848 | 39038 | hMap = osCreateFileMappingW(pShmNode->hFile.h, |
| 38849 | 39039 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 38850 | 39040 | ); |
| 38851 | | -#elif defined(SQLITE_WIN32_HAS_ANSI) |
| 39041 | +#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA |
| 38852 | 39042 | hMap = osCreateFileMappingA(pShmNode->hFile.h, |
| 38853 | 39043 | NULL, PAGE_READWRITE, 0, nByte, NULL |
| 38854 | 39044 | ); |
| 38855 | 39045 | #endif |
| 38856 | 39046 | OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", |
| | @@ -39002,11 +39192,11 @@ |
| 39002 | 39192 | pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); |
| 39003 | 39193 | #elif defined(SQLITE_WIN32_HAS_WIDE) |
| 39004 | 39194 | pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, |
| 39005 | 39195 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39006 | 39196 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39007 | | -#elif defined(SQLITE_WIN32_HAS_ANSI) |
| 39197 | +#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA |
| 39008 | 39198 | pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, |
| 39009 | 39199 | (DWORD)((nMap>>32) & 0xffffffff), |
| 39010 | 39200 | (DWORD)(nMap & 0xffffffff), NULL); |
| 39011 | 39201 | #endif |
| 39012 | 39202 | if( pFd->hMap==NULL ){ |
| | @@ -43066,11 +43256,11 @@ |
| 43066 | 43256 | */ |
| 43067 | 43257 | static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ |
| 43068 | 43258 | assert( p!=0 ); |
| 43069 | 43259 | if( p->nFresh==0 ){ |
| 43070 | 43260 | struct RowSetChunk *pNew; |
| 43071 | | - pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); |
| 43261 | + pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew)); |
| 43072 | 43262 | if( pNew==0 ){ |
| 43073 | 43263 | return 0; |
| 43074 | 43264 | } |
| 43075 | 43265 | pNew->pNextChunk = p->pChunk; |
| 43076 | 43266 | p->pChunk = pNew; |
| | @@ -43973,10 +44163,24 @@ |
| 43973 | 44163 | ** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. |
| 43974 | 44164 | ** This could conceivably cause corruption following a power failure on |
| 43975 | 44165 | ** such a system. This is currently an undocumented limit. |
| 43976 | 44166 | */ |
| 43977 | 44167 | #define MAX_SECTOR_SIZE 0x10000 |
| 44168 | + |
| 44169 | +/* |
| 44170 | +** If the option SQLITE_EXTRA_DURABLE option is set at compile-time, then |
| 44171 | +** SQLite will do extra fsync() operations when synchronous==FULL to help |
| 44172 | +** ensure that transactions are durable across a power failure. Most |
| 44173 | +** applications are happy as long as transactions are consistent across |
| 44174 | +** a power failure, and are perfectly willing to lose the last transaction |
| 44175 | +** in exchange for the extra performance of avoiding directory syncs. |
| 44176 | +** And so the default SQLITE_EXTRA_DURABLE setting is off. |
| 44177 | +*/ |
| 44178 | +#ifndef SQLITE_EXTRA_DURABLE |
| 44179 | +# define SQLITE_EXTRA_DURABLE 0 |
| 44180 | +#endif |
| 44181 | + |
| 43978 | 44182 | |
| 43979 | 44183 | /* |
| 43980 | 44184 | ** An instance of the following structure is allocated for each active |
| 43981 | 44185 | ** savepoint and statement transaction in the system. All such structures |
| 43982 | 44186 | ** are stored in the Pager.aSavepoint[] array, which is allocated and |
| | @@ -44169,10 +44373,11 @@ |
| 44169 | 44373 | u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ |
| 44170 | 44374 | u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ |
| 44171 | 44375 | u8 useJournal; /* Use a rollback journal on this file */ |
| 44172 | 44376 | u8 noSync; /* Do not sync the journal if true */ |
| 44173 | 44377 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 44378 | + u8 extraSync; /* sync directory after journal delete */ |
| 44174 | 44379 | u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ |
| 44175 | 44380 | u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ |
| 44176 | 44381 | u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ |
| 44177 | 44382 | u8 tempFile; /* zFilename is a temporary or immutable file */ |
| 44178 | 44383 | u8 noLock; /* Do not lock (except in WAL mode) */ |
| | @@ -45529,11 +45734,11 @@ |
| 45529 | 45734 | || pPager->journalMode==PAGER_JOURNALMODE_MEMORY |
| 45530 | 45735 | || pPager->journalMode==PAGER_JOURNALMODE_WAL |
| 45531 | 45736 | ); |
| 45532 | 45737 | sqlite3OsClose(pPager->jfd); |
| 45533 | 45738 | if( bDelete ){ |
| 45534 | | - rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); |
| 45739 | + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync); |
| 45535 | 45740 | } |
| 45536 | 45741 | } |
| 45537 | 45742 | } |
| 45538 | 45743 | |
| 45539 | 45744 | #ifdef SQLITE_CHECK_PAGES |
| | @@ -47035,13 +47240,19 @@ |
| 47035 | 47240 | SQLITE_PRIVATE void sqlite3PagerSetFlags( |
| 47036 | 47241 | Pager *pPager, /* The pager to set safety level for */ |
| 47037 | 47242 | unsigned pgFlags /* Various flags */ |
| 47038 | 47243 | ){ |
| 47039 | 47244 | 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; |
| 47245 | + if( pPager->tempFile ){ |
| 47246 | + pPager->noSync = 1; |
| 47247 | + pPager->fullSync = 0; |
| 47248 | + pPager->extraSync = 0; |
| 47249 | + }else{ |
| 47250 | + pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; |
| 47251 | + pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; |
| 47252 | + pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; |
| 47253 | + } |
| 47043 | 47254 | if( pPager->noSync ){ |
| 47044 | 47255 | pPager->syncFlags = 0; |
| 47045 | 47256 | pPager->ckptSyncFlags = 0; |
| 47046 | 47257 | }else if( pgFlags & PAGER_FULLFSYNC ){ |
| 47047 | 47258 | pPager->syncFlags = SQLITE_SYNC_FULL; |
| | @@ -48342,15 +48553,21 @@ |
| 48342 | 48553 | pPager->readOnly = (u8)readOnly; |
| 48343 | 48554 | assert( useJournal || pPager->tempFile ); |
| 48344 | 48555 | pPager->noSync = pPager->tempFile; |
| 48345 | 48556 | if( pPager->noSync ){ |
| 48346 | 48557 | assert( pPager->fullSync==0 ); |
| 48558 | + assert( pPager->extraSync==0 ); |
| 48347 | 48559 | assert( pPager->syncFlags==0 ); |
| 48348 | 48560 | assert( pPager->walSyncFlags==0 ); |
| 48349 | 48561 | assert( pPager->ckptSyncFlags==0 ); |
| 48350 | 48562 | }else{ |
| 48351 | 48563 | pPager->fullSync = 1; |
| 48564 | +#if SQLITE_EXTRA_DURABLE |
| 48565 | + pPager->extraSync = 1; |
| 48566 | +#else |
| 48567 | + pPager->extraSync = 0; |
| 48568 | +#endif |
| 48352 | 48569 | pPager->syncFlags = SQLITE_SYNC_NORMAL; |
| 48353 | 48570 | pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; |
| 48354 | 48571 | pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; |
| 48355 | 48572 | } |
| 48356 | 48573 | /* pPager->pFirst = 0; */ |
| | @@ -53972,14 +54189,20 @@ |
| 53972 | 54189 | u32 iWrite = 0; |
| 53973 | 54190 | VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); |
| 53974 | 54191 | assert( rc==SQLITE_OK || iWrite==0 ); |
| 53975 | 54192 | if( iWrite>=iFirst ){ |
| 53976 | 54193 | i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; |
| 54194 | + void *pData; |
| 53977 | 54195 | if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){ |
| 53978 | 54196 | pWal->iReCksum = iWrite; |
| 53979 | 54197 | } |
| 53980 | | - rc = sqlite3OsWrite(pWal->pWalFd, p->pData, szPage, iOff); |
| 54198 | +#if defined(SQLITE_HAS_CODEC) |
| 54199 | + if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM; |
| 54200 | +#else |
| 54201 | + pData = p->pData; |
| 54202 | +#endif |
| 54203 | + rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff); |
| 53981 | 54204 | if( rc ) return rc; |
| 53982 | 54205 | p->flags &= ~PGHDR_WAL_APPEND; |
| 53983 | 54206 | continue; |
| 53984 | 54207 | } |
| 53985 | 54208 | } |
| | @@ -57680,11 +57903,10 @@ |
| 57680 | 57903 | MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) |
| 57681 | 57904 | if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ |
| 57682 | 57905 | pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); |
| 57683 | 57906 | if( pBt->mutex==0 ){ |
| 57684 | 57907 | rc = SQLITE_NOMEM; |
| 57685 | | - db->mallocFailed = 0; |
| 57686 | 57908 | goto btree_open_out; |
| 57687 | 57909 | } |
| 57688 | 57910 | } |
| 57689 | 57911 | sqlite3_mutex_enter(mutexShared); |
| 57690 | 57912 | pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList); |
| | @@ -59391,17 +59613,17 @@ |
| 59391 | 59613 | ** iTable. If a read-only cursor is requested, it is assumed that |
| 59392 | 59614 | ** the caller already has at least a read-only transaction open |
| 59393 | 59615 | ** on the database already. If a write-cursor is requested, then |
| 59394 | 59616 | ** the caller is assumed to have an open write transaction. |
| 59395 | 59617 | ** |
| 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: |
| 59618 | +** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only |
| 59619 | +** be used for reading. If the BTREE_WRCSR bit is set, then the cursor |
| 59620 | +** can be used for reading or for writing if other conditions for writing |
| 59621 | +** are also met. These are the conditions that must be met in order |
| 59622 | +** for writing to be allowed: |
| 59401 | 59623 | ** |
| 59402 | | -** 1: The cursor must have been opened with wrFlag==1 |
| 59624 | +** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR |
| 59403 | 59625 | ** |
| 59404 | 59626 | ** 2: Other database connections that share the same pager cache |
| 59405 | 59627 | ** but which are not in the READ_UNCOMMITTED state may not have |
| 59406 | 59628 | ** cursors open with wrFlag==0 on the same table. Otherwise |
| 59407 | 59629 | ** the changes made by this write cursor would be visible to |
| | @@ -59408,10 +59630,20 @@ |
| 59408 | 59630 | ** the read cursors in the other database connection. |
| 59409 | 59631 | ** |
| 59410 | 59632 | ** 3: The database must be writable (not on read-only media) |
| 59411 | 59633 | ** |
| 59412 | 59634 | ** 4: There must be an active transaction. |
| 59635 | +** |
| 59636 | +** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR |
| 59637 | +** is set. If FORDELETE is set, that is a hint to the implementation that |
| 59638 | +** this cursor will only be used to seek to and delete entries of an index |
| 59639 | +** as part of a larger DELETE statement. The FORDELETE hint is not used by |
| 59640 | +** this implementation. But in a hypothetical alternative storage engine |
| 59641 | +** in which index entries are automatically deleted when corresponding table |
| 59642 | +** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE |
| 59643 | +** operations on this cursor can be no-ops and all READ operations can |
| 59644 | +** return a null row (2-bytes: 0x01 0x00). |
| 59413 | 59645 | ** |
| 59414 | 59646 | ** No checking is done to make sure that page iTable really is the |
| 59415 | 59647 | ** root page of a b-tree. If it is not, then the cursor acquired |
| 59416 | 59648 | ** will not work correctly. |
| 59417 | 59649 | ** |
| | @@ -61481,11 +61713,11 @@ |
| 61481 | 61713 | */ |
| 61482 | 61714 | #if SQLITE_DEBUG |
| 61483 | 61715 | { |
| 61484 | 61716 | CellInfo info; |
| 61485 | 61717 | pPage->xParseCell(pPage, pCell, &info); |
| 61486 | | - assert( nHeader=(int)(info.pPayload - pCell) ); |
| 61718 | + assert( nHeader==(int)(info.pPayload - pCell) ); |
| 61487 | 61719 | assert( info.nKey==nKey ); |
| 61488 | 61720 | assert( *pnSize == info.nSize ); |
| 61489 | 61721 | assert( spaceLeft == info.nLocal ); |
| 61490 | 61722 | } |
| 61491 | 61723 | #endif |
| | @@ -63140,12 +63372,12 @@ |
| 63140 | 63372 | int rc = SQLITE_OK; |
| 63141 | 63373 | const int nMin = pCur->pBt->usableSize * 2 / 3; |
| 63142 | 63374 | u8 aBalanceQuickSpace[13]; |
| 63143 | 63375 | u8 *pFree = 0; |
| 63144 | 63376 | |
| 63145 | | - TESTONLY( int balance_quick_called = 0 ); |
| 63146 | | - TESTONLY( int balance_deeper_called = 0 ); |
| 63377 | + VVA_ONLY( int balance_quick_called = 0 ); |
| 63378 | + VVA_ONLY( int balance_deeper_called = 0 ); |
| 63147 | 63379 | |
| 63148 | 63380 | do { |
| 63149 | 63381 | int iPage = pCur->iPage; |
| 63150 | 63382 | MemPage *pPage = pCur->apPage[iPage]; |
| 63151 | 63383 | |
| | @@ -63154,11 +63386,12 @@ |
| 63154 | 63386 | /* The root page of the b-tree is overfull. In this case call the |
| 63155 | 63387 | ** balance_deeper() function to create a new child for the root-page |
| 63156 | 63388 | ** and copy the current contents of the root-page to it. The |
| 63157 | 63389 | ** next iteration of the do-loop will balance the child page. |
| 63158 | 63390 | */ |
| 63159 | | - assert( (balance_deeper_called++)==0 ); |
| 63391 | + assert( balance_deeper_called==0 ); |
| 63392 | + VVA_ONLY( balance_deeper_called++ ); |
| 63160 | 63393 | rc = balance_deeper(pPage, &pCur->apPage[1]); |
| 63161 | 63394 | if( rc==SQLITE_OK ){ |
| 63162 | 63395 | pCur->iPage = 1; |
| 63163 | 63396 | pCur->aiIdx[0] = 0; |
| 63164 | 63397 | pCur->aiIdx[1] = 0; |
| | @@ -63193,11 +63426,12 @@ |
| 63193 | 63426 | ** The purpose of the following assert() is to check that only a |
| 63194 | 63427 | ** single call to balance_quick() is made for each call to this |
| 63195 | 63428 | ** function. If this were not verified, a subtle bug involving reuse |
| 63196 | 63429 | ** of the aBalanceQuickSpace[] might sneak in. |
| 63197 | 63430 | */ |
| 63198 | | - assert( (balance_quick_called++)==0 ); |
| 63431 | + assert( balance_quick_called==0 ); |
| 63432 | + VVA_ONLY( balance_quick_called++ ); |
| 63199 | 63433 | rc = balance_quick(pParent, pPage, aBalanceQuickSpace); |
| 63200 | 63434 | }else |
| 63201 | 63435 | #endif |
| 63202 | 63436 | { |
| 63203 | 63437 | /* In this case, call balance_nonroot() to redistribute cells |
| | @@ -63424,35 +63658,45 @@ |
| 63424 | 63658 | } |
| 63425 | 63659 | |
| 63426 | 63660 | /* |
| 63427 | 63661 | ** Delete the entry that the cursor is pointing to. |
| 63428 | 63662 | ** |
| 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. |
| 63663 | +** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then |
| 63664 | +** the cursor is left pointing at an arbitrary location after the delete. |
| 63665 | +** But if that bit is set, then the cursor is left in a state such that |
| 63666 | +** the next call to BtreeNext() or BtreePrev() moves it to the same row |
| 63667 | +** as it would have been on if the call to BtreeDelete() had been omitted. |
| 63668 | +** |
| 63669 | +** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes |
| 63670 | +** associated with a single table entry and its indexes. Only one of those |
| 63671 | +** deletes is considered the "primary" delete. The primary delete occurs |
| 63672 | +** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete |
| 63673 | +** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag. |
| 63674 | +** The BTREE_AUXDELETE bit is a hint that is not used by this implementation, |
| 63675 | +** but which might be used by alternative storage engines. |
| 63434 | 63676 | */ |
| 63435 | | -SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){ |
| 63677 | +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ |
| 63436 | 63678 | Btree *p = pCur->pBtree; |
| 63437 | 63679 | BtShared *pBt = p->pBt; |
| 63438 | 63680 | int rc; /* Return code */ |
| 63439 | 63681 | MemPage *pPage; /* Page to delete cell from */ |
| 63440 | 63682 | unsigned char *pCell; /* Pointer to cell to delete */ |
| 63441 | 63683 | int iCellIdx; /* Index of cell to delete */ |
| 63442 | 63684 | int iCellDepth; /* Depth of node containing pCell */ |
| 63443 | 63685 | u16 szCell; /* Size of the cell being deleted */ |
| 63444 | 63686 | int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ |
| 63687 | + u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ |
| 63445 | 63688 | |
| 63446 | 63689 | assert( cursorOwnsBtShared(pCur) ); |
| 63447 | 63690 | assert( pBt->inTransaction==TRANS_WRITE ); |
| 63448 | 63691 | assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); |
| 63449 | 63692 | assert( pCur->curFlags & BTCF_WriteFlag ); |
| 63450 | 63693 | assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); |
| 63451 | 63694 | assert( !hasReadConflicts(p, pCur->pgnoRoot) ); |
| 63452 | 63695 | assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); |
| 63453 | 63696 | assert( pCur->eState==CURSOR_VALID ); |
| 63697 | + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); |
| 63454 | 63698 | |
| 63455 | 63699 | iCellDepth = pCur->iPage; |
| 63456 | 63700 | iCellIdx = pCur->aiIdx[iCellDepth]; |
| 63457 | 63701 | pPage = pCur->apPage[iCellDepth]; |
| 63458 | 63702 | pCell = findCell(pPage, iCellIdx); |
| | @@ -63561,11 +63805,11 @@ |
| 63561 | 63805 | } |
| 63562 | 63806 | |
| 63563 | 63807 | if( rc==SQLITE_OK ){ |
| 63564 | 63808 | if( bSkipnext ){ |
| 63565 | 63809 | assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); |
| 63566 | | - assert( pPage==pCur->apPage[pCur->iPage] ); |
| 63810 | + assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB ); |
| 63567 | 63811 | assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); |
| 63568 | 63812 | pCur->eState = CURSOR_SKIPNEXT; |
| 63569 | 63813 | if( iCellIdx>=pPage->nCell ){ |
| 63570 | 63814 | pCur->skipNext = -1; |
| 63571 | 63815 | pCur->aiIdx[iCellDepth] = pPage->nCell-1; |
| | @@ -64147,13 +64391,13 @@ |
| 64147 | 64391 | va_start(ap, zFormat); |
| 64148 | 64392 | if( pCheck->errMsg.nChar ){ |
| 64149 | 64393 | sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); |
| 64150 | 64394 | } |
| 64151 | 64395 | if( pCheck->zPfx ){ |
| 64152 | | - sqlite3XPrintf(&pCheck->errMsg, 0, pCheck->zPfx, pCheck->v1, pCheck->v2); |
| 64396 | + sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); |
| 64153 | 64397 | } |
| 64154 | | - sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); |
| 64398 | + sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); |
| 64155 | 64399 | va_end(ap); |
| 64156 | 64400 | if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ |
| 64157 | 64401 | pCheck->mallocFailed = 1; |
| 64158 | 64402 | } |
| 64159 | 64403 | } |
| | @@ -64650,11 +64894,12 @@ |
| 64650 | 64894 | char zErr[100]; |
| 64651 | 64895 | VVA_ONLY( int nRef ); |
| 64652 | 64896 | |
| 64653 | 64897 | sqlite3BtreeEnter(p); |
| 64654 | 64898 | assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); |
| 64655 | | - assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 ); |
| 64899 | + VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) ); |
| 64900 | + assert( nRef>=0 ); |
| 64656 | 64901 | sCheck.pBt = pBt; |
| 64657 | 64902 | sCheck.pPager = pBt->pPager; |
| 64658 | 64903 | sCheck.nPage = btreePagecount(sCheck.pBt); |
| 64659 | 64904 | sCheck.mxErr = mxErr; |
| 64660 | 64905 | sCheck.nErr = 0; |
| | @@ -64663,10 +64908,11 @@ |
| 64663 | 64908 | sCheck.v1 = 0; |
| 64664 | 64909 | sCheck.v2 = 0; |
| 64665 | 64910 | sCheck.aPgRef = 0; |
| 64666 | 64911 | sCheck.heap = 0; |
| 64667 | 64912 | sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); |
| 64913 | + sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; |
| 64668 | 64914 | if( sCheck.nPage==0 ){ |
| 64669 | 64915 | goto integrity_ck_cleanup; |
| 64670 | 64916 | } |
| 64671 | 64917 | |
| 64672 | 64918 | sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); |
| | @@ -65939,10 +66185,11 @@ |
| 65939 | 66185 | ** in pMem->z is discarded. |
| 65940 | 66186 | */ |
| 65941 | 66187 | SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ |
| 65942 | 66188 | assert( sqlite3VdbeCheckMemInvariants(pMem) ); |
| 65943 | 66189 | assert( (pMem->flags&MEM_RowSet)==0 ); |
| 66190 | + testcase( pMem->db==0 ); |
| 65944 | 66191 | |
| 65945 | 66192 | /* If the bPreserve flag is set to true, then the memory cell must already |
| 65946 | 66193 | ** contain a valid string or blob value. */ |
| 65947 | 66194 | assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); |
| 65948 | 66195 | testcase( bPreserve && pMem->z==0 ); |
| | @@ -66542,11 +66789,11 @@ |
| 66542 | 66789 | SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ |
| 66543 | 66790 | sqlite3 *db = pMem->db; |
| 66544 | 66791 | assert( db!=0 ); |
| 66545 | 66792 | assert( (pMem->flags & MEM_RowSet)==0 ); |
| 66546 | 66793 | sqlite3VdbeMemRelease(pMem); |
| 66547 | | - pMem->zMalloc = sqlite3DbMallocRaw(db, 64); |
| 66794 | + pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); |
| 66548 | 66795 | if( db->mallocFailed ){ |
| 66549 | 66796 | pMem->flags = MEM_Null; |
| 66550 | 66797 | pMem->szMalloc = 0; |
| 66551 | 66798 | }else{ |
| 66552 | 66799 | assert( pMem->zMalloc ); |
| | @@ -67204,11 +67451,11 @@ |
| 67204 | 67451 | |
| 67205 | 67452 | *ppVal = pVal; |
| 67206 | 67453 | return rc; |
| 67207 | 67454 | |
| 67208 | 67455 | no_mem: |
| 67209 | | - db->mallocFailed = 1; |
| 67456 | + sqlite3OomFault(db); |
| 67210 | 67457 | sqlite3DbFree(db, zVal); |
| 67211 | 67458 | assert( *ppVal==0 ); |
| 67212 | 67459 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 67213 | 67460 | if( pCtx==0 ) sqlite3ValueFree(pVal); |
| 67214 | 67461 | #else |
| | @@ -67263,11 +67510,11 @@ |
| 67263 | 67510 | iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal); |
| 67264 | 67511 | nSerial = sqlite3VarintLen(iSerial); |
| 67265 | 67512 | db = sqlite3_context_db_handle(context); |
| 67266 | 67513 | |
| 67267 | 67514 | nRet = 1 + nSerial + nVal; |
| 67268 | | - aRet = sqlite3DbMallocRaw(db, nRet); |
| 67515 | + aRet = sqlite3DbMallocRawNN(db, nRet); |
| 67269 | 67516 | if( aRet==0 ){ |
| 67270 | 67517 | sqlite3_result_error_nomem(context); |
| 67271 | 67518 | }else{ |
| 67272 | 67519 | aRet[0] = nSerial+1; |
| 67273 | 67520 | putVarint32(&aRet[1], iSerial); |
| | @@ -67715,11 +67962,11 @@ |
| 67715 | 67962 | int i; |
| 67716 | 67963 | VdbeOp *pOp; |
| 67717 | 67964 | |
| 67718 | 67965 | i = p->nOp; |
| 67719 | 67966 | assert( p->magic==VDBE_MAGIC_INIT ); |
| 67720 | | - assert( op>0 && op<0xff ); |
| 67967 | + assert( op>=0 && op<0xff ); |
| 67721 | 67968 | if( p->pParse->nOpAlloc<=i ){ |
| 67722 | 67969 | return growOp3(p, op, p1, p2, p3); |
| 67723 | 67970 | } |
| 67724 | 67971 | p->nOp++; |
| 67725 | 67972 | pOp = &p->aOp[i]; |
| | @@ -67833,11 +68080,11 @@ |
| 67833 | 68080 | int p2, /* The P2 operand */ |
| 67834 | 68081 | int p3, /* The P3 operand */ |
| 67835 | 68082 | const u8 *zP4, /* The P4 operand */ |
| 67836 | 68083 | int p4type /* P4 operand type */ |
| 67837 | 68084 | ){ |
| 67838 | | - char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8); |
| 68085 | + char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8); |
| 67839 | 68086 | if( p4copy ) memcpy(p4copy, zP4, 8); |
| 67840 | 68087 | return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); |
| 67841 | 68088 | } |
| 67842 | 68089 | |
| 67843 | 68090 | /* |
| | @@ -67867,10 +68114,25 @@ |
| 67867 | 68114 | ){ |
| 67868 | 68115 | int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); |
| 67869 | 68116 | sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); |
| 67870 | 68117 | return addr; |
| 67871 | 68118 | } |
| 68119 | + |
| 68120 | +/* Insert the end of a co-routine |
| 68121 | +*/ |
| 68122 | +SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ |
| 68123 | + sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); |
| 68124 | + |
| 68125 | + /* Clear the temporary register cache, thereby ensuring that each |
| 68126 | + ** co-routine has its own independent set of registers, because co-routines |
| 68127 | + ** might expect their registers to be preserved across an OP_Yield, and |
| 68128 | + ** that could cause problems if two or more co-routines are using the same |
| 68129 | + ** temporary register. |
| 68130 | + */ |
| 68131 | + v->pParse->nTempReg = 0; |
| 68132 | + v->pParse->nRangeReg = 0; |
| 68133 | +} |
| 67872 | 68134 | |
| 67873 | 68135 | /* |
| 67874 | 68136 | ** Create a new symbolic label for an instruction that has yet to be |
| 67875 | 68137 | ** coded. The symbolic label is really just a negative number. The |
| 67876 | 68138 | ** label can be used as the P2 value of an operation. Later, when |
| | @@ -68078,11 +68340,11 @@ |
| 68078 | 68340 | p->readOnly = 1; |
| 68079 | 68341 | p->bIsReader = 0; |
| 68080 | 68342 | for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ |
| 68081 | 68343 | u8 opcode = pOp->opcode; |
| 68082 | 68344 | |
| 68083 | | - /* NOTE: Be sure to update mkopcodeh.awk when adding or removing |
| 68345 | + /* NOTE: Be sure to update mkopcodeh.tcl when adding or removing |
| 68084 | 68346 | ** cases from this switch! */ |
| 68085 | 68347 | switch( opcode ){ |
| 68086 | 68348 | case OP_Transaction: { |
| 68087 | 68349 | if( pOp->p2!=0 ) p->readOnly = 0; |
| 68088 | 68350 | /* fall thru */ |
| | @@ -68190,10 +68452,13 @@ |
| 68190 | 68452 | } |
| 68191 | 68453 | |
| 68192 | 68454 | /* |
| 68193 | 68455 | ** Add a whole list of operations to the operation stack. Return a |
| 68194 | 68456 | ** pointer to the first operation inserted. |
| 68457 | +** |
| 68458 | +** Non-zero P2 arguments to jump instructions are automatically adjusted |
| 68459 | +** so that the jump target is relative to the first operation inserted. |
| 68195 | 68460 | */ |
| 68196 | 68461 | SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList( |
| 68197 | 68462 | Vdbe *p, /* Add opcodes to the prepared statement */ |
| 68198 | 68463 | int nOp, /* Number of opcodes to add */ |
| 68199 | 68464 | VdbeOpList const *aOp, /* The opcodes to be added */ |
| | @@ -68210,10 +68475,13 @@ |
| 68210 | 68475 | for(i=0; i<nOp; i++, aOp++, pOut++){ |
| 68211 | 68476 | pOut->opcode = aOp->opcode; |
| 68212 | 68477 | pOut->p1 = aOp->p1; |
| 68213 | 68478 | pOut->p2 = aOp->p2; |
| 68214 | 68479 | assert( aOp->p2>=0 ); |
| 68480 | + if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){ |
| 68481 | + pOut->p2 += p->nOp; |
| 68482 | + } |
| 68215 | 68483 | pOut->p3 = aOp->p3; |
| 68216 | 68484 | pOut->p4type = P4_NOTUSED; |
| 68217 | 68485 | pOut->p4.p = 0; |
| 68218 | 68486 | pOut->p5 = 0; |
| 68219 | 68487 | #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS |
| | @@ -68661,32 +68929,31 @@ |
| 68661 | 68929 | #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) |
| 68662 | 68930 | /* |
| 68663 | 68931 | ** Translate the P4.pExpr value for an OP_CursorHint opcode into text |
| 68664 | 68932 | ** that can be displayed in the P4 column of EXPLAIN output. |
| 68665 | 68933 | */ |
| 68666 | | -static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ |
| 68934 | +static void displayP4Expr(StrAccum *p, Expr *pExpr){ |
| 68667 | 68935 | const char *zOp = 0; |
| 68668 | | - int n; |
| 68669 | 68936 | switch( pExpr->op ){ |
| 68670 | 68937 | case TK_STRING: |
| 68671 | | - sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken); |
| 68938 | + sqlite3XPrintf(p, "%Q", pExpr->u.zToken); |
| 68672 | 68939 | break; |
| 68673 | 68940 | case TK_INTEGER: |
| 68674 | | - sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue); |
| 68941 | + sqlite3XPrintf(p, "%d", pExpr->u.iValue); |
| 68675 | 68942 | break; |
| 68676 | 68943 | case TK_NULL: |
| 68677 | | - sqlite3_snprintf(nTemp, zTemp, "NULL"); |
| 68944 | + sqlite3XPrintf(p, "NULL"); |
| 68678 | 68945 | break; |
| 68679 | 68946 | case TK_REGISTER: { |
| 68680 | | - sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable); |
| 68947 | + sqlite3XPrintf(p, "r[%d]", pExpr->iTable); |
| 68681 | 68948 | break; |
| 68682 | 68949 | } |
| 68683 | 68950 | case TK_COLUMN: { |
| 68684 | 68951 | if( pExpr->iColumn<0 ){ |
| 68685 | | - sqlite3_snprintf(nTemp, zTemp, "rowid"); |
| 68952 | + sqlite3XPrintf(p, "rowid"); |
| 68686 | 68953 | }else{ |
| 68687 | | - sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn); |
| 68954 | + sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); |
| 68688 | 68955 | } |
| 68689 | 68956 | break; |
| 68690 | 68957 | } |
| 68691 | 68958 | case TK_LT: zOp = "LT"; break; |
| 68692 | 68959 | case TK_LE: zOp = "LE"; break; |
| | @@ -68714,25 +68981,23 @@ |
| 68714 | 68981 | case TK_NOT: zOp = "NOT"; break; |
| 68715 | 68982 | case TK_ISNULL: zOp = "ISNULL"; break; |
| 68716 | 68983 | case TK_NOTNULL: zOp = "NOTNULL"; break; |
| 68717 | 68984 | |
| 68718 | 68985 | default: |
| 68719 | | - sqlite3_snprintf(nTemp, zTemp, "%s", "expr"); |
| 68986 | + sqlite3XPrintf(p, "%s", "expr"); |
| 68720 | 68987 | break; |
| 68721 | 68988 | } |
| 68722 | 68989 | |
| 68723 | 68990 | 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); |
| 68991 | + sqlite3XPrintf(p, "%s(", zOp); |
| 68992 | + displayP4Expr(p, pExpr->pLeft); |
| 68993 | + if( pExpr->pRight ){ |
| 68994 | + sqlite3StrAccumAppend(p, ",", 1); |
| 68995 | + displayP4Expr(p, pExpr->pRight); |
| 68996 | + } |
| 68997 | + sqlite3StrAccumAppend(p, ")", 1); |
| 68998 | + } |
| 68734 | 68999 | } |
| 68735 | 69000 | #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ |
| 68736 | 69001 | |
| 68737 | 69002 | |
| 68738 | 69003 | #if VDBE_DISPLAY_P4 |
| | @@ -68740,107 +69005,100 @@ |
| 68740 | 69005 | ** Compute a string that describes the P4 parameter for an opcode. |
| 68741 | 69006 | ** Use zTemp for any required temporary buffer space. |
| 68742 | 69007 | */ |
| 68743 | 69008 | static char *displayP4(Op *pOp, char *zTemp, int nTemp){ |
| 68744 | 69009 | char *zP4 = zTemp; |
| 69010 | + StrAccum x; |
| 68745 | 69011 | assert( nTemp>=20 ); |
| 69012 | + sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0); |
| 68746 | 69013 | switch( pOp->p4type ){ |
| 68747 | 69014 | case P4_KEYINFO: { |
| 68748 | | - int i, j; |
| 69015 | + int j; |
| 68749 | 69016 | KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; |
| 68750 | 69017 | assert( pKeyInfo->aSortOrder!=0 ); |
| 68751 | | - sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField); |
| 68752 | | - i = sqlite3Strlen30(zTemp); |
| 69018 | + sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField); |
| 68753 | 69019 | for(j=0; j<pKeyInfo->nField; j++){ |
| 68754 | 69020 | 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 ); |
| 69021 | + const char *zColl = pColl ? pColl->zName : ""; |
| 69022 | + if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; |
| 69023 | + sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); |
| 69024 | + } |
| 69025 | + sqlite3StrAccumAppend(&x, ")", 1); |
| 68776 | 69026 | break; |
| 68777 | 69027 | } |
| 68778 | 69028 | #ifdef SQLITE_ENABLE_CURSOR_HINTS |
| 68779 | 69029 | case P4_EXPR: { |
| 68780 | | - displayP4Expr(nTemp, zTemp, pOp->p4.pExpr); |
| 69030 | + displayP4Expr(&x, pOp->p4.pExpr); |
| 68781 | 69031 | break; |
| 68782 | 69032 | } |
| 68783 | 69033 | #endif |
| 68784 | 69034 | case P4_COLLSEQ: { |
| 68785 | 69035 | CollSeq *pColl = pOp->p4.pColl; |
| 68786 | | - sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); |
| 69036 | + sqlite3XPrintf(&x, "(%.20s)", pColl->zName); |
| 68787 | 69037 | break; |
| 68788 | 69038 | } |
| 68789 | 69039 | case P4_FUNCDEF: { |
| 68790 | 69040 | FuncDef *pDef = pOp->p4.pFunc; |
| 68791 | | - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); |
| 69041 | + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); |
| 68792 | 69042 | break; |
| 68793 | 69043 | } |
| 68794 | 69044 | #ifdef SQLITE_DEBUG |
| 68795 | 69045 | case P4_FUNCCTX: { |
| 68796 | 69046 | FuncDef *pDef = pOp->p4.pCtx->pFunc; |
| 68797 | | - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); |
| 69047 | + sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); |
| 68798 | 69048 | break; |
| 68799 | 69049 | } |
| 68800 | 69050 | #endif |
| 68801 | 69051 | case P4_INT64: { |
| 68802 | | - sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); |
| 69052 | + sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); |
| 68803 | 69053 | break; |
| 68804 | 69054 | } |
| 68805 | 69055 | case P4_INT32: { |
| 68806 | | - sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i); |
| 69056 | + sqlite3XPrintf(&x, "%d", pOp->p4.i); |
| 68807 | 69057 | break; |
| 68808 | 69058 | } |
| 68809 | 69059 | case P4_REAL: { |
| 68810 | | - sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal); |
| 69060 | + sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); |
| 68811 | 69061 | break; |
| 68812 | 69062 | } |
| 68813 | 69063 | case P4_MEM: { |
| 68814 | 69064 | Mem *pMem = pOp->p4.pMem; |
| 68815 | 69065 | if( pMem->flags & MEM_Str ){ |
| 68816 | 69066 | zP4 = pMem->z; |
| 68817 | 69067 | }else if( pMem->flags & MEM_Int ){ |
| 68818 | | - sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); |
| 69068 | + sqlite3XPrintf(&x, "%lld", pMem->u.i); |
| 68819 | 69069 | }else if( pMem->flags & MEM_Real ){ |
| 68820 | | - sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->u.r); |
| 69070 | + sqlite3XPrintf(&x, "%.16g", pMem->u.r); |
| 68821 | 69071 | }else if( pMem->flags & MEM_Null ){ |
| 68822 | | - sqlite3_snprintf(nTemp, zTemp, "NULL"); |
| 69072 | + zP4 = "NULL"; |
| 68823 | 69073 | }else{ |
| 68824 | 69074 | assert( pMem->flags & MEM_Blob ); |
| 68825 | 69075 | zP4 = "(blob)"; |
| 68826 | 69076 | } |
| 68827 | 69077 | break; |
| 68828 | 69078 | } |
| 68829 | 69079 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 68830 | 69080 | case P4_VTAB: { |
| 68831 | 69081 | sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; |
| 68832 | | - sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); |
| 69082 | + sqlite3XPrintf(&x, "vtab:%p", pVtab); |
| 68833 | 69083 | break; |
| 68834 | 69084 | } |
| 68835 | 69085 | #endif |
| 68836 | 69086 | case P4_INTARRAY: { |
| 68837 | | - sqlite3_snprintf(nTemp, zTemp, "intarray"); |
| 69087 | + int i; |
| 69088 | + int *ai = pOp->p4.ai; |
| 69089 | + int n = ai[0]; /* The first element of an INTARRAY is always the |
| 69090 | + ** count of the number of elements to follow */ |
| 69091 | + for(i=1; i<n; i++){ |
| 69092 | + sqlite3XPrintf(&x, ",%d", ai[i]); |
| 69093 | + } |
| 69094 | + zTemp[0] = '['; |
| 69095 | + sqlite3StrAccumAppend(&x, "]", 1); |
| 68838 | 69096 | break; |
| 68839 | 69097 | } |
| 68840 | 69098 | case P4_SUBPROGRAM: { |
| 68841 | | - sqlite3_snprintf(nTemp, zTemp, "program"); |
| 69099 | + sqlite3XPrintf(&x, "program"); |
| 68842 | 69100 | break; |
| 68843 | 69101 | } |
| 68844 | 69102 | case P4_ADVANCE: { |
| 68845 | 69103 | zTemp[0] = 0; |
| 68846 | 69104 | break; |
| | @@ -68851,10 +69109,11 @@ |
| 68851 | 69109 | zP4 = zTemp; |
| 68852 | 69110 | zTemp[0] = 0; |
| 68853 | 69111 | } |
| 68854 | 69112 | } |
| 68855 | 69113 | } |
| 69114 | + sqlite3StrAccumFinish(&x); |
| 68856 | 69115 | assert( zP4!=0 ); |
| 68857 | 69116 | return zP4; |
| 68858 | 69117 | } |
| 68859 | 69118 | #endif /* VDBE_DISPLAY_P4 */ |
| 68860 | 69119 | |
| | @@ -68970,11 +69229,10 @@ |
| 68970 | 69229 | */ |
| 68971 | 69230 | static void releaseMemArray(Mem *p, int N){ |
| 68972 | 69231 | if( p && N ){ |
| 68973 | 69232 | Mem *pEnd = &p[N]; |
| 68974 | 69233 | sqlite3 *db = p->db; |
| 68975 | | - u8 malloc_failed = db->mallocFailed; |
| 68976 | 69234 | if( db->pnBytesFreed ){ |
| 68977 | 69235 | do{ |
| 68978 | 69236 | if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); |
| 68979 | 69237 | }while( (++p)<pEnd ); |
| 68980 | 69238 | return; |
| | @@ -69006,11 +69264,10 @@ |
| 69006 | 69264 | p->szMalloc = 0; |
| 69007 | 69265 | } |
| 69008 | 69266 | |
| 69009 | 69267 | p->flags = MEM_Undefined; |
| 69010 | 69268 | }while( (++p)<pEnd ); |
| 69011 | | - db->mallocFailed = malloc_failed; |
| 69012 | 69269 | } |
| 69013 | 69270 | } |
| 69014 | 69271 | |
| 69015 | 69272 | /* |
| 69016 | 69273 | ** Delete a VdbeFrame object and its contents. VdbeFrame objects are |
| | @@ -69067,11 +69324,11 @@ |
| 69067 | 69324 | p->pResultSet = 0; |
| 69068 | 69325 | |
| 69069 | 69326 | if( p->rc==SQLITE_NOMEM ){ |
| 69070 | 69327 | /* This happens if a malloc() inside a call to sqlite3_column_text() or |
| 69071 | 69328 | ** sqlite3_column_text16() failed. */ |
| 69072 | | - db->mallocFailed = 1; |
| 69329 | + sqlite3OomFault(db); |
| 69073 | 69330 | return SQLITE_ERROR; |
| 69074 | 69331 | } |
| 69075 | 69332 | |
| 69076 | 69333 | /* When the number of output rows reaches nRow, that means the |
| 69077 | 69334 | ** listing has finished and sqlite3_step() should return SQLITE_DONE. |
| | @@ -69265,45 +69522,47 @@ |
| 69265 | 69522 | sqlite3IoTrace("SQL %s\n", z); |
| 69266 | 69523 | } |
| 69267 | 69524 | } |
| 69268 | 69525 | #endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ |
| 69269 | 69526 | |
| 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. |
| 69527 | +/* An instance of this object describes bulk memory available for use |
| 69528 | +** by subcomponents of a prepared statement. Space is allocated out |
| 69529 | +** of a ReusableSpace object by the allocSpace() routine below. |
| 69530 | +*/ |
| 69531 | +struct ReusableSpace { |
| 69532 | + u8 *pSpace; /* Available memory */ |
| 69533 | + int nFree; /* Bytes of available memory */ |
| 69534 | + int nNeeded; /* Total bytes that could not be allocated */ |
| 69535 | +}; |
| 69536 | + |
| 69537 | +/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf |
| 69538 | +** from the ReusableSpace object. Return a pointer to the allocated |
| 69539 | +** memory on success. If insufficient memory is available in the |
| 69540 | +** ReusableSpace object, increase the ReusableSpace.nNeeded |
| 69541 | +** value by the amount needed and return NULL. |
| 69542 | +** |
| 69543 | +** If pBuf is not initially NULL, that means that the memory has already |
| 69544 | +** been allocated by a prior call to this routine, so just return a copy |
| 69545 | +** of pBuf and leave ReusableSpace unchanged. |
| 69546 | +** |
| 69547 | +** This allocator is employed to repurpose unused slots at the end of the |
| 69548 | +** opcode array of prepared state for other memory needs of the prepared |
| 69549 | +** statement. |
| 69289 | 69550 | */ |
| 69290 | 69551 | 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 */ |
| 69552 | + struct ReusableSpace *p, /* Bulk memory available for allocation */ |
| 69553 | + void *pBuf, /* Pointer to a prior allocation */ |
| 69554 | + int nByte /* Bytes of memory needed */ |
| 69296 | 69555 | ){ |
| 69297 | | - assert( EIGHT_BYTE_ALIGNMENT(pFrom) ); |
| 69556 | + assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); |
| 69298 | 69557 | if( pBuf==0 ){ |
| 69299 | 69558 | nByte = ROUND8(nByte); |
| 69300 | | - if( nByte <= *pnFrom ){ |
| 69301 | | - *pnFrom -= nByte; |
| 69302 | | - pBuf = &pFrom[*pnFrom]; |
| 69559 | + if( nByte <= p->nFree ){ |
| 69560 | + p->nFree -= nByte; |
| 69561 | + pBuf = &p->pSpace[p->nFree]; |
| 69303 | 69562 | }else{ |
| 69304 | | - *pnNeeded += nByte; |
| 69563 | + p->nNeeded += nByte; |
| 69305 | 69564 | } |
| 69306 | 69565 | } |
| 69307 | 69566 | assert( EIGHT_BYTE_ALIGNMENT(pBuf) ); |
| 69308 | 69567 | return pBuf; |
| 69309 | 69568 | } |
| | @@ -69332,11 +69591,10 @@ |
| 69332 | 69591 | } |
| 69333 | 69592 | #endif |
| 69334 | 69593 | p->pc = -1; |
| 69335 | 69594 | p->rc = SQLITE_OK; |
| 69336 | 69595 | p->errorAction = OE_Abort; |
| 69337 | | - p->magic = VDBE_MAGIC_RUN; |
| 69338 | 69596 | p->nChange = 0; |
| 69339 | 69597 | p->cacheCtr = 1; |
| 69340 | 69598 | p->minWriteFileFormat = 255; |
| 69341 | 69599 | p->iStatement = 0; |
| 69342 | 69600 | p->nFkConstraint = 0; |
| | @@ -69375,13 +69633,11 @@ |
| 69375 | 69633 | int nMem; /* Number of VM memory registers */ |
| 69376 | 69634 | int nCursor; /* Number of cursors required */ |
| 69377 | 69635 | int nArg; /* Number of arguments in subprograms */ |
| 69378 | 69636 | int nOnce; /* Number of OP_Once instructions */ |
| 69379 | 69637 | 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 */ |
| 69638 | + struct ReusableSpace x; /* Reusable bulk memory */ |
| 69383 | 69639 | |
| 69384 | 69640 | assert( p!=0 ); |
| 69385 | 69641 | assert( p->nOp>0 ); |
| 69386 | 69642 | assert( pParse!=0 ); |
| 69387 | 69643 | assert( p->magic==VDBE_MAGIC_INIT ); |
| | @@ -69395,69 +69651,64 @@ |
| 69395 | 69651 | nOnce = pParse->nOnce; |
| 69396 | 69652 | if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ |
| 69397 | 69653 | |
| 69398 | 69654 | /* For each cursor required, also allocate a memory cell. Memory |
| 69399 | 69655 | ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by |
| 69400 | | - ** the vdbe program. Instead they are used to allocate space for |
| 69656 | + ** the vdbe program. Instead they are used to allocate memory for |
| 69401 | 69657 | ** VdbeCursor/BtCursor structures. The blob of memory associated with |
| 69402 | 69658 | ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) |
| 69403 | 69659 | ** stores the blob of memory associated with cursor 1, etc. |
| 69404 | 69660 | ** |
| 69405 | 69661 | ** See also: allocateCursor(). |
| 69406 | 69662 | */ |
| 69407 | 69663 | nMem += nCursor; |
| 69408 | 69664 | |
| 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. |
| 69665 | + /* Figure out how much reusable memory is available at the end of the |
| 69666 | + ** opcode array. This extra memory will be reallocated for other elements |
| 69667 | + ** of the prepared statement. |
| 69414 | 69668 | */ |
| 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]) ); |
| 69669 | + n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ |
| 69670 | + x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ |
| 69671 | + assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); |
| 69672 | + x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ |
| 69673 | + assert( x.nFree>=0 ); |
| 69674 | + if( x.nFree>0 ){ |
| 69675 | + memset(x.pSpace, 0, x.nFree); |
| 69676 | + assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); |
| 69423 | 69677 | } |
| 69424 | 69678 | |
| 69425 | 69679 | resolveP2Values(p, &nArg); |
| 69426 | 69680 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| 69427 | 69681 | if( pParse->explain && nMem<10 ){ |
| 69428 | 69682 | nMem = 10; |
| 69429 | 69683 | } |
| 69430 | 69684 | p->expired = 0; |
| 69431 | 69685 | |
| 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 |
| 69686 | + /* Memory for registers, parameters, cursor, etc, is allocated in one or two |
| 69687 | + ** passes. On the first pass, we try to reuse unused memory at the |
| 69434 | 69688 | ** end of the opcode array. If we are unable to satisfy all memory |
| 69435 | 69689 | ** requirements by reusing the opcode array tail, then the second |
| 69436 | | - ** pass will fill in the rest using a fresh allocation. |
| 69690 | + ** pass will fill in the remainder using a fresh memory allocation. |
| 69437 | 69691 | ** |
| 69438 | 69692 | ** 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 |
| 69693 | + ** the leftover memory at the end of the opcode array. This can significantly |
| 69440 | 69694 | ** reduce the amount of memory held by a prepared statement. |
| 69441 | 69695 | */ |
| 69442 | 69696 | 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); |
| 69697 | + x.nNeeded = 0; |
| 69698 | + p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem)); |
| 69699 | + p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem)); |
| 69700 | + p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*)); |
| 69701 | + p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); |
| 69702 | + p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce); |
| 69450 | 69703 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 69451 | | - p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte); |
| 69704 | + p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); |
| 69452 | 69705 | #endif |
| 69453 | | - if( nByte ){ |
| 69454 | | - p->pFree = sqlite3DbMallocZero(db, nByte); |
| 69455 | | - } |
| 69456 | | - zCsr = p->pFree; |
| 69457 | | - nFree = nByte; |
| 69458 | | - }while( nByte && !db->mallocFailed ); |
| 69706 | + if( x.nNeeded==0 ) break; |
| 69707 | + x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); |
| 69708 | + x.nFree = x.nNeeded; |
| 69709 | + }while( !db->mallocFailed ); |
| 69459 | 69710 | |
| 69460 | 69711 | p->nCursor = nCursor; |
| 69461 | 69712 | p->nOnceFlag = nOnce; |
| 69462 | 69713 | if( p->aVar ){ |
| 69463 | 69714 | p->nVar = (ynVar)nVar; |
| | @@ -70066,11 +70317,11 @@ |
| 70066 | 70317 | ** Then the internal cache might have been left in an inconsistent |
| 70067 | 70318 | ** state. We need to rollback the statement transaction, if there is |
| 70068 | 70319 | ** one, or the complete transaction if there is no statement transaction. |
| 70069 | 70320 | */ |
| 70070 | 70321 | |
| 70071 | | - if( p->db->mallocFailed ){ |
| 70322 | + if( db->mallocFailed ){ |
| 70072 | 70323 | p->rc = SQLITE_NOMEM; |
| 70073 | 70324 | } |
| 70074 | 70325 | if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); |
| 70075 | 70326 | closeAllCursors(p); |
| 70076 | 70327 | if( p->magic!=VDBE_MAGIC_RUN ){ |
| | @@ -70227,11 +70478,11 @@ |
| 70227 | 70478 | assert( db->nVdbeRead>=db->nVdbeWrite ); |
| 70228 | 70479 | assert( db->nVdbeWrite>=0 ); |
| 70229 | 70480 | } |
| 70230 | 70481 | p->magic = VDBE_MAGIC_HALT; |
| 70231 | 70482 | checkActiveVdbeCnt(db); |
| 70232 | | - if( p->db->mallocFailed ){ |
| 70483 | + if( db->mallocFailed ){ |
| 70233 | 70484 | p->rc = SQLITE_NOMEM; |
| 70234 | 70485 | } |
| 70235 | 70486 | |
| 70236 | 70487 | /* If the auto-commit flag is set to true, then any locks that were held |
| 70237 | 70488 | ** by connection db have now been released. Call sqlite3ConnectionUnlocked() |
| | @@ -70264,16 +70515,16 @@ |
| 70264 | 70515 | */ |
| 70265 | 70516 | SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ |
| 70266 | 70517 | sqlite3 *db = p->db; |
| 70267 | 70518 | int rc = p->rc; |
| 70268 | 70519 | if( p->zErrMsg ){ |
| 70269 | | - u8 mallocFailed = db->mallocFailed; |
| 70520 | + db->bBenignMalloc++; |
| 70270 | 70521 | sqlite3BeginBenignMalloc(); |
| 70271 | 70522 | if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); |
| 70272 | 70523 | sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); |
| 70273 | 70524 | sqlite3EndBenignMalloc(); |
| 70274 | | - db->mallocFailed = mallocFailed; |
| 70525 | + db->bBenignMalloc--; |
| 70275 | 70526 | db->errCode = rc; |
| 70276 | 70527 | }else{ |
| 70277 | 70528 | sqlite3Error(db, rc); |
| 70278 | 70529 | } |
| 70279 | 70530 | return rc; |
| | @@ -70558,13 +70809,20 @@ |
| 70558 | 70809 | ** a NULL row. |
| 70559 | 70810 | ** |
| 70560 | 70811 | ** If the cursor is already pointing to the correct row and that row has |
| 70561 | 70812 | ** not been deleted out from under the cursor, then this routine is a no-op. |
| 70562 | 70813 | */ |
| 70563 | | -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ |
| 70814 | +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ |
| 70815 | + VdbeCursor *p = *pp; |
| 70564 | 70816 | if( p->eCurType==CURTYPE_BTREE ){ |
| 70565 | 70817 | if( p->deferredMoveto ){ |
| 70818 | + int iMap; |
| 70819 | + if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ |
| 70820 | + *pp = p->pAltCursor; |
| 70821 | + *piCol = iMap - 1; |
| 70822 | + return SQLITE_OK; |
| 70823 | + } |
| 70566 | 70824 | return handleDeferredMoveto(p); |
| 70567 | 70825 | } |
| 70568 | 70826 | if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ |
| 70569 | 70827 | return handleMovedCursor(p); |
| 70570 | 70828 | } |
| | @@ -72191,11 +72449,12 @@ |
| 72191 | 72449 | } |
| 72192 | 72450 | SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){ |
| 72193 | 72451 | return sqlite3VdbeIntValue((Mem*)pVal); |
| 72194 | 72452 | } |
| 72195 | 72453 | SQLITE_API unsigned int SQLITE_STDCALL sqlite3_value_subtype(sqlite3_value *pVal){ |
| 72196 | | - return ((Mem*)pVal)->eSubtype; |
| 72454 | + Mem *pMem = (Mem*)pVal; |
| 72455 | + return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); |
| 72197 | 72456 | } |
| 72198 | 72457 | SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){ |
| 72199 | 72458 | return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); |
| 72200 | 72459 | } |
| 72201 | 72460 | #ifndef SQLITE_OMIT_UTF16 |
| | @@ -72372,12 +72631,14 @@ |
| 72372 | 72631 | SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){ |
| 72373 | 72632 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72374 | 72633 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72375 | 72634 | } |
| 72376 | 72635 | 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; |
| 72636 | + Mem *pOut = pCtx->pOut; |
| 72637 | + assert( sqlite3_mutex_held(pOut->db->mutex) ); |
| 72638 | + pOut->eSubtype = eSubtype & 0xff; |
| 72639 | + pOut->flags |= MEM_Subtype; |
| 72379 | 72640 | } |
| 72380 | 72641 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text( |
| 72381 | 72642 | sqlite3_context *pCtx, |
| 72382 | 72643 | const char *z, |
| 72383 | 72644 | int n, |
| | @@ -72473,11 +72734,11 @@ |
| 72473 | 72734 | SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){ |
| 72474 | 72735 | assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); |
| 72475 | 72736 | sqlite3VdbeMemSetNull(pCtx->pOut); |
| 72476 | 72737 | pCtx->isError = SQLITE_NOMEM; |
| 72477 | 72738 | pCtx->fErrorOrAux = 1; |
| 72478 | | - pCtx->pOut->db->mallocFailed = 1; |
| 72739 | + sqlite3OomFault(pCtx->pOut->db); |
| 72479 | 72740 | } |
| 72480 | 72741 | |
| 72481 | 72742 | /* |
| 72482 | 72743 | ** This function is called after a transaction has been committed. It |
| 72483 | 72744 | ** invokes callbacks registered with sqlite3_wal_hook() as required. |
| | @@ -73101,11 +73362,11 @@ |
| 73101 | 73362 | ret = xFunc(&p->aColName[N]); |
| 73102 | 73363 | /* A malloc may have failed inside of the xFunc() call. If this |
| 73103 | 73364 | ** is the case, clear the mallocFailed flag and return NULL. |
| 73104 | 73365 | */ |
| 73105 | 73366 | if( db->mallocFailed ){ |
| 73106 | | - db->mallocFailed = 0; |
| 73367 | + sqlite3OomClear(db); |
| 73107 | 73368 | ret = 0; |
| 73108 | 73369 | } |
| 73109 | 73370 | sqlite3_mutex_leave(db->mutex); |
| 73110 | 73371 | } |
| 73111 | 73372 | return ret; |
| | @@ -73802,13 +74063,13 @@ |
| 73802 | 74063 | assert( idx>0 && idx<=p->nVar ); |
| 73803 | 74064 | pVar = &p->aVar[idx-1]; |
| 73804 | 74065 | if( pVar->flags & MEM_Null ){ |
| 73805 | 74066 | sqlite3StrAccumAppend(&out, "NULL", 4); |
| 73806 | 74067 | }else if( pVar->flags & MEM_Int ){ |
| 73807 | | - sqlite3XPrintf(&out, 0, "%lld", pVar->u.i); |
| 74068 | + sqlite3XPrintf(&out, "%lld", pVar->u.i); |
| 73808 | 74069 | }else if( pVar->flags & MEM_Real ){ |
| 73809 | | - sqlite3XPrintf(&out, 0, "%!.15g", pVar->u.r); |
| 74070 | + sqlite3XPrintf(&out, "%!.15g", pVar->u.r); |
| 73810 | 74071 | }else if( pVar->flags & MEM_Str ){ |
| 73811 | 74072 | int nOut; /* Number of bytes of the string text to include in output */ |
| 73812 | 74073 | #ifndef SQLITE_OMIT_UTF16 |
| 73813 | 74074 | u8 enc = ENC(db); |
| 73814 | 74075 | Mem utf8; |
| | @@ -73825,36 +74086,36 @@ |
| 73825 | 74086 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ |
| 73826 | 74087 | nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 73827 | 74088 | while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } |
| 73828 | 74089 | } |
| 73829 | 74090 | #endif |
| 73830 | | - sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z); |
| 74091 | + sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); |
| 73831 | 74092 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73832 | 74093 | if( nOut<pVar->n ){ |
| 73833 | | - sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); |
| 74094 | + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); |
| 73834 | 74095 | } |
| 73835 | 74096 | #endif |
| 73836 | 74097 | #ifndef SQLITE_OMIT_UTF16 |
| 73837 | 74098 | if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); |
| 73838 | 74099 | #endif |
| 73839 | 74100 | }else if( pVar->flags & MEM_Zero ){ |
| 73840 | | - sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero); |
| 74101 | + sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); |
| 73841 | 74102 | }else{ |
| 73842 | 74103 | int nOut; /* Number of bytes of the blob to include in output */ |
| 73843 | 74104 | assert( pVar->flags & MEM_Blob ); |
| 73844 | 74105 | sqlite3StrAccumAppend(&out, "x'", 2); |
| 73845 | 74106 | nOut = pVar->n; |
| 73846 | 74107 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73847 | 74108 | if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; |
| 73848 | 74109 | #endif |
| 73849 | 74110 | for(i=0; i<nOut; i++){ |
| 73850 | | - sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff); |
| 74111 | + sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); |
| 73851 | 74112 | } |
| 73852 | 74113 | sqlite3StrAccumAppend(&out, "'", 1); |
| 73853 | 74114 | #ifdef SQLITE_TRACE_SIZE_LIMIT |
| 73854 | 74115 | if( nOut<pVar->n ){ |
| 73855 | | - sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut); |
| 74116 | + sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); |
| 73856 | 74117 | } |
| 73857 | 74118 | #endif |
| 73858 | 74119 | } |
| 73859 | 74120 | } |
| 73860 | 74121 | } |
| | @@ -74336,10 +74597,11 @@ |
| 74336 | 74597 | }else{ |
| 74337 | 74598 | char zBuf[200]; |
| 74338 | 74599 | sqlite3VdbeMemPrettyPrint(p, zBuf); |
| 74339 | 74600 | printf(" %s", zBuf); |
| 74340 | 74601 | } |
| 74602 | + if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); |
| 74341 | 74603 | } |
| 74342 | 74604 | static void registerTrace(int iReg, Mem *p){ |
| 74343 | 74605 | printf("REG[%d] = ", iReg); |
| 74344 | 74606 | memTracePrint(p); |
| 74345 | 74607 | printf("\n"); |
| | @@ -74506,10 +74768,13 @@ |
| 74506 | 74768 | Op *aOp = p->aOp; /* Copy of p->aOp */ |
| 74507 | 74769 | Op *pOp = aOp; /* Current operation */ |
| 74508 | 74770 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 74509 | 74771 | Op *pOrigOp; /* Value of pOp at the top of the loop */ |
| 74510 | 74772 | #endif |
| 74773 | +#ifdef SQLITE_DEBUG |
| 74774 | + int nExtraDelete = 0; /* Verifies FORDELETE and AUXDELETE flags */ |
| 74775 | +#endif |
| 74511 | 74776 | int rc = SQLITE_OK; /* Value to return */ |
| 74512 | 74777 | sqlite3 *db = p->db; /* The database */ |
| 74513 | 74778 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ |
| 74514 | 74779 | u8 encoding = ENC(db); /* The database encoding */ |
| 74515 | 74780 | int iCompare = 0; /* Result of last OP_Compare operation */ |
| | @@ -74579,11 +74844,10 @@ |
| 74579 | 74844 | } |
| 74580 | 74845 | sqlite3EndBenignMalloc(); |
| 74581 | 74846 | #endif |
| 74582 | 74847 | for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ |
| 74583 | 74848 | assert( pOp>=aOp && pOp<&aOp[p->nOp]); |
| 74584 | | - if( db->mallocFailed ) goto no_mem; |
| 74585 | 74849 | #ifdef VDBE_PROFILE |
| 74586 | 74850 | start = sqlite3Hwtime(); |
| 74587 | 74851 | #endif |
| 74588 | 74852 | nVmStep++; |
| 74589 | 74853 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| | @@ -75577,11 +75841,11 @@ |
| 75577 | 75841 | assert( pOp->p4type==P4_FUNCDEF ); |
| 75578 | 75842 | n = pOp->p5; |
| 75579 | 75843 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 75580 | 75844 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 75581 | 75845 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 75582 | | - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 75846 | + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 75583 | 75847 | if( pCtx==0 ) goto no_mem; |
| 75584 | 75848 | pCtx->pOut = 0; |
| 75585 | 75849 | pCtx->pFunc = pOp->p4.pFunc; |
| 75586 | 75850 | pCtx->iOp = (int)(pOp - aOp); |
| 75587 | 75851 | pCtx->pVdbe = p; |
| | @@ -76021,15 +76285,18 @@ |
| 76021 | 76285 | ** of integers in P4. |
| 76022 | 76286 | ** |
| 76023 | 76287 | ** The permutation is only valid until the next OP_Compare that has |
| 76024 | 76288 | ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should |
| 76025 | 76289 | ** occur immediately prior to the OP_Compare. |
| 76290 | +** |
| 76291 | +** The first integer in the P4 integer array is the length of the array |
| 76292 | +** and does not become part of the permutation. |
| 76026 | 76293 | */ |
| 76027 | 76294 | case OP_Permutation: { |
| 76028 | 76295 | assert( pOp->p4type==P4_INTARRAY ); |
| 76029 | 76296 | assert( pOp->p4.ai ); |
| 76030 | | - aPermute = pOp->p4.ai; |
| 76297 | + aPermute = pOp->p4.ai + 1; |
| 76031 | 76298 | break; |
| 76032 | 76299 | } |
| 76033 | 76300 | |
| 76034 | 76301 | /* Opcode: Compare P1 P2 P3 P4 P5 |
| 76035 | 76302 | ** Synopsis: r[P1@P3] <-> r[P2@P3] |
| | @@ -76330,26 +76597,28 @@ |
| 76330 | 76597 | u64 offset64; /* 64-bit offset */ |
| 76331 | 76598 | u32 avail; /* Number of bytes of available data */ |
| 76332 | 76599 | u32 t; /* A type code from the record header */ |
| 76333 | 76600 | Mem *pReg; /* PseudoTable input register */ |
| 76334 | 76601 | |
| 76602 | + pC = p->apCsr[pOp->p1]; |
| 76335 | 76603 | p2 = pOp->p2; |
| 76604 | + |
| 76605 | + /* If the cursor cache is stale, bring it up-to-date */ |
| 76606 | + rc = sqlite3VdbeCursorMoveto(&pC, &p2); |
| 76607 | + |
| 76336 | 76608 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 76337 | 76609 | pDest = &aMem[pOp->p3]; |
| 76338 | 76610 | memAboutToChange(p, pDest); |
| 76339 | 76611 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 76340 | | - pC = p->apCsr[pOp->p1]; |
| 76341 | 76612 | assert( pC!=0 ); |
| 76342 | 76613 | assert( p2<pC->nField ); |
| 76343 | 76614 | aOffset = pC->aOffset; |
| 76344 | 76615 | assert( pC->eCurType!=CURTYPE_VTAB ); |
| 76345 | 76616 | assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); |
| 76346 | 76617 | assert( pC->eCurType!=CURTYPE_SORTER ); |
| 76347 | 76618 | pCrsr = pC->uc.pCursor; |
| 76348 | 76619 | |
| 76349 | | - /* If the cursor cache is stale, bring it up-to-date */ |
| 76350 | | - rc = sqlite3VdbeCursorMoveto(pC); |
| 76351 | 76620 | if( rc ) goto abort_due_to_error; |
| 76352 | 76621 | if( pC->cacheStatus!=p->cacheCtr ){ |
| 76353 | 76622 | if( pC->nullRow ){ |
| 76354 | 76623 | if( pC->eCurType==CURTYPE_PSEUDO ){ |
| 76355 | 76624 | assert( pC->uc.pseudoTableReg>0 ); |
| | @@ -76816,11 +77085,11 @@ |
| 76816 | 77085 | db->nStatement+db->nSavepoint); |
| 76817 | 77086 | if( rc!=SQLITE_OK ) goto abort_due_to_error; |
| 76818 | 77087 | #endif |
| 76819 | 77088 | |
| 76820 | 77089 | /* Create a new savepoint structure. */ |
| 76821 | | - pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); |
| 77090 | + pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1); |
| 76822 | 77091 | if( pNew ){ |
| 76823 | 77092 | pNew->zName = (char *)&pNew[1]; |
| 76824 | 77093 | memcpy(pNew->zName, zName, nName+1); |
| 76825 | 77094 | |
| 76826 | 77095 | /* If there is no open transaction, then mark this as a special |
| | @@ -76953,32 +77222,31 @@ |
| 76953 | 77222 | ** This instruction causes the VM to halt. |
| 76954 | 77223 | */ |
| 76955 | 77224 | case OP_AutoCommit: { |
| 76956 | 77225 | int desiredAutoCommit; |
| 76957 | 77226 | int iRollback; |
| 76958 | | - int turnOnAC; |
| 76959 | 77227 | |
| 76960 | 77228 | desiredAutoCommit = pOp->p1; |
| 76961 | 77229 | iRollback = pOp->p2; |
| 76962 | | - turnOnAC = desiredAutoCommit && !db->autoCommit; |
| 76963 | 77230 | assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); |
| 76964 | 77231 | assert( desiredAutoCommit==1 || iRollback==0 ); |
| 76965 | 77232 | assert( db->nVdbeActive>0 ); /* At least this one VM is active */ |
| 76966 | 77233 | assert( p->bIsReader ); |
| 76967 | 77234 | |
| 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 ){ |
| 77235 | + if( desiredAutoCommit!=db->autoCommit ){ |
| 76976 | 77236 | if( iRollback ){ |
| 76977 | 77237 | assert( desiredAutoCommit==1 ); |
| 76978 | 77238 | sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); |
| 76979 | 77239 | db->autoCommit = 1; |
| 77240 | + }else if( desiredAutoCommit && db->nVdbeWrite>0 ){ |
| 77241 | + /* If this instruction implements a COMMIT and other VMs are writing |
| 77242 | + ** return an error indicating that the other VMs must complete first. |
| 77243 | + */ |
| 77244 | + sqlite3VdbeError(p, "cannot commit transaction - " |
| 77245 | + "SQL statements in progress"); |
| 77246 | + rc = SQLITE_BUSY; |
| 77247 | + break; |
| 76980 | 77248 | }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ |
| 76981 | 77249 | goto vdbe_return; |
| 76982 | 77250 | }else{ |
| 76983 | 77251 | db->autoCommit = (u8)desiredAutoCommit; |
| 76984 | 77252 | } |
| | @@ -77159,38 +77427,36 @@ |
| 77159 | 77427 | break; |
| 77160 | 77428 | } |
| 77161 | 77429 | |
| 77162 | 77430 | /* Opcode: SetCookie P1 P2 P3 * * |
| 77163 | 77431 | ** |
| 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 |
| 77432 | +** Write the integer value P3 into cookie number P2 of database P1. |
| 77433 | +** P2==1 is the schema version. P2==2 is the database format. |
| 77434 | +** P2==3 is the recommended pager cache |
| 77167 | 77435 | ** size, and so forth. P1==0 is the main database file and P1==1 is the |
| 77168 | 77436 | ** database file used to store temporary tables. |
| 77169 | 77437 | ** |
| 77170 | 77438 | ** A transaction must be started before executing this opcode. |
| 77171 | 77439 | */ |
| 77172 | | -case OP_SetCookie: { /* in3 */ |
| 77440 | +case OP_SetCookie: { |
| 77173 | 77441 | Db *pDb; |
| 77174 | 77442 | assert( pOp->p2<SQLITE_N_BTREE_META ); |
| 77175 | 77443 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 77176 | 77444 | assert( DbMaskTest(p->btreeMask, pOp->p1) ); |
| 77177 | 77445 | assert( p->readOnly==0 ); |
| 77178 | 77446 | pDb = &db->aDb[pOp->p1]; |
| 77179 | 77447 | assert( pDb->pBt!=0 ); |
| 77180 | 77448 | assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); |
| 77181 | | - pIn3 = &aMem[pOp->p3]; |
| 77182 | | - sqlite3VdbeMemIntegerify(pIn3); |
| 77183 | 77449 | /* See note about index shifting on OP_ReadCookie */ |
| 77184 | | - rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); |
| 77450 | + rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3); |
| 77185 | 77451 | if( pOp->p2==BTREE_SCHEMA_VERSION ){ |
| 77186 | 77452 | /* When the schema cookie changes, record the new cookie internally */ |
| 77187 | | - pDb->pSchema->schema_cookie = (int)pIn3->u.i; |
| 77453 | + pDb->pSchema->schema_cookie = pOp->p3; |
| 77188 | 77454 | db->flags |= SQLITE_InternChanges; |
| 77189 | 77455 | }else if( pOp->p2==BTREE_FILE_FORMAT ){ |
| 77190 | 77456 | /* Record changes in the file format */ |
| 77191 | | - pDb->pSchema->file_format = (u8)pIn3->u.i; |
| 77457 | + pDb->pSchema->file_format = pOp->p3; |
| 77192 | 77458 | } |
| 77193 | 77459 | if( pOp->p1==1 ){ |
| 77194 | 77460 | /* Invalidate all prepared statements whenever the TEMP database |
| 77195 | 77461 | ** schema is changed. Ticket #1644 */ |
| 77196 | 77462 | sqlite3ExpirePreparedStatements(db); |
| | @@ -77346,10 +77612,13 @@ |
| 77346 | 77612 | pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); |
| 77347 | 77613 | if( pCur==0 ) goto no_mem; |
| 77348 | 77614 | pCur->nullRow = 1; |
| 77349 | 77615 | pCur->isOrdered = 1; |
| 77350 | 77616 | pCur->pgnoRoot = p2; |
| 77617 | +#ifdef SQLITE_DEBUG |
| 77618 | + pCur->wrFlag = wrFlag; |
| 77619 | +#endif |
| 77351 | 77620 | rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor); |
| 77352 | 77621 | pCur->pKeyInfo = pKeyInfo; |
| 77353 | 77622 | /* Set the VdbeCursor.isTable variable. Previous versions of |
| 77354 | 77623 | ** SQLite used to check if the root-page flags were sane at this point |
| 77355 | 77624 | ** and report database corruption if they were not, but this check has |
| | @@ -77799,36 +78068,10 @@ |
| 77799 | 78068 | assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); |
| 77800 | 78069 | pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */ |
| 77801 | 78070 | } |
| 77802 | 78071 | break; |
| 77803 | 78072 | } |
| 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 | 78073 | |
| 77831 | 78074 | |
| 77832 | 78075 | /* Opcode: Found P1 P2 P3 P4 * |
| 77833 | 78076 | ** Synopsis: key=r[P3@P4] |
| 77834 | 78077 | ** |
| | @@ -78295,18 +78538,26 @@ |
| 78295 | 78538 | |
| 78296 | 78539 | /* Opcode: Delete P1 P2 * P4 P5 |
| 78297 | 78540 | ** |
| 78298 | 78541 | ** Delete the record at which the P1 cursor is currently pointing. |
| 78299 | 78542 | ** |
| 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. |
| 78543 | +** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then |
| 78544 | +** the cursor will be left pointing at either the next or the previous |
| 78545 | +** record in the table. If it is left pointing at the next record, then |
| 78546 | +** the next Next instruction will be a no-op. As a result, in this case |
| 78547 | +** it is ok to delete a record from within a Next loop. If |
| 78548 | +** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be |
| 78549 | +** left in an undefined state. |
| 78305 | 78550 | ** |
| 78306 | | -** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is |
| 78307 | | -** incremented (otherwise not). |
| 78551 | +** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this |
| 78552 | +** delete one of several associated with deleting a table row and all its |
| 78553 | +** associated index entries. Exactly one of those deletes is the "primary" |
| 78554 | +** delete. The others are all on OPFLAG_FORDELETE cursors or else are |
| 78555 | +** marked with the AUXDELETE flag. |
| 78556 | +** |
| 78557 | +** If the OPFLAG_NCHANGE flag of P2 (NB: P2 not P5) is set, then the row |
| 78558 | +** change count is incremented (otherwise not). |
| 78308 | 78559 | ** |
| 78309 | 78560 | ** P1 must not be pseudo-table. It has to be a real table with |
| 78310 | 78561 | ** multiple rows. |
| 78311 | 78562 | ** |
| 78312 | 78563 | ** If P4 is not NULL, then it is the name of the table that P1 is |
| | @@ -78338,11 +78589,30 @@ |
| 78338 | 78589 | i64 iKey = 0; |
| 78339 | 78590 | sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); |
| 78340 | 78591 | assert( pC->movetoTarget==iKey ); |
| 78341 | 78592 | } |
| 78342 | 78593 | #endif |
| 78343 | | - |
| 78594 | + |
| 78595 | + /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ |
| 78596 | + assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 ); |
| 78597 | + assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION ); |
| 78598 | + assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE ); |
| 78599 | + |
| 78600 | +#ifdef SQLITE_DEBUG |
| 78601 | + if( p->pFrame==0 ){ |
| 78602 | + if( pC->isEphemeral==0 |
| 78603 | + && (pOp->p5 & OPFLAG_AUXDELETE)==0 |
| 78604 | + && (pC->wrFlag & OPFLAG_FORDELETE)==0 |
| 78605 | + ){ |
| 78606 | + nExtraDelete++; |
| 78607 | + } |
| 78608 | + if( pOp->p2 & OPFLAG_NCHANGE ){ |
| 78609 | + nExtraDelete--; |
| 78610 | + } |
| 78611 | + } |
| 78612 | +#endif |
| 78613 | + |
| 78344 | 78614 | rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); |
| 78345 | 78615 | pC->cacheStatus = CACHE_STALE; |
| 78346 | 78616 | |
| 78347 | 78617 | /* Invoke the update-hook if required. */ |
| 78348 | 78618 | if( rc==SQLITE_OK && hasUpdateCallback ){ |
| | @@ -78883,62 +79153,98 @@ |
| 78883 | 79153 | assert( pOp->p5==0 ); |
| 78884 | 79154 | r.pKeyInfo = pC->pKeyInfo; |
| 78885 | 79155 | r.nField = (u16)pOp->p3; |
| 78886 | 79156 | r.default_rc = 0; |
| 78887 | 79157 | 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 | 79158 | rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); |
| 78892 | 79159 | if( rc==SQLITE_OK && res==0 ){ |
| 78893 | | - rc = sqlite3BtreeDelete(pCrsr, 0); |
| 79160 | + rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); |
| 78894 | 79161 | } |
| 78895 | 79162 | assert( pC->deferredMoveto==0 ); |
| 78896 | 79163 | pC->cacheStatus = CACHE_STALE; |
| 78897 | 79164 | break; |
| 78898 | 79165 | } |
| 78899 | 79166 | |
| 79167 | +/* Opcode: Seek P1 * P3 P4 * |
| 79168 | +** Synopsis: Move P3 to P1.rowid |
| 79169 | +** |
| 79170 | +** P1 is an open index cursor and P3 is a cursor on the corresponding |
| 79171 | +** table. This opcode does a deferred seek of the P3 table cursor |
| 79172 | +** to the row that corresponds to the current row of P1. |
| 79173 | +** |
| 79174 | +** This is a deferred seek. Nothing actually happens until |
| 79175 | +** the cursor is used to read a record. That way, if no reads |
| 79176 | +** occur, no unnecessary I/O happens. |
| 79177 | +** |
| 79178 | +** P4 may be an array of integers (type P4_INTARRAY) containing |
| 79179 | +** one entry for each column in the P3 table. If array entry a(i) |
| 79180 | +** is non-zero, then reading column a(i)-1 from cursor P3 is |
| 79181 | +** equivalent to performing the deferred seek and then reading column i |
| 79182 | +** from P1. This information is stored in P3 and used to redirect |
| 79183 | +** reads against P3 over to P1, thus possibly avoiding the need to |
| 79184 | +** seek and read cursor P3. |
| 79185 | +*/ |
| 78900 | 79186 | /* Opcode: IdxRowid P1 P2 * * * |
| 78901 | 79187 | ** Synopsis: r[P2]=rowid |
| 78902 | 79188 | ** |
| 78903 | 79189 | ** Write into register P2 an integer which is the last entry in the record at |
| 78904 | 79190 | ** the end of the index key pointed to by cursor P1. This integer should be |
| 78905 | 79191 | ** the rowid of the table entry to which this index entry points. |
| 78906 | 79192 | ** |
| 78907 | 79193 | ** See also: Rowid, MakeRecord. |
| 78908 | 79194 | */ |
| 79195 | +case OP_Seek: |
| 78909 | 79196 | case OP_IdxRowid: { /* out2 */ |
| 78910 | | - BtCursor *pCrsr; |
| 78911 | | - VdbeCursor *pC; |
| 78912 | | - i64 rowid; |
| 79197 | + VdbeCursor *pC; /* The P1 index cursor */ |
| 79198 | + VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */ |
| 79199 | + i64 rowid; /* Rowid that P1 current points to */ |
| 78913 | 79200 | |
| 78914 | | - pOut = out2Prerelease(p, pOp); |
| 78915 | 79201 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 78916 | 79202 | pC = p->apCsr[pOp->p1]; |
| 78917 | 79203 | assert( pC!=0 ); |
| 78918 | 79204 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 78919 | | - pCrsr = pC->uc.pCursor; |
| 78920 | | - assert( pCrsr!=0 ); |
| 78921 | | - pOut->flags = MEM_Null; |
| 79205 | + assert( pC->uc.pCursor!=0 ); |
| 78922 | 79206 | assert( pC->isTable==0 ); |
| 78923 | 79207 | assert( pC->deferredMoveto==0 ); |
| 79208 | + assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); |
| 79209 | + |
| 79210 | + /* The IdxRowid and Seek opcodes are combined because of the commonality |
| 79211 | + ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ |
| 79212 | + rc = sqlite3VdbeCursorRestore(pC); |
| 78924 | 79213 | |
| 78925 | 79214 | /* 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); |
| 79215 | + ** out from under the cursor. That will never happens for an IdxRowid |
| 79216 | + ** or Seek opcode */ |
| 78930 | 79217 | if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; |
| 78931 | 79218 | |
| 78932 | 79219 | if( !pC->nullRow ){ |
| 78933 | 79220 | rowid = 0; /* Not needed. Only used to silence a warning. */ |
| 78934 | | - rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); |
| 79221 | + rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid); |
| 78935 | 79222 | if( rc!=SQLITE_OK ){ |
| 78936 | 79223 | goto abort_due_to_error; |
| 78937 | 79224 | } |
| 78938 | | - pOut->u.i = rowid; |
| 78939 | | - pOut->flags = MEM_Int; |
| 79225 | + if( pOp->opcode==OP_Seek ){ |
| 79226 | + assert( pOp->p3>=0 && pOp->p3<p->nCursor ); |
| 79227 | + pTabCur = p->apCsr[pOp->p3]; |
| 79228 | + assert( pTabCur!=0 ); |
| 79229 | + assert( pTabCur->eCurType==CURTYPE_BTREE ); |
| 79230 | + assert( pTabCur->uc.pCursor!=0 ); |
| 79231 | + assert( pTabCur->isTable ); |
| 79232 | + pTabCur->nullRow = 0; |
| 79233 | + pTabCur->movetoTarget = rowid; |
| 79234 | + pTabCur->deferredMoveto = 1; |
| 79235 | + assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); |
| 79236 | + pTabCur->aAltMap = pOp->p4.ai; |
| 79237 | + pTabCur->pAltCursor = pC; |
| 79238 | + }else{ |
| 79239 | + pOut = out2Prerelease(p, pOp); |
| 79240 | + pOut->u.i = rowid; |
| 79241 | + pOut->flags = MEM_Int; |
| 79242 | + } |
| 79243 | + }else{ |
| 79244 | + assert( pOp->opcode==OP_IdxRowid ); |
| 79245 | + sqlite3VdbeMemSetNull(&aMem[pOp->p2]); |
| 78940 | 79246 | } |
| 78941 | 79247 | break; |
| 78942 | 79248 | } |
| 78943 | 79249 | |
| 78944 | 79250 | /* Opcode: IdxGE P1 P2 P3 P4 P5 |
| | @@ -79329,11 +79635,11 @@ |
| 79329 | 79635 | Mem *pnErr; /* Register keeping track of errors remaining */ |
| 79330 | 79636 | |
| 79331 | 79637 | assert( p->bIsReader ); |
| 79332 | 79638 | nRoot = pOp->p2; |
| 79333 | 79639 | assert( nRoot>0 ); |
| 79334 | | - aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); |
| 79640 | + aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(nRoot+1) ); |
| 79335 | 79641 | if( aRoot==0 ) goto no_mem; |
| 79336 | 79642 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 79337 | 79643 | pnErr = &aMem[pOp->p3]; |
| 79338 | 79644 | assert( (pnErr->flags & MEM_Int)!=0 ); |
| 79339 | 79645 | assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); |
| | @@ -79711,24 +80017,35 @@ |
| 79711 | 80017 | goto jump_to_p2; |
| 79712 | 80018 | } |
| 79713 | 80019 | break; |
| 79714 | 80020 | } |
| 79715 | 80021 | |
| 79716 | | -/* Opcode: SetIfNotPos P1 P2 P3 * * |
| 79717 | | -** Synopsis: if r[P1]<=0 then r[P2]=P3 |
| 80022 | +/* Opcode: OffsetLimit P1 P2 P3 * * |
| 80023 | +** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) |
| 79718 | 80024 | ** |
| 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. |
| 80025 | +** This opcode performs a commonly used computation associated with |
| 80026 | +** LIMIT and OFFSET process. r[P1] holds the limit counter. r[P3] |
| 80027 | +** holds the offset counter. The opcode computes the combined value |
| 80028 | +** of the LIMIT and OFFSET and stores that value in r[P2]. The r[P2] |
| 80029 | +** value computed is the total number of rows that will need to be |
| 80030 | +** visited in order to complete the query. |
| 80031 | +** |
| 80032 | +** If r[P3] is zero or negative, that means there is no OFFSET |
| 80033 | +** and r[P2] is set to be the value of the LIMIT, r[P1]. |
| 80034 | +** |
| 80035 | +** if r[P1] is zero or negative, that means there is no LIMIT |
| 80036 | +** and r[P2] is set to -1. |
| 80037 | +** |
| 80038 | +** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. |
| 79722 | 80039 | */ |
| 79723 | | -case OP_SetIfNotPos: { /* in1, in2 */ |
| 80040 | +case OP_OffsetLimit: { /* in1, out2, in3 */ |
| 79724 | 80041 | 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 | | - } |
| 80042 | + pIn3 = &aMem[pOp->p3]; |
| 80043 | + pOut = out2Prerelease(p, pOp); |
| 80044 | + assert( pIn1->flags & MEM_Int ); |
| 80045 | + assert( pIn3->flags & MEM_Int ); |
| 80046 | + pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0); |
| 79730 | 80047 | break; |
| 79731 | 80048 | } |
| 79732 | 80049 | |
| 79733 | 80050 | /* Opcode: IfNotZero P1 P2 P3 * * |
| 79734 | 80051 | ** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 |
| | @@ -79815,11 +80132,11 @@ |
| 79815 | 80132 | assert( pOp->p4type==P4_FUNCDEF ); |
| 79816 | 80133 | n = pOp->p5; |
| 79817 | 80134 | assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); |
| 79818 | 80135 | assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) ); |
| 79819 | 80136 | assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); |
| 79820 | | - pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 80137 | + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); |
| 79821 | 80138 | if( pCtx==0 ) goto no_mem; |
| 79822 | 80139 | pCtx->pMem = 0; |
| 79823 | 80140 | pCtx->pFunc = pOp->p4.pFunc; |
| 79824 | 80141 | pCtx->iOp = (int)(pOp - aOp); |
| 79825 | 80142 | pCtx->pVdbe = p; |
| | @@ -80682,11 +80999,11 @@ |
| 80682 | 80999 | p->rc = rc; |
| 80683 | 81000 | testcase( sqlite3GlobalConfig.xLog!=0 ); |
| 80684 | 81001 | sqlite3_log(rc, "statement aborts at %d: [%s] %s", |
| 80685 | 81002 | (int)(pOp - aOp), p->zSql, p->zErrMsg); |
| 80686 | 81003 | sqlite3VdbeHalt(p); |
| 80687 | | - if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; |
| 81004 | + if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); |
| 80688 | 81005 | rc = SQLITE_ERROR; |
| 80689 | 81006 | if( resetSchemaOnFault>0 ){ |
| 80690 | 81007 | sqlite3ResetOneSchema(db, resetSchemaOnFault-1); |
| 80691 | 81008 | } |
| 80692 | 81009 | |
| | @@ -80696,10 +81013,13 @@ |
| 80696 | 81013 | vdbe_return: |
| 80697 | 81014 | db->lastRowid = lastRowid; |
| 80698 | 81015 | testcase( nVmStep>0 ); |
| 80699 | 81016 | p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; |
| 80700 | 81017 | sqlite3VdbeLeave(p); |
| 81018 | + assert( rc!=SQLITE_OK || nExtraDelete==0 |
| 81019 | + || sqlite3_strlike("DELETE%",p->zSql,0)!=0 |
| 81020 | + ); |
| 80701 | 81021 | return rc; |
| 80702 | 81022 | |
| 80703 | 81023 | /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH |
| 80704 | 81024 | ** is encountered. |
| 80705 | 81025 | */ |
| | @@ -80709,11 +81029,11 @@ |
| 80709 | 81029 | goto vdbe_error_halt; |
| 80710 | 81030 | |
| 80711 | 81031 | /* Jump to here if a malloc() fails. |
| 80712 | 81032 | */ |
| 80713 | 81033 | no_mem: |
| 80714 | | - db->mallocFailed = 1; |
| 81034 | + sqlite3OomFault(db); |
| 80715 | 81035 | sqlite3VdbeError(p, "out of memory"); |
| 80716 | 81036 | rc = SQLITE_NOMEM; |
| 80717 | 81037 | goto vdbe_error_halt; |
| 80718 | 81038 | |
| 80719 | 81039 | /* Jump to here for any other kind of fatal error. The "rc" variable |
| | @@ -80730,11 +81050,11 @@ |
| 80730 | 81050 | /* Jump to here if the sqlite3_interrupt() API sets the interrupt |
| 80731 | 81051 | ** flag. |
| 80732 | 81052 | */ |
| 80733 | 81053 | abort_due_to_interrupt: |
| 80734 | 81054 | assert( db->u1.isInterrupted ); |
| 80735 | | - rc = SQLITE_INTERRUPT; |
| 81055 | + rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_INTERRUPT; |
| 80736 | 81056 | p->rc = rc; |
| 80737 | 81057 | sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc)); |
| 80738 | 81058 | goto vdbe_error_halt; |
| 80739 | 81059 | } |
| 80740 | 81060 | |
| | @@ -80990,23 +81310,21 @@ |
| 80990 | 81310 | ** |
| 80991 | 81311 | ** The sqlite3_blob_close() function finalizes the vdbe program, |
| 80992 | 81312 | ** which closes the b-tree cursor and (possibly) commits the |
| 80993 | 81313 | ** transaction. |
| 80994 | 81314 | */ |
| 80995 | | - static const int iLn = VDBE_OFFSET_LINENO(4); |
| 81315 | + static const int iLn = VDBE_OFFSET_LINENO(2); |
| 80996 | 81316 | 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 */ |
| 81317 | + {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ |
| 81318 | + {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ |
| 81319 | + {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */ |
| 81320 | + {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */ |
| 81321 | + {OP_Column, 0, 0, 1}, /* 4 */ |
| 81322 | + {OP_ResultRow, 1, 0, 0}, /* 5 */ |
| 81323 | + {OP_Goto, 0, 2, 0}, /* 6 */ |
| 81324 | + {OP_Close, 0, 0, 0}, /* 7 */ |
| 81325 | + {OP_Halt, 0, 0, 0}, /* 8 */ |
| 81008 | 81326 | }; |
| 81009 | 81327 | Vdbe *v = (Vdbe *)pBlob->pStmt; |
| 81010 | 81328 | int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 81011 | 81329 | VdbeOp *aOp; |
| 81012 | 81330 | |
| | @@ -83044,27 +83362,28 @@ |
| 83044 | 83362 | if( pSorter->list.aMemory ){ |
| 83045 | 83363 | int nMin = pSorter->iMemory + nReq; |
| 83046 | 83364 | |
| 83047 | 83365 | if( nMin>pSorter->nMemory ){ |
| 83048 | 83366 | u8 *aNew; |
| 83367 | + int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; |
| 83049 | 83368 | int nNew = pSorter->nMemory * 2; |
| 83050 | 83369 | while( nNew < nMin ) nNew = nNew*2; |
| 83051 | 83370 | if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; |
| 83052 | 83371 | if( nNew < nMin ) nNew = nMin; |
| 83053 | 83372 | |
| 83054 | 83373 | aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); |
| 83055 | 83374 | if( !aNew ) return SQLITE_NOMEM; |
| 83056 | | - pSorter->list.pList = (SorterRecord*)( |
| 83057 | | - aNew + ((u8*)pSorter->list.pList - pSorter->list.aMemory) |
| 83058 | | - ); |
| 83375 | + pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; |
| 83059 | 83376 | pSorter->list.aMemory = aNew; |
| 83060 | 83377 | pSorter->nMemory = nNew; |
| 83061 | 83378 | } |
| 83062 | 83379 | |
| 83063 | 83380 | pNew = (SorterRecord*)&pSorter->list.aMemory[pSorter->iMemory]; |
| 83064 | 83381 | pSorter->iMemory += ROUND8(nReq); |
| 83065 | | - pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); |
| 83382 | + if( pSorter->list.pList ){ |
| 83383 | + pNew->u.iNext = (int)((u8*)(pSorter->list.pList) - pSorter->list.aMemory); |
| 83384 | + } |
| 83066 | 83385 | }else{ |
| 83067 | 83386 | pNew = (SorterRecord *)sqlite3Malloc(nReq); |
| 83068 | 83387 | if( pNew==0 ){ |
| 83069 | 83388 | return SQLITE_NOMEM; |
| 83070 | 83389 | } |
| | @@ -86230,12 +86549,11 @@ |
| 86230 | 86549 | return pExpr; |
| 86231 | 86550 | } |
| 86232 | 86551 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
| 86233 | 86552 | Token s; |
| 86234 | 86553 | assert( zC!=0 ); |
| 86235 | | - s.z = zC; |
| 86236 | | - s.n = sqlite3Strlen30(s.z); |
| 86554 | + sqlite3TokenInit(&s, (char*)zC); |
| 86237 | 86555 | return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); |
| 86238 | 86556 | } |
| 86239 | 86557 | |
| 86240 | 86558 | /* |
| 86241 | 86559 | ** Skip over any TK_COLLATE operators and any unlikely() |
| | @@ -86599,18 +86917,19 @@ |
| 86599 | 86917 | ){ |
| 86600 | 86918 | Expr *pNew; |
| 86601 | 86919 | int nExtra = 0; |
| 86602 | 86920 | int iValue = 0; |
| 86603 | 86921 | |
| 86922 | + assert( db!=0 ); |
| 86604 | 86923 | if( pToken ){ |
| 86605 | 86924 | if( op!=TK_INTEGER || pToken->z==0 |
| 86606 | 86925 | || sqlite3GetInt32(pToken->z, &iValue)==0 ){ |
| 86607 | 86926 | nExtra = pToken->n+1; |
| 86608 | 86927 | assert( iValue>=0 ); |
| 86609 | 86928 | } |
| 86610 | 86929 | } |
| 86611 | | - pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra); |
| 86930 | + pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); |
| 86612 | 86931 | if( pNew ){ |
| 86613 | 86932 | memset(pNew, 0, sizeof(Expr)); |
| 86614 | 86933 | pNew->op = (u8)op; |
| 86615 | 86934 | pNew->iAgg = -1; |
| 86616 | 86935 | if( pToken ){ |
| | @@ -86845,11 +87164,14 @@ |
| 86845 | 87164 | } |
| 86846 | 87165 | if( x>0 ){ |
| 86847 | 87166 | if( x>pParse->nzVar ){ |
| 86848 | 87167 | char **a; |
| 86849 | 87168 | a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); |
| 86850 | | - if( a==0 ) return; /* Error reported through db->mallocFailed */ |
| 87169 | + if( a==0 ){ |
| 87170 | + assert( db->mallocFailed ); /* Error reported through mallocFailed */ |
| 87171 | + return; |
| 87172 | + } |
| 86851 | 87173 | pParse->azVar = a; |
| 86852 | 87174 | memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); |
| 86853 | 87175 | pParse->nzVar = x; |
| 86854 | 87176 | } |
| 86855 | 87177 | if( z[0]!='?' || pParse->azVar[x-1]==0 ){ |
| | @@ -87000,10 +87322,11 @@ |
| 87000 | 87322 | ** portion of the buffer copied into by this function. |
| 87001 | 87323 | */ |
| 87002 | 87324 | static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ |
| 87003 | 87325 | Expr *pNew = 0; /* Value to return */ |
| 87004 | 87326 | assert( flags==0 || flags==EXPRDUP_REDUCE ); |
| 87327 | + assert( db!=0 ); |
| 87005 | 87328 | if( p ){ |
| 87006 | 87329 | const int isReduced = (flags&EXPRDUP_REDUCE); |
| 87007 | 87330 | u8 *zAlloc; |
| 87008 | 87331 | u32 staticFlag = 0; |
| 87009 | 87332 | |
| | @@ -87012,11 +87335,11 @@ |
| 87012 | 87335 | /* Figure out where to write the new Expr structure. */ |
| 87013 | 87336 | if( pzBuffer ){ |
| 87014 | 87337 | zAlloc = *pzBuffer; |
| 87015 | 87338 | staticFlag = EP_Static; |
| 87016 | 87339 | }else{ |
| 87017 | | - zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); |
| 87340 | + zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, flags)); |
| 87018 | 87341 | } |
| 87019 | 87342 | pNew = (Expr *)zAlloc; |
| 87020 | 87343 | |
| 87021 | 87344 | if( pNew ){ |
| 87022 | 87345 | /* Set nNewSize to the size allocated for the structure pointed to |
| | @@ -87135,16 +87458,17 @@ |
| 87135 | 87458 | } |
| 87136 | 87459 | SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ |
| 87137 | 87460 | ExprList *pNew; |
| 87138 | 87461 | struct ExprList_item *pItem, *pOldItem; |
| 87139 | 87462 | int i; |
| 87463 | + assert( db!=0 ); |
| 87140 | 87464 | if( p==0 ) return 0; |
| 87141 | | - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); |
| 87465 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); |
| 87142 | 87466 | if( pNew==0 ) return 0; |
| 87143 | 87467 | pNew->nExpr = i = p->nExpr; |
| 87144 | 87468 | if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){} |
| 87145 | | - pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) ); |
| 87469 | + pNew->a = pItem = sqlite3DbMallocRawNN(db, i*sizeof(p->a[0]) ); |
| 87146 | 87470 | if( pItem==0 ){ |
| 87147 | 87471 | sqlite3DbFree(db, pNew); |
| 87148 | 87472 | return 0; |
| 87149 | 87473 | } |
| 87150 | 87474 | pOldItem = p->a; |
| | @@ -87171,13 +87495,14 @@ |
| 87171 | 87495 | || !defined(SQLITE_OMIT_SUBQUERY) |
| 87172 | 87496 | SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ |
| 87173 | 87497 | SrcList *pNew; |
| 87174 | 87498 | int i; |
| 87175 | 87499 | int nByte; |
| 87500 | + assert( db!=0 ); |
| 87176 | 87501 | if( p==0 ) return 0; |
| 87177 | 87502 | nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); |
| 87178 | | - pNew = sqlite3DbMallocRaw(db, nByte ); |
| 87503 | + pNew = sqlite3DbMallocRawNN(db, nByte ); |
| 87179 | 87504 | if( pNew==0 ) return 0; |
| 87180 | 87505 | pNew->nSrc = pNew->nAlloc = p->nSrc; |
| 87181 | 87506 | for(i=0; i<p->nSrc; i++){ |
| 87182 | 87507 | struct SrcList_item *pNewItem = &pNew->a[i]; |
| 87183 | 87508 | struct SrcList_item *pOldItem = &p->a[i]; |
| | @@ -87210,15 +87535,16 @@ |
| 87210 | 87535 | return pNew; |
| 87211 | 87536 | } |
| 87212 | 87537 | SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ |
| 87213 | 87538 | IdList *pNew; |
| 87214 | 87539 | int i; |
| 87540 | + assert( db!=0 ); |
| 87215 | 87541 | if( p==0 ) return 0; |
| 87216 | | - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); |
| 87542 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); |
| 87217 | 87543 | if( pNew==0 ) return 0; |
| 87218 | 87544 | pNew->nId = p->nId; |
| 87219 | | - pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); |
| 87545 | + pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) ); |
| 87220 | 87546 | if( pNew->a==0 ){ |
| 87221 | 87547 | sqlite3DbFree(db, pNew); |
| 87222 | 87548 | return 0; |
| 87223 | 87549 | } |
| 87224 | 87550 | /* Note that because the size of the allocation for p->a[] is not |
| | @@ -87232,12 +87558,13 @@ |
| 87232 | 87558 | } |
| 87233 | 87559 | return pNew; |
| 87234 | 87560 | } |
| 87235 | 87561 | SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ |
| 87236 | 87562 | Select *pNew, *pPrior; |
| 87563 | + assert( db!=0 ); |
| 87237 | 87564 | if( p==0 ) return 0; |
| 87238 | | - pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); |
| 87565 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); |
| 87239 | 87566 | if( pNew==0 ) return 0; |
| 87240 | 87567 | pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); |
| 87241 | 87568 | pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); |
| 87242 | 87569 | pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); |
| 87243 | 87570 | pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); |
| | @@ -87279,17 +87606,18 @@ |
| 87279 | 87606 | Parse *pParse, /* Parsing context */ |
| 87280 | 87607 | ExprList *pList, /* List to which to append. Might be NULL */ |
| 87281 | 87608 | Expr *pExpr /* Expression to be appended. Might be NULL */ |
| 87282 | 87609 | ){ |
| 87283 | 87610 | sqlite3 *db = pParse->db; |
| 87611 | + assert( db!=0 ); |
| 87284 | 87612 | if( pList==0 ){ |
| 87285 | | - pList = sqlite3DbMallocRaw(db, sizeof(ExprList) ); |
| 87613 | + pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) ); |
| 87286 | 87614 | if( pList==0 ){ |
| 87287 | 87615 | goto no_mem; |
| 87288 | 87616 | } |
| 87289 | 87617 | pList->nExpr = 0; |
| 87290 | | - pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0])); |
| 87618 | + pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0])); |
| 87291 | 87619 | if( pList->a==0 ) goto no_mem; |
| 87292 | 87620 | }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ |
| 87293 | 87621 | struct ExprList_item *a; |
| 87294 | 87622 | assert( pList->nExpr>0 ); |
| 87295 | 87623 | a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0])); |
| | @@ -90989,37 +91317,10 @@ |
| 90989 | 91317 | sqlite3SrcListDelete(db, pSrc); |
| 90990 | 91318 | sqlite3DbFree(db, zName); |
| 90991 | 91319 | db->flags = savedDbFlags; |
| 90992 | 91320 | } |
| 90993 | 91321 | |
| 90994 | | - |
| 90995 | | -/* |
| 90996 | | -** Generate code to make sure the file format number is at least minFormat. |
| 90997 | | -** The generated code will increase the file format number if necessary. |
| 90998 | | -*/ |
| 90999 | | -SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ |
| 91000 | | - Vdbe *v; |
| 91001 | | - v = sqlite3GetVdbe(pParse); |
| 91002 | | - /* The VDBE should have been allocated before this routine is called. |
| 91003 | | - ** If that allocation failed, we would have quit before reaching this |
| 91004 | | - ** point */ |
| 91005 | | - if( ALWAYS(v) ){ |
| 91006 | | - int r1 = sqlite3GetTempReg(pParse); |
| 91007 | | - int r2 = sqlite3GetTempReg(pParse); |
| 91008 | | - int addr1; |
| 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 | | -} |
| 91020 | | - |
| 91021 | 91322 | /* |
| 91022 | 91323 | ** This function is called after an "ALTER TABLE ... ADD" statement |
| 91023 | 91324 | ** has been parsed. Argument pColDef contains the text of the new |
| 91024 | 91325 | ** column definition. |
| 91025 | 91326 | ** |
| | @@ -91034,13 +91335,15 @@ |
| 91034 | 91335 | const char *zTab; /* Table name */ |
| 91035 | 91336 | char *zCol; /* Null-terminated column definition */ |
| 91036 | 91337 | Column *pCol; /* The new column */ |
| 91037 | 91338 | Expr *pDflt; /* Default value for the new column */ |
| 91038 | 91339 | sqlite3 *db; /* The database connection; */ |
| 91340 | + Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ |
| 91039 | 91341 | |
| 91040 | 91342 | db = pParse->db; |
| 91041 | 91343 | if( pParse->nErr || db->mallocFailed ) return; |
| 91344 | + assert( v!=0 ); |
| 91042 | 91345 | pNew = pParse->pNewTable; |
| 91043 | 91346 | assert( pNew ); |
| 91044 | 91347 | |
| 91045 | 91348 | assert( sqlite3BtreeHoldsAllMutexes(db) ); |
| 91046 | 91349 | iDb = sqlite3SchemaToIndex(db, pNew->pSchema); |
| | @@ -91096,11 +91399,11 @@ |
| 91096 | 91399 | sqlite3_value *pVal = 0; |
| 91097 | 91400 | int rc; |
| 91098 | 91401 | rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal); |
| 91099 | 91402 | assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); |
| 91100 | 91403 | if( rc!=SQLITE_OK ){ |
| 91101 | | - db->mallocFailed = 1; |
| 91404 | + assert( db->mallocFailed == 1 ); |
| 91102 | 91405 | return; |
| 91103 | 91406 | } |
| 91104 | 91407 | if( !pVal ){ |
| 91105 | 91408 | sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); |
| 91106 | 91409 | return; |
| | @@ -91126,15 +91429,20 @@ |
| 91126 | 91429 | ); |
| 91127 | 91430 | sqlite3DbFree(db, zCol); |
| 91128 | 91431 | db->flags = savedDbFlags; |
| 91129 | 91432 | } |
| 91130 | 91433 | |
| 91131 | | - /* If the default value of the new column is NULL, then set the file |
| 91434 | + /* If the default value of the new column is NULL, then the file |
| 91132 | 91435 | ** format to 2. If the default value of the new column is not NULL, |
| 91133 | | - ** the file format becomes 3. |
| 91436 | + ** the file format be 3. Back when this feature was first added |
| 91437 | + ** in 2006, we went to the trouble to upgrade the file format to the |
| 91438 | + ** minimum support values. But 10-years on, we can assume that all |
| 91439 | + ** extent versions of SQLite support file-format 4, so we always and |
| 91440 | + ** unconditionally upgrade to 4. |
| 91134 | 91441 | */ |
| 91135 | | - sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); |
| 91442 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, |
| 91443 | + SQLITE_MAX_FILE_FORMAT); |
| 91136 | 91444 | |
| 91137 | 91445 | /* Reload the schema of the modified table. */ |
| 91138 | 91446 | reloadTableSchema(pParse, pTab, pTab->zName); |
| 91139 | 91447 | } |
| 91140 | 91448 | |
| | @@ -91204,11 +91512,11 @@ |
| 91204 | 91512 | nAlloc = (((pNew->nCol-1)/8)*8)+8; |
| 91205 | 91513 | assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); |
| 91206 | 91514 | pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); |
| 91207 | 91515 | pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); |
| 91208 | 91516 | if( !pNew->aCol || !pNew->zName ){ |
| 91209 | | - db->mallocFailed = 1; |
| 91517 | + assert( db->mallocFailed ); |
| 91210 | 91518 | goto exit_begin_add_column; |
| 91211 | 91519 | } |
| 91212 | 91520 | memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); |
| 91213 | 91521 | for(i=0; i<pNew->nCol; i++){ |
| 91214 | 91522 | Column *pCol = &pNew->aCol[i]; |
| | @@ -91549,11 +91857,11 @@ |
| 91549 | 91857 | */ |
| 91550 | 91858 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 91551 | 91859 | static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){ |
| 91552 | 91860 | assert( db!=0 ); |
| 91553 | 91861 | if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); |
| 91554 | | - p->u.aRowid = sqlite3DbMallocRaw(db, n); |
| 91862 | + p->u.aRowid = sqlite3DbMallocRawNN(db, n); |
| 91555 | 91863 | if( p->u.aRowid ){ |
| 91556 | 91864 | p->nRowid = n; |
| 91557 | 91865 | memcpy(p->u.aRowid, pData, n); |
| 91558 | 91866 | }else{ |
| 91559 | 91867 | p->nRowid = 0; |
| | @@ -92351,11 +92659,11 @@ |
| 92351 | 92659 | addrNextRow = sqlite3VdbeCurrentAddr(v); |
| 92352 | 92660 | |
| 92353 | 92661 | if( nColTest>0 ){ |
| 92354 | 92662 | int endDistinctTest = sqlite3VdbeMakeLabel(v); |
| 92355 | 92663 | int *aGotoChng; /* Array of jump instruction addresses */ |
| 92356 | | - aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest); |
| 92664 | + aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest); |
| 92357 | 92665 | if( aGotoChng==0 ) continue; |
| 92358 | 92666 | |
| 92359 | 92667 | /* |
| 92360 | 92668 | ** next_row: |
| 92361 | 92669 | ** regChng = 0 |
| | @@ -92759,11 +93067,11 @@ |
| 92759 | 93067 | /* Index.aiRowEst may already be set here if there are duplicate |
| 92760 | 93068 | ** sqlite_stat1 entries for this index. In that case just clobber |
| 92761 | 93069 | ** the old data with the new instead of allocating a new array. */ |
| 92762 | 93070 | if( pIndex->aiRowEst==0 ){ |
| 92763 | 93071 | pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); |
| 92764 | | - if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; |
| 93072 | + if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db); |
| 92765 | 93073 | } |
| 92766 | 93074 | aiRowEst = pIndex->aiRowEst; |
| 92767 | 93075 | #endif |
| 92768 | 93076 | pIndex->bUnordered = 0; |
| 92769 | 93077 | decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); |
| | @@ -92906,11 +93214,11 @@ |
| 92906 | 93214 | sqlite3_stmt *pStmt = 0; /* An SQL statement being run */ |
| 92907 | 93215 | char *zSql; /* Text of the SQL statement */ |
| 92908 | 93216 | Index *pPrevIdx = 0; /* Previous index in the loop */ |
| 92909 | 93217 | IndexSample *pSample; /* A slot in pIdx->aSample[] */ |
| 92910 | 93218 | |
| 92911 | | - assert( db->lookaside.bEnabled==0 ); |
| 93219 | + assert( db->lookaside.bDisable ); |
| 92912 | 93220 | zSql = sqlite3MPrintf(db, zSql1, zDb); |
| 92913 | 93221 | if( !zSql ){ |
| 92914 | 93222 | return SQLITE_NOMEM; |
| 92915 | 93223 | } |
| 92916 | 93224 | rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); |
| | @@ -93020,11 +93328,11 @@ |
| 93020 | 93328 | ** the Index.aSample[] arrays of all indices. |
| 93021 | 93329 | */ |
| 93022 | 93330 | static int loadStat4(sqlite3 *db, const char *zDb){ |
| 93023 | 93331 | int rc = SQLITE_OK; /* Result codes from subroutines */ |
| 93024 | 93332 | |
| 93025 | | - assert( db->lookaside.bEnabled==0 ); |
| 93333 | + assert( db->lookaside.bDisable ); |
| 93026 | 93334 | if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){ |
| 93027 | 93335 | rc = loadStatTbl(db, 0, |
| 93028 | 93336 | "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", |
| 93029 | 93337 | "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", |
| 93030 | 93338 | zDb |
| | @@ -93102,24 +93410,23 @@ |
| 93102 | 93410 | |
| 93103 | 93411 | |
| 93104 | 93412 | /* Load the statistics from the sqlite_stat4 table. */ |
| 93105 | 93413 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 93106 | 93414 | if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ |
| 93107 | | - int lookasideEnabled = db->lookaside.bEnabled; |
| 93108 | | - db->lookaside.bEnabled = 0; |
| 93415 | + db->lookaside.bDisable++; |
| 93109 | 93416 | rc = loadStat4(db, sInfo.zDatabase); |
| 93110 | | - db->lookaside.bEnabled = lookasideEnabled; |
| 93417 | + db->lookaside.bDisable--; |
| 93111 | 93418 | } |
| 93112 | 93419 | for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ |
| 93113 | 93420 | Index *pIdx = sqliteHashData(i); |
| 93114 | 93421 | sqlite3_free(pIdx->aiRowEst); |
| 93115 | 93422 | pIdx->aiRowEst = 0; |
| 93116 | 93423 | } |
| 93117 | 93424 | #endif |
| 93118 | 93425 | |
| 93119 | 93426 | if( rc==SQLITE_NOMEM ){ |
| 93120 | | - db->mallocFailed = 1; |
| 93427 | + sqlite3OomFault(db); |
| 93121 | 93428 | } |
| 93122 | 93429 | return rc; |
| 93123 | 93430 | } |
| 93124 | 93431 | |
| 93125 | 93432 | |
| | @@ -93236,11 +93543,11 @@ |
| 93236 | 93543 | |
| 93237 | 93544 | /* Allocate the new entry in the db->aDb[] array and initialize the schema |
| 93238 | 93545 | ** hash tables. |
| 93239 | 93546 | */ |
| 93240 | 93547 | if( db->aDb==db->aDbStatic ){ |
| 93241 | | - aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); |
| 93548 | + aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); |
| 93242 | 93549 | if( aNew==0 ) return; |
| 93243 | 93550 | memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); |
| 93244 | 93551 | }else{ |
| 93245 | 93552 | aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); |
| 93246 | 93553 | if( aNew==0 ) return; |
| | @@ -93254,11 +93561,11 @@ |
| 93254 | 93561 | ** or may not be initialized. |
| 93255 | 93562 | */ |
| 93256 | 93563 | flags = db->openFlags; |
| 93257 | 93564 | rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); |
| 93258 | 93565 | if( rc!=SQLITE_OK ){ |
| 93259 | | - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 93566 | + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
| 93260 | 93567 | sqlite3_result_error(context, zErr, -1); |
| 93261 | 93568 | sqlite3_free(zErr); |
| 93262 | 93569 | return; |
| 93263 | 93570 | } |
| 93264 | 93571 | assert( pVfs ); |
| | @@ -93283,11 +93590,12 @@ |
| 93283 | 93590 | pPager = sqlite3BtreePager(aNew->pBt); |
| 93284 | 93591 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 93285 | 93592 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 93286 | 93593 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 93287 | 93594 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 93288 | | - sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 93595 | + sqlite3BtreeSetPagerFlags(aNew->pBt, |
| 93596 | + PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); |
| 93289 | 93597 | #endif |
| 93290 | 93598 | sqlite3BtreeLeave(aNew->pBt); |
| 93291 | 93599 | } |
| 93292 | 93600 | aNew->safety_level = 3; |
| 93293 | 93601 | aNew->zName = sqlite3DbStrDup(db, zName); |
| | @@ -93356,11 +93664,11 @@ |
| 93356 | 93664 | db->aDb[iDb].pSchema = 0; |
| 93357 | 93665 | } |
| 93358 | 93666 | sqlite3ResetAllSchemasOfConnection(db); |
| 93359 | 93667 | db->nDb = iDb; |
| 93360 | 93668 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 93361 | | - db->mallocFailed = 1; |
| 93669 | + sqlite3OomFault(db); |
| 93362 | 93670 | sqlite3DbFree(db, zErrDyn); |
| 93363 | 93671 | zErrDyn = sqlite3MPrintf(db, "out of memory"); |
| 93364 | 93672 | }else if( zErrDyn==0 ){ |
| 93365 | 93673 | zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); |
| 93366 | 93674 | } |
| | @@ -94053,11 +94361,11 @@ |
| 94053 | 94361 | p->iTab = iTab; |
| 94054 | 94362 | p->isWriteLock = isWriteLock; |
| 94055 | 94363 | p->zName = zName; |
| 94056 | 94364 | }else{ |
| 94057 | 94365 | pToplevel->nTableLock = 0; |
| 94058 | | - pToplevel->db->mallocFailed = 1; |
| 94366 | + sqlite3OomFault(pToplevel->db); |
| 94059 | 94367 | } |
| 94060 | 94368 | } |
| 94061 | 94369 | |
| 94062 | 94370 | /* |
| 94063 | 94371 | ** Code an OP_TableLock instruction for each table locked by the |
| | @@ -94901,11 +95209,11 @@ |
| 94901 | 95209 | } |
| 94902 | 95210 | } |
| 94903 | 95211 | |
| 94904 | 95212 | pTable = sqlite3DbMallocZero(db, sizeof(Table)); |
| 94905 | 95213 | if( pTable==0 ){ |
| 94906 | | - db->mallocFailed = 1; |
| 95214 | + assert( db->mallocFailed ); |
| 94907 | 95215 | pParse->rc = SQLITE_NOMEM; |
| 94908 | 95216 | pParse->nErr++; |
| 94909 | 95217 | goto begin_table_error; |
| 94910 | 95218 | } |
| 94911 | 95219 | pTable->zName = zName; |
| | @@ -94958,14 +95266,12 @@ |
| 94958 | 95266 | sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); |
| 94959 | 95267 | sqlite3VdbeUsesBtree(v, iDb); |
| 94960 | 95268 | addr1 = sqlite3VdbeAddOp1(v, OP_If, reg3); VdbeCoverage(v); |
| 94961 | 95269 | fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? |
| 94962 | 95270 | 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); |
| 95271 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, fileFormat); |
| 95272 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db)); |
| 94967 | 95273 | sqlite3VdbeJumpHere(v, addr1); |
| 94968 | 95274 | |
| 94969 | 95275 | /* This just creates a place-holder record in the sqlite_master table. |
| 94970 | 95276 | ** The record created does not contain anything yet. It will be replaced |
| 94971 | 95277 | ** by the real entry in code generated at sqlite3EndTable(). |
| | @@ -95446,17 +95752,15 @@ |
| 95446 | 95752 | ** set back to prior value. But schema changes are infrequent |
| 95447 | 95753 | ** and the probability of hitting the same cookie value is only |
| 95448 | 95754 | ** 1 chance in 2^32. So we're safe enough. |
| 95449 | 95755 | */ |
| 95450 | 95756 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ |
| 95451 | | - int r1 = sqlite3GetTempReg(pParse); |
| 95452 | 95757 | sqlite3 *db = pParse->db; |
| 95453 | 95758 | Vdbe *v = pParse->pVdbe; |
| 95454 | 95759 | 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); |
| 95760 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, |
| 95761 | + db->aDb[iDb].pSchema->schema_cookie+1); |
| 95458 | 95762 | } |
| 95459 | 95763 | |
| 95460 | 95764 | /* |
| 95461 | 95765 | ** Measure the number of characters needed to output the given |
| 95462 | 95766 | ** identifier. The number returned includes any quotes used |
| | @@ -95534,11 +95838,11 @@ |
| 95534 | 95838 | zEnd = "\n)"; |
| 95535 | 95839 | } |
| 95536 | 95840 | n += 35 + 6*p->nCol; |
| 95537 | 95841 | zStmt = sqlite3DbMallocRaw(0, n); |
| 95538 | 95842 | if( zStmt==0 ){ |
| 95539 | | - db->mallocFailed = 1; |
| 95843 | + sqlite3OomFault(db); |
| 95540 | 95844 | return 0; |
| 95541 | 95845 | } |
| 95542 | 95846 | sqlite3_snprintf(n, zStmt, "CREATE TABLE "); |
| 95543 | 95847 | k = sqlite3Strlen30(zStmt); |
| 95544 | 95848 | identPut(zStmt, &k, p->zName); |
| | @@ -95683,12 +95987,11 @@ |
| 95683 | 95987 | ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. |
| 95684 | 95988 | */ |
| 95685 | 95989 | if( pTab->iPKey>=0 ){ |
| 95686 | 95990 | ExprList *pList; |
| 95687 | 95991 | Token ipkToken; |
| 95688 | | - ipkToken.z = pTab->aCol[pTab->iPKey].zName; |
| 95689 | | - ipkToken.n = sqlite3Strlen30(ipkToken.z); |
| 95992 | + sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName); |
| 95690 | 95993 | pList = sqlite3ExprListAppend(pParse, 0, |
| 95691 | 95994 | sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); |
| 95692 | 95995 | if( pList==0 ) return; |
| 95693 | 95996 | pList->a[0].sortOrder = pParse->iPkSortOrder; |
| 95694 | 95997 | assert( pParse->pNewTable==pTab ); |
| | @@ -95934,11 +96237,11 @@ |
| 95934 | 96237 | pParse->nTab = 2; |
| 95935 | 96238 | addrTop = sqlite3VdbeCurrentAddr(v) + 1; |
| 95936 | 96239 | sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); |
| 95937 | 96240 | sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); |
| 95938 | 96241 | sqlite3Select(pParse, pSelect, &dest); |
| 95939 | | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); |
| 96242 | + sqlite3VdbeEndCoroutine(v, regYield); |
| 95940 | 96243 | sqlite3VdbeJumpHere(v, addrTop - 1); |
| 95941 | 96244 | if( pParse->nErr ) return; |
| 95942 | 96245 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); |
| 95943 | 96246 | if( pSelTab==0 ) return; |
| 95944 | 96247 | assert( p->aCol==0 ); |
| | @@ -96018,11 +96321,11 @@ |
| 96018 | 96321 | Schema *pSchema = p->pSchema; |
| 96019 | 96322 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 96020 | 96323 | pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); |
| 96021 | 96324 | if( pOld ){ |
| 96022 | 96325 | assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 96023 | | - db->mallocFailed = 1; |
| 96326 | + sqlite3OomFault(db); |
| 96024 | 96327 | return; |
| 96025 | 96328 | } |
| 96026 | 96329 | pParse->pNewTable = 0; |
| 96027 | 96330 | db->flags |= SQLITE_InternChanges; |
| 96028 | 96331 | |
| | @@ -96122,11 +96425,10 @@ |
| 96122 | 96425 | Select *pSel; /* Copy of the SELECT that implements the view */ |
| 96123 | 96426 | int nErr = 0; /* Number of errors encountered */ |
| 96124 | 96427 | int n; /* Temporarily holds the number of cursors assigned */ |
| 96125 | 96428 | sqlite3 *db = pParse->db; /* Database connection for malloc errors */ |
| 96126 | 96429 | sqlite3_xauth xAuth; /* Saved xAuth pointer */ |
| 96127 | | - u8 bEnabledLA; /* Saved db->lookaside.bEnabled state */ |
| 96128 | 96430 | |
| 96129 | 96431 | assert( pTable ); |
| 96130 | 96432 | |
| 96131 | 96433 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 96132 | 96434 | if( sqlite3VtabCallConnect(pParse, pTable) ){ |
| | @@ -96168,30 +96470,31 @@ |
| 96168 | 96470 | ** to the elements of the FROM clause. But we do not want these changes |
| 96169 | 96471 | ** to be permanent. So the computation is done on a copy of the SELECT |
| 96170 | 96472 | ** statement that defines the view. |
| 96171 | 96473 | */ |
| 96172 | 96474 | assert( pTable->pSelect ); |
| 96173 | | - bEnabledLA = db->lookaside.bEnabled; |
| 96174 | 96475 | if( pTable->pCheck ){ |
| 96175 | | - db->lookaside.bEnabled = 0; |
| 96476 | + db->lookaside.bDisable++; |
| 96176 | 96477 | sqlite3ColumnsFromExprList(pParse, pTable->pCheck, |
| 96177 | 96478 | &pTable->nCol, &pTable->aCol); |
| 96479 | + db->lookaside.bDisable--; |
| 96178 | 96480 | }else{ |
| 96179 | 96481 | pSel = sqlite3SelectDup(db, pTable->pSelect, 0); |
| 96180 | 96482 | if( pSel ){ |
| 96181 | 96483 | n = pParse->nTab; |
| 96182 | 96484 | sqlite3SrcListAssignCursors(pParse, pSel->pSrc); |
| 96183 | 96485 | pTable->nCol = -1; |
| 96184 | | - db->lookaside.bEnabled = 0; |
| 96486 | + db->lookaside.bDisable++; |
| 96185 | 96487 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 96186 | 96488 | xAuth = db->xAuth; |
| 96187 | 96489 | db->xAuth = 0; |
| 96188 | 96490 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96189 | 96491 | db->xAuth = xAuth; |
| 96190 | 96492 | #else |
| 96191 | 96493 | pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); |
| 96192 | 96494 | #endif |
| 96495 | + db->lookaside.bDisable--; |
| 96193 | 96496 | pParse->nTab = n; |
| 96194 | 96497 | if( pSelTab ){ |
| 96195 | 96498 | assert( pTable->aCol==0 ); |
| 96196 | 96499 | pTable->nCol = pSelTab->nCol; |
| 96197 | 96500 | pTable->aCol = pSelTab->aCol; |
| | @@ -96206,11 +96509,10 @@ |
| 96206 | 96509 | sqlite3SelectDelete(db, pSel); |
| 96207 | 96510 | } else { |
| 96208 | 96511 | nErr++; |
| 96209 | 96512 | } |
| 96210 | 96513 | } |
| 96211 | | - db->lookaside.bEnabled = bEnabledLA; |
| 96212 | 96514 | pTable->pSchema->schemaFlags |= DB_UnresetViews; |
| 96213 | 96515 | #endif /* SQLITE_OMIT_VIEW */ |
| 96214 | 96516 | return nErr; |
| 96215 | 96517 | } |
| 96216 | 96518 | #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ |
| | @@ -96672,11 +96974,11 @@ |
| 96672 | 96974 | assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); |
| 96673 | 96975 | pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, |
| 96674 | 96976 | pFKey->zTo, (void *)pFKey |
| 96675 | 96977 | ); |
| 96676 | 96978 | if( pNextTo==pFKey ){ |
| 96677 | | - db->mallocFailed = 1; |
| 96979 | + sqlite3OomFault(db); |
| 96678 | 96980 | goto fk_end; |
| 96679 | 96981 | } |
| 96680 | 96982 | if( pNextTo ){ |
| 96681 | 96983 | assert( pNextTo->pPrevTo==0 ); |
| 96682 | 96984 | pFKey->pNextTo = pNextTo; |
| | @@ -97032,12 +97334,11 @@ |
| 97032 | 97334 | ** key out of the last column added to the table under construction. |
| 97033 | 97335 | ** So create a fake list to simulate this. |
| 97034 | 97336 | */ |
| 97035 | 97337 | if( pList==0 ){ |
| 97036 | 97338 | Token prevCol; |
| 97037 | | - prevCol.z = pTab->aCol[pTab->nCol-1].zName; |
| 97038 | | - prevCol.n = sqlite3Strlen30(prevCol.z); |
| 97339 | + sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName); |
| 97039 | 97340 | pList = sqlite3ExprListAppend(pParse, 0, |
| 97040 | 97341 | sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); |
| 97041 | 97342 | if( pList==0 ) goto exit_create_index; |
| 97042 | 97343 | assert( pList->nExpr==1 ); |
| 97043 | 97344 | sqlite3ExprListSetSortOrder(pList, sortOrder); |
| | @@ -97255,11 +97556,11 @@ |
| 97255 | 97556 | assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); |
| 97256 | 97557 | p = sqlite3HashInsert(&pIndex->pSchema->idxHash, |
| 97257 | 97558 | pIndex->zName, pIndex); |
| 97258 | 97559 | if( p ){ |
| 97259 | 97560 | assert( p==pIndex ); /* Malloc must have failed */ |
| 97260 | | - db->mallocFailed = 1; |
| 97561 | + sqlite3OomFault(db); |
| 97261 | 97562 | goto exit_create_index; |
| 97262 | 97563 | } |
| 97263 | 97564 | db->flags |= SQLITE_InternChanges; |
| 97264 | 97565 | if( pTblName!=0 ){ |
| 97265 | 97566 | pIndex->tnum = db->init.newTnum; |
| | @@ -97684,12 +97985,13 @@ |
| 97684 | 97985 | Token *pTable, /* Table to append */ |
| 97685 | 97986 | Token *pDatabase /* Database of the table */ |
| 97686 | 97987 | ){ |
| 97687 | 97988 | struct SrcList_item *pItem; |
| 97688 | 97989 | assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ |
| 97990 | + assert( db!=0 ); |
| 97689 | 97991 | if( pList==0 ){ |
| 97690 | | - pList = sqlite3DbMallocRaw(db, sizeof(SrcList) ); |
| 97992 | + pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) ); |
| 97691 | 97993 | if( pList==0 ) return 0; |
| 97692 | 97994 | pList->nAlloc = 1; |
| 97693 | 97995 | pList->nSrc = 0; |
| 97694 | 97996 | } |
| 97695 | 97997 | pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); |
| | @@ -97869,21 +98171,20 @@ |
| 97869 | 98171 | p->a[0].fg.jointype = 0; |
| 97870 | 98172 | } |
| 97871 | 98173 | } |
| 97872 | 98174 | |
| 97873 | 98175 | /* |
| 97874 | | -** Begin a transaction |
| 98176 | +** Generate VDBE code for a BEGIN statement. |
| 97875 | 98177 | */ |
| 97876 | 98178 | SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ |
| 97877 | 98179 | sqlite3 *db; |
| 97878 | 98180 | Vdbe *v; |
| 97879 | 98181 | int i; |
| 97880 | 98182 | |
| 97881 | 98183 | assert( pParse!=0 ); |
| 97882 | 98184 | db = pParse->db; |
| 97883 | 98185 | assert( db!=0 ); |
| 97884 | | -/* if( db->aDb[0].pBt==0 ) return; */ |
| 97885 | 98186 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ |
| 97886 | 98187 | return; |
| 97887 | 98188 | } |
| 97888 | 98189 | v = sqlite3GetVdbe(pParse); |
| 97889 | 98190 | if( !v ) return; |
| | @@ -97891,15 +98192,15 @@ |
| 97891 | 98192 | for(i=0; i<db->nDb; i++){ |
| 97892 | 98193 | sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); |
| 97893 | 98194 | sqlite3VdbeUsesBtree(v, i); |
| 97894 | 98195 | } |
| 97895 | 98196 | } |
| 97896 | | - sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0); |
| 98197 | + sqlite3VdbeAddOp0(v, OP_AutoCommit); |
| 97897 | 98198 | } |
| 97898 | 98199 | |
| 97899 | 98200 | /* |
| 97900 | | -** Commit a transaction |
| 98201 | +** Generate VDBE code for a COMMIT statement. |
| 97901 | 98202 | */ |
| 97902 | 98203 | SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){ |
| 97903 | 98204 | Vdbe *v; |
| 97904 | 98205 | |
| 97905 | 98206 | assert( pParse!=0 ); |
| | @@ -97907,16 +98208,16 @@ |
| 97907 | 98208 | if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ |
| 97908 | 98209 | return; |
| 97909 | 98210 | } |
| 97910 | 98211 | v = sqlite3GetVdbe(pParse); |
| 97911 | 98212 | if( v ){ |
| 97912 | | - sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); |
| 98213 | + sqlite3VdbeAddOp1(v, OP_AutoCommit, 1); |
| 97913 | 98214 | } |
| 97914 | 98215 | } |
| 97915 | 98216 | |
| 97916 | 98217 | /* |
| 97917 | | -** Rollback a transaction |
| 98218 | +** Generate VDBE code for a ROLLBACK statement. |
| 97918 | 98219 | */ |
| 97919 | 98220 | SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){ |
| 97920 | 98221 | Vdbe *v; |
| 97921 | 98222 | |
| 97922 | 98223 | assert( pParse!=0 ); |
| | @@ -97974,11 +98275,11 @@ |
| 97974 | 98275 | return 1; |
| 97975 | 98276 | } |
| 97976 | 98277 | db->aDb[1].pBt = pBt; |
| 97977 | 98278 | assert( db->aDb[1].pSchema ); |
| 97978 | 98279 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ |
| 97979 | | - db->mallocFailed = 1; |
| 98280 | + sqlite3OomFault(db); |
| 97980 | 98281 | return 1; |
| 97981 | 98282 | } |
| 97982 | 98283 | } |
| 97983 | 98284 | return 0; |
| 97984 | 98285 | } |
| | @@ -98109,18 +98410,18 @@ |
| 98109 | 98410 | StrAccum errMsg; |
| 98110 | 98411 | Table *pTab = pIdx->pTable; |
| 98111 | 98412 | |
| 98112 | 98413 | sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); |
| 98113 | 98414 | if( pIdx->aColExpr ){ |
| 98114 | | - sqlite3XPrintf(&errMsg, 0, "index '%q'", pIdx->zName); |
| 98415 | + sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); |
| 98115 | 98416 | }else{ |
| 98116 | 98417 | for(j=0; j<pIdx->nKeyCol; j++){ |
| 98117 | 98418 | char *zCol; |
| 98118 | 98419 | assert( pIdx->aiColumn[j]>=0 ); |
| 98119 | 98420 | zCol = pTab->aCol[pIdx->aiColumn[j]].zName; |
| 98120 | 98421 | if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); |
| 98121 | | - sqlite3XPrintf(&errMsg, 0, "%s.%s", pTab->zName, zCol); |
| 98422 | + sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol); |
| 98122 | 98423 | } |
| 98123 | 98424 | } |
| 98124 | 98425 | zErr = sqlite3StrAccumFinish(&errMsg); |
| 98125 | 98426 | sqlite3HaltConstraint(pParse, |
| 98126 | 98427 | IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY |
| | @@ -98349,14 +98650,13 @@ |
| 98349 | 98650 | int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); |
| 98350 | 98651 | pNew = sqlite3DbRealloc(db, pWith, nByte); |
| 98351 | 98652 | }else{ |
| 98352 | 98653 | pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); |
| 98353 | 98654 | } |
| 98354 | | - assert( zName!=0 || pNew==0 ); |
| 98355 | | - assert( db->mallocFailed==0 || pNew==0 ); |
| 98655 | + assert( (pNew!=0 && zName!=0) || db->mallocFailed ); |
| 98356 | 98656 | |
| 98357 | | - if( pNew==0 ){ |
| 98657 | + if( db->mallocFailed ){ |
| 98358 | 98658 | sqlite3ExprListDelete(db, pArglist); |
| 98359 | 98659 | sqlite3SelectDelete(db, pQuery); |
| 98360 | 98660 | sqlite3DbFree(db, zName); |
| 98361 | 98661 | pNew = pWith; |
| 98362 | 98662 | }else{ |
| | @@ -98566,11 +98866,11 @@ |
| 98566 | 98866 | ** return the pColl pointer to be deleted (because it wasn't added |
| 98567 | 98867 | ** to the hash table). |
| 98568 | 98868 | */ |
| 98569 | 98869 | assert( pDel==0 || pDel==pColl ); |
| 98570 | 98870 | if( pDel!=0 ){ |
| 98571 | | - db->mallocFailed = 1; |
| 98871 | + sqlite3OomFault(db); |
| 98572 | 98872 | sqlite3DbFree(db, pDel); |
| 98573 | 98873 | pColl = 0; |
| 98574 | 98874 | } |
| 98575 | 98875 | } |
| 98576 | 98876 | } |
| | @@ -98854,11 +99154,11 @@ |
| 98854 | 99154 | p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); |
| 98855 | 99155 | }else{ |
| 98856 | 99156 | p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); |
| 98857 | 99157 | } |
| 98858 | 99158 | if( !p ){ |
| 98859 | | - db->mallocFailed = 1; |
| 99159 | + sqlite3OomFault(db); |
| 98860 | 99160 | }else if ( 0==p->file_format ){ |
| 98861 | 99161 | sqlite3HashInit(&p->tblHash); |
| 98862 | 99162 | sqlite3HashInit(&p->idxHash); |
| 98863 | 99163 | sqlite3HashInit(&p->trigHash); |
| 98864 | 99164 | sqlite3HashInit(&p->fkeyHash); |
| | @@ -99308,11 +99608,11 @@ |
| 99308 | 99608 | if( eOnePass!=ONEPASS_OFF ){ |
| 99309 | 99609 | /* For ONEPASS, no need to store the rowid/primary-key. There is only |
| 99310 | 99610 | ** one, so just keep it in its register(s) and fall through to the |
| 99311 | 99611 | ** delete code. */ |
| 99312 | 99612 | nKey = nPk; /* OP_Found will use an unpacked key */ |
| 99313 | | - aToOpen = sqlite3DbMallocRaw(db, nIdx+2); |
| 99613 | + aToOpen = sqlite3DbMallocRawNN(db, nIdx+2); |
| 99314 | 99614 | if( aToOpen==0 ){ |
| 99315 | 99615 | sqlite3WhereEnd(pWInfo); |
| 99316 | 99616 | goto delete_from_cleanup; |
| 99317 | 99617 | } |
| 99318 | 99618 | memset(aToOpen, 1, nIdx+1); |
| | @@ -99348,17 +99648,16 @@ |
| 99348 | 99648 | ** only effect this statement has is to fire the INSTEAD OF |
| 99349 | 99649 | ** triggers. |
| 99350 | 99650 | */ |
| 99351 | 99651 | if( !isView ){ |
| 99352 | 99652 | int iAddrOnce = 0; |
| 99353 | | - u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE); |
| 99354 | 99653 | if( eOnePass==ONEPASS_MULTI ){ |
| 99355 | 99654 | iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); |
| 99356 | 99655 | } |
| 99357 | 99656 | testcase( IsVirtual(pTab) ); |
| 99358 | | - sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, |
| 99359 | | - aToOpen, &iDataCur, &iIdxCur); |
| 99657 | + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, |
| 99658 | + iTabCur, aToOpen, &iDataCur, &iIdxCur); |
| 99360 | 99659 | assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); |
| 99361 | 99660 | assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); |
| 99362 | 99661 | if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); |
| 99363 | 99662 | } |
| 99364 | 99663 | |
| | @@ -99587,19 +99886,24 @@ |
| 99587 | 99886 | |
| 99588 | 99887 | /* Delete the index and table entries. Skip this step if pTab is really |
| 99589 | 99888 | ** a view (in which case the only effect of the DELETE statement is to |
| 99590 | 99889 | ** fire the INSTEAD OF triggers). */ |
| 99591 | 99890 | if( pTab->pSelect==0 ){ |
| 99891 | + u8 p5 = 0; |
| 99592 | 99892 | sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); |
| 99593 | 99893 | sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); |
| 99594 | 99894 | if( count ){ |
| 99595 | 99895 | sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); |
| 99596 | 99896 | } |
| 99897 | + if( eMode!=ONEPASS_OFF ){ |
| 99898 | + sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); |
| 99899 | + } |
| 99597 | 99900 | if( iIdxNoSeek>=0 ){ |
| 99598 | 99901 | sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); |
| 99599 | 99902 | } |
| 99600 | | - sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI); |
| 99903 | + if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; |
| 99904 | + sqlite3VdbeChangeP5(v, p5); |
| 99601 | 99905 | } |
| 99602 | 99906 | |
| 99603 | 99907 | /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
| 99604 | 99908 | ** handle rows (possibly in other tables) that refer via a foreign key |
| 99605 | 99909 | ** to the row just deleted. */ |
| | @@ -100005,11 +100309,12 @@ |
| 100005 | 100309 | if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
| 100006 | 100310 | x.nArg = argc-1; |
| 100007 | 100311 | x.nUsed = 0; |
| 100008 | 100312 | x.apArg = argv+1; |
| 100009 | 100313 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 100010 | | - sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); |
| 100314 | + str.printfFlags = SQLITE_PRINTF_SQLFUNC; |
| 100315 | + sqlite3XPrintf(&str, zFormat, &x); |
| 100011 | 100316 | n = str.nChar; |
| 100012 | 100317 | sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, |
| 100013 | 100318 | SQLITE_DYNAMIC); |
| 100014 | 100319 | } |
| 100015 | 100320 | } |
| | @@ -101380,11 +101685,11 @@ |
| 101380 | 101685 | */ |
| 101381 | 101686 | SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ |
| 101382 | 101687 | int rc = sqlite3_overload_function(db, "MATCH", 2); |
| 101383 | 101688 | assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); |
| 101384 | 101689 | if( rc==SQLITE_NOMEM ){ |
| 101385 | | - db->mallocFailed = 1; |
| 101690 | + sqlite3OomFault(db); |
| 101386 | 101691 | } |
| 101387 | 101692 | } |
| 101388 | 101693 | |
| 101389 | 101694 | /* |
| 101390 | 101695 | ** Set the LIKEOPT flag on the 2-argument function with the given name. |
| | @@ -101795,11 +102100,11 @@ |
| 101795 | 102100 | if( !zKey ) return 0; |
| 101796 | 102101 | if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; |
| 101797 | 102102 | } |
| 101798 | 102103 | }else if( paiCol ){ |
| 101799 | 102104 | assert( nCol>1 ); |
| 101800 | | - aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int)); |
| 102105 | + aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); |
| 101801 | 102106 | if( !aiCol ) return 1; |
| 101802 | 102107 | *paiCol = aiCol; |
| 101803 | 102108 | } |
| 101804 | 102109 | |
| 101805 | 102110 | for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ |
| | @@ -102741,11 +103046,10 @@ |
| 102741 | 103046 | |
| 102742 | 103047 | action = pFKey->aAction[iAction]; |
| 102743 | 103048 | pTrigger = pFKey->apTrigger[iAction]; |
| 102744 | 103049 | |
| 102745 | 103050 | if( action!=OE_None && !pTrigger ){ |
| 102746 | | - u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ |
| 102747 | 103051 | char const *zFrom; /* Name of child table */ |
| 102748 | 103052 | int nFrom; /* Length in bytes of zFrom */ |
| 102749 | 103053 | Index *pIdx = 0; /* Parent key index for this FK */ |
| 102750 | 103054 | int *aiCol = 0; /* child table cols -> parent key cols */ |
| 102751 | 103055 | TriggerStep *pStep = 0; /* First (only) step of trigger program */ |
| | @@ -102768,15 +103072,13 @@ |
| 102768 | 103072 | |
| 102769 | 103073 | iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
| 102770 | 103074 | assert( iFromCol>=0 ); |
| 102771 | 103075 | assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
| 102772 | 103076 | 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); |
| 103077 | + sqlite3TokenInit(&tToCol, |
| 103078 | + pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName); |
| 103079 | + sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName); |
| 102778 | 103080 | |
| 102779 | 103081 | /* Create the expression "OLD.zToCol = zFromCol". It is important |
| 102780 | 103082 | ** that the "OLD.zToCol" term is on the LHS of the = operator, so |
| 102781 | 103083 | ** that the affinity and collation sequence associated with the |
| 102782 | 103084 | ** parent table are used for the comparison. */ |
| | @@ -102852,12 +103154,11 @@ |
| 102852 | 103154 | ); |
| 102853 | 103155 | pWhere = 0; |
| 102854 | 103156 | } |
| 102855 | 103157 | |
| 102856 | 103158 | /* Disable lookaside memory allocation */ |
| 102857 | | - enableLookaside = db->lookaside.bEnabled; |
| 102858 | | - db->lookaside.bEnabled = 0; |
| 103159 | + db->lookaside.bDisable++; |
| 102859 | 103160 | |
| 102860 | 103161 | pTrigger = (Trigger *)sqlite3DbMallocZero(db, |
| 102861 | 103162 | sizeof(Trigger) + /* struct Trigger */ |
| 102862 | 103163 | sizeof(TriggerStep) + /* Single step in trigger program */ |
| 102863 | 103164 | nFrom + 1 /* Space for pStep->zTarget */ |
| | @@ -102875,11 +103176,11 @@ |
| 102875 | 103176 | pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
| 102876 | 103177 | } |
| 102877 | 103178 | } |
| 102878 | 103179 | |
| 102879 | 103180 | /* Re-enable the lookaside buffer, if it was disabled earlier. */ |
| 102880 | | - db->lookaside.bEnabled = enableLookaside; |
| 103181 | + db->lookaside.bDisable--; |
| 102881 | 103182 | |
| 102882 | 103183 | sqlite3ExprDelete(db, pWhere); |
| 102883 | 103184 | sqlite3ExprDelete(db, pWhen); |
| 102884 | 103185 | sqlite3ExprListDelete(db, pList); |
| 102885 | 103186 | sqlite3SelectDelete(db, pSelect); |
| | @@ -103070,11 +103371,11 @@ |
| 103070 | 103371 | */ |
| 103071 | 103372 | int n; |
| 103072 | 103373 | Table *pTab = pIdx->pTable; |
| 103073 | 103374 | pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); |
| 103074 | 103375 | if( !pIdx->zColAff ){ |
| 103075 | | - db->mallocFailed = 1; |
| 103376 | + sqlite3OomFault(db); |
| 103076 | 103377 | return 0; |
| 103077 | 103378 | } |
| 103078 | 103379 | for(n=0; n<pIdx->nColumn; n++){ |
| 103079 | 103380 | i16 x = pIdx->aiColumn[n]; |
| 103080 | 103381 | if( x>=0 ){ |
| | @@ -103121,11 +103422,11 @@ |
| 103121 | 103422 | char *zColAff = pTab->zColAff; |
| 103122 | 103423 | if( zColAff==0 ){ |
| 103123 | 103424 | sqlite3 *db = sqlite3VdbeDb(v); |
| 103124 | 103425 | zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); |
| 103125 | 103426 | if( !zColAff ){ |
| 103126 | | - db->mallocFailed = 1; |
| 103427 | + sqlite3OomFault(db); |
| 103127 | 103428 | return; |
| 103128 | 103429 | } |
| 103129 | 103430 | |
| 103130 | 103431 | for(i=0; i<pTab->nCol; i++){ |
| 103131 | 103432 | zColAff[i] = pTab->aCol[i].affinity; |
| | @@ -103217,11 +103518,11 @@ |
| 103217 | 103518 | AutoincInfo *pInfo; |
| 103218 | 103519 | |
| 103219 | 103520 | pInfo = pToplevel->pAinc; |
| 103220 | 103521 | while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } |
| 103221 | 103522 | if( pInfo==0 ){ |
| 103222 | | - pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo)); |
| 103523 | + pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); |
| 103223 | 103524 | if( pInfo==0 ) return 0; |
| 103224 | 103525 | pInfo->pNext = pToplevel->pAinc; |
| 103225 | 103526 | pToplevel->pAinc = pInfo; |
| 103226 | 103527 | pInfo->pTab = pTab; |
| 103227 | 103528 | pInfo->iDb = iDb; |
| | @@ -103241,47 +103542,59 @@ |
| 103241 | 103542 | SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ |
| 103242 | 103543 | AutoincInfo *p; /* Information about an AUTOINCREMENT */ |
| 103243 | 103544 | sqlite3 *db = pParse->db; /* The database connection */ |
| 103244 | 103545 | Db *pDb; /* Database only autoinc table */ |
| 103245 | 103546 | int memId; /* Register holding max rowid */ |
| 103246 | | - int addr; /* A VDBE address */ |
| 103247 | 103547 | Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
| 103248 | 103548 | |
| 103249 | 103549 | /* This routine is never called during trigger-generation. It is |
| 103250 | 103550 | ** only called from the top-level */ |
| 103251 | 103551 | assert( pParse->pTriggerTab==0 ); |
| 103252 | 103552 | assert( sqlite3IsToplevel(pParse) ); |
| 103253 | 103553 | |
| 103254 | 103554 | assert( v ); /* We failed long ago if this is not so */ |
| 103255 | 103555 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103556 | + static const int iLn = VDBE_OFFSET_LINENO(2); |
| 103557 | + static const VdbeOpList autoInc[] = { |
| 103558 | + /* 0 */ {OP_Null, 0, 0, 0}, |
| 103559 | + /* 1 */ {OP_Rewind, 0, 9, 0}, |
| 103560 | + /* 2 */ {OP_Column, 0, 0, 0}, |
| 103561 | + /* 3 */ {OP_Ne, 0, 7, 0}, |
| 103562 | + /* 4 */ {OP_Rowid, 0, 0, 0}, |
| 103563 | + /* 5 */ {OP_Column, 0, 1, 0}, |
| 103564 | + /* 6 */ {OP_Goto, 0, 9, 0}, |
| 103565 | + /* 7 */ {OP_Next, 0, 2, 0}, |
| 103566 | + /* 8 */ {OP_Integer, 0, 0, 0}, |
| 103567 | + /* 9 */ {OP_Close, 0, 0, 0} |
| 103568 | + }; |
| 103569 | + VdbeOp *aOp; |
| 103256 | 103570 | pDb = &db->aDb[p->iDb]; |
| 103257 | 103571 | memId = p->regCtr; |
| 103258 | 103572 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103259 | 103573 | sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); |
| 103260 | | - sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); |
| 103261 | | - addr = sqlite3VdbeCurrentAddr(v); |
| 103262 | 103574 | 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); |
| 103575 | + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); |
| 103576 | + if( aOp==0 ) break; |
| 103577 | + aOp[0].p2 = memId; |
| 103578 | + aOp[0].p3 = memId+1; |
| 103579 | + aOp[2].p3 = memId; |
| 103580 | + aOp[3].p1 = memId-1; |
| 103581 | + aOp[3].p3 = memId; |
| 103582 | + aOp[3].p5 = SQLITE_JUMPIFNULL; |
| 103583 | + aOp[4].p2 = memId+1; |
| 103584 | + aOp[5].p3 = memId; |
| 103585 | + aOp[8].p2 = memId; |
| 103273 | 103586 | } |
| 103274 | 103587 | } |
| 103275 | 103588 | |
| 103276 | 103589 | /* |
| 103277 | 103590 | ** Update the maximum rowid for an autoincrement calculation. |
| 103278 | 103591 | ** |
| 103279 | | -** This routine should be called when the top of the stack holds a |
| 103592 | +** This routine should be called when the regRowid register holds a |
| 103280 | 103593 | ** new rowid that is about to be inserted. If that new rowid is |
| 103281 | 103594 | ** larger than the maximum rowid in the memId memory cell, then the |
| 103282 | | -** memory cell is updated. The stack is unchanged. |
| 103595 | +** memory cell is updated. |
| 103283 | 103596 | */ |
| 103284 | 103597 | static void autoIncStep(Parse *pParse, int memId, int regRowid){ |
| 103285 | 103598 | if( memId>0 ){ |
| 103286 | 103599 | sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); |
| 103287 | 103600 | } |
| | @@ -103292,34 +103605,47 @@ |
| 103292 | 103605 | ** maximum rowid values back into the sqlite_sequence register. |
| 103293 | 103606 | ** Every statement that might do an INSERT into an autoincrement |
| 103294 | 103607 | ** table (either directly or through triggers) needs to call this |
| 103295 | 103608 | ** routine just before the "exit" code. |
| 103296 | 103609 | */ |
| 103297 | | -SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ |
| 103610 | +static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ |
| 103298 | 103611 | AutoincInfo *p; |
| 103299 | 103612 | Vdbe *v = pParse->pVdbe; |
| 103300 | 103613 | sqlite3 *db = pParse->db; |
| 103301 | 103614 | |
| 103302 | 103615 | assert( v ); |
| 103303 | 103616 | for(p = pParse->pAinc; p; p = p->pNext){ |
| 103617 | + static const int iLn = VDBE_OFFSET_LINENO(2); |
| 103618 | + static const VdbeOpList autoIncEnd[] = { |
| 103619 | + /* 0 */ {OP_NotNull, 0, 2, 0}, |
| 103620 | + /* 1 */ {OP_NewRowid, 0, 0, 0}, |
| 103621 | + /* 2 */ {OP_MakeRecord, 0, 2, 0}, |
| 103622 | + /* 3 */ {OP_Insert, 0, 0, 0}, |
| 103623 | + /* 4 */ {OP_Close, 0, 0, 0} |
| 103624 | + }; |
| 103625 | + VdbeOp *aOp; |
| 103304 | 103626 | Db *pDb = &db->aDb[p->iDb]; |
| 103305 | | - int addr1; |
| 103306 | 103627 | int iRec; |
| 103307 | 103628 | int memId = p->regCtr; |
| 103308 | 103629 | |
| 103309 | 103630 | iRec = sqlite3GetTempReg(pParse); |
| 103310 | 103631 | assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
| 103311 | 103632 | 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); |
| 103633 | + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); |
| 103634 | + if( aOp==0 ) break; |
| 103635 | + aOp[0].p1 = memId+1; |
| 103636 | + aOp[1].p2 = memId+1; |
| 103637 | + aOp[2].p1 = memId-1; |
| 103638 | + aOp[2].p3 = iRec; |
| 103639 | + aOp[3].p2 = iRec; |
| 103640 | + aOp[3].p3 = memId+1; |
| 103641 | + aOp[3].p5 = OPFLAG_APPEND; |
| 103319 | 103642 | sqlite3ReleaseTempReg(pParse, iRec); |
| 103320 | 103643 | } |
| 103644 | +} |
| 103645 | +SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ |
| 103646 | + if( pParse->pAinc ) autoIncrementEnd(pParse); |
| 103321 | 103647 | } |
| 103322 | 103648 | #else |
| 103323 | 103649 | /* |
| 103324 | 103650 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines |
| 103325 | 103651 | ** above are all no-ops |
| | @@ -103647,11 +103973,11 @@ |
| 103647 | 103973 | dest.iSdst = bIdListInOrder ? regData : 0; |
| 103648 | 103974 | dest.nSdst = pTab->nCol; |
| 103649 | 103975 | rc = sqlite3Select(pParse, pSelect, &dest); |
| 103650 | 103976 | regFromSelect = dest.iSdst; |
| 103651 | 103977 | if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; |
| 103652 | | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); |
| 103978 | + sqlite3VdbeEndCoroutine(v, regYield); |
| 103653 | 103979 | sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ |
| 103654 | 103980 | assert( pSelect->pEList ); |
| 103655 | 103981 | nColumn = pSelect->pEList->nExpr; |
| 103656 | 103982 | |
| 103657 | 103983 | /* Set useTempTable to TRUE if the result of the SELECT statement |
| | @@ -103749,11 +104075,11 @@ |
| 103749 | 104075 | /* If this is not a view, open the table and and all indices */ |
| 103750 | 104076 | if( !isView ){ |
| 103751 | 104077 | int nIdx; |
| 103752 | 104078 | nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, |
| 103753 | 104079 | &iDataCur, &iIdxCur); |
| 103754 | | - aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); |
| 104080 | + aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); |
| 103755 | 104081 | if( aRegIdx==0 ){ |
| 103756 | 104082 | goto insert_cleanup; |
| 103757 | 104083 | } |
| 103758 | 104084 | for(i=0; i<nIdx; i++){ |
| 103759 | 104085 | aRegIdx[i] = ++pParse->nMem; |
| | @@ -103957,11 +104283,11 @@ |
| 103957 | 104283 | }else |
| 103958 | 104284 | #endif |
| 103959 | 104285 | { |
| 103960 | 104286 | int isReplace; /* Set to true if constraints may cause a replace */ |
| 103961 | 104287 | sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, |
| 103962 | | - regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace |
| 104288 | + regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 |
| 103963 | 104289 | ); |
| 103964 | 104290 | sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); |
| 103965 | 104291 | sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, |
| 103966 | 104292 | regIns, aRegIdx, 0, appendFlag, isReplace==0); |
| 103967 | 104293 | } |
| | @@ -104038,10 +104364,63 @@ |
| 104038 | 104364 | #undef pTrigger |
| 104039 | 104365 | #endif |
| 104040 | 104366 | #ifdef tmask |
| 104041 | 104367 | #undef tmask |
| 104042 | 104368 | #endif |
| 104369 | + |
| 104370 | +/* |
| 104371 | +** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() |
| 104372 | +*/ |
| 104373 | +#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ |
| 104374 | +#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ |
| 104375 | + |
| 104376 | +/* This is the Walker callback from checkConstraintUnchanged(). Set |
| 104377 | +** bit 0x01 of pWalker->eCode if |
| 104378 | +** pWalker->eCode to 0 if this expression node references any of the |
| 104379 | +** columns that are being modifed by an UPDATE statement. |
| 104380 | +*/ |
| 104381 | +static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ |
| 104382 | + if( pExpr->op==TK_COLUMN ){ |
| 104383 | + assert( pExpr->iColumn>=0 || pExpr->iColumn==-1 ); |
| 104384 | + if( pExpr->iColumn>=0 ){ |
| 104385 | + if( pWalker->u.aiCol[pExpr->iColumn]>=0 ){ |
| 104386 | + pWalker->eCode |= CKCNSTRNT_COLUMN; |
| 104387 | + } |
| 104388 | + }else{ |
| 104389 | + pWalker->eCode |= CKCNSTRNT_ROWID; |
| 104390 | + } |
| 104391 | + } |
| 104392 | + return WRC_Continue; |
| 104393 | +} |
| 104394 | + |
| 104395 | +/* |
| 104396 | +** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The |
| 104397 | +** only columns that are modified by the UPDATE are those for which |
| 104398 | +** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. |
| 104399 | +** |
| 104400 | +** Return true if CHECK constraint pExpr does not use any of the |
| 104401 | +** changing columns (or the rowid if it is changing). In other words, |
| 104402 | +** return true if this CHECK constraint can be skipped when validating |
| 104403 | +** the new row in the UPDATE statement. |
| 104404 | +*/ |
| 104405 | +static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ |
| 104406 | + Walker w; |
| 104407 | + memset(&w, 0, sizeof(w)); |
| 104408 | + w.eCode = 0; |
| 104409 | + w.xExprCallback = checkConstraintExprNode; |
| 104410 | + w.u.aiCol = aiChng; |
| 104411 | + sqlite3WalkExpr(&w, pExpr); |
| 104412 | + if( !chngRowid ){ |
| 104413 | + testcase( (w.eCode & CKCNSTRNT_ROWID)!=0 ); |
| 104414 | + w.eCode &= ~CKCNSTRNT_ROWID; |
| 104415 | + } |
| 104416 | + testcase( w.eCode==0 ); |
| 104417 | + testcase( w.eCode==CKCNSTRNT_COLUMN ); |
| 104418 | + testcase( w.eCode==CKCNSTRNT_ROWID ); |
| 104419 | + testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); |
| 104420 | + return !w.eCode; |
| 104421 | +} |
| 104043 | 104422 | |
| 104044 | 104423 | /* |
| 104045 | 104424 | ** Generate code to do constraint checks prior to an INSERT or an UPDATE |
| 104046 | 104425 | ** on table pTab. |
| 104047 | 104426 | ** |
| | @@ -104133,11 +104512,12 @@ |
| 104133 | 104512 | int regNewData, /* First register in a range holding values to insert */ |
| 104134 | 104513 | int regOldData, /* Previous content. 0 for INSERTs */ |
| 104135 | 104514 | u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ |
| 104136 | 104515 | u8 overrideError, /* Override onError to this if not OE_Default */ |
| 104137 | 104516 | int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ |
| 104138 | | - int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */ |
| 104517 | + int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ |
| 104518 | + int *aiChng /* column i is unchanged if aiChng[i]<0 */ |
| 104139 | 104519 | ){ |
| 104140 | 104520 | Vdbe *v; /* VDBE under constrution */ |
| 104141 | 104521 | Index *pIdx; /* Pointer to one of the indices */ |
| 104142 | 104522 | Index *pPk = 0; /* The PRIMARY KEY index */ |
| 104143 | 104523 | sqlite3 *db; /* Database connection */ |
| | @@ -104179,14 +104559,18 @@ |
| 104179 | 104559 | |
| 104180 | 104560 | /* Test all NOT NULL constraints. |
| 104181 | 104561 | */ |
| 104182 | 104562 | for(i=0; i<nCol; i++){ |
| 104183 | 104563 | if( i==pTab->iPKey ){ |
| 104564 | + continue; /* ROWID is never NULL */ |
| 104565 | + } |
| 104566 | + if( aiChng && aiChng[i]<0 ){ |
| 104567 | + /* Don't bother checking for NOT NULL on columns that do not change */ |
| 104184 | 104568 | continue; |
| 104185 | 104569 | } |
| 104186 | 104570 | onError = pTab->aCol[i].notNull; |
| 104187 | | - if( onError==OE_None ) continue; |
| 104571 | + if( onError==OE_None ) continue; /* This column is allowed to be NULL */ |
| 104188 | 104572 | if( overrideError!=OE_Default ){ |
| 104189 | 104573 | onError = overrideError; |
| 104190 | 104574 | }else if( onError==OE_Default ){ |
| 104191 | 104575 | onError = OE_Abort; |
| 104192 | 104576 | } |
| | @@ -104231,12 +104615,15 @@ |
| 104231 | 104615 | if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ |
| 104232 | 104616 | ExprList *pCheck = pTab->pCheck; |
| 104233 | 104617 | pParse->ckBase = regNewData+1; |
| 104234 | 104618 | onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
| 104235 | 104619 | for(i=0; i<pCheck->nExpr; i++){ |
| 104236 | | - int allOk = sqlite3VdbeMakeLabel(v); |
| 104237 | | - sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); |
| 104620 | + int allOk; |
| 104621 | + Expr *pExpr = pCheck->a[i].pExpr; |
| 104622 | + if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; |
| 104623 | + allOk = sqlite3VdbeMakeLabel(v); |
| 104624 | + sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); |
| 104238 | 104625 | if( onError==OE_Ignore ){ |
| 104239 | 104626 | sqlite3VdbeGoto(v, ignoreDest); |
| 104240 | 104627 | }else{ |
| 104241 | 104628 | char *zName = pCheck->a[i].zName; |
| 104242 | 104629 | if( zName==0 ) zName = pTab->zName; |
| | @@ -104634,11 +105021,11 @@ |
| 104634 | 105021 | */ |
| 104635 | 105022 | SQLITE_PRIVATE int sqlite3OpenTableAndIndices( |
| 104636 | 105023 | Parse *pParse, /* Parsing context */ |
| 104637 | 105024 | Table *pTab, /* Table to be opened */ |
| 104638 | 105025 | int op, /* OP_OpenRead or OP_OpenWrite */ |
| 104639 | | - u8 p5, /* P5 value for OP_Open* instructions */ |
| 105026 | + u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ |
| 104640 | 105027 | int iBase, /* Use this for the table cursor, if there is one */ |
| 104641 | 105028 | u8 *aToOpen, /* If not NULL: boolean for each table and index */ |
| 104642 | 105029 | int *piDataCur, /* Write the database source cursor number here */ |
| 104643 | 105030 | int *piIdxCur /* Write the first index cursor number here */ |
| 104644 | 105031 | ){ |
| | @@ -104669,18 +105056,19 @@ |
| 104669 | 105056 | } |
| 104670 | 105057 | if( piIdxCur ) *piIdxCur = iBase; |
| 104671 | 105058 | for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ |
| 104672 | 105059 | int iIdxCur = iBase++; |
| 104673 | 105060 | assert( pIdx->pSchema==pTab->pSchema ); |
| 104674 | | - if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){ |
| 104675 | | - *piDataCur = iIdxCur; |
| 104676 | | - } |
| 104677 | 105061 | if( aToOpen==0 || aToOpen[i+1] ){ |
| 104678 | 105062 | sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); |
| 104679 | 105063 | sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
| 104680 | | - sqlite3VdbeChangeP5(v, p5); |
| 104681 | 105064 | VdbeComment((v, "%s", pIdx->zName)); |
| 105065 | + } |
| 105066 | + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ |
| 105067 | + if( piDataCur ) *piDataCur = iIdxCur; |
| 105068 | + }else{ |
| 105069 | + sqlite3VdbeChangeP5(v, p5); |
| 104682 | 105070 | } |
| 104683 | 105071 | } |
| 104684 | 105072 | if( iBase>pParse->nTab ) pParse->nTab = iBase; |
| 104685 | 105073 | return i; |
| 104686 | 105074 | } |
| | @@ -105167,11 +105555,11 @@ |
| 105167 | 105555 | if( rc==SQLITE_ROW ){ |
| 105168 | 105556 | azVals = &azCols[nCol]; |
| 105169 | 105557 | for(i=0; i<nCol; i++){ |
| 105170 | 105558 | azVals[i] = (char *)sqlite3_column_text(pStmt, i); |
| 105171 | 105559 | if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ |
| 105172 | | - db->mallocFailed = 1; |
| 105560 | + sqlite3OomFault(db); |
| 105173 | 105561 | goto exec_out; |
| 105174 | 105562 | } |
| 105175 | 105563 | } |
| 105176 | 105564 | } |
| 105177 | 105565 | if( xCallback(pArg, nCol, azVals, azCols) ){ |
| | @@ -107055,32 +107443,35 @@ |
| 107055 | 107443 | /************** End of pragma.h **********************************************/ |
| 107056 | 107444 | /************** Continuing where we left off in pragma.c *********************/ |
| 107057 | 107445 | |
| 107058 | 107446 | /* |
| 107059 | 107447 | ** 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 |
| 107448 | +** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or |
| 107449 | +** unrecognized string argument. The FULL and EXTRA option is disallowed |
| 107062 | 107450 | ** if the omitFull parameter it 1. |
| 107063 | 107451 | ** |
| 107064 | 107452 | ** Note that the values returned are one less that the values that |
| 107065 | 107453 | ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done |
| 107066 | 107454 | ** to support legacy SQL code. The safety level used to be boolean |
| 107067 | 107455 | ** and older scripts may have used numbers 0 for OFF and 1 for ON. |
| 107068 | 107456 | */ |
| 107069 | 107457 | 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}; |
| 107458 | + /* 123456789 123456789 123 */ |
| 107459 | + static const char zText[] = "onoffalseyestruextrafull"; |
| 107460 | + static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 15, 20}; |
| 107461 | + static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 5, 4}; |
| 107462 | + static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 3, 2}; |
| 107463 | + /* on no off false yes true extra full */ |
| 107075 | 107464 | int i, n; |
| 107076 | 107465 | if( sqlite3Isdigit(*z) ){ |
| 107077 | 107466 | return (u8)sqlite3Atoi(z); |
| 107078 | 107467 | } |
| 107079 | 107468 | n = sqlite3Strlen30(z); |
| 107080 | | - for(i=0; i<ArraySize(iLength)-omitFull; i++){ |
| 107081 | | - if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ |
| 107469 | + for(i=0; i<ArraySize(iLength); i++){ |
| 107470 | + if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 |
| 107471 | + && (!omitFull || iValue[i]<=1) |
| 107472 | + ){ |
| 107082 | 107473 | return iValue[i]; |
| 107083 | 107474 | } |
| 107084 | 107475 | } |
| 107085 | 107476 | return dflt; |
| 107086 | 107477 | } |
| | @@ -107467,12 +107858,11 @@ |
| 107467 | 107858 | aOp[1].p1 = iDb; |
| 107468 | 107859 | aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE; |
| 107469 | 107860 | }else{ |
| 107470 | 107861 | int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); |
| 107471 | 107862 | sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 107472 | | - sqlite3VdbeAddOp2(v, OP_Integer, size, 1); |
| 107473 | | - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); |
| 107863 | + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, size); |
| 107474 | 107864 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 107475 | 107865 | pDb->pSchema->cache_size = size; |
| 107476 | 107866 | sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
| 107477 | 107867 | } |
| 107478 | 107868 | break; |
| | @@ -107499,11 +107889,11 @@ |
| 107499 | 107889 | /* Malloc may fail when setting the page-size, as there is an internal |
| 107500 | 107890 | ** buffer that the pager module resizes using sqlite3_realloc(). |
| 107501 | 107891 | */ |
| 107502 | 107892 | db->nextPagesize = sqlite3Atoi(zRight); |
| 107503 | 107893 | if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ |
| 107504 | | - db->mallocFailed = 1; |
| 107894 | + sqlite3OomFault(db); |
| 107505 | 107895 | } |
| 107506 | 107896 | } |
| 107507 | 107897 | break; |
| 107508 | 107898 | } |
| 107509 | 107899 | |
| | @@ -107706,23 +108096,22 @@ |
| 107706 | 108096 | static const VdbeOpList setMeta6[] = { |
| 107707 | 108097 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 107708 | 108098 | { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, |
| 107709 | 108099 | { OP_If, 1, 0, 0}, /* 2 */ |
| 107710 | 108100 | { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ |
| 107711 | | - { OP_Integer, 0, 1, 0}, /* 4 */ |
| 107712 | | - { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ |
| 108101 | + { OP_SetCookie, 0, BTREE_INCR_VACUUM, 0}, /* 4 */ |
| 107713 | 108102 | }; |
| 107714 | 108103 | VdbeOp *aOp; |
| 107715 | 108104 | int iAddr = sqlite3VdbeCurrentAddr(v); |
| 107716 | 108105 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setMeta6)); |
| 107717 | 108106 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); |
| 107718 | 108107 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 107719 | 108108 | aOp[0].p1 = iDb; |
| 107720 | 108109 | aOp[1].p1 = iDb; |
| 107721 | 108110 | aOp[2].p2 = iAddr+4; |
| 107722 | | - aOp[4].p1 = eAuto - 1; |
| 107723 | | - aOp[5].p1 = iDb; |
| 108111 | + aOp[4].p1 = iDb; |
| 108112 | + aOp[4].p3 = eAuto - 1; |
| 107724 | 108113 | sqlite3VdbeUsesBtree(v, iDb); |
| 107725 | 108114 | } |
| 107726 | 108115 | } |
| 107727 | 108116 | break; |
| 107728 | 108117 | } |
| | @@ -107997,11 +108386,11 @@ |
| 107997 | 108386 | } |
| 107998 | 108387 | #endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
| 107999 | 108388 | |
| 108000 | 108389 | /* |
| 108001 | 108390 | ** PRAGMA [schema.]synchronous |
| 108002 | | - ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL |
| 108391 | + ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA |
| 108003 | 108392 | ** |
| 108004 | 108393 | ** Return or set the local value of the synchronous flag. Changing |
| 108005 | 108394 | ** the local value does not make changes to the disk file and the |
| 108006 | 108395 | ** default value will be restored the next time the database is |
| 108007 | 108396 | ** opened. |
| | @@ -108624,20 +109013,19 @@ |
| 108624 | 109013 | } |
| 108625 | 109014 | { |
| 108626 | 109015 | static const int iLn = VDBE_OFFSET_LINENO(2); |
| 108627 | 109016 | static const VdbeOpList endCode[] = { |
| 108628 | 109017 | { OP_AddImm, 1, 0, 0}, /* 0 */ |
| 108629 | | - { OP_If, 1, 0, 0}, /* 1 */ |
| 109018 | + { OP_If, 1, 4, 0}, /* 1 */ |
| 108630 | 109019 | { OP_String8, 0, 3, 0}, /* 2 */ |
| 108631 | | - { OP_ResultRow, 3, 1, 0}, |
| 109020 | + { OP_ResultRow, 3, 1, 0}, /* 3 */ |
| 108632 | 109021 | }; |
| 108633 | 109022 | VdbeOp *aOp; |
| 108634 | 109023 | |
| 108635 | 109024 | aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
| 108636 | 109025 | if( aOp ){ |
| 108637 | 109026 | aOp[0].p2 = -mxErr; |
| 108638 | | - aOp[1].p2 = sqlite3VdbeCurrentAddr(v); |
| 108639 | 109027 | aOp[2].p4type = P4_STATIC; |
| 108640 | 109028 | aOp[2].p4.z = "ok"; |
| 108641 | 109029 | } |
| 108642 | 109030 | } |
| 108643 | 109031 | } |
| | @@ -108751,21 +109139,20 @@ |
| 108751 | 109139 | sqlite3VdbeUsesBtree(v, iDb); |
| 108752 | 109140 | if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ |
| 108753 | 109141 | /* Write the specified cookie value */ |
| 108754 | 109142 | static const VdbeOpList setCookie[] = { |
| 108755 | 109143 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 108756 | | - { OP_Integer, 0, 1, 0}, /* 1 */ |
| 108757 | | - { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| 109144 | + { OP_SetCookie, 0, 0, 0}, /* 1 */ |
| 108758 | 109145 | }; |
| 108759 | 109146 | VdbeOp *aOp; |
| 108760 | 109147 | sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); |
| 108761 | 109148 | aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); |
| 108762 | 109149 | if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
| 108763 | 109150 | aOp[0].p1 = iDb; |
| 108764 | | - aOp[1].p1 = sqlite3Atoi(zRight); |
| 108765 | | - aOp[2].p1 = iDb; |
| 108766 | | - aOp[2].p2 = iCookie; |
| 109151 | + aOp[1].p1 = iDb; |
| 109152 | + aOp[1].p2 = iCookie; |
| 109153 | + aOp[1].p3 = sqlite3Atoi(zRight); |
| 108767 | 109154 | }else{ |
| 108768 | 109155 | /* Read the specified cookie value */ |
| 108769 | 109156 | static const VdbeOpList readCookie[] = { |
| 108770 | 109157 | { OP_Transaction, 0, 0, 0}, /* 0 */ |
| 108771 | 109158 | { OP_ReadCookie, 0, 1, 0}, /* 1 */ |
| | @@ -109033,15 +109420,14 @@ |
| 109033 | 109420 | ){ |
| 109034 | 109421 | sqlite3 *db = pData->db; |
| 109035 | 109422 | if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ |
| 109036 | 109423 | char *z; |
| 109037 | 109424 | if( zObj==0 ) zObj = "?"; |
| 109038 | | - z = sqlite3_mprintf("malformed database schema (%s)", zObj); |
| 109039 | | - if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra); |
| 109425 | + z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); |
| 109426 | + if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); |
| 109040 | 109427 | sqlite3DbFree(db, *pData->pzErrMsg); |
| 109041 | 109428 | *pData->pzErrMsg = z; |
| 109042 | | - if( z==0 ) db->mallocFailed = 1; |
| 109043 | 109429 | } |
| 109044 | 109430 | pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; |
| 109045 | 109431 | } |
| 109046 | 109432 | |
| 109047 | 109433 | /* |
| | @@ -109096,11 +109482,11 @@ |
| 109096 | 109482 | if( db->init.orphanTrigger ){ |
| 109097 | 109483 | assert( iDb==1 ); |
| 109098 | 109484 | }else{ |
| 109099 | 109485 | pData->rc = rc; |
| 109100 | 109486 | if( rc==SQLITE_NOMEM ){ |
| 109101 | | - db->mallocFailed = 1; |
| 109487 | + sqlite3OomFault(db); |
| 109102 | 109488 | }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ |
| 109103 | 109489 | corruptSchema(pData, argv[0], sqlite3_errmsg(db)); |
| 109104 | 109490 | } |
| 109105 | 109491 | } |
| 109106 | 109492 | } |
| | @@ -109341,11 +109727,11 @@ |
| 109341 | 109727 | } |
| 109342 | 109728 | sqlite3BtreeLeave(pDb->pBt); |
| 109343 | 109729 | |
| 109344 | 109730 | error_out: |
| 109345 | 109731 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109346 | | - db->mallocFailed = 1; |
| 109732 | + sqlite3OomFault(db); |
| 109347 | 109733 | } |
| 109348 | 109734 | return rc; |
| 109349 | 109735 | } |
| 109350 | 109736 | |
| 109351 | 109737 | /* |
| | @@ -109439,11 +109825,11 @@ |
| 109439 | 109825 | ** on the b-tree database, open one now. If a transaction is opened, it |
| 109440 | 109826 | ** will be closed immediately after reading the meta-value. */ |
| 109441 | 109827 | if( !sqlite3BtreeIsInReadTrans(pBt) ){ |
| 109442 | 109828 | rc = sqlite3BtreeBeginTrans(pBt, 0); |
| 109443 | 109829 | if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
| 109444 | | - db->mallocFailed = 1; |
| 109830 | + sqlite3OomFault(db); |
| 109445 | 109831 | } |
| 109446 | 109832 | if( rc!=SQLITE_OK ) return; |
| 109447 | 109833 | openedTransaction = 1; |
| 109448 | 109834 | } |
| 109449 | 109835 | |
| | @@ -109502,10 +109888,15 @@ |
| 109502 | 109888 | SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ |
| 109503 | 109889 | if( pParse ){ |
| 109504 | 109890 | sqlite3 *db = pParse->db; |
| 109505 | 109891 | sqlite3DbFree(db, pParse->aLabel); |
| 109506 | 109892 | sqlite3ExprListDelete(db, pParse->pConstExpr); |
| 109893 | + if( db ){ |
| 109894 | + assert( db->lookaside.bDisable >= pParse->disableLookaside ); |
| 109895 | + db->lookaside.bDisable -= pParse->disableLookaside; |
| 109896 | + } |
| 109897 | + pParse->disableLookaside = 0; |
| 109507 | 109898 | } |
| 109508 | 109899 | } |
| 109509 | 109900 | |
| 109510 | 109901 | /* |
| 109511 | 109902 | ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. |
| | @@ -109530,11 +109921,11 @@ |
| 109530 | 109921 | rc = SQLITE_NOMEM; |
| 109531 | 109922 | goto end_prepare; |
| 109532 | 109923 | } |
| 109533 | 109924 | pParse->pReprepare = pReprepare; |
| 109534 | 109925 | assert( ppStmt && *ppStmt==0 ); |
| 109535 | | - assert( !db->mallocFailed ); |
| 109926 | + /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ |
| 109536 | 109927 | assert( sqlite3_mutex_held(db->mutex) ); |
| 109537 | 109928 | |
| 109538 | 109929 | /* Check to verify that it is possible to get a read lock on all |
| 109539 | 109930 | ** database schemas. The inability to get a read lock indicates that |
| 109540 | 109931 | ** some other database connection is holding a write-lock, which in |
| | @@ -109587,23 +109978,20 @@ |
| 109587 | 109978 | goto end_prepare; |
| 109588 | 109979 | } |
| 109589 | 109980 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 109590 | 109981 | if( zSqlCopy ){ |
| 109591 | 109982 | sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); |
| 109592 | | - sqlite3DbFree(db, zSqlCopy); |
| 109593 | 109983 | pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; |
| 109984 | + sqlite3DbFree(db, zSqlCopy); |
| 109594 | 109985 | }else{ |
| 109595 | 109986 | pParse->zTail = &zSql[nBytes]; |
| 109596 | 109987 | } |
| 109597 | 109988 | }else{ |
| 109598 | 109989 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 109599 | 109990 | } |
| 109600 | 109991 | assert( 0==pParse->nQueryLoop ); |
| 109601 | 109992 | |
| 109602 | | - if( db->mallocFailed ){ |
| 109603 | | - pParse->rc = SQLITE_NOMEM; |
| 109604 | | - } |
| 109605 | 109993 | if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; |
| 109606 | 109994 | if( pParse->checkSchema ){ |
| 109607 | 109995 | schemaIsValid(pParse); |
| 109608 | 109996 | } |
| 109609 | 109997 | if( db->mallocFailed ){ |
| | @@ -109721,11 +110109,11 @@ |
| 109721 | 110109 | db = sqlite3VdbeDb(p); |
| 109722 | 110110 | assert( sqlite3_mutex_held(db->mutex) ); |
| 109723 | 110111 | rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0); |
| 109724 | 110112 | if( rc ){ |
| 109725 | 110113 | if( rc==SQLITE_NOMEM ){ |
| 109726 | | - db->mallocFailed = 1; |
| 110114 | + sqlite3OomFault(db); |
| 109727 | 110115 | } |
| 109728 | 110116 | assert( pNew==0 ); |
| 109729 | 110117 | return rc; |
| 109730 | 110118 | }else{ |
| 109731 | 110119 | assert( pNew!=0 ); |
| | @@ -109975,11 +110363,11 @@ |
| 109975 | 110363 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 109976 | 110364 | ){ |
| 109977 | 110365 | Select *pNew; |
| 109978 | 110366 | Select standin; |
| 109979 | 110367 | sqlite3 *db = pParse->db; |
| 109980 | | - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); |
| 110368 | + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); |
| 109981 | 110369 | if( pNew==0 ){ |
| 109982 | 110370 | assert( db->mallocFailed ); |
| 109983 | 110371 | pNew = &standin; |
| 109984 | 110372 | } |
| 109985 | 110373 | if( pEList==0 ){ |
| | @@ -110879,11 +111267,11 @@ |
| 110879 | 111267 | p->enc = ENC(db); |
| 110880 | 111268 | p->db = db; |
| 110881 | 111269 | p->nRef = 1; |
| 110882 | 111270 | memset(&p[1], 0, nExtra); |
| 110883 | 111271 | }else{ |
| 110884 | | - db->mallocFailed = 1; |
| 111272 | + sqlite3OomFault(db); |
| 110885 | 111273 | } |
| 110886 | 111274 | return p; |
| 110887 | 111275 | } |
| 110888 | 111276 | |
| 110889 | 111277 | /* |
| | @@ -111540,11 +111928,11 @@ |
| 111540 | 111928 | if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); |
| 111541 | 111929 | } |
| 111542 | 111930 | pCol->zName = zName; |
| 111543 | 111931 | sqlite3ColumnPropertiesFromName(0, pCol); |
| 111544 | 111932 | if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ |
| 111545 | | - db->mallocFailed = 1; |
| 111933 | + sqlite3OomFault(db); |
| 111546 | 111934 | } |
| 111547 | 111935 | } |
| 111548 | 111936 | sqlite3HashClear(&ht); |
| 111549 | 111937 | if( db->mallocFailed ){ |
| 111550 | 111938 | for(j=0; j<i; j++){ |
| | @@ -111627,11 +112015,11 @@ |
| 111627 | 112015 | if( pTab==0 ){ |
| 111628 | 112016 | return 0; |
| 111629 | 112017 | } |
| 111630 | 112018 | /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside |
| 111631 | 112019 | ** is disabled */ |
| 111632 | | - assert( db->lookaside.bEnabled==0 ); |
| 112020 | + assert( db->lookaside.bDisable ); |
| 111633 | 112021 | pTab->nRef = 1; |
| 111634 | 112022 | pTab->zName = 0; |
| 111635 | 112023 | pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 111636 | 112024 | sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
| 111637 | 112025 | selectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
| | @@ -111723,14 +112111,12 @@ |
| 111723 | 112111 | p->iOffset = iOffset = ++pParse->nMem; |
| 111724 | 112112 | pParse->nMem++; /* Allocate an extra register for limit+offset */ |
| 111725 | 112113 | sqlite3ExprCode(pParse, p->pOffset, iOffset); |
| 111726 | 112114 | sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); |
| 111727 | 112115 | VdbeComment((v, "OFFSET counter")); |
| 111728 | | - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0); |
| 111729 | | - sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); |
| 112116 | + sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); |
| 111730 | 112117 | VdbeComment((v, "LIMIT+OFFSET")); |
| 111731 | | - sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1); |
| 111732 | 112118 | } |
| 111733 | 112119 | } |
| 111734 | 112120 | } |
| 111735 | 112121 | |
| 111736 | 112122 | #ifndef SQLITE_OMIT_COMPOUND_SELECT |
| | @@ -112143,13 +112529,12 @@ |
| 112143 | 112529 | p->iOffset = pPrior->iOffset; |
| 112144 | 112530 | if( p->iLimit ){ |
| 112145 | 112531 | addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); |
| 112146 | 112532 | VdbeComment((v, "Jump ahead if LIMIT reached")); |
| 112147 | 112533 | 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); |
| 112534 | + sqlite3VdbeAddOp3(v, OP_OffsetLimit, |
| 112535 | + p->iLimit, p->iOffset+1, p->iOffset); |
| 112151 | 112536 | } |
| 112152 | 112537 | } |
| 112153 | 112538 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 112154 | 112539 | rc = sqlite3Select(pParse, p, &dest); |
| 112155 | 112540 | testcase( rc!=SQLITE_OK ); |
| | @@ -112736,14 +113121,15 @@ |
| 112736 | 113121 | ** row of results comes from selectA or selectB. Also add explicit |
| 112737 | 113122 | ** collations to the ORDER BY clause terms so that when the subqueries |
| 112738 | 113123 | ** to the right and the left are evaluated, they use the correct |
| 112739 | 113124 | ** collation. |
| 112740 | 113125 | */ |
| 112741 | | - aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); |
| 113126 | + aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1)); |
| 112742 | 113127 | if( aPermute ){ |
| 112743 | 113128 | struct ExprList_item *pItem; |
| 112744 | | - for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ |
| 113129 | + aPermute[0] = nOrderBy; |
| 113130 | + for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ |
| 112745 | 113131 | assert( pItem->u.x.iOrderByCol>0 ); |
| 112746 | 113132 | assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
| 112747 | 113133 | aPermute[i] = pItem->u.x.iOrderByCol - 1; |
| 112748 | 113134 | } |
| 112749 | 113135 | pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); |
| | @@ -112817,11 +113203,11 @@ |
| 112817 | 113203 | addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
| 112818 | 113204 | VdbeComment((v, "left SELECT")); |
| 112819 | 113205 | pPrior->iLimit = regLimitA; |
| 112820 | 113206 | explainSetInteger(iSub1, pParse->iNextSelectId); |
| 112821 | 113207 | sqlite3Select(pParse, pPrior, &destA); |
| 112822 | | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA); |
| 113208 | + sqlite3VdbeEndCoroutine(v, regAddrA); |
| 112823 | 113209 | sqlite3VdbeJumpHere(v, addr1); |
| 112824 | 113210 | |
| 112825 | 113211 | /* Generate a coroutine to evaluate the SELECT statement on |
| 112826 | 113212 | ** the right - the "B" select |
| 112827 | 113213 | */ |
| | @@ -112834,11 +113220,11 @@ |
| 112834 | 113220 | p->iOffset = 0; |
| 112835 | 113221 | explainSetInteger(iSub2, pParse->iNextSelectId); |
| 112836 | 113222 | sqlite3Select(pParse, p, &destB); |
| 112837 | 113223 | p->iLimit = savedLimit; |
| 112838 | 113224 | p->iOffset = savedOffset; |
| 112839 | | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB); |
| 113225 | + sqlite3VdbeEndCoroutine(v, regAddrB); |
| 112840 | 113226 | |
| 112841 | 113227 | /* Generate a subroutine that outputs the current row of the A |
| 112842 | 113228 | ** select as the next output row of the compound select. |
| 112843 | 113229 | */ |
| 112844 | 113230 | VdbeNoopComment((v, "Output routine for A")); |
| | @@ -114301,12 +114687,11 @@ |
| 114301 | 114687 | } |
| 114302 | 114688 | }else{ |
| 114303 | 114689 | pExpr = pRight; |
| 114304 | 114690 | } |
| 114305 | 114691 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 114306 | | - sColname.z = zColname; |
| 114307 | | - sColname.n = sqlite3Strlen30(zColname); |
| 114692 | + sqlite3TokenInit(&sColname, zColname); |
| 114308 | 114693 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 114309 | 114694 | if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ |
| 114310 | 114695 | struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; |
| 114311 | 114696 | if( pSub ){ |
| 114312 | 114697 | pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); |
| | @@ -114856,11 +115241,11 @@ |
| 114856 | 115241 | explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
| 114857 | 115242 | sqlite3Select(pParse, pSub, &dest); |
| 114858 | 115243 | pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); |
| 114859 | 115244 | pItem->fg.viaCoroutine = 1; |
| 114860 | 115245 | pItem->regResult = dest.iSdst; |
| 114861 | | - sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); |
| 115246 | + sqlite3VdbeEndCoroutine(v, pItem->regReturn); |
| 114862 | 115247 | sqlite3VdbeJumpHere(v, addrTop-1); |
| 114863 | 115248 | sqlite3ClearTempRegCache(pParse); |
| 114864 | 115249 | }else{ |
| 114865 | 115250 | /* Generate a subroutine that will fill an ephemeral table with |
| 114866 | 115251 | ** the content of this subquery. pItem->addrFillSub will point |
| | @@ -115428,11 +115813,12 @@ |
| 115428 | 115813 | assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); |
| 115429 | 115814 | |
| 115430 | 115815 | if( flag ){ |
| 115431 | 115816 | pMinMax = sqlite3ExprListDup(db, pMinMax, 0); |
| 115432 | 115817 | pDel = pMinMax; |
| 115433 | | - if( pMinMax && !db->mallocFailed ){ |
| 115818 | + assert( db->mallocFailed || pMinMax!=0 ); |
| 115819 | + if( !db->mallocFailed ){ |
| 115434 | 115820 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 115435 | 115821 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 115436 | 115822 | } |
| 115437 | 115823 | } |
| 115438 | 115824 | |
| | @@ -116001,12 +116387,11 @@ |
| 116001 | 116387 | pTrig->step_list = pStepList; |
| 116002 | 116388 | while( pStepList ){ |
| 116003 | 116389 | pStepList->pTrig = pTrig; |
| 116004 | 116390 | pStepList = pStepList->pNext; |
| 116005 | 116391 | } |
| 116006 | | - nameToken.z = pTrig->zName; |
| 116007 | | - nameToken.n = sqlite3Strlen30(nameToken.z); |
| 116392 | + sqlite3TokenInit(&nameToken, pTrig->zName); |
| 116008 | 116393 | sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
| 116009 | 116394 | if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) |
| 116010 | 116395 | || sqlite3FixExpr(&sFix, pTrig->pWhen) |
| 116011 | 116396 | ){ |
| 116012 | 116397 | goto triggerfinish_cleanup; |
| | @@ -116038,11 +116423,11 @@ |
| 116038 | 116423 | Trigger *pLink = pTrig; |
| 116039 | 116424 | Hash *pHash = &db->aDb[iDb].pSchema->trigHash; |
| 116040 | 116425 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 116041 | 116426 | pTrig = sqlite3HashInsert(pHash, zName, pTrig); |
| 116042 | 116427 | if( pTrig ){ |
| 116043 | | - db->mallocFailed = 1; |
| 116428 | + sqlite3OomFault(db); |
| 116044 | 116429 | }else if( pLink->pSchema==pLink->pTabSchema ){ |
| 116045 | 116430 | Table *pTab; |
| 116046 | 116431 | pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); |
| 116047 | 116432 | assert( pTab!=0 ); |
| 116048 | 116433 | pLink->pNext = pTab->pTrigger; |
| | @@ -117014,11 +117399,11 @@ |
| 117014 | 117399 | } |
| 117015 | 117400 | |
| 117016 | 117401 | /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. |
| 117017 | 117402 | ** Initialize aXRef[] and aToOpen[] to their default values. |
| 117018 | 117403 | */ |
| 117019 | | - aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); |
| 117404 | + aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); |
| 117020 | 117405 | if( aXRef==0 ) goto update_cleanup; |
| 117021 | 117406 | aRegIdx = aXRef+pTab->nCol; |
| 117022 | 117407 | aToOpen = (u8*)(aRegIdx+nIdx); |
| 117023 | 117408 | memset(aToOpen, 1, nIdx+1); |
| 117024 | 117409 | aToOpen[nIdx+1] = 0; |
| | @@ -117389,11 +117774,12 @@ |
| 117389 | 117774 | int bReplace = 0; /* True if REPLACE conflict resolution might happen */ |
| 117390 | 117775 | |
| 117391 | 117776 | /* Do constraint checks. */ |
| 117392 | 117777 | assert( regOldRowid>0 ); |
| 117393 | 117778 | sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, |
| 117394 | | - regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace); |
| 117779 | + regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, |
| 117780 | + aXRef); |
| 117395 | 117781 | |
| 117396 | 117782 | /* Do FK constraint checks. */ |
| 117397 | 117783 | if( hasFK ){ |
| 117398 | 117784 | sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); |
| 117399 | 117785 | } |
| | @@ -118054,11 +118440,11 @@ |
| 118054 | 118440 | nName = sqlite3Strlen30(zName); |
| 118055 | 118441 | if( sqlite3HashFind(&db->aModule, zName) ){ |
| 118056 | 118442 | rc = SQLITE_MISUSE_BKPT; |
| 118057 | 118443 | }else{ |
| 118058 | 118444 | Module *pMod; |
| 118059 | | - pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); |
| 118445 | + pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); |
| 118060 | 118446 | if( pMod ){ |
| 118061 | 118447 | Module *pDel; |
| 118062 | 118448 | char *zCopy = (char *)(&pMod[1]); |
| 118063 | 118449 | memcpy(zCopy, zName, nName+1); |
| 118064 | 118450 | pMod->zName = zCopy; |
| | @@ -118067,11 +118453,11 @@ |
| 118067 | 118453 | pMod->xDestroy = xDestroy; |
| 118068 | 118454 | pMod->pEpoTab = 0; |
| 118069 | 118455 | pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); |
| 118070 | 118456 | assert( pDel==0 || pDel==pMod ); |
| 118071 | 118457 | if( pDel ){ |
| 118072 | | - db->mallocFailed = 1; |
| 118458 | + sqlite3OomFault(db); |
| 118073 | 118459 | sqlite3DbFree(db, pDel); |
| 118074 | 118460 | } |
| 118075 | 118461 | } |
| 118076 | 118462 | } |
| 118077 | 118463 | rc = sqlite3ApiExit(db, rc); |
| | @@ -118444,11 +118830,11 @@ |
| 118444 | 118830 | Schema *pSchema = pTab->pSchema; |
| 118445 | 118831 | const char *zName = pTab->zName; |
| 118446 | 118832 | assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); |
| 118447 | 118833 | pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); |
| 118448 | 118834 | if( pOld ){ |
| 118449 | | - db->mallocFailed = 1; |
| 118835 | + sqlite3OomFault(db); |
| 118450 | 118836 | assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ |
| 118451 | 118837 | return; |
| 118452 | 118838 | } |
| 118453 | 118839 | pParse->pNewTable = 0; |
| 118454 | 118840 | } |
| | @@ -118535,11 +118921,11 @@ |
| 118535 | 118921 | sCtx.pPrior = db->pVtabCtx; |
| 118536 | 118922 | sCtx.bDeclared = 0; |
| 118537 | 118923 | db->pVtabCtx = &sCtx; |
| 118538 | 118924 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
| 118539 | 118925 | db->pVtabCtx = sCtx.pPrior; |
| 118540 | | - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 118926 | + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
| 118541 | 118927 | assert( sCtx.pTab==pTab ); |
| 118542 | 118928 | |
| 118543 | 118929 | if( SQLITE_OK!=rc ){ |
| 118544 | 118930 | if( zErr==0 ){ |
| 118545 | 118931 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
| | @@ -119093,11 +119479,11 @@ |
| 119093 | 119479 | apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); |
| 119094 | 119480 | if( apVtabLock ){ |
| 119095 | 119481 | pToplevel->apVtabLock = apVtabLock; |
| 119096 | 119482 | pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; |
| 119097 | 119483 | }else{ |
| 119098 | | - pToplevel->db->mallocFailed = 1; |
| 119484 | + sqlite3OomFault(pToplevel->db); |
| 119099 | 119485 | } |
| 119100 | 119486 | } |
| 119101 | 119487 | |
| 119102 | 119488 | /* |
| 119103 | 119489 | ** Check to see if virtual tale module pMod can be have an eponymous |
| | @@ -119835,11 +120221,11 @@ |
| 119835 | 120221 | if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; |
| 119836 | 120222 | sqlite3StrAccumAppend(pStr, " (", 2); |
| 119837 | 120223 | for(i=0; i<nEq; i++){ |
| 119838 | 120224 | const char *z = explainIndexColumnName(pIndex, i); |
| 119839 | 120225 | if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5); |
| 119840 | | - sqlite3XPrintf(pStr, 0, i>=nSkip ? "%s=?" : "ANY(%s)", z); |
| 120226 | + sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); |
| 119841 | 120227 | } |
| 119842 | 120228 | |
| 119843 | 120229 | j = i; |
| 119844 | 120230 | if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ |
| 119845 | 120231 | const char *z = explainIndexColumnName(pIndex, i); |
| | @@ -119894,17 +120280,17 @@ |
| 119894 | 120280 | || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); |
| 119895 | 120281 | |
| 119896 | 120282 | sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); |
| 119897 | 120283 | sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); |
| 119898 | 120284 | if( pItem->pSelect ){ |
| 119899 | | - sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); |
| 120285 | + sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); |
| 119900 | 120286 | }else{ |
| 119901 | | - sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName); |
| 120287 | + sqlite3XPrintf(&str, " TABLE %s", pItem->zName); |
| 119902 | 120288 | } |
| 119903 | 120289 | |
| 119904 | 120290 | if( pItem->zAlias ){ |
| 119905 | | - sqlite3XPrintf(&str, 0, " AS %s", pItem->zAlias); |
| 120291 | + sqlite3XPrintf(&str, " AS %s", pItem->zAlias); |
| 119906 | 120292 | } |
| 119907 | 120293 | if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ |
| 119908 | 120294 | const char *zFmt = 0; |
| 119909 | 120295 | Index *pIdx; |
| 119910 | 120296 | |
| | @@ -119924,11 +120310,11 @@ |
| 119924 | 120310 | }else{ |
| 119925 | 120311 | zFmt = "INDEX %s"; |
| 119926 | 120312 | } |
| 119927 | 120313 | if( zFmt ){ |
| 119928 | 120314 | sqlite3StrAccumAppend(&str, " USING ", 7); |
| 119929 | | - sqlite3XPrintf(&str, 0, zFmt, pIdx->zName); |
| 120315 | + sqlite3XPrintf(&str, zFmt, pIdx->zName); |
| 119930 | 120316 | explainIndexRange(&str, pLoop); |
| 119931 | 120317 | } |
| 119932 | 120318 | }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ |
| 119933 | 120319 | const char *zRangeOp; |
| 119934 | 120320 | if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ |
| | @@ -119939,21 +120325,21 @@ |
| 119939 | 120325 | zRangeOp = ">"; |
| 119940 | 120326 | }else{ |
| 119941 | 120327 | assert( flags&WHERE_TOP_LIMIT); |
| 119942 | 120328 | zRangeOp = "<"; |
| 119943 | 120329 | } |
| 119944 | | - sqlite3XPrintf(&str, 0, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); |
| 120330 | + sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); |
| 119945 | 120331 | } |
| 119946 | 120332 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 119947 | 120333 | else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ |
| 119948 | | - sqlite3XPrintf(&str, 0, " VIRTUAL TABLE INDEX %d:%s", |
| 120334 | + sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", |
| 119949 | 120335 | pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); |
| 119950 | 120336 | } |
| 119951 | 120337 | #endif |
| 119952 | 120338 | #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS |
| 119953 | 120339 | if( pLoop->nOut>=10 ){ |
| 119954 | | - sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); |
| 120340 | + sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); |
| 119955 | 120341 | }else{ |
| 119956 | 120342 | sqlite3StrAccumAppend(&str, " (~1 row)", 9); |
| 119957 | 120343 | } |
| 119958 | 120344 | #endif |
| 119959 | 120345 | zMsg = sqlite3StrAccumFinish(&str); |
| | @@ -120254,13 +120640,11 @@ |
| 120254 | 120640 | regBase = pParse->nMem + 1; |
| 120255 | 120641 | nReg = pLoop->u.btree.nEq + nExtraReg; |
| 120256 | 120642 | pParse->nMem += nReg; |
| 120257 | 120643 | |
| 120258 | 120644 | zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx)); |
| 120259 | | - if( !zAff ){ |
| 120260 | | - pParse->db->mallocFailed = 1; |
| 120261 | | - } |
| 120645 | + assert( zAff!=0 || pParse->db->mallocFailed ); |
| 120262 | 120646 | |
| 120263 | 120647 | if( nSkip ){ |
| 120264 | 120648 | int iIdxCur = pLevel->iIdxCur; |
| 120265 | 120649 | sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); |
| 120266 | 120650 | VdbeCoverageIf(v, bRev==0); |
| | @@ -120504,10 +120888,58 @@ |
| 120504 | 120888 | } |
| 120505 | 120889 | } |
| 120506 | 120890 | #else |
| 120507 | 120891 | # define codeCursorHint(A,B,C) /* No-op */ |
| 120508 | 120892 | #endif /* SQLITE_ENABLE_CURSOR_HINTS */ |
| 120893 | + |
| 120894 | +/* |
| 120895 | +** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains |
| 120896 | +** a rowid value just read from cursor iIdxCur, open on index pIdx. This |
| 120897 | +** function generates code to do a deferred seek of cursor iCur to the |
| 120898 | +** rowid stored in register iRowid. |
| 120899 | +** |
| 120900 | +** Normally, this is just: |
| 120901 | +** |
| 120902 | +** OP_Seek $iCur $iRowid |
| 120903 | +** |
| 120904 | +** However, if the scan currently being coded is a branch of an OR-loop and |
| 120905 | +** the statement currently being coded is a SELECT, then P3 of the OP_Seek |
| 120906 | +** is set to iIdxCur and P4 is set to point to an array of integers |
| 120907 | +** containing one entry for each column of the table cursor iCur is open |
| 120908 | +** on. For each table column, if the column is the i'th column of the |
| 120909 | +** index, then the corresponding array entry is set to (i+1). If the column |
| 120910 | +** does not appear in the index at all, the array entry is set to 0. |
| 120911 | +*/ |
| 120912 | +static void codeDeferredSeek( |
| 120913 | + WhereInfo *pWInfo, /* Where clause context */ |
| 120914 | + Index *pIdx, /* Index scan is using */ |
| 120915 | + int iCur, /* Cursor for IPK b-tree */ |
| 120916 | + int iIdxCur /* Index cursor */ |
| 120917 | +){ |
| 120918 | + Parse *pParse = pWInfo->pParse; /* Parse context */ |
| 120919 | + Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */ |
| 120920 | + |
| 120921 | + assert( iIdxCur>0 ); |
| 120922 | + assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); |
| 120923 | + |
| 120924 | + sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur); |
| 120925 | + if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE) |
| 120926 | + && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) |
| 120927 | + ){ |
| 120928 | + int i; |
| 120929 | + Table *pTab = pIdx->pTable; |
| 120930 | + int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*(pTab->nCol+1)); |
| 120931 | + if( ai ){ |
| 120932 | + ai[0] = pTab->nCol; |
| 120933 | + for(i=0; i<pIdx->nColumn-1; i++){ |
| 120934 | + assert( pIdx->aiColumn[i]<pTab->nCol ); |
| 120935 | + if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1; |
| 120936 | + } |
| 120937 | + sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY); |
| 120938 | + } |
| 120939 | + } |
| 120940 | +} |
| 120509 | 120941 | |
| 120510 | 120942 | /* |
| 120511 | 120943 | ** Generate code for the start of the iLevel-th loop in the WHERE clause |
| 120512 | 120944 | ** implementation described by pWInfo. |
| 120513 | 120945 | */ |
| | @@ -120984,18 +121416,18 @@ |
| 120984 | 121416 | disableTerm(pLevel, pRangeStart); |
| 120985 | 121417 | disableTerm(pLevel, pRangeEnd); |
| 120986 | 121418 | if( omitTable ){ |
| 120987 | 121419 | /* pIdx is a covering index. No need to access the main table. */ |
| 120988 | 121420 | }else if( HasRowid(pIdx->pTable) ){ |
| 120989 | | - iRowidReg = ++pParse->nMem; |
| 120990 | | - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); |
| 120991 | | - sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); |
| 120992 | 121421 | if( pWInfo->eOnePass!=ONEPASS_OFF ){ |
| 121422 | + iRowidReg = ++pParse->nMem; |
| 121423 | + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); |
| 121424 | + sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); |
| 120993 | 121425 | sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); |
| 120994 | 121426 | VdbeCoverage(v); |
| 120995 | 121427 | }else{ |
| 120996 | | - sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ |
| 121428 | + codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); |
| 120997 | 121429 | } |
| 120998 | 121430 | }else if( iCur!=iIdxCur ){ |
| 120999 | 121431 | Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); |
| 121000 | 121432 | iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); |
| 121001 | 121433 | for(j=0; j<pPk->nKeyCol; j++){ |
| | @@ -121160,11 +121592,13 @@ |
| 121160 | 121592 | int iTerm; |
| 121161 | 121593 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 121162 | 121594 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 121163 | 121595 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 121164 | 121596 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 121165 | | - if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; |
| 121597 | + testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); |
| 121598 | + testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); |
| 121599 | + if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; |
| 121166 | 121600 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 121167 | 121601 | testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); |
| 121168 | 121602 | pExpr = sqlite3ExprDup(db, pExpr, 0); |
| 121169 | 121603 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
| 121170 | 121604 | } |
| | @@ -121500,11 +121934,11 @@ |
| 121500 | 121934 | int idx; |
| 121501 | 121935 | testcase( wtFlags & TERM_VIRTUAL ); |
| 121502 | 121936 | if( pWC->nTerm>=pWC->nSlot ){ |
| 121503 | 121937 | WhereTerm *pOld = pWC->a; |
| 121504 | 121938 | sqlite3 *db = pWC->pWInfo->pParse->db; |
| 121505 | | - pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); |
| 121939 | + pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); |
| 121506 | 121940 | if( pWC->a==0 ){ |
| 121507 | 121941 | if( wtFlags & TERM_DYNAMIC ){ |
| 121508 | 121942 | sqlite3ExprDelete(db, p); |
| 121509 | 121943 | } |
| 121510 | 121944 | pWC->a = pOld; |
| | @@ -121985,11 +122419,11 @@ |
| 121985 | 122419 | for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ |
| 121986 | 122420 | if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ |
| 121987 | 122421 | WhereAndInfo *pAndInfo; |
| 121988 | 122422 | assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); |
| 121989 | 122423 | chngToIN = 0; |
| 121990 | | - pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); |
| 122424 | + pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo)); |
| 121991 | 122425 | if( pAndInfo ){ |
| 121992 | 122426 | WhereClause *pAndWC; |
| 121993 | 122427 | WhereTerm *pAndTerm; |
| 121994 | 122428 | int j; |
| 121995 | 122429 | Bitmask b = 0; |
| | @@ -121999,11 +122433,10 @@ |
| 121999 | 122433 | pAndWC = &pAndInfo->wc; |
| 122000 | 122434 | sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); |
| 122001 | 122435 | sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); |
| 122002 | 122436 | sqlite3WhereExprAnalyze(pSrc, pAndWC); |
| 122003 | 122437 | pAndWC->pOuter = pWC; |
| 122004 | | - testcase( db->mallocFailed ); |
| 122005 | 122438 | if( !db->mallocFailed ){ |
| 122006 | 122439 | for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ |
| 122007 | 122440 | assert( pAndTerm->pExpr ); |
| 122008 | 122441 | if( allowedOp(pAndTerm->pExpr->op) ){ |
| 122009 | 122442 | b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); |
| | @@ -123742,11 +124175,11 @@ |
| 123742 | 124175 | rc = pVtab->pModule->xBestIndex(pVtab, p); |
| 123743 | 124176 | TRACE_IDX_OUTPUTS(p); |
| 123744 | 124177 | |
| 123745 | 124178 | if( rc!=SQLITE_OK ){ |
| 123746 | 124179 | if( rc==SQLITE_NOMEM ){ |
| 123747 | | - pParse->db->mallocFailed = 1; |
| 124180 | + sqlite3OomFault(pParse->db); |
| 123748 | 124181 | }else if( !pVtab->zErrMsg ){ |
| 123749 | 124182 | sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); |
| 123750 | 124183 | }else{ |
| 123751 | 124184 | sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); |
| 123752 | 124185 | } |
| | @@ -124534,11 +124967,11 @@ |
| 124534 | 124967 | */ |
| 124535 | 124968 | static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ |
| 124536 | 124969 | WhereTerm **paNew; |
| 124537 | 124970 | if( p->nLSlot>=n ) return SQLITE_OK; |
| 124538 | 124971 | n = (n+7)&~7; |
| 124539 | | - paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n); |
| 124972 | + paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n); |
| 124540 | 124973 | if( paNew==0 ) return SQLITE_NOMEM; |
| 124541 | 124974 | memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); |
| 124542 | 124975 | if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm); |
| 124543 | 124976 | p->aLTerm = paNew; |
| 124544 | 124977 | p->nLSlot = n; |
| | @@ -124831,11 +125264,11 @@ |
| 124831 | 125264 | whereLoopPrint(pTemplate, pBuilder->pWC); |
| 124832 | 125265 | } |
| 124833 | 125266 | #endif |
| 124834 | 125267 | if( p==0 ){ |
| 124835 | 125268 | /* Allocate a new WhereLoop to add to the end of the list */ |
| 124836 | | - *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); |
| 125269 | + *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop)); |
| 124837 | 125270 | if( p==0 ) return SQLITE_NOMEM; |
| 124838 | 125271 | whereLoopInit(p); |
| 124839 | 125272 | p->pNextLoop = 0; |
| 124840 | 125273 | }else{ |
| 124841 | 125274 | /* We will be overwriting WhereLoop p[]. But before we do, first |
| | @@ -126237,11 +126670,10 @@ |
| 126237 | 126670 | ** Return the cost of sorting nRow rows, assuming that the keys have |
| 126238 | 126671 | ** nOrderby columns and that the first nSorted columns are already in |
| 126239 | 126672 | ** order. |
| 126240 | 126673 | */ |
| 126241 | 126674 | static LogEst whereSortingCost( |
| 126242 | | - WhereInfo *pWInfo, |
| 126243 | 126675 | LogEst nRow, |
| 126244 | 126676 | int nOrderBy, |
| 126245 | 126677 | int nSorted |
| 126246 | 126678 | ){ |
| 126247 | 126679 | /* TUNING: Estimated cost of a full external sort, where N is |
| | @@ -126259,18 +126691,10 @@ |
| 126259 | 126691 | ** below. */ |
| 126260 | 126692 | LogEst rScale, rSortCost; |
| 126261 | 126693 | assert( nOrderBy>0 && 66==sqlite3LogEst(100) ); |
| 126262 | 126694 | rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66; |
| 126263 | 126695 | rSortCost = nRow + estLog(nRow) + rScale + 16; |
| 126264 | | - |
| 126265 | | - /* TUNING: The cost of implementing DISTINCT using a B-TREE is |
| 126266 | | - ** similar but with a larger constant of proportionality. |
| 126267 | | - ** Multiply by an additional factor of 3.0. */ |
| 126268 | | - if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ |
| 126269 | | - rSortCost += 16; |
| 126270 | | - } |
| 126271 | | - |
| 126272 | 126696 | return rSortCost; |
| 126273 | 126697 | } |
| 126274 | 126698 | |
| 126275 | 126699 | /* |
| 126276 | 126700 | ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine |
| | @@ -126328,11 +126752,11 @@ |
| 126328 | 126752 | } |
| 126329 | 126753 | |
| 126330 | 126754 | /* Allocate and initialize space for aTo, aFrom and aSortCost[] */ |
| 126331 | 126755 | nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; |
| 126332 | 126756 | nSpace += sizeof(LogEst) * nOrderBy; |
| 126333 | | - pSpace = sqlite3DbMallocRaw(db, nSpace); |
| 126757 | + pSpace = sqlite3DbMallocRawNN(db, nSpace); |
| 126334 | 126758 | if( pSpace==0 ) return SQLITE_NOMEM; |
| 126335 | 126759 | aTo = (WherePath*)pSpace; |
| 126336 | 126760 | aFrom = aTo+mxChoice; |
| 126337 | 126761 | memset(aFrom, 0, sizeof(aFrom[0])); |
| 126338 | 126762 | pX = (WhereLoop**)(aFrom+mxChoice); |
| | @@ -126400,11 +126824,11 @@ |
| 126400 | 126824 | revMask = pFrom->revLoop; |
| 126401 | 126825 | } |
| 126402 | 126826 | if( isOrdered>=0 && isOrdered<nOrderBy ){ |
| 126403 | 126827 | if( aSortCost[isOrdered]==0 ){ |
| 126404 | 126828 | aSortCost[isOrdered] = whereSortingCost( |
| 126405 | | - pWInfo, nRowEst, nOrderBy, isOrdered |
| 126829 | + nRowEst, nOrderBy, isOrdered |
| 126406 | 126830 | ); |
| 126407 | 126831 | } |
| 126408 | 126832 | rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]); |
| 126409 | 126833 | |
| 126410 | 126834 | WHERETRACE(0x002, |
| | @@ -126813,11 +127237,11 @@ |
| 126813 | 127237 | WhereLevel *pLevel; /* A single level in pWInfo->a[] */ |
| 126814 | 127238 | WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ |
| 126815 | 127239 | int ii; /* Loop counter */ |
| 126816 | 127240 | sqlite3 *db; /* Database connection */ |
| 126817 | 127241 | int rc; /* Return code */ |
| 126818 | | - u8 bFordelete = 0; |
| 127242 | + u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */ |
| 126819 | 127243 | |
| 126820 | 127244 | assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || ( |
| 126821 | 127245 | (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 |
| 126822 | 127246 | && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 |
| 126823 | 127247 | )); |
| | @@ -127058,20 +127482,19 @@ |
| 127058 | 127482 | WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); |
| 127059 | 127483 | pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; |
| 127060 | 127484 | |
| 127061 | 127485 | /* If the caller is an UPDATE or DELETE statement that is requesting |
| 127062 | 127486 | ** 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 | 127487 | */ |
| 127066 | 127488 | assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); |
| 127067 | 127489 | if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ |
| 127068 | 127490 | int wsFlags = pWInfo->a[0].pWLoop->wsFlags; |
| 127069 | 127491 | int bOnerow = (wsFlags & WHERE_ONEROW)!=0; |
| 127070 | | - if( bOnerow || ( (wctrlFlags & WHERE_ONEPASS_MULTIROW) |
| 127071 | | - && 0==(wsFlags & WHERE_VIRTUALTABLE) |
| 127072 | | - )){ |
| 127492 | + if( bOnerow |
| 127493 | + || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0 |
| 127494 | + && 0==(wsFlags & WHERE_VIRTUALTABLE)) |
| 127495 | + ){ |
| 127073 | 127496 | pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; |
| 127074 | 127497 | if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ |
| 127075 | 127498 | if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ |
| 127076 | 127499 | bFordelete = OPFLAG_FORDELETE; |
| 127077 | 127500 | } |
| | @@ -127511,10 +127934,19 @@ |
| 127511 | 127934 | /* |
| 127512 | 127935 | ** An instance of this structure holds the ATTACH key and the key type. |
| 127513 | 127936 | */ |
| 127514 | 127937 | struct AttachKey { int type; Token key; }; |
| 127515 | 127938 | |
| 127939 | +/* |
| 127940 | +** Disable lookaside memory allocation for objects that might be |
| 127941 | +** shared across database connections. |
| 127942 | +*/ |
| 127943 | +static void disableLookaside(Parse *pParse){ |
| 127944 | + pParse->disableLookaside++; |
| 127945 | + pParse->db->lookaside.bDisable++; |
| 127946 | +} |
| 127947 | + |
| 127516 | 127948 | |
| 127517 | 127949 | /* |
| 127518 | 127950 | ** For a compound SELECT statement, make sure p->pPrior->pNext==p for |
| 127519 | 127951 | ** all elements in the list. And make sure list length does not exceed |
| 127520 | 127952 | ** SQLITE_LIMIT_COMPOUND_SELECT. |
| | @@ -127593,11 +128025,11 @@ |
| 127593 | 128025 | |
| 127594 | 128026 | /* A routine to convert a binary TK_IS or TK_ISNOT expression into a |
| 127595 | 128027 | ** unary TK_ISNULL or TK_NOTNULL expression. */ |
| 127596 | 128028 | static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ |
| 127597 | 128029 | sqlite3 *db = pParse->db; |
| 127598 | | - if( pY && pA && pY->op==TK_NULL ){ |
| 128030 | + if( pA && pY && pY->op==TK_NULL ){ |
| 127599 | 128031 | pA->op = (u8)op; |
| 127600 | 128032 | sqlite3ExprDelete(db, pA->pRight); |
| 127601 | 128033 | pA->pRight = 0; |
| 127602 | 128034 | } |
| 127603 | 128035 | } |
| | @@ -129635,11 +130067,11 @@ |
| 129635 | 130067 | sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); |
| 129636 | 130068 | } |
| 129637 | 130069 | break; |
| 129638 | 130070 | case 27: /* createkw ::= CREATE */ |
| 129639 | 130071 | { |
| 129640 | | - pParse->db->lookaside.bEnabled = 0; |
| 130072 | + disableLookaside(pParse); |
| 129641 | 130073 | yygotominor.yy0 = yymsp[0].minor.yy0; |
| 129642 | 130074 | } |
| 129643 | 130075 | break; |
| 129644 | 130076 | case 28: /* ifnotexists ::= */ |
| 129645 | 130077 | case 31: /* temp ::= */ yytestcase(yyruleno==31); |
| | @@ -130717,11 +131149,11 @@ |
| 130717 | 131149 | sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); |
| 130718 | 131150 | } |
| 130719 | 131151 | break; |
| 130720 | 131152 | case 307: /* add_column_fullname ::= fullname */ |
| 130721 | 131153 | { |
| 130722 | | - pParse->db->lookaside.bEnabled = 0; |
| 131154 | + disableLookaside(pParse); |
| 130723 | 131155 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); |
| 130724 | 131156 | } |
| 130725 | 131157 | break; |
| 130726 | 131158 | case 310: /* cmd ::= create_vtab */ |
| 130727 | 131159 | {sqlite3VtabFinishParse(pParse,0);} |
| | @@ -131097,16 +131529,96 @@ |
| 131097 | 131529 | ** parser for analysis. |
| 131098 | 131530 | */ |
| 131099 | 131531 | /* #include "sqliteInt.h" */ |
| 131100 | 131532 | /* #include <stdlib.h> */ |
| 131101 | 131533 | |
| 131534 | +/* Character classes for tokenizing |
| 131535 | +** |
| 131536 | +** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented |
| 131537 | +** using a lookup table, whereas a switch() directly on c uses a binary search. |
| 131538 | +** The lookup table is much faster. To maximize speed, and to ensure that |
| 131539 | +** a lookup table is used, all of the classes need to be small integers and |
| 131540 | +** all of them need to be used within the switch. |
| 131541 | +*/ |
| 131542 | +#define CC_X 0 /* The letter 'x', or start of BLOB literal */ |
| 131543 | +#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */ |
| 131544 | +#define CC_ID 2 /* unicode characters usable in IDs */ |
| 131545 | +#define CC_DIGIT 3 /* Digits */ |
| 131546 | +#define CC_DOLLAR 4 /* '$' */ |
| 131547 | +#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */ |
| 131548 | +#define CC_VARNUM 6 /* '?'. Numeric SQL variables */ |
| 131549 | +#define CC_SPACE 7 /* Space characters */ |
| 131550 | +#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */ |
| 131551 | +#define CC_QUOTE2 9 /* '['. [...] style quoted ids */ |
| 131552 | +#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */ |
| 131553 | +#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */ |
| 131554 | +#define CC_LT 12 /* '<'. Part of < or <= or <> */ |
| 131555 | +#define CC_GT 13 /* '>'. Part of > or >= */ |
| 131556 | +#define CC_EQ 14 /* '='. Part of = or == */ |
| 131557 | +#define CC_BANG 15 /* '!'. Part of != */ |
| 131558 | +#define CC_SLASH 16 /* '/'. / or c-style comment */ |
| 131559 | +#define CC_LP 17 /* '(' */ |
| 131560 | +#define CC_RP 18 /* ')' */ |
| 131561 | +#define CC_SEMI 19 /* ';' */ |
| 131562 | +#define CC_PLUS 20 /* '+' */ |
| 131563 | +#define CC_STAR 21 /* '*' */ |
| 131564 | +#define CC_PERCENT 22 /* '%' */ |
| 131565 | +#define CC_COMMA 23 /* ',' */ |
| 131566 | +#define CC_AND 24 /* '&' */ |
| 131567 | +#define CC_TILDA 25 /* '~' */ |
| 131568 | +#define CC_DOT 26 /* '.' */ |
| 131569 | +#define CC_ILLEGAL 27 /* Illegal character */ |
| 131570 | + |
| 131571 | +static const unsigned char aiClass[] = { |
| 131572 | +#ifdef SQLITE_ASCII |
| 131573 | +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ |
| 131574 | +/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, |
| 131575 | +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131576 | +/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, |
| 131577 | +/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, |
| 131578 | +/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 131579 | +/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1, |
| 131580 | +/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 131581 | +/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27, |
| 131582 | +/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131583 | +/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131584 | +/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131585 | +/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131586 | +/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131587 | +/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131588 | +/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 131589 | +/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 |
| 131590 | +#endif |
| 131591 | +#ifdef SQLITE_EBCDIC |
| 131592 | +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ |
| 131593 | +/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27, |
| 131594 | +/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131595 | +/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131596 | +/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, |
| 131597 | +/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 12, 17, 20, 10, |
| 131598 | +/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27, |
| 131599 | +/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 7, |
| 131600 | +/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8, |
| 131601 | +/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131602 | +/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131603 | +/* 9x */ 25, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131604 | +/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, |
| 131605 | +/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131606 | +/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131607 | +/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, |
| 131608 | +/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, |
| 131609 | +#endif |
| 131610 | +}; |
| 131611 | + |
| 131102 | 131612 | /* |
| 131103 | | -** The charMap() macro maps alphabetic characters into their |
| 131613 | +** The charMap() macro maps alphabetic characters (only) into their |
| 131104 | 131614 | ** lower-case ASCII equivalent. On ASCII machines, this is just |
| 131105 | 131615 | ** 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. |
| 131616 | +** to adjust the encoding. The mapping is only valid for alphabetics |
| 131617 | +** which are the only characters for which this feature is used. |
| 131618 | +** |
| 131619 | +** Used by keywordhash.h |
| 131108 | 131620 | */ |
| 131109 | 131621 | #ifdef SQLITE_ASCII |
| 131110 | 131622 | # define charMap(X) sqlite3UpperToLower[(unsigned char)X] |
| 131111 | 131623 | #endif |
| 131112 | 131624 | #ifdef SQLITE_EBCDIC |
| | @@ -131136,11 +131648,11 @@ |
| 131136 | 131648 | ** The sqlite3KeywordCode function looks up an identifier to determine if |
| 131137 | 131649 | ** it is a keyword. If it is a keyword, the token code of that keyword is |
| 131138 | 131650 | ** returned. If the input is not a keyword, TK_ID is returned. |
| 131139 | 131651 | ** |
| 131140 | 131652 | ** The implementation of this routine was generated by a program, |
| 131141 | | -** mkkeywordhash.h, located in the tool subdirectory of the distribution. |
| 131653 | +** mkkeywordhash.c, located in the tool subdirectory of the distribution. |
| 131142 | 131654 | ** The output of the mkkeywordhash.c program is written into a file |
| 131143 | 131655 | ** named keywordhash.h and then included into this source file by |
| 131144 | 131656 | ** the #include below. |
| 131145 | 131657 | */ |
| 131146 | 131658 | /************** Include keywordhash.h in the middle of tokenize.c ************/ |
| | @@ -131277,142 +131789,151 @@ |
| 131277 | 131789 | TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, |
| 131278 | 131790 | TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, |
| 131279 | 131791 | TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, |
| 131280 | 131792 | TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, |
| 131281 | 131793 | }; |
| 131282 | | - int h, i; |
| 131794 | + int i, j; |
| 131795 | + const char *zKW; |
| 131283 | 131796 | 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 | | - } |
| 131797 | + i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; |
| 131798 | + for(i=((int)aHash[i])-1; i>=0; i=((int)aNext[i])-1){ |
| 131799 | + if( aLen[i]!=n ) continue; |
| 131800 | + j = 0; |
| 131801 | + zKW = &zText[aOffset[i]]; |
| 131802 | +#ifdef SQLITE_ASCII |
| 131803 | + while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; } |
| 131804 | +#endif |
| 131805 | +#ifdef SQLITE_EBCDIC |
| 131806 | + while( j<n && toupper(z[j])==zKW[j] ){ j++; } |
| 131807 | +#endif |
| 131808 | + if( j<n ) continue; |
| 131809 | + testcase( i==0 ); /* REINDEX */ |
| 131810 | + testcase( i==1 ); /* INDEXED */ |
| 131811 | + testcase( i==2 ); /* INDEX */ |
| 131812 | + testcase( i==3 ); /* DESC */ |
| 131813 | + testcase( i==4 ); /* ESCAPE */ |
| 131814 | + testcase( i==5 ); /* EACH */ |
| 131815 | + testcase( i==6 ); /* CHECK */ |
| 131816 | + testcase( i==7 ); /* KEY */ |
| 131817 | + testcase( i==8 ); /* BEFORE */ |
| 131818 | + testcase( i==9 ); /* FOREIGN */ |
| 131819 | + testcase( i==10 ); /* FOR */ |
| 131820 | + testcase( i==11 ); /* IGNORE */ |
| 131821 | + testcase( i==12 ); /* REGEXP */ |
| 131822 | + testcase( i==13 ); /* EXPLAIN */ |
| 131823 | + testcase( i==14 ); /* INSTEAD */ |
| 131824 | + testcase( i==15 ); /* ADD */ |
| 131825 | + testcase( i==16 ); /* DATABASE */ |
| 131826 | + testcase( i==17 ); /* AS */ |
| 131827 | + testcase( i==18 ); /* SELECT */ |
| 131828 | + testcase( i==19 ); /* TABLE */ |
| 131829 | + testcase( i==20 ); /* LEFT */ |
| 131830 | + testcase( i==21 ); /* THEN */ |
| 131831 | + testcase( i==22 ); /* END */ |
| 131832 | + testcase( i==23 ); /* DEFERRABLE */ |
| 131833 | + testcase( i==24 ); /* ELSE */ |
| 131834 | + testcase( i==25 ); /* EXCEPT */ |
| 131835 | + testcase( i==26 ); /* TRANSACTION */ |
| 131836 | + testcase( i==27 ); /* ACTION */ |
| 131837 | + testcase( i==28 ); /* ON */ |
| 131838 | + testcase( i==29 ); /* NATURAL */ |
| 131839 | + testcase( i==30 ); /* ALTER */ |
| 131840 | + testcase( i==31 ); /* RAISE */ |
| 131841 | + testcase( i==32 ); /* EXCLUSIVE */ |
| 131842 | + testcase( i==33 ); /* EXISTS */ |
| 131843 | + testcase( i==34 ); /* SAVEPOINT */ |
| 131844 | + testcase( i==35 ); /* INTERSECT */ |
| 131845 | + testcase( i==36 ); /* TRIGGER */ |
| 131846 | + testcase( i==37 ); /* REFERENCES */ |
| 131847 | + testcase( i==38 ); /* CONSTRAINT */ |
| 131848 | + testcase( i==39 ); /* INTO */ |
| 131849 | + testcase( i==40 ); /* OFFSET */ |
| 131850 | + testcase( i==41 ); /* OF */ |
| 131851 | + testcase( i==42 ); /* SET */ |
| 131852 | + testcase( i==43 ); /* TEMPORARY */ |
| 131853 | + testcase( i==44 ); /* TEMP */ |
| 131854 | + testcase( i==45 ); /* OR */ |
| 131855 | + testcase( i==46 ); /* UNIQUE */ |
| 131856 | + testcase( i==47 ); /* QUERY */ |
| 131857 | + testcase( i==48 ); /* WITHOUT */ |
| 131858 | + testcase( i==49 ); /* WITH */ |
| 131859 | + testcase( i==50 ); /* OUTER */ |
| 131860 | + testcase( i==51 ); /* RELEASE */ |
| 131861 | + testcase( i==52 ); /* ATTACH */ |
| 131862 | + testcase( i==53 ); /* HAVING */ |
| 131863 | + testcase( i==54 ); /* GROUP */ |
| 131864 | + testcase( i==55 ); /* UPDATE */ |
| 131865 | + testcase( i==56 ); /* BEGIN */ |
| 131866 | + testcase( i==57 ); /* INNER */ |
| 131867 | + testcase( i==58 ); /* RECURSIVE */ |
| 131868 | + testcase( i==59 ); /* BETWEEN */ |
| 131869 | + testcase( i==60 ); /* NOTNULL */ |
| 131870 | + testcase( i==61 ); /* NOT */ |
| 131871 | + testcase( i==62 ); /* NO */ |
| 131872 | + testcase( i==63 ); /* NULL */ |
| 131873 | + testcase( i==64 ); /* LIKE */ |
| 131874 | + testcase( i==65 ); /* CASCADE */ |
| 131875 | + testcase( i==66 ); /* ASC */ |
| 131876 | + testcase( i==67 ); /* DELETE */ |
| 131877 | + testcase( i==68 ); /* CASE */ |
| 131878 | + testcase( i==69 ); /* COLLATE */ |
| 131879 | + testcase( i==70 ); /* CREATE */ |
| 131880 | + testcase( i==71 ); /* CURRENT_DATE */ |
| 131881 | + testcase( i==72 ); /* DETACH */ |
| 131882 | + testcase( i==73 ); /* IMMEDIATE */ |
| 131883 | + testcase( i==74 ); /* JOIN */ |
| 131884 | + testcase( i==75 ); /* INSERT */ |
| 131885 | + testcase( i==76 ); /* MATCH */ |
| 131886 | + testcase( i==77 ); /* PLAN */ |
| 131887 | + testcase( i==78 ); /* ANALYZE */ |
| 131888 | + testcase( i==79 ); /* PRAGMA */ |
| 131889 | + testcase( i==80 ); /* ABORT */ |
| 131890 | + testcase( i==81 ); /* VALUES */ |
| 131891 | + testcase( i==82 ); /* VIRTUAL */ |
| 131892 | + testcase( i==83 ); /* LIMIT */ |
| 131893 | + testcase( i==84 ); /* WHEN */ |
| 131894 | + testcase( i==85 ); /* WHERE */ |
| 131895 | + testcase( i==86 ); /* RENAME */ |
| 131896 | + testcase( i==87 ); /* AFTER */ |
| 131897 | + testcase( i==88 ); /* REPLACE */ |
| 131898 | + testcase( i==89 ); /* AND */ |
| 131899 | + testcase( i==90 ); /* DEFAULT */ |
| 131900 | + testcase( i==91 ); /* AUTOINCREMENT */ |
| 131901 | + testcase( i==92 ); /* TO */ |
| 131902 | + testcase( i==93 ); /* IN */ |
| 131903 | + testcase( i==94 ); /* CAST */ |
| 131904 | + testcase( i==95 ); /* COLUMN */ |
| 131905 | + testcase( i==96 ); /* COMMIT */ |
| 131906 | + testcase( i==97 ); /* CONFLICT */ |
| 131907 | + testcase( i==98 ); /* CROSS */ |
| 131908 | + testcase( i==99 ); /* CURRENT_TIMESTAMP */ |
| 131909 | + testcase( i==100 ); /* CURRENT_TIME */ |
| 131910 | + testcase( i==101 ); /* PRIMARY */ |
| 131911 | + testcase( i==102 ); /* DEFERRED */ |
| 131912 | + testcase( i==103 ); /* DISTINCT */ |
| 131913 | + testcase( i==104 ); /* IS */ |
| 131914 | + testcase( i==105 ); /* DROP */ |
| 131915 | + testcase( i==106 ); /* FAIL */ |
| 131916 | + testcase( i==107 ); /* FROM */ |
| 131917 | + testcase( i==108 ); /* FULL */ |
| 131918 | + testcase( i==109 ); /* GLOB */ |
| 131919 | + testcase( i==110 ); /* BY */ |
| 131920 | + testcase( i==111 ); /* IF */ |
| 131921 | + testcase( i==112 ); /* ISNULL */ |
| 131922 | + testcase( i==113 ); /* ORDER */ |
| 131923 | + testcase( i==114 ); /* RESTRICT */ |
| 131924 | + testcase( i==115 ); /* RIGHT */ |
| 131925 | + testcase( i==116 ); /* ROLLBACK */ |
| 131926 | + testcase( i==117 ); /* ROW */ |
| 131927 | + testcase( i==118 ); /* UNION */ |
| 131928 | + testcase( i==119 ); /* USING */ |
| 131929 | + testcase( i==120 ); /* VACUUM */ |
| 131930 | + testcase( i==121 ); /* VIEW */ |
| 131931 | + testcase( i==122 ); /* INITIALLY */ |
| 131932 | + testcase( i==123 ); /* ALL */ |
| 131933 | + *pType = aCode[i]; |
| 131934 | + break; |
| 131414 | 131935 | } |
| 131415 | 131936 | } |
| 131416 | 131937 | return n; |
| 131417 | 131938 | } |
| 131418 | 131939 | SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ |
| | @@ -131469,74 +131990,76 @@ |
| 131469 | 131990 | SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } |
| 131470 | 131991 | #endif |
| 131471 | 131992 | |
| 131472 | 131993 | |
| 131473 | 131994 | /* |
| 131474 | | -** Return the length of the token that begins at z[0]. |
| 131995 | +** Return the length (in bytes) of the token that begins at z[0]. |
| 131475 | 131996 | ** Store the token type in *tokenType before returning. |
| 131476 | 131997 | */ |
| 131477 | 131998 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ |
| 131478 | 131999 | int i, c; |
| 131479 | | - switch( *z ){ |
| 131480 | | - case ' ': case '\t': case '\n': case '\f': case '\r': { |
| 132000 | + switch( aiClass[*z] ){ /* Switch on the character-class of the first byte |
| 132001 | + ** of the token. See the comment on the CC_ defines |
| 132002 | + ** above. */ |
| 132003 | + case CC_SPACE: { |
| 131481 | 132004 | testcase( z[0]==' ' ); |
| 131482 | 132005 | testcase( z[0]=='\t' ); |
| 131483 | 132006 | testcase( z[0]=='\n' ); |
| 131484 | 132007 | testcase( z[0]=='\f' ); |
| 131485 | 132008 | testcase( z[0]=='\r' ); |
| 131486 | 132009 | for(i=1; sqlite3Isspace(z[i]); i++){} |
| 131487 | 132010 | *tokenType = TK_SPACE; |
| 131488 | 132011 | return i; |
| 131489 | 132012 | } |
| 131490 | | - case '-': { |
| 132013 | + case CC_MINUS: { |
| 131491 | 132014 | if( z[1]=='-' ){ |
| 131492 | 132015 | for(i=2; (c=z[i])!=0 && c!='\n'; i++){} |
| 131493 | 132016 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131494 | 132017 | return i; |
| 131495 | 132018 | } |
| 131496 | 132019 | *tokenType = TK_MINUS; |
| 131497 | 132020 | return 1; |
| 131498 | 132021 | } |
| 131499 | | - case '(': { |
| 132022 | + case CC_LP: { |
| 131500 | 132023 | *tokenType = TK_LP; |
| 131501 | 132024 | return 1; |
| 131502 | 132025 | } |
| 131503 | | - case ')': { |
| 132026 | + case CC_RP: { |
| 131504 | 132027 | *tokenType = TK_RP; |
| 131505 | 132028 | return 1; |
| 131506 | 132029 | } |
| 131507 | | - case ';': { |
| 132030 | + case CC_SEMI: { |
| 131508 | 132031 | *tokenType = TK_SEMI; |
| 131509 | 132032 | return 1; |
| 131510 | 132033 | } |
| 131511 | | - case '+': { |
| 132034 | + case CC_PLUS: { |
| 131512 | 132035 | *tokenType = TK_PLUS; |
| 131513 | 132036 | return 1; |
| 131514 | 132037 | } |
| 131515 | | - case '*': { |
| 132038 | + case CC_STAR: { |
| 131516 | 132039 | *tokenType = TK_STAR; |
| 131517 | 132040 | return 1; |
| 131518 | 132041 | } |
| 131519 | | - case '/': { |
| 132042 | + case CC_SLASH: { |
| 131520 | 132043 | if( z[1]!='*' || z[2]==0 ){ |
| 131521 | 132044 | *tokenType = TK_SLASH; |
| 131522 | 132045 | return 1; |
| 131523 | 132046 | } |
| 131524 | 132047 | for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} |
| 131525 | 132048 | if( c ) i++; |
| 131526 | 132049 | *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
| 131527 | 132050 | return i; |
| 131528 | 132051 | } |
| 131529 | | - case '%': { |
| 132052 | + case CC_PERCENT: { |
| 131530 | 132053 | *tokenType = TK_REM; |
| 131531 | 132054 | return 1; |
| 131532 | 132055 | } |
| 131533 | | - case '=': { |
| 132056 | + case CC_EQ: { |
| 131534 | 132057 | *tokenType = TK_EQ; |
| 131535 | 132058 | return 1 + (z[1]=='='); |
| 131536 | 132059 | } |
| 131537 | | - case '<': { |
| 132060 | + case CC_LT: { |
| 131538 | 132061 | if( (c=z[1])=='=' ){ |
| 131539 | 132062 | *tokenType = TK_LE; |
| 131540 | 132063 | return 2; |
| 131541 | 132064 | }else if( c=='>' ){ |
| 131542 | 132065 | *tokenType = TK_NE; |
| | @@ -131547,11 +132070,11 @@ |
| 131547 | 132070 | }else{ |
| 131548 | 132071 | *tokenType = TK_LT; |
| 131549 | 132072 | return 1; |
| 131550 | 132073 | } |
| 131551 | 132074 | } |
| 131552 | | - case '>': { |
| 132075 | + case CC_GT: { |
| 131553 | 132076 | if( (c=z[1])=='=' ){ |
| 131554 | 132077 | *tokenType = TK_GE; |
| 131555 | 132078 | return 2; |
| 131556 | 132079 | }else if( c=='>' ){ |
| 131557 | 132080 | *tokenType = TK_RSHIFT; |
| | @@ -131559,43 +132082,41 @@ |
| 131559 | 132082 | }else{ |
| 131560 | 132083 | *tokenType = TK_GT; |
| 131561 | 132084 | return 1; |
| 131562 | 132085 | } |
| 131563 | 132086 | } |
| 131564 | | - case '!': { |
| 132087 | + case CC_BANG: { |
| 131565 | 132088 | if( z[1]!='=' ){ |
| 131566 | 132089 | *tokenType = TK_ILLEGAL; |
| 131567 | 132090 | return 2; |
| 131568 | 132091 | }else{ |
| 131569 | 132092 | *tokenType = TK_NE; |
| 131570 | 132093 | return 2; |
| 131571 | 132094 | } |
| 131572 | 132095 | } |
| 131573 | | - case '|': { |
| 132096 | + case CC_PIPE: { |
| 131574 | 132097 | if( z[1]!='|' ){ |
| 131575 | 132098 | *tokenType = TK_BITOR; |
| 131576 | 132099 | return 1; |
| 131577 | 132100 | }else{ |
| 131578 | 132101 | *tokenType = TK_CONCAT; |
| 131579 | 132102 | return 2; |
| 131580 | 132103 | } |
| 131581 | 132104 | } |
| 131582 | | - case ',': { |
| 132105 | + case CC_COMMA: { |
| 131583 | 132106 | *tokenType = TK_COMMA; |
| 131584 | 132107 | return 1; |
| 131585 | 132108 | } |
| 131586 | | - case '&': { |
| 132109 | + case CC_AND: { |
| 131587 | 132110 | *tokenType = TK_BITAND; |
| 131588 | 132111 | return 1; |
| 131589 | 132112 | } |
| 131590 | | - case '~': { |
| 132113 | + case CC_TILDA: { |
| 131591 | 132114 | *tokenType = TK_BITNOT; |
| 131592 | 132115 | return 1; |
| 131593 | 132116 | } |
| 131594 | | - case '`': |
| 131595 | | - case '\'': |
| 131596 | | - case '"': { |
| 132117 | + case CC_QUOTE: { |
| 131597 | 132118 | int delim = z[0]; |
| 131598 | 132119 | testcase( delim=='`' ); |
| 131599 | 132120 | testcase( delim=='\'' ); |
| 131600 | 132121 | testcase( delim=='"' ); |
| 131601 | 132122 | for(i=1; (c=z[i])!=0; i++){ |
| | @@ -131616,11 +132137,11 @@ |
| 131616 | 132137 | }else{ |
| 131617 | 132138 | *tokenType = TK_ILLEGAL; |
| 131618 | 132139 | return i; |
| 131619 | 132140 | } |
| 131620 | 132141 | } |
| 131621 | | - case '.': { |
| 132142 | + case CC_DOT: { |
| 131622 | 132143 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 131623 | 132144 | if( !sqlite3Isdigit(z[1]) ) |
| 131624 | 132145 | #endif |
| 131625 | 132146 | { |
| 131626 | 132147 | *tokenType = TK_DOT; |
| | @@ -131627,12 +132148,11 @@ |
| 131627 | 132148 | return 1; |
| 131628 | 132149 | } |
| 131629 | 132150 | /* If the next character is a digit, this is a floating point |
| 131630 | 132151 | ** number that begins with ".". Fall thru into the next case */ |
| 131631 | 132152 | } |
| 131632 | | - case '0': case '1': case '2': case '3': case '4': |
| 131633 | | - case '5': case '6': case '7': case '8': case '9': { |
| 132153 | + case CC_DIGIT: { |
| 131634 | 132154 | testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); |
| 131635 | 132155 | testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); |
| 131636 | 132156 | testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); |
| 131637 | 132157 | testcase( z[0]=='9' ); |
| 131638 | 132158 | *tokenType = TK_INTEGER; |
| | @@ -131663,26 +132183,22 @@ |
| 131663 | 132183 | *tokenType = TK_ILLEGAL; |
| 131664 | 132184 | i++; |
| 131665 | 132185 | } |
| 131666 | 132186 | return i; |
| 131667 | 132187 | } |
| 131668 | | - case '[': { |
| 132188 | + case CC_QUOTE2: { |
| 131669 | 132189 | for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} |
| 131670 | 132190 | *tokenType = c==']' ? TK_ID : TK_ILLEGAL; |
| 131671 | 132191 | return i; |
| 131672 | 132192 | } |
| 131673 | | - case '?': { |
| 132193 | + case CC_VARNUM: { |
| 131674 | 132194 | *tokenType = TK_VARIABLE; |
| 131675 | 132195 | for(i=1; sqlite3Isdigit(z[i]); i++){} |
| 131676 | 132196 | return i; |
| 131677 | 132197 | } |
| 131678 | | -#ifndef SQLITE_OMIT_TCL_VARIABLE |
| 131679 | | - case '$': |
| 131680 | | -#endif |
| 131681 | | - case '@': /* For compatibility with MS SQL Server */ |
| 131682 | | - case '#': |
| 131683 | | - case ':': { |
| 132198 | + case CC_DOLLAR: |
| 132199 | + case CC_VARALPHA: { |
| 131684 | 132200 | int n = 0; |
| 131685 | 132201 | testcase( z[0]=='$' ); testcase( z[0]=='@' ); |
| 131686 | 132202 | testcase( z[0]==':' ); testcase( z[0]=='#' ); |
| 131687 | 132203 | *tokenType = TK_VARIABLE; |
| 131688 | 132204 | for(i=1; (c=z[i])!=0; i++){ |
| | @@ -131707,12 +132223,24 @@ |
| 131707 | 132223 | } |
| 131708 | 132224 | } |
| 131709 | 132225 | if( n==0 ) *tokenType = TK_ILLEGAL; |
| 131710 | 132226 | return i; |
| 131711 | 132227 | } |
| 132228 | + case CC_KYWD: { |
| 132229 | + for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} |
| 132230 | + if( IdChar(z[i]) ){ |
| 132231 | + /* This token started out using characters that can appear in keywords, |
| 132232 | + ** but z[i] is a character not allowed within keywords, so this must |
| 132233 | + ** be an identifier instead */ |
| 132234 | + i++; |
| 132235 | + break; |
| 132236 | + } |
| 132237 | + *tokenType = TK_ID; |
| 132238 | + return keywordCode((char*)z, i, tokenType); |
| 132239 | + } |
| 131712 | 132240 | #ifndef SQLITE_OMIT_BLOB_LITERAL |
| 131713 | | - case 'x': case 'X': { |
| 132241 | + case CC_X: { |
| 131714 | 132242 | testcase( z[0]=='x' ); testcase( z[0]=='X' ); |
| 131715 | 132243 | if( z[1]=='\'' ){ |
| 131716 | 132244 | *tokenType = TK_BLOB; |
| 131717 | 132245 | for(i=2; sqlite3Isxdigit(z[i]); i++){} |
| 131718 | 132246 | if( z[i]!='\'' || i%2 ){ |
| | @@ -131720,24 +132248,26 @@ |
| 131720 | 132248 | while( z[i] && z[i]!='\'' ){ i++; } |
| 131721 | 132249 | } |
| 131722 | 132250 | if( z[i] ) i++; |
| 131723 | 132251 | return i; |
| 131724 | 132252 | } |
| 131725 | | - /* Otherwise fall through to the next case */ |
| 132253 | + /* If it is not a BLOB literal, then it must be an ID, since no |
| 132254 | + ** SQL keywords start with the letter 'x'. Fall through */ |
| 131726 | 132255 | } |
| 131727 | 132256 | #endif |
| 132257 | + case CC_ID: { |
| 132258 | + i = 1; |
| 132259 | + break; |
| 132260 | + } |
| 131728 | 132261 | 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); |
| 132262 | + *tokenType = TK_ILLEGAL; |
| 132263 | + return 1; |
| 131735 | 132264 | } |
| 131736 | 132265 | } |
| 131737 | | - *tokenType = TK_ILLEGAL; |
| 131738 | | - return 1; |
| 132266 | + while( IdChar(z[i]) ){ i++; } |
| 132267 | + *tokenType = TK_ID; |
| 132268 | + return i; |
| 131739 | 132269 | } |
| 131740 | 132270 | |
| 131741 | 132271 | /* |
| 131742 | 132272 | ** Run the parser on the given SQL string. The parser structure is |
| 131743 | 132273 | ** passed in. An SQLITE_ status code is returned. If an error occurs |
| | @@ -131749,11 +132279,10 @@ |
| 131749 | 132279 | int nErr = 0; /* Number of errors encountered */ |
| 131750 | 132280 | int i; /* Loop counter */ |
| 131751 | 132281 | void *pEngine; /* The LEMON-generated LALR(1) parser */ |
| 131752 | 132282 | int tokenType; /* type of the next token */ |
| 131753 | 132283 | int lastTokenParsed = -1; /* type of the previous token */ |
| 131754 | | - u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 131755 | 132284 | sqlite3 *db = pParse->db; /* The database connection */ |
| 131756 | 132285 | int mxSqlLen; /* Max length of an SQL string */ |
| 131757 | 132286 | |
| 131758 | 132287 | assert( zSql!=0 ); |
| 131759 | 132288 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| | @@ -131765,20 +132294,18 @@ |
| 131765 | 132294 | i = 0; |
| 131766 | 132295 | assert( pzErrMsg!=0 ); |
| 131767 | 132296 | /* sqlite3ParserTrace(stdout, "parser: "); */ |
| 131768 | 132297 | pEngine = sqlite3ParserAlloc(sqlite3Malloc); |
| 131769 | 132298 | if( pEngine==0 ){ |
| 131770 | | - db->mallocFailed = 1; |
| 132299 | + sqlite3OomFault(db); |
| 131771 | 132300 | return SQLITE_NOMEM; |
| 131772 | 132301 | } |
| 131773 | 132302 | assert( pParse->pNewTable==0 ); |
| 131774 | 132303 | assert( pParse->pNewTrigger==0 ); |
| 131775 | 132304 | assert( pParse->nVar==0 ); |
| 131776 | 132305 | assert( pParse->nzVar==0 ); |
| 131777 | 132306 | assert( pParse->azVar==0 ); |
| 131778 | | - enableLookaside = db->lookaside.bEnabled; |
| 131779 | | - if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; |
| 131780 | 132307 | while( zSql[i]!=0 ){ |
| 131781 | 132308 | assert( i>=0 ); |
| 131782 | 132309 | pParse->sLastToken.z = &zSql[i]; |
| 131783 | 132310 | pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); |
| 131784 | 132311 | i += pParse->sLastToken.n; |
| | @@ -131787,11 +132314,10 @@ |
| 131787 | 132314 | break; |
| 131788 | 132315 | } |
| 131789 | 132316 | if( tokenType>=TK_SPACE ){ |
| 131790 | 132317 | assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); |
| 131791 | 132318 | if( db->u1.isInterrupted ){ |
| 131792 | | - sqlite3ErrorMsg(pParse, "interrupt"); |
| 131793 | 132319 | pParse->rc = SQLITE_INTERRUPT; |
| 131794 | 132320 | break; |
| 131795 | 132321 | } |
| 131796 | 132322 | if( tokenType==TK_ILLEGAL ){ |
| 131797 | 132323 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", |
| | @@ -131822,11 +132348,10 @@ |
| 131822 | 132348 | sqlite3ParserStackPeak(pEngine) |
| 131823 | 132349 | ); |
| 131824 | 132350 | sqlite3_mutex_leave(sqlite3MallocMutex()); |
| 131825 | 132351 | #endif /* YYDEBUG */ |
| 131826 | 132352 | sqlite3ParserFree(pEngine, sqlite3_free); |
| 131827 | | - db->lookaside.bEnabled = enableLookaside; |
| 131828 | 132353 | if( db->mallocFailed ){ |
| 131829 | 132354 | pParse->rc = SQLITE_NOMEM; |
| 131830 | 132355 | } |
| 131831 | 132356 | if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ |
| 131832 | 132357 | pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); |
| | @@ -132963,16 +133488,16 @@ |
| 132963 | 133488 | p->pNext = db->lookaside.pFree; |
| 132964 | 133489 | db->lookaside.pFree = p; |
| 132965 | 133490 | p = (LookasideSlot*)&((u8*)p)[sz]; |
| 132966 | 133491 | } |
| 132967 | 133492 | db->lookaside.pEnd = p; |
| 132968 | | - db->lookaside.bEnabled = 1; |
| 133493 | + db->lookaside.bDisable = 0; |
| 132969 | 133494 | db->lookaside.bMalloced = pBuf==0 ?1:0; |
| 132970 | 133495 | }else{ |
| 132971 | 133496 | db->lookaside.pStart = db; |
| 132972 | 133497 | db->lookaside.pEnd = db; |
| 132973 | | - db->lookaside.bEnabled = 0; |
| 133498 | + db->lookaside.bDisable = 1; |
| 132974 | 133499 | db->lookaside.bMalloced = 0; |
| 132975 | 133500 | } |
| 132976 | 133501 | #endif /* SQLITE_OMIT_LOOKASIDE */ |
| 132977 | 133502 | return SQLITE_OK; |
| 132978 | 133503 | } |
| | @@ -134473,11 +134998,11 @@ |
| 134473 | 134998 | /* A malloc() may have failed within the call to sqlite3_value_text16() |
| 134474 | 134999 | ** above. If this is the case, then the db->mallocFailed flag needs to |
| 134475 | 135000 | ** be cleared before returning. Do this directly, instead of via |
| 134476 | 135001 | ** sqlite3ApiExit(), to avoid setting the database handle error message. |
| 134477 | 135002 | */ |
| 134478 | | - db->mallocFailed = 0; |
| 135003 | + sqlite3OomClear(db); |
| 134479 | 135004 | } |
| 134480 | 135005 | sqlite3_mutex_leave(db->mutex); |
| 134481 | 135006 | return z; |
| 134482 | 135007 | } |
| 134483 | 135008 | #endif /* SQLITE_OMIT_UTF16 */ |
| | @@ -135111,11 +135636,11 @@ |
| 135111 | 135636 | |
| 135112 | 135637 | /* Parse the filename/URI argument. */ |
| 135113 | 135638 | db->openFlags = flags; |
| 135114 | 135639 | rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); |
| 135115 | 135640 | if( rc!=SQLITE_OK ){ |
| 135116 | | - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
| 135641 | + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
| 135117 | 135642 | sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); |
| 135118 | 135643 | sqlite3_free(zErrMsg); |
| 135119 | 135644 | goto opendb_out; |
| 135120 | 135645 | } |
| 135121 | 135646 | |
| | @@ -135831,11 +136356,11 @@ |
| 135831 | 136356 | ** process aborts. If X is false and assert() is disabled, then the |
| 135832 | 136357 | ** return value is zero. |
| 135833 | 136358 | */ |
| 135834 | 136359 | case SQLITE_TESTCTRL_ASSERT: { |
| 135835 | 136360 | volatile int x = 0; |
| 135836 | | - assert( (x = va_arg(ap,int))!=0 ); |
| 136361 | + assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 ); |
| 135837 | 136362 | rc = x; |
| 135838 | 136363 | break; |
| 135839 | 136364 | } |
| 135840 | 136365 | |
| 135841 | 136366 | |
| | @@ -136864,10 +137389,16 @@ |
| 136864 | 137389 | #define _FTSINT_H |
| 136865 | 137390 | |
| 136866 | 137391 | #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 136867 | 137392 | # define NDEBUG 1 |
| 136868 | 137393 | #endif |
| 137394 | + |
| 137395 | +/* FTS3/FTS4 require virtual tables */ |
| 137396 | +#ifdef SQLITE_OMIT_VIRTUALTABLE |
| 137397 | +# undef SQLITE_ENABLE_FTS3 |
| 137398 | +# undef SQLITE_ENABLE_FTS4 |
| 137399 | +#endif |
| 136869 | 137400 | |
| 136870 | 137401 | /* |
| 136871 | 137402 | ** FTS4 is really an extension for FTS3. It is enabled using the |
| 136872 | 137403 | ** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all |
| 136873 | 137404 | ** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. |
| | @@ -146361,10 +146892,11 @@ |
| 146361 | 146892 | |
| 146362 | 146893 | zName = sqlite3_value_text(argv[0]); |
| 146363 | 146894 | nName = sqlite3_value_bytes(argv[0])+1; |
| 146364 | 146895 | |
| 146365 | 146896 | if( argc==2 ){ |
| 146897 | +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER |
| 146366 | 146898 | void *pOld; |
| 146367 | 146899 | int n = sqlite3_value_bytes(argv[1]); |
| 146368 | 146900 | if( zName==0 || n!=sizeof(pPtr) ){ |
| 146369 | 146901 | sqlite3_result_error(context, "argument type mismatch", -1); |
| 146370 | 146902 | return; |
| | @@ -146373,11 +146905,18 @@ |
| 146373 | 146905 | pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); |
| 146374 | 146906 | if( pOld==pPtr ){ |
| 146375 | 146907 | sqlite3_result_error(context, "out of memory", -1); |
| 146376 | 146908 | return; |
| 146377 | 146909 | } |
| 146378 | | - }else{ |
| 146910 | +#else |
| 146911 | + sqlite3_result_error(context, "fts3tokenize: " |
| 146912 | + "disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER", -1 |
| 146913 | + ); |
| 146914 | + return; |
| 146915 | +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ |
| 146916 | + }else |
| 146917 | + { |
| 146379 | 146918 | if( zName ){ |
| 146380 | 146919 | pPtr = sqlite3Fts3HashFind(pHash, zName, nName); |
| 146381 | 146920 | } |
| 146382 | 146921 | if( !pPtr ){ |
| 146383 | 146922 | char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); |
| | @@ -146622,10 +147161,11 @@ |
| 146622 | 147161 | sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); |
| 146623 | 147162 | } |
| 146624 | 147163 | Tcl_DecrRefCount(pRet); |
| 146625 | 147164 | } |
| 146626 | 147165 | |
| 147166 | +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER |
| 146627 | 147167 | static |
| 146628 | 147168 | int registerTokenizer( |
| 146629 | 147169 | sqlite3 *db, |
| 146630 | 147170 | char *zName, |
| 146631 | 147171 | const sqlite3_tokenizer_module *p |
| | @@ -146643,10 +147183,12 @@ |
| 146643 | 147183 | sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); |
| 146644 | 147184 | sqlite3_step(pStmt); |
| 146645 | 147185 | |
| 146646 | 147186 | return sqlite3_finalize(pStmt); |
| 146647 | 147187 | } |
| 147188 | +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ |
| 147189 | + |
| 146648 | 147190 | |
| 146649 | 147191 | static |
| 146650 | 147192 | int queryTokenizer( |
| 146651 | 147193 | sqlite3 *db, |
| 146652 | 147194 | char *zName, |
| | @@ -146714,15 +147256,17 @@ |
| 146714 | 147256 | assert( rc==SQLITE_ERROR ); |
| 146715 | 147257 | assert( p2==0 ); |
| 146716 | 147258 | assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); |
| 146717 | 147259 | |
| 146718 | 147260 | /* Test the storage function */ |
| 147261 | +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER |
| 146719 | 147262 | rc = registerTokenizer(db, "nosuchtokenizer", p1); |
| 146720 | 147263 | assert( rc==SQLITE_OK ); |
| 146721 | 147264 | rc = queryTokenizer(db, "nosuchtokenizer", &p2); |
| 146722 | 147265 | assert( rc==SQLITE_OK ); |
| 146723 | 147266 | assert( p2==p1 ); |
| 147267 | +#endif |
| 146724 | 147268 | |
| 146725 | 147269 | sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); |
| 146726 | 147270 | } |
| 146727 | 147271 | |
| 146728 | 147272 | #endif |
| | @@ -164601,11 +165145,13 @@ |
| 164601 | 165145 | StatTable *pTab = 0; |
| 164602 | 165146 | int rc = SQLITE_OK; |
| 164603 | 165147 | int iDb; |
| 164604 | 165148 | |
| 164605 | 165149 | if( argc>=4 ){ |
| 164606 | | - iDb = sqlite3FindDbName(db, argv[3]); |
| 165150 | + Token nm; |
| 165151 | + sqlite3TokenInit(&nm, (char*)argv[3]); |
| 165152 | + iDb = sqlite3FindDb(db, &nm); |
| 164607 | 165153 | if( iDb<0 ){ |
| 164608 | 165154 | *pzErr = sqlite3_mprintf("no such database: %s", argv[3]); |
| 164609 | 165155 | return SQLITE_ERROR; |
| 164610 | 165156 | } |
| 164611 | 165157 | }else{ |
| | @@ -165186,11 +165732,15 @@ |
| 165186 | 165732 | /* #include <assert.h> */ |
| 165187 | 165733 | /* #include <string.h> */ |
| 165188 | 165734 | /* #include <stdlib.h> */ |
| 165189 | 165735 | /* #include <stdarg.h> */ |
| 165190 | 165736 | |
| 165191 | | -#define UNUSED_PARAM(X) (void)(X) |
| 165737 | +/* Mark a function parameter as unused, to suppress nuisance compiler |
| 165738 | +** warnings. */ |
| 165739 | +#ifndef UNUSED_PARAM |
| 165740 | +# define UNUSED_PARAM(X) (void)(X) |
| 165741 | +#endif |
| 165192 | 165742 | |
| 165193 | 165743 | #ifndef LARGEST_INT64 |
| 165194 | 165744 | # define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) |
| 165195 | 165745 | # define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) |
| 165196 | 165746 | #endif |
| | @@ -165431,14 +165981,37 @@ |
| 165431 | 165981 | static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ |
| 165432 | 165982 | u32 i; |
| 165433 | 165983 | if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; |
| 165434 | 165984 | p->zBuf[p->nUsed++] = '"'; |
| 165435 | 165985 | for(i=0; i<N; i++){ |
| 165436 | | - char c = zIn[i]; |
| 165986 | + unsigned char c = ((unsigned const char*)zIn)[i]; |
| 165437 | 165987 | if( c=='"' || c=='\\' ){ |
| 165988 | + json_simple_escape: |
| 165438 | 165989 | if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; |
| 165439 | 165990 | p->zBuf[p->nUsed++] = '\\'; |
| 165991 | + }else if( c<=0x1f ){ |
| 165992 | + static const char aSpecial[] = { |
| 165993 | + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, |
| 165994 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 165995 | + }; |
| 165996 | + assert( sizeof(aSpecial)==32 ); |
| 165997 | + assert( aSpecial['\b']=='b' ); |
| 165998 | + assert( aSpecial['\f']=='f' ); |
| 165999 | + assert( aSpecial['\n']=='n' ); |
| 166000 | + assert( aSpecial['\r']=='r' ); |
| 166001 | + assert( aSpecial['\t']=='t' ); |
| 166002 | + if( aSpecial[c] ){ |
| 166003 | + c = aSpecial[c]; |
| 166004 | + goto json_simple_escape; |
| 166005 | + } |
| 166006 | + if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; |
| 166007 | + p->zBuf[p->nUsed++] = '\\'; |
| 166008 | + p->zBuf[p->nUsed++] = 'u'; |
| 166009 | + p->zBuf[p->nUsed++] = '0'; |
| 166010 | + p->zBuf[p->nUsed++] = '0'; |
| 166011 | + p->zBuf[p->nUsed++] = '0' + (c>>4); |
| 166012 | + c = "0123456789abcdef"[c&0xf]; |
| 165440 | 166013 | } |
| 165441 | 166014 | p->zBuf[p->nUsed++] = c; |
| 165442 | 166015 | } |
| 165443 | 166016 | p->zBuf[p->nUsed++] = '"'; |
| 165444 | 166017 | assert( p->nUsed<p->nAlloc ); |
| | @@ -165475,11 +166048,11 @@ |
| 165475 | 166048 | break; |
| 165476 | 166049 | } |
| 165477 | 166050 | default: { |
| 165478 | 166051 | if( p->bErr==0 ){ |
| 165479 | 166052 | sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); |
| 165480 | | - p->bErr = 1; |
| 166053 | + p->bErr = 2; |
| 165481 | 166054 | jsonReset(p); |
| 165482 | 166055 | } |
| 165483 | 166056 | break; |
| 165484 | 166057 | } |
| 165485 | 166058 | } |
| | @@ -166684,10 +167257,11 @@ |
| 166684 | 167257 | sqlite3_context *ctx, |
| 166685 | 167258 | int argc, |
| 166686 | 167259 | sqlite3_value **argv |
| 166687 | 167260 | ){ |
| 166688 | 167261 | JsonString *pStr; |
| 167262 | + UNUSED_PARAM(argc); |
| 166689 | 167263 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); |
| 166690 | 167264 | if( pStr ){ |
| 166691 | 167265 | if( pStr->zBuf==0 ){ |
| 166692 | 167266 | jsonInit(pStr, ctx); |
| 166693 | 167267 | jsonAppendChar(pStr, '['); |
| | @@ -166703,11 +167277,11 @@ |
| 166703 | 167277 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 166704 | 167278 | if( pStr ){ |
| 166705 | 167279 | pStr->pCtx = ctx; |
| 166706 | 167280 | jsonAppendChar(pStr, ']'); |
| 166707 | 167281 | if( pStr->bErr ){ |
| 166708 | | - sqlite3_result_error_nomem(ctx); |
| 167282 | + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); |
| 166709 | 167283 | assert( pStr->bStatic ); |
| 166710 | 167284 | }else{ |
| 166711 | 167285 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 166712 | 167286 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 166713 | 167287 | pStr->bStatic = 1; |
| | @@ -166729,10 +167303,11 @@ |
| 166729 | 167303 | sqlite3_value **argv |
| 166730 | 167304 | ){ |
| 166731 | 167305 | JsonString *pStr; |
| 166732 | 167306 | const char *z; |
| 166733 | 167307 | u32 n; |
| 167308 | + UNUSED_PARAM(argc); |
| 166734 | 167309 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); |
| 166735 | 167310 | if( pStr ){ |
| 166736 | 167311 | if( pStr->zBuf==0 ){ |
| 166737 | 167312 | jsonInit(pStr, ctx); |
| 166738 | 167313 | jsonAppendChar(pStr, '{'); |
| | @@ -166751,11 +167326,11 @@ |
| 166751 | 167326 | JsonString *pStr; |
| 166752 | 167327 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); |
| 166753 | 167328 | if( pStr ){ |
| 166754 | 167329 | jsonAppendChar(pStr, '}'); |
| 166755 | 167330 | if( pStr->bErr ){ |
| 166756 | | - sqlite3_result_error_nomem(ctx); |
| 167331 | + if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); |
| 166757 | 167332 | assert( pStr->bStatic ); |
| 166758 | 167333 | }else{ |
| 166759 | 167334 | sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, |
| 166760 | 167335 | pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); |
| 166761 | 167336 | pStr->bStatic = 1; |
| | @@ -167937,14 +168512,15 @@ |
| 167937 | 168512 | #ifndef SQLITE_AMALGAMATION |
| 167938 | 168513 | |
| 167939 | 168514 | typedef unsigned char u8; |
| 167940 | 168515 | typedef unsigned int u32; |
| 167941 | 168516 | typedef unsigned short u16; |
| 168517 | +typedef short i16; |
| 167942 | 168518 | typedef sqlite3_int64 i64; |
| 167943 | 168519 | typedef sqlite3_uint64 u64; |
| 167944 | 168520 | |
| 167945 | | -#define ArraySize(x) (sizeof(x) / sizeof(x[0])) |
| 168521 | +#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) |
| 167946 | 168522 | |
| 167947 | 168523 | #define testcase(x) |
| 167948 | 168524 | #define ALWAYS(x) 1 |
| 167949 | 168525 | #define NEVER(x) 0 |
| 167950 | 168526 | |
| | @@ -167990,10 +168566,20 @@ |
| 167990 | 168566 | SQLITE_API extern int sqlite3_fts5_may_be_corrupt; |
| 167991 | 168567 | # define assert_nc(x) assert(sqlite3_fts5_may_be_corrupt || (x)) |
| 167992 | 168568 | #else |
| 167993 | 168569 | # define assert_nc(x) assert(x) |
| 167994 | 168570 | #endif |
| 168571 | + |
| 168572 | +/* Mark a function parameter as unused, to suppress nuisance compiler |
| 168573 | +** warnings. */ |
| 168574 | +#ifndef UNUSED_PARAM |
| 168575 | +# define UNUSED_PARAM(X) (void)(X) |
| 168576 | +#endif |
| 168577 | + |
| 168578 | +#ifndef UNUSED_PARAM2 |
| 168579 | +# define UNUSED_PARAM2(X, Y) (void)(X), (void)(Y) |
| 168580 | +#endif |
| 167995 | 168581 | |
| 167996 | 168582 | typedef struct Fts5Global Fts5Global; |
| 167997 | 168583 | typedef struct Fts5Colset Fts5Colset; |
| 167998 | 168584 | |
| 167999 | 168585 | /* If a NEAR() clump or phrase may only match a specific set of columns, |
| | @@ -168136,12 +168722,12 @@ |
| 168136 | 168722 | ** Buffer object for the incremental building of string data. |
| 168137 | 168723 | */ |
| 168138 | 168724 | typedef struct Fts5Buffer Fts5Buffer; |
| 168139 | 168725 | struct Fts5Buffer { |
| 168140 | 168726 | u8 *p; |
| 168141 | | - u32 n; |
| 168142 | | - u32 nSpace; |
| 168727 | + int n; |
| 168728 | + int nSpace; |
| 168143 | 168729 | }; |
| 168144 | 168730 | |
| 168145 | 168731 | static int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32); |
| 168146 | 168732 | static void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64); |
| 168147 | 168733 | static void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, u32, const u8*); |
| | @@ -168158,11 +168744,11 @@ |
| 168158 | 168744 | #define fts5BufferFree(a) sqlite3Fts5BufferFree(a) |
| 168159 | 168745 | #define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d) |
| 168160 | 168746 | #define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) |
| 168161 | 168747 | |
| 168162 | 168748 | #define fts5BufferGrow(pRc,pBuf,nn) ( \ |
| 168163 | | - (pBuf)->n + (nn) <= (pBuf)->nSpace ? 0 : \ |
| 168749 | + (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \ |
| 168164 | 168750 | sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \ |
| 168165 | 168751 | ) |
| 168166 | 168752 | |
| 168167 | 168753 | /* Write and decode big-endian 32-bit integer values */ |
| 168168 | 168754 | static void sqlite3Fts5Put32(u8*, int); |
| | @@ -168193,10 +168779,11 @@ |
| 168193 | 168779 | typedef struct Fts5PoslistWriter Fts5PoslistWriter; |
| 168194 | 168780 | struct Fts5PoslistWriter { |
| 168195 | 168781 | i64 iPrev; |
| 168196 | 168782 | }; |
| 168197 | 168783 | static int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); |
| 168784 | +static void sqlite3Fts5PoslistSafeAppend(Fts5Buffer*, i64*, i64); |
| 168198 | 168785 | |
| 168199 | 168786 | static int sqlite3Fts5PoslistNext64( |
| 168200 | 168787 | const u8 *a, int n, /* Buffer containing poslist */ |
| 168201 | 168788 | int *pi, /* IN/OUT: Offset within a[] */ |
| 168202 | 168789 | i64 *piOff /* IN/OUT: Current offset */ |
| | @@ -168226,34 +168813,39 @@ |
| 168226 | 168813 | */ |
| 168227 | 168814 | |
| 168228 | 168815 | typedef struct Fts5Index Fts5Index; |
| 168229 | 168816 | typedef struct Fts5IndexIter Fts5IndexIter; |
| 168230 | 168817 | |
| 168818 | +struct Fts5IndexIter { |
| 168819 | + i64 iRowid; |
| 168820 | + const u8 *pData; |
| 168821 | + int nData; |
| 168822 | + u8 bEof; |
| 168823 | +}; |
| 168824 | + |
| 168825 | +#define sqlite3Fts5IterEof(x) ((x)->bEof) |
| 168826 | + |
| 168231 | 168827 | /* |
| 168232 | 168828 | ** Values used as part of the flags argument passed to IndexQuery(). |
| 168233 | 168829 | */ |
| 168234 | 168830 | #define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ |
| 168235 | 168831 | #define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ |
| 168236 | 168832 | #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ |
| 168237 | 168833 | #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ |
| 168238 | 168834 | |
| 168835 | +/* The following are used internally by the fts5_index.c module. They are |
| 168836 | +** defined here only to make it easier to avoid clashes with the flags |
| 168837 | +** above. */ |
| 168838 | +#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 |
| 168839 | +#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 |
| 168840 | + |
| 168239 | 168841 | /* |
| 168240 | 168842 | ** Create/destroy an Fts5Index object. |
| 168241 | 168843 | */ |
| 168242 | 168844 | static int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); |
| 168243 | 168845 | static int sqlite3Fts5IndexClose(Fts5Index *p); |
| 168244 | 168846 | |
| 168245 | | -/* |
| 168246 | | -** for( |
| 168247 | | -** sqlite3Fts5IndexQuery(p, "token", 5, 0, 0, &pIter); |
| 168248 | | -** 0==sqlite3Fts5IterEof(pIter); |
| 168249 | | -** sqlite3Fts5IterNext(pIter) |
| 168250 | | -** ){ |
| 168251 | | -** i64 iRowid = sqlite3Fts5IterRowid(pIter); |
| 168252 | | -** } |
| 168253 | | -*/ |
| 168254 | | - |
| 168255 | 168847 | /* |
| 168256 | 168848 | ** Return a simple checksum value based on the arguments. |
| 168257 | 168849 | */ |
| 168258 | 168850 | static u64 sqlite3Fts5IndexEntryCksum( |
| 168259 | 168851 | i64 iRowid, |
| | @@ -168289,16 +168881,12 @@ |
| 168289 | 168881 | |
| 168290 | 168882 | /* |
| 168291 | 168883 | ** The various operations on open token or token prefix iterators opened |
| 168292 | 168884 | ** using sqlite3Fts5IndexQuery(). |
| 168293 | 168885 | */ |
| 168294 | | -static int sqlite3Fts5IterEof(Fts5IndexIter*); |
| 168295 | 168886 | static int sqlite3Fts5IterNext(Fts5IndexIter*); |
| 168296 | 168887 | 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 | 168888 | |
| 168301 | 168889 | /* |
| 168302 | 168890 | ** Close an iterator opened by sqlite3Fts5IndexQuery(). |
| 168303 | 168891 | */ |
| 168304 | 168892 | static void sqlite3Fts5IterClose(Fts5IndexIter*); |
| | @@ -168380,12 +168968,10 @@ |
| 168380 | 168968 | static int sqlite3Fts5IndexOptimize(Fts5Index *p); |
| 168381 | 168969 | static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); |
| 168382 | 168970 | |
| 168383 | 168971 | static int sqlite3Fts5IndexLoadConfig(Fts5Index *p); |
| 168384 | 168972 | |
| 168385 | | -static int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*); |
| 168386 | | - |
| 168387 | 168973 | /* |
| 168388 | 168974 | ** End of interface to code in fts5_index.c. |
| 168389 | 168975 | **************************************************************************/ |
| 168390 | 168976 | |
| 168391 | 168977 | /************************************************************************** |
| | @@ -168581,11 +169167,11 @@ |
| 168581 | 169167 | Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int |
| 168582 | 169168 | ); |
| 168583 | 169169 | static void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64); |
| 168584 | 169170 | static void sqlite3Fts5ExprClearEof(Fts5Expr*); |
| 168585 | 169171 | |
| 168586 | | -static int sqlite3Fts5ExprClonePhrase(Fts5Config*, Fts5Expr*, int, Fts5Expr**); |
| 169172 | +static int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**); |
| 168587 | 169173 | |
| 168588 | 169174 | static int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *); |
| 168589 | 169175 | |
| 168590 | 169176 | /******************************************* |
| 168591 | 169177 | ** The fts5_expr.c API above this point is used by the other hand-written |
| | @@ -169372,11 +169958,12 @@ |
| 169372 | 169958 | while( fts5yypParser->fts5yyidx>=0 ) fts5yy_pop_parser_stack(fts5yypParser); |
| 169373 | 169959 | /* Here code is inserted which will execute if the parser |
| 169374 | 169960 | ** stack every overflows */ |
| 169375 | 169961 | /******** Begin %stack_overflow code ******************************************/ |
| 169376 | 169962 | |
| 169377 | | - assert( 0 ); |
| 169963 | + UNUSED_PARAM(fts5yypMinor); /* Silence a compiler warning */ |
| 169964 | + sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); |
| 169378 | 169965 | /******** End %stack_overflow code ********************************************/ |
| 169379 | 169966 | sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ |
| 169380 | 169967 | } |
| 169381 | 169968 | |
| 169382 | 169969 | /* |
| | @@ -169669,10 +170256,11 @@ |
| 169669 | 170256 | ){ |
| 169670 | 170257 | sqlite3Fts5ParserARG_FETCH; |
| 169671 | 170258 | #define FTS5TOKEN (fts5yyminor.fts5yy0) |
| 169672 | 170259 | /************ Begin %syntax_error code ****************************************/ |
| 169673 | 170260 | |
| 170261 | + UNUSED_PARAM(fts5yymajor); /* Silence a compiler warning */ |
| 169674 | 170262 | sqlite3Fts5ParseError( |
| 169675 | 170263 | pParse, "fts5: syntax error near \"%.*s\"",FTS5TOKEN.n,FTS5TOKEN.p |
| 169676 | 170264 | ); |
| 169677 | 170265 | /************ End %syntax_error code ******************************************/ |
| 169678 | 170266 | sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ |
| | @@ -170045,10 +170633,12 @@ |
| 170045 | 170633 | int iEndOff /* End offset of token */ |
| 170046 | 170634 | ){ |
| 170047 | 170635 | HighlightContext *p = (HighlightContext*)pContext; |
| 170048 | 170636 | int rc = SQLITE_OK; |
| 170049 | 170637 | int iPos; |
| 170638 | + |
| 170639 | + UNUSED_PARAM2(pToken, nToken); |
| 170050 | 170640 | |
| 170051 | 170641 | if( tflags & FTS5_TOKEN_COLOCATED ) return SQLITE_OK; |
| 170052 | 170642 | iPos = p->iPos++; |
| 170053 | 170643 | |
| 170054 | 170644 | if( p->iRangeEnd>0 ){ |
| | @@ -170279,10 +170869,11 @@ |
| 170279 | 170869 | const Fts5ExtensionApi *pApi, |
| 170280 | 170870 | Fts5Context *pFts, |
| 170281 | 170871 | void *pUserData /* Pointer to sqlite3_int64 variable */ |
| 170282 | 170872 | ){ |
| 170283 | 170873 | sqlite3_int64 *pn = (sqlite3_int64*)pUserData; |
| 170874 | + UNUSED_PARAM2(pApi, pFts); |
| 170284 | 170875 | (*pn)++; |
| 170285 | 170876 | return SQLITE_OK; |
| 170286 | 170877 | } |
| 170287 | 170878 | |
| 170288 | 170879 | /* |
| | @@ -170432,11 +171023,11 @@ |
| 170432 | 171023 | { "bm25", 0, fts5Bm25Function, 0 }, |
| 170433 | 171024 | }; |
| 170434 | 171025 | int rc = SQLITE_OK; /* Return code */ |
| 170435 | 171026 | int i; /* To iterate through builtin functions */ |
| 170436 | 171027 | |
| 170437 | | - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ |
| 171028 | + for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){ |
| 170438 | 171029 | rc = pApi->xCreateFunction(pApi, |
| 170439 | 171030 | aBuiltin[i].zFunc, |
| 170440 | 171031 | aBuiltin[i].pUserData, |
| 170441 | 171032 | aBuiltin[i].xFunc, |
| 170442 | 171033 | aBuiltin[i].xDestroy |
| | @@ -170464,22 +171055,24 @@ |
| 170464 | 171055 | |
| 170465 | 171056 | |
| 170466 | 171057 | /* #include "fts5Int.h" */ |
| 170467 | 171058 | |
| 170468 | 171059 | 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; |
| 171060 | + if( (u32)pBuf->nSpace<nByte ){ |
| 171061 | + u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64; |
| 171062 | + u8 *pNew; |
| 171063 | + while( nNew<nByte ){ |
| 171064 | + nNew = nNew * 2; |
| 171065 | + } |
| 171066 | + pNew = sqlite3_realloc(pBuf->p, nNew); |
| 171067 | + if( pNew==0 ){ |
| 171068 | + *pRc = SQLITE_NOMEM; |
| 171069 | + return 1; |
| 171070 | + }else{ |
| 171071 | + pBuf->nSpace = nNew; |
| 171072 | + pBuf->p = pNew; |
| 171073 | + } |
| 170481 | 171074 | } |
| 170482 | 171075 | return 0; |
| 170483 | 171076 | } |
| 170484 | 171077 | |
| 170485 | 171078 | |
| | @@ -170655,28 +171248,41 @@ |
| 170655 | 171248 | pIter->a = a; |
| 170656 | 171249 | pIter->n = n; |
| 170657 | 171250 | sqlite3Fts5PoslistReaderNext(pIter); |
| 170658 | 171251 | return pIter->bEof; |
| 170659 | 171252 | } |
| 171253 | + |
| 171254 | +/* |
| 171255 | +** Append position iPos to the position list being accumulated in buffer |
| 171256 | +** pBuf, which must be already be large enough to hold the new data. |
| 171257 | +** The previous position written to this list is *piPrev. *piPrev is set |
| 171258 | +** to iPos before returning. |
| 171259 | +*/ |
| 171260 | +static void sqlite3Fts5PoslistSafeAppend( |
| 171261 | + Fts5Buffer *pBuf, |
| 171262 | + i64 *piPrev, |
| 171263 | + i64 iPos |
| 171264 | +){ |
| 171265 | + static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; |
| 171266 | + if( (iPos & colmask) != (*piPrev & colmask) ){ |
| 171267 | + pBuf->p[pBuf->n++] = 1; |
| 171268 | + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); |
| 171269 | + *piPrev = (iPos & colmask); |
| 171270 | + } |
| 171271 | + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); |
| 171272 | + *piPrev = iPos; |
| 171273 | +} |
| 170660 | 171274 | |
| 170661 | 171275 | static int sqlite3Fts5PoslistWriterAppend( |
| 170662 | 171276 | Fts5Buffer *pBuf, |
| 170663 | 171277 | Fts5PoslistWriter *pWriter, |
| 170664 | 171278 | i64 iPos |
| 170665 | 171279 | ){ |
| 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; |
| 171280 | + int rc = 0; /* Initialized only to suppress erroneous warning from Clang */ |
| 171281 | + if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; |
| 171282 | + sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); |
| 171283 | + return SQLITE_OK; |
| 170678 | 171284 | } |
| 170679 | 171285 | |
| 170680 | 171286 | static void *sqlite3Fts5MallocZero(int *pRc, int nByte){ |
| 170681 | 171287 | void *pRet = 0; |
| 170682 | 171288 | if( *pRc==SQLITE_OK ){ |
| | @@ -170770,11 +171376,11 @@ |
| 170770 | 171376 | ){ |
| 170771 | 171377 | int rc = SQLITE_OK; |
| 170772 | 171378 | *pbPresent = 0; |
| 170773 | 171379 | if( p ){ |
| 170774 | 171380 | int i; |
| 170775 | | - int hash = 13; |
| 171381 | + u32 hash = 13; |
| 170776 | 171382 | Fts5TermsetEntry *pEntry; |
| 170777 | 171383 | |
| 170778 | 171384 | /* Calculate a hash value for this term. This is the same hash checksum |
| 170779 | 171385 | ** used by the fts5_hash.c module. This is not important for correct |
| 170780 | 171386 | ** operation of the module, but is necessary to ensure that some tests |
| | @@ -170787,11 +171393,11 @@ |
| 170787 | 171393 | |
| 170788 | 171394 | for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){ |
| 170789 | 171395 | if( pEntry->iIdx==iIdx |
| 170790 | 171396 | && pEntry->nTerm==nTerm |
| 170791 | 171397 | && memcmp(pEntry->pTerm, pTerm, nTerm)==0 |
| 170792 | | - ){ |
| 171398 | + ){ |
| 170793 | 171399 | *pbPresent = 1; |
| 170794 | 171400 | break; |
| 170795 | 171401 | } |
| 170796 | 171402 | } |
| 170797 | 171403 | |
| | @@ -170811,11 +171417,11 @@ |
| 170811 | 171417 | return rc; |
| 170812 | 171418 | } |
| 170813 | 171419 | |
| 170814 | 171420 | static void sqlite3Fts5TermsetFree(Fts5Termset *p){ |
| 170815 | 171421 | if( p ){ |
| 170816 | | - int i; |
| 171422 | + u32 i; |
| 170817 | 171423 | for(i=0; i<ArraySize(p->apHash); i++){ |
| 170818 | 171424 | Fts5TermsetEntry *pEntry = p->apHash[i]; |
| 170819 | 171425 | while( pEntry ){ |
| 170820 | 171426 | Fts5TermsetEntry *pDel = pEntry; |
| 170821 | 171427 | pEntry = pEntry->pNext; |
| | @@ -170823,13 +171429,10 @@ |
| 170823 | 171429 | } |
| 170824 | 171430 | } |
| 170825 | 171431 | sqlite3_free(p); |
| 170826 | 171432 | } |
| 170827 | 171433 | } |
| 170828 | | - |
| 170829 | | - |
| 170830 | | - |
| 170831 | 171434 | |
| 170832 | 171435 | /* |
| 170833 | 171436 | ** 2014 Jun 09 |
| 170834 | 171437 | ** |
| 170835 | 171438 | ** The author disclaims copyright to this source code. In place of |
| | @@ -171035,11 +171638,11 @@ |
| 171035 | 171638 | static int fts5ConfigSetEnum( |
| 171036 | 171639 | const Fts5Enum *aEnum, |
| 171037 | 171640 | const char *zEnum, |
| 171038 | 171641 | int *peVal |
| 171039 | 171642 | ){ |
| 171040 | | - int nEnum = strlen(zEnum); |
| 171643 | + int nEnum = (int)strlen(zEnum); |
| 171041 | 171644 | int i; |
| 171042 | 171645 | int iVal = -1; |
| 171043 | 171646 | |
| 171044 | 171647 | for(i=0; aEnum[i].zName; i++){ |
| 171045 | 171648 | if( sqlite3_strnicmp(aEnum[i].zName, zEnum, nEnum)==0 ){ |
| | @@ -171773,11 +172376,10 @@ |
| 171773 | 172376 | pConfig->iCookie = iCookie; |
| 171774 | 172377 | } |
| 171775 | 172378 | return rc; |
| 171776 | 172379 | } |
| 171777 | 172380 | |
| 171778 | | - |
| 171779 | 172381 | /* |
| 171780 | 172382 | ** 2014 May 31 |
| 171781 | 172383 | ** |
| 171782 | 172384 | ** The author disclaims copyright to this source code. In place of |
| 171783 | 172385 | ** a legal notice, here is a blessing: |
| | @@ -171838,10 +172440,13 @@ |
| 171838 | 172440 | struct Fts5ExprNode { |
| 171839 | 172441 | int eType; /* Node type */ |
| 171840 | 172442 | int bEof; /* True at EOF */ |
| 171841 | 172443 | int bNomatch; /* True if entry is not a match */ |
| 171842 | 172444 | |
| 172445 | + /* Next method for this node. */ |
| 172446 | + int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64); |
| 172447 | + |
| 171843 | 172448 | i64 iRowid; /* Current rowid */ |
| 171844 | 172449 | Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ |
| 171845 | 172450 | |
| 171846 | 172451 | /* Child nodes. For a NOT node, this array always contains 2 entries. For |
| 171847 | 172452 | ** AND or OR nodes, it contains 2 or more entries. */ |
| | @@ -171849,10 +172454,16 @@ |
| 171849 | 172454 | Fts5ExprNode *apChild[1]; /* Array of child nodes */ |
| 171850 | 172455 | }; |
| 171851 | 172456 | |
| 171852 | 172457 | #define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) |
| 171853 | 172458 | |
| 172459 | +/* |
| 172460 | +** Invoke the xNext method of an Fts5ExprNode object. This macro should be |
| 172461 | +** used as if it has the same signature as the xNext() methods themselves. |
| 172462 | +*/ |
| 172463 | +#define fts5ExprNodeNext(a,b,c,d) (b)->xNext((a), (b), (c), (d)) |
| 172464 | + |
| 171854 | 172465 | /* |
| 171855 | 172466 | ** An instance of the following structure represents a single search term |
| 171856 | 172467 | ** or term prefix. |
| 171857 | 172468 | */ |
| 171858 | 172469 | struct Fts5ExprTerm { |
| | @@ -172010,11 +172621,19 @@ |
| 172010 | 172621 | *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); |
| 172011 | 172622 | if( pNew==0 ){ |
| 172012 | 172623 | sParse.rc = SQLITE_NOMEM; |
| 172013 | 172624 | sqlite3Fts5ParseNodeFree(sParse.pExpr); |
| 172014 | 172625 | }else{ |
| 172015 | | - pNew->pRoot = sParse.pExpr; |
| 172626 | + if( !sParse.pExpr ){ |
| 172627 | + const int nByte = sizeof(Fts5ExprNode); |
| 172628 | + pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte); |
| 172629 | + if( pNew->pRoot ){ |
| 172630 | + pNew->pRoot->bEof = 1; |
| 172631 | + } |
| 172632 | + }else{ |
| 172633 | + pNew->pRoot = sParse.pExpr; |
| 172634 | + } |
| 172016 | 172635 | pNew->pIndex = 0; |
| 172017 | 172636 | pNew->pConfig = pConfig; |
| 172018 | 172637 | pNew->apExprPhrase = sParse.apPhrase; |
| 172019 | 172638 | pNew->nPhrase = sParse.nPhrase; |
| 172020 | 172639 | sParse.apPhrase = 0; |
| | @@ -172062,11 +172681,11 @@ |
| 172062 | 172681 | |
| 172063 | 172682 | assert( pTerm->pSynonym ); |
| 172064 | 172683 | assert( bDesc==0 || bDesc==1 ); |
| 172065 | 172684 | for(p=pTerm; p; p=p->pSynonym){ |
| 172066 | 172685 | if( 0==sqlite3Fts5IterEof(p->pIter) ){ |
| 172067 | | - i64 iRowid = sqlite3Fts5IterRowid(p->pIter); |
| 172686 | + i64 iRowid = p->pIter->iRowid; |
| 172068 | 172687 | if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){ |
| 172069 | 172688 | iRet = iRowid; |
| 172070 | 172689 | bRetValid = 1; |
| 172071 | 172690 | } |
| 172072 | 172691 | } |
| | @@ -172079,14 +172698,12 @@ |
| 172079 | 172698 | /* |
| 172080 | 172699 | ** Argument pTerm must be a synonym iterator. |
| 172081 | 172700 | */ |
| 172082 | 172701 | static int fts5ExprSynonymList( |
| 172083 | 172702 | Fts5ExprTerm *pTerm, |
| 172084 | | - int bCollist, |
| 172085 | | - Fts5Colset *pColset, |
| 172086 | 172703 | i64 iRowid, |
| 172087 | | - int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */ |
| 172704 | + Fts5Buffer *pBuf, /* Use this buffer for space if required */ |
| 172088 | 172705 | u8 **pa, int *pn |
| 172089 | 172706 | ){ |
| 172090 | 172707 | Fts5PoslistReader aStatic[4]; |
| 172091 | 172708 | Fts5PoslistReader *aIter = aStatic; |
| 172092 | 172709 | int nIter = 0; |
| | @@ -172095,23 +172712,12 @@ |
| 172095 | 172712 | Fts5ExprTerm *p; |
| 172096 | 172713 | |
| 172097 | 172714 | assert( pTerm->pSynonym ); |
| 172098 | 172715 | for(p=pTerm; p; p=p->pSynonym){ |
| 172099 | 172716 | 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; |
| 172717 | + if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){ |
| 172718 | + if( pIter->nData==0 ) continue; |
| 172113 | 172719 | if( nIter==nAlloc ){ |
| 172114 | 172720 | int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; |
| 172115 | 172721 | Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172116 | 172722 | if( aNew==0 ){ |
| 172117 | 172723 | rc = SQLITE_NOMEM; |
| | @@ -172120,24 +172726,23 @@ |
| 172120 | 172726 | memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); |
| 172121 | 172727 | nAlloc = nAlloc*2; |
| 172122 | 172728 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| 172123 | 172729 | aIter = aNew; |
| 172124 | 172730 | } |
| 172125 | | - sqlite3Fts5PoslistReaderInit(a, n, &aIter[nIter]); |
| 172731 | + sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &aIter[nIter]); |
| 172126 | 172732 | assert( aIter[nIter].bEof==0 ); |
| 172127 | 172733 | nIter++; |
| 172128 | 172734 | } |
| 172129 | 172735 | } |
| 172130 | 172736 | |
| 172131 | | - assert( *pbDel==0 ); |
| 172132 | 172737 | if( nIter==1 ){ |
| 172133 | 172738 | *pa = (u8*)aIter[0].a; |
| 172134 | 172739 | *pn = aIter[0].n; |
| 172135 | 172740 | }else{ |
| 172136 | 172741 | Fts5PoslistWriter writer = {0}; |
| 172137 | | - Fts5Buffer buf = {0,0,0}; |
| 172138 | 172742 | i64 iPrev = -1; |
| 172743 | + fts5BufferZero(pBuf); |
| 172139 | 172744 | while( 1 ){ |
| 172140 | 172745 | int i; |
| 172141 | 172746 | i64 iMin = FTS5_LARGEST_INT64; |
| 172142 | 172747 | for(i=0; i<nIter; i++){ |
| 172143 | 172748 | if( aIter[i].bEof==0 ){ |
| | @@ -172148,19 +172753,16 @@ |
| 172148 | 172753 | iMin = aIter[i].iPos; |
| 172149 | 172754 | } |
| 172150 | 172755 | } |
| 172151 | 172756 | } |
| 172152 | 172757 | if( iMin==FTS5_LARGEST_INT64 || rc!=SQLITE_OK ) break; |
| 172153 | | - rc = sqlite3Fts5PoslistWriterAppend(&buf, &writer, iMin); |
| 172758 | + rc = sqlite3Fts5PoslistWriterAppend(pBuf, &writer, iMin); |
| 172154 | 172759 | iPrev = iMin; |
| 172155 | 172760 | } |
| 172156 | | - if( rc ){ |
| 172157 | | - sqlite3_free(buf.p); |
| 172158 | | - }else{ |
| 172159 | | - *pa = buf.p; |
| 172160 | | - *pn = buf.n; |
| 172161 | | - *pbDel = 1; |
| 172761 | + if( rc==SQLITE_OK ){ |
| 172762 | + *pa = pBuf->p; |
| 172763 | + *pn = pBuf->n; |
| 172162 | 172764 | } |
| 172163 | 172765 | } |
| 172164 | 172766 | |
| 172165 | 172767 | synonym_poslist_out: |
| 172166 | 172768 | if( aIter!=aStatic ) sqlite3_free(aIter); |
| | @@ -172179,11 +172781,10 @@ |
| 172179 | 172781 | ** otherwise. It is not considered an error code if the current rowid is |
| 172180 | 172782 | ** not a match. |
| 172181 | 172783 | */ |
| 172182 | 172784 | static int fts5ExprPhraseIsMatch( |
| 172183 | 172785 | Fts5ExprNode *pNode, /* Node pPhrase belongs to */ |
| 172184 | | - Fts5Colset *pColset, /* Restrict matches to these columns */ |
| 172185 | 172786 | Fts5ExprPhrase *pPhrase, /* Phrase object to initialize */ |
| 172186 | 172787 | int *pbMatch /* OUT: Set to true if really a match */ |
| 172187 | 172788 | ){ |
| 172188 | 172789 | Fts5PoslistWriter writer = {0}; |
| 172189 | 172790 | Fts5PoslistReader aStatic[4]; |
| | @@ -172193,32 +172794,35 @@ |
| 172193 | 172794 | |
| 172194 | 172795 | fts5BufferZero(&pPhrase->poslist); |
| 172195 | 172796 | |
| 172196 | 172797 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172197 | 172798 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172198 | | - if( pPhrase->nTerm>(int)ArraySize(aStatic) ){ |
| 172799 | + if( pPhrase->nTerm>ArraySize(aStatic) ){ |
| 172199 | 172800 | int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; |
| 172200 | 172801 | aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); |
| 172201 | 172802 | if( !aIter ) return SQLITE_NOMEM; |
| 172202 | 172803 | } |
| 172203 | 172804 | memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm); |
| 172204 | 172805 | |
| 172205 | 172806 | /* Initialize a term iterator for each term in the phrase */ |
| 172206 | 172807 | for(i=0; i<pPhrase->nTerm; i++){ |
| 172207 | 172808 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 172208 | | - i64 dummy; |
| 172209 | 172809 | int n = 0; |
| 172210 | 172810 | int bFlag = 0; |
| 172211 | | - const u8 *a = 0; |
| 172811 | + u8 *a = 0; |
| 172212 | 172812 | if( pTerm->pSynonym ){ |
| 172213 | | - rc = fts5ExprSynonymList( |
| 172214 | | - pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n |
| 172215 | | - ); |
| 172813 | + Fts5Buffer buf = {0, 0, 0}; |
| 172814 | + rc = fts5ExprSynonymList(pTerm, pNode->iRowid, &buf, &a, &n); |
| 172815 | + if( rc ){ |
| 172816 | + sqlite3_free(a); |
| 172817 | + goto ismatch_out; |
| 172818 | + } |
| 172819 | + if( a==buf.p ) bFlag = 1; |
| 172216 | 172820 | }else{ |
| 172217 | | - rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy); |
| 172821 | + a = (u8*)pTerm->pIter->pData; |
| 172822 | + n = pTerm->pIter->nData; |
| 172218 | 172823 | } |
| 172219 | | - if( rc!=SQLITE_OK ) goto ismatch_out; |
| 172220 | 172824 | sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); |
| 172221 | 172825 | aIter[i].bFlag = (u8)bFlag; |
| 172222 | 172826 | if( aIter[i].bEof ) goto ismatch_out; |
| 172223 | 172827 | } |
| 172224 | 172828 | |
| | @@ -172286,16 +172890,10 @@ |
| 172286 | 172890 | p->n = n; |
| 172287 | 172891 | fts5LookaheadReaderNext(p); |
| 172288 | 172892 | return fts5LookaheadReaderNext(p); |
| 172289 | 172893 | } |
| 172290 | 172894 | |
| 172291 | | -#if 0 |
| 172292 | | -static int fts5LookaheadReaderEof(Fts5LookaheadReader *p){ |
| 172293 | | - return (p->iPos==FTS5_LOOKAHEAD_EOF); |
| 172294 | | -} |
| 172295 | | -#endif |
| 172296 | | - |
| 172297 | 172895 | typedef struct Fts5NearTrimmer Fts5NearTrimmer; |
| 172298 | 172896 | struct Fts5NearTrimmer { |
| 172299 | 172897 | Fts5LookaheadReader reader; /* Input iterator */ |
| 172300 | 172898 | Fts5PoslistWriter writer; /* Writer context */ |
| 172301 | 172899 | Fts5Buffer *pOut; /* Output poslist */ |
| | @@ -172329,11 +172927,11 @@ |
| 172329 | 172927 | |
| 172330 | 172928 | assert( pNear->nPhrase>1 ); |
| 172331 | 172929 | |
| 172332 | 172930 | /* If the aStatic[] array is not large enough, allocate a large array |
| 172333 | 172931 | ** using sqlite3_malloc(). This approach could be improved upon. */ |
| 172334 | | - if( pNear->nPhrase>(int)ArraySize(aStatic) ){ |
| 172932 | + if( pNear->nPhrase>ArraySize(aStatic) ){ |
| 172335 | 172933 | int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; |
| 172336 | 172934 | a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); |
| 172337 | 172935 | }else{ |
| 172338 | 172936 | memset(aStatic, 0, sizeof(aStatic)); |
| 172339 | 172937 | } |
| | @@ -172406,75 +173004,10 @@ |
| 172406 | 173004 | if( a!=aStatic ) sqlite3_free(a); |
| 172407 | 173005 | return bRet; |
| 172408 | 173006 | } |
| 172409 | 173007 | } |
| 172410 | 173008 | |
| 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 | 173009 | /* |
| 172477 | 173010 | ** Advance iterator pIter until it points to a value equal to or laster |
| 172478 | 173011 | ** than the initial value of *piLast. If this means the iterator points |
| 172479 | 173012 | ** to a value laster than *piLast, update *piLast to the new lastest value. |
| 172480 | 173013 | ** |
| | @@ -172490,19 +173023,19 @@ |
| 172490 | 173023 | int *pbEof /* OUT: Set to true if EOF */ |
| 172491 | 173024 | ){ |
| 172492 | 173025 | i64 iLast = *piLast; |
| 172493 | 173026 | i64 iRowid; |
| 172494 | 173027 | |
| 172495 | | - iRowid = sqlite3Fts5IterRowid(pIter); |
| 173028 | + iRowid = pIter->iRowid; |
| 172496 | 173029 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172497 | 173030 | int rc = sqlite3Fts5IterNextFrom(pIter, iLast); |
| 172498 | 173031 | if( rc || sqlite3Fts5IterEof(pIter) ){ |
| 172499 | 173032 | *pRc = rc; |
| 172500 | 173033 | *pbEof = 1; |
| 172501 | 173034 | return 1; |
| 172502 | 173035 | } |
| 172503 | | - iRowid = sqlite3Fts5IterRowid(pIter); |
| 173036 | + iRowid = pIter->iRowid; |
| 172504 | 173037 | assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) ); |
| 172505 | 173038 | } |
| 172506 | 173039 | *piLast = iRowid; |
| 172507 | 173040 | |
| 172508 | 173041 | return 0; |
| | @@ -172519,11 +173052,11 @@ |
| 172519 | 173052 | Fts5ExprTerm *p; |
| 172520 | 173053 | int bEof = 0; |
| 172521 | 173054 | |
| 172522 | 173055 | for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){ |
| 172523 | 173056 | if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 172524 | | - i64 iRowid = sqlite3Fts5IterRowid(p->pIter); |
| 173057 | + i64 iRowid = p->pIter->iRowid; |
| 172525 | 173058 | if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){ |
| 172526 | 173059 | rc = sqlite3Fts5IterNextFrom(p->pIter, iLast); |
| 172527 | 173060 | } |
| 172528 | 173061 | } |
| 172529 | 173062 | } |
| | @@ -172551,17 +173084,11 @@ |
| 172551 | 173084 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; |
| 172552 | 173085 | pPhrase->poslist.n = 0; |
| 172553 | 173086 | for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ |
| 172554 | 173087 | Fts5IndexIter *pIter = pTerm->pIter; |
| 172555 | 173088 | 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 ){ |
| 173089 | + if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){ |
| 172563 | 173090 | pPhrase->poslist.n = 1; |
| 172564 | 173091 | } |
| 172565 | 173092 | } |
| 172566 | 173093 | } |
| 172567 | 173094 | return pPhrase->poslist.n; |
| | @@ -172573,16 +173100,15 @@ |
| 172573 | 173100 | ** phrase is not a match, break out of the loop early. */ |
| 172574 | 173101 | for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){ |
| 172575 | 173102 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 172576 | 173103 | if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ |
| 172577 | 173104 | int bMatch = 0; |
| 172578 | | - rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch); |
| 173105 | + rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch); |
| 172579 | 173106 | if( bMatch==0 ) break; |
| 172580 | 173107 | }else{ |
| 172581 | | - rc = sqlite3Fts5IterPoslistBuffer( |
| 172582 | | - pPhrase->aTerm[0].pIter, &pPhrase->poslist |
| 172583 | | - ); |
| 173108 | + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 173109 | + fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData); |
| 172584 | 173110 | } |
| 172585 | 173111 | } |
| 172586 | 173112 | |
| 172587 | 173113 | *pRc = rc; |
| 172588 | 173114 | if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){ |
| | @@ -172590,107 +173116,10 @@ |
| 172590 | 173116 | } |
| 172591 | 173117 | return 0; |
| 172592 | 173118 | } |
| 172593 | 173119 | } |
| 172594 | 173120 | |
| 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 | 173121 | |
| 172693 | 173122 | /* |
| 172694 | 173123 | ** Initialize all term iterators in the pNear object. If any term is found |
| 172695 | 173124 | ** to match no documents at all, return immediately without initializing any |
| 172696 | 173125 | ** further iterators. |
| | @@ -172701,10 +173130,11 @@ |
| 172701 | 173130 | ){ |
| 172702 | 173131 | Fts5ExprNearset *pNear = pNode->pNear; |
| 172703 | 173132 | int i, j; |
| 172704 | 173133 | int rc = SQLITE_OK; |
| 172705 | 173134 | |
| 173135 | + assert( pNode->bNomatch==0 ); |
| 172706 | 173136 | for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){ |
| 172707 | 173137 | Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 172708 | 173138 | for(j=0; j<pPhrase->nTerm; j++){ |
| 172709 | 173139 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; |
| 172710 | 173140 | Fts5ExprTerm *p; |
| | @@ -172735,14 +173165,10 @@ |
| 172735 | 173165 | } |
| 172736 | 173166 | } |
| 172737 | 173167 | |
| 172738 | 173168 | return rc; |
| 172739 | 173169 | } |
| 172740 | | - |
| 172741 | | -/* fts5ExprNodeNext() calls fts5ExprNodeNextMatch(). And vice-versa. */ |
| 172742 | | -static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*); |
| 172743 | | - |
| 172744 | 173170 | |
| 172745 | 173171 | /* |
| 172746 | 173172 | ** If pExpr is an ASC iterator, this function returns a value with the |
| 172747 | 173173 | ** same sign as: |
| 172748 | 173174 | ** |
| | @@ -172768,10 +173194,11 @@ |
| 172768 | 173194 | } |
| 172769 | 173195 | |
| 172770 | 173196 | static void fts5ExprSetEof(Fts5ExprNode *pNode){ |
| 172771 | 173197 | int i; |
| 172772 | 173198 | pNode->bEof = 1; |
| 173199 | + pNode->bNomatch = 0; |
| 172773 | 173200 | for(i=0; i<pNode->nChild; i++){ |
| 172774 | 173201 | fts5ExprSetEof(pNode->apChild[i]); |
| 172775 | 173202 | } |
| 172776 | 173203 | } |
| 172777 | 173204 | |
| | @@ -172790,16 +173217,279 @@ |
| 172790 | 173217 | } |
| 172791 | 173218 | } |
| 172792 | 173219 | } |
| 172793 | 173220 | |
| 172794 | 173221 | |
| 172795 | | -static int fts5ExprNodeNext(Fts5Expr*, Fts5ExprNode*, int, i64); |
| 173222 | + |
| 173223 | +/* |
| 173224 | +** Compare the values currently indicated by the two nodes as follows: |
| 173225 | +** |
| 173226 | +** res = (*p1) - (*p2) |
| 173227 | +** |
| 173228 | +** Nodes that point to values that come later in the iteration order are |
| 173229 | +** considered to be larger. Nodes at EOF are the largest of all. |
| 173230 | +** |
| 173231 | +** This means that if the iteration order is ASC, then numerically larger |
| 173232 | +** rowids are considered larger. Or if it is the default DESC, numerically |
| 173233 | +** smaller rowids are larger. |
| 173234 | +*/ |
| 173235 | +static int fts5NodeCompare( |
| 173236 | + Fts5Expr *pExpr, |
| 173237 | + Fts5ExprNode *p1, |
| 173238 | + Fts5ExprNode *p2 |
| 173239 | +){ |
| 173240 | + if( p2->bEof ) return -1; |
| 173241 | + if( p1->bEof ) return +1; |
| 173242 | + return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); |
| 173243 | +} |
| 173244 | + |
| 173245 | +/* |
| 173246 | +** All individual term iterators in pNear are guaranteed to be valid when |
| 173247 | +** this function is called. This function checks if all term iterators |
| 173248 | +** point to the same rowid, and if not, advances them until they do. |
| 173249 | +** If an EOF is reached before this happens, *pbEof is set to true before |
| 173250 | +** returning. |
| 173251 | +** |
| 173252 | +** SQLITE_OK is returned if an error occurs, or an SQLite error code |
| 173253 | +** otherwise. It is not considered an error code if an iterator reaches |
| 173254 | +** EOF. |
| 173255 | +*/ |
| 173256 | +static int fts5ExprNodeTest_STRING( |
| 173257 | + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 173258 | + Fts5ExprNode *pNode |
| 173259 | +){ |
| 173260 | + Fts5ExprNearset *pNear = pNode->pNear; |
| 173261 | + Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; |
| 173262 | + int rc = SQLITE_OK; |
| 173263 | + i64 iLast; /* Lastest rowid any iterator points to */ |
| 173264 | + int i, j; /* Phrase and token index, respectively */ |
| 173265 | + int bMatch; /* True if all terms are at the same rowid */ |
| 173266 | + const int bDesc = pExpr->bDesc; |
| 173267 | + |
| 173268 | + /* Check that this node should not be FTS5_TERM */ |
| 173269 | + assert( pNear->nPhrase>1 |
| 173270 | + || pNear->apPhrase[0]->nTerm>1 |
| 173271 | + || pNear->apPhrase[0]->aTerm[0].pSynonym |
| 173272 | + ); |
| 173273 | + |
| 173274 | + /* Initialize iLast, the "lastest" rowid any iterator points to. If the |
| 173275 | + ** iterator skips through rowids in the default ascending order, this means |
| 173276 | + ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it |
| 173277 | + ** means the minimum rowid. */ |
| 173278 | + if( pLeft->aTerm[0].pSynonym ){ |
| 173279 | + iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); |
| 173280 | + }else{ |
| 173281 | + iLast = pLeft->aTerm[0].pIter->iRowid; |
| 173282 | + } |
| 173283 | + |
| 173284 | + do { |
| 173285 | + bMatch = 1; |
| 173286 | + for(i=0; i<pNear->nPhrase; i++){ |
| 173287 | + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; |
| 173288 | + for(j=0; j<pPhrase->nTerm; j++){ |
| 173289 | + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; |
| 173290 | + if( pTerm->pSynonym ){ |
| 173291 | + i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); |
| 173292 | + if( iRowid==iLast ) continue; |
| 173293 | + bMatch = 0; |
| 173294 | + if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ |
| 173295 | + pNode->bNomatch = 0; |
| 173296 | + pNode->bEof = 1; |
| 173297 | + return rc; |
| 173298 | + } |
| 173299 | + }else{ |
| 173300 | + Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; |
| 173301 | + if( pIter->iRowid==iLast ) continue; |
| 173302 | + bMatch = 0; |
| 173303 | + if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ |
| 173304 | + return rc; |
| 173305 | + } |
| 173306 | + } |
| 173307 | + } |
| 173308 | + } |
| 173309 | + }while( bMatch==0 ); |
| 173310 | + |
| 173311 | + pNode->iRowid = iLast; |
| 173312 | + pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK); |
| 173313 | + assert( pNode->bEof==0 || pNode->bNomatch==0 ); |
| 173314 | + |
| 173315 | + return rc; |
| 173316 | +} |
| 173317 | + |
| 173318 | +/* |
| 173319 | +** Advance the first term iterator in the first phrase of pNear. Set output |
| 173320 | +** variable *pbEof to true if it reaches EOF or if an error occurs. |
| 173321 | +** |
| 173322 | +** Return SQLITE_OK if successful, or an SQLite error code if an error |
| 173323 | +** occurs. |
| 173324 | +*/ |
| 173325 | +static int fts5ExprNodeNext_STRING( |
| 173326 | + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 173327 | + Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ |
| 173328 | + int bFromValid, |
| 173329 | + i64 iFrom |
| 173330 | +){ |
| 173331 | + Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; |
| 173332 | + int rc = SQLITE_OK; |
| 173333 | + |
| 173334 | + pNode->bNomatch = 0; |
| 173335 | + if( pTerm->pSynonym ){ |
| 173336 | + int bEof = 1; |
| 173337 | + Fts5ExprTerm *p; |
| 173338 | + |
| 173339 | + /* Find the firstest rowid any synonym points to. */ |
| 173340 | + i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); |
| 173341 | + |
| 173342 | + /* Advance each iterator that currently points to iRowid. Or, if iFrom |
| 173343 | + ** is valid - each iterator that points to a rowid before iFrom. */ |
| 173344 | + for(p=pTerm; p; p=p->pSynonym){ |
| 173345 | + if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 173346 | + i64 ii = p->pIter->iRowid; |
| 173347 | + if( ii==iRowid |
| 173348 | + || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) |
| 173349 | + ){ |
| 173350 | + if( bFromValid ){ |
| 173351 | + rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); |
| 173352 | + }else{ |
| 173353 | + rc = sqlite3Fts5IterNext(p->pIter); |
| 173354 | + } |
| 173355 | + if( rc!=SQLITE_OK ) break; |
| 173356 | + if( sqlite3Fts5IterEof(p->pIter)==0 ){ |
| 173357 | + bEof = 0; |
| 173358 | + } |
| 173359 | + }else{ |
| 173360 | + bEof = 0; |
| 173361 | + } |
| 173362 | + } |
| 173363 | + } |
| 173364 | + |
| 173365 | + /* Set the EOF flag if either all synonym iterators are at EOF or an |
| 173366 | + ** error has occurred. */ |
| 173367 | + pNode->bEof = (rc || bEof); |
| 173368 | + }else{ |
| 173369 | + Fts5IndexIter *pIter = pTerm->pIter; |
| 173370 | + |
| 173371 | + assert( Fts5NodeIsString(pNode) ); |
| 173372 | + if( bFromValid ){ |
| 173373 | + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); |
| 173374 | + }else{ |
| 173375 | + rc = sqlite3Fts5IterNext(pIter); |
| 173376 | + } |
| 173377 | + |
| 173378 | + pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); |
| 173379 | + } |
| 173380 | + |
| 173381 | + if( pNode->bEof==0 ){ |
| 173382 | + assert( rc==SQLITE_OK ); |
| 173383 | + rc = fts5ExprNodeTest_STRING(pExpr, pNode); |
| 173384 | + } |
| 173385 | + |
| 173386 | + return rc; |
| 173387 | +} |
| 173388 | + |
| 173389 | + |
| 173390 | +static int fts5ExprNodeTest_TERM( |
| 173391 | + Fts5Expr *pExpr, /* Expression that pNear is a part of */ |
| 173392 | + Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ |
| 173393 | +){ |
| 173394 | + /* As this "NEAR" object is actually a single phrase that consists |
| 173395 | + ** of a single term only, grab pointers into the poslist managed by the |
| 173396 | + ** fts5_index.c iterator object. This is much faster than synthesizing |
| 173397 | + ** a new poslist the way we have to for more complicated phrase or NEAR |
| 173398 | + ** expressions. */ |
| 173399 | + Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; |
| 173400 | + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; |
| 173401 | + |
| 173402 | + assert( pNode->eType==FTS5_TERM ); |
| 173403 | + assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 ); |
| 173404 | + assert( pPhrase->aTerm[0].pSynonym==0 ); |
| 173405 | + |
| 173406 | + pPhrase->poslist.n = pIter->nData; |
| 173407 | + if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 173408 | + pPhrase->poslist.p = (u8*)pIter->pData; |
| 173409 | + } |
| 173410 | + pNode->iRowid = pIter->iRowid; |
| 173411 | + pNode->bNomatch = (pPhrase->poslist.n==0); |
| 173412 | + return SQLITE_OK; |
| 173413 | +} |
| 173414 | + |
| 173415 | +/* |
| 173416 | +** xNext() method for a node of type FTS5_TERM. |
| 173417 | +*/ |
| 173418 | +static int fts5ExprNodeNext_TERM( |
| 173419 | + Fts5Expr *pExpr, |
| 173420 | + Fts5ExprNode *pNode, |
| 173421 | + int bFromValid, |
| 173422 | + i64 iFrom |
| 173423 | +){ |
| 173424 | + int rc; |
| 173425 | + Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; |
| 173426 | + |
| 173427 | + assert( pNode->bEof==0 ); |
| 173428 | + if( bFromValid ){ |
| 173429 | + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); |
| 173430 | + }else{ |
| 173431 | + rc = sqlite3Fts5IterNext(pIter); |
| 173432 | + } |
| 173433 | + if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ |
| 173434 | + rc = fts5ExprNodeTest_TERM(pExpr, pNode); |
| 173435 | + }else{ |
| 173436 | + pNode->bEof = 1; |
| 173437 | + pNode->bNomatch = 0; |
| 173438 | + } |
| 173439 | + return rc; |
| 173440 | +} |
| 173441 | + |
| 173442 | +static void fts5ExprNodeTest_OR( |
| 173443 | + Fts5Expr *pExpr, /* Expression of which pNode is a part */ |
| 173444 | + Fts5ExprNode *pNode /* Expression node to test */ |
| 173445 | +){ |
| 173446 | + Fts5ExprNode *pNext = pNode->apChild[0]; |
| 173447 | + int i; |
| 173448 | + |
| 173449 | + for(i=1; i<pNode->nChild; i++){ |
| 173450 | + Fts5ExprNode *pChild = pNode->apChild[i]; |
| 173451 | + int cmp = fts5NodeCompare(pExpr, pNext, pChild); |
| 173452 | + if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ |
| 173453 | + pNext = pChild; |
| 173454 | + } |
| 173455 | + } |
| 173456 | + pNode->iRowid = pNext->iRowid; |
| 173457 | + pNode->bEof = pNext->bEof; |
| 173458 | + pNode->bNomatch = pNext->bNomatch; |
| 173459 | +} |
| 173460 | + |
| 173461 | +static int fts5ExprNodeNext_OR( |
| 173462 | + Fts5Expr *pExpr, |
| 173463 | + Fts5ExprNode *pNode, |
| 173464 | + int bFromValid, |
| 173465 | + i64 iFrom |
| 173466 | +){ |
| 173467 | + int i; |
| 173468 | + i64 iLast = pNode->iRowid; |
| 173469 | + |
| 173470 | + for(i=0; i<pNode->nChild; i++){ |
| 173471 | + Fts5ExprNode *p1 = pNode->apChild[i]; |
| 173472 | + assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); |
| 173473 | + if( p1->bEof==0 ){ |
| 173474 | + if( (p1->iRowid==iLast) |
| 173475 | + || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) |
| 173476 | + ){ |
| 173477 | + int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); |
| 173478 | + if( rc!=SQLITE_OK ) return rc; |
| 173479 | + } |
| 173480 | + } |
| 173481 | + } |
| 173482 | + |
| 173483 | + fts5ExprNodeTest_OR(pExpr, pNode); |
| 173484 | + return SQLITE_OK; |
| 173485 | +} |
| 172796 | 173486 | |
| 172797 | 173487 | /* |
| 172798 | 173488 | ** Argument pNode is an FTS5_AND node. |
| 172799 | 173489 | */ |
| 172800 | | -static int fts5ExprAndNextRowid( |
| 173490 | +static int fts5ExprNodeTest_AND( |
| 172801 | 173491 | Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 172802 | 173492 | Fts5ExprNode *pAnd /* FTS5_AND node to advance */ |
| 172803 | 173493 | ){ |
| 172804 | 173494 | int iChild; |
| 172805 | 173495 | i64 iLast = pAnd->iRowid; |
| | @@ -172810,19 +173500,15 @@ |
| 172810 | 173500 | do { |
| 172811 | 173501 | pAnd->bNomatch = 0; |
| 172812 | 173502 | bMatch = 1; |
| 172813 | 173503 | for(iChild=0; iChild<pAnd->nChild; iChild++){ |
| 172814 | 173504 | 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 | | - } |
| 173505 | + int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); |
| 173506 | + if( cmp>0 ){ |
| 173507 | + /* Advance pChild until it points to iLast or laster */ |
| 173508 | + rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); |
| 173509 | + if( rc!=SQLITE_OK ) return rc; |
| 172824 | 173510 | } |
| 172825 | 173511 | |
| 172826 | 173512 | /* If the child node is now at EOF, so is the parent AND node. Otherwise, |
| 172827 | 173513 | ** the child node is guaranteed to have advanced at least as far as |
| 172828 | 173514 | ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the |
| | @@ -172848,190 +173534,99 @@ |
| 172848 | 173534 | } |
| 172849 | 173535 | pAnd->iRowid = iLast; |
| 172850 | 173536 | return SQLITE_OK; |
| 172851 | 173537 | } |
| 172852 | 173538 | |
| 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( |
| 173539 | +static int fts5ExprNodeNext_AND( |
| 173540 | + Fts5Expr *pExpr, |
| 173541 | + Fts5ExprNode *pNode, |
| 173542 | + int bFromValid, |
| 173543 | + i64 iFrom |
| 173544 | +){ |
| 173545 | + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 173546 | + if( rc==SQLITE_OK ){ |
| 173547 | + rc = fts5ExprNodeTest_AND(pExpr, pNode); |
| 173548 | + } |
| 173549 | + return rc; |
| 173550 | +} |
| 173551 | + |
| 173552 | +static int fts5ExprNodeTest_NOT( |
| 173553 | + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ |
| 173554 | + Fts5ExprNode *pNode /* FTS5_NOT node to advance */ |
| 173555 | +){ |
| 173556 | + int rc = SQLITE_OK; |
| 173557 | + Fts5ExprNode *p1 = pNode->apChild[0]; |
| 173558 | + Fts5ExprNode *p2 = pNode->apChild[1]; |
| 173559 | + assert( pNode->nChild==2 ); |
| 173560 | + |
| 173561 | + while( rc==SQLITE_OK && p1->bEof==0 ){ |
| 173562 | + int cmp = fts5NodeCompare(pExpr, p1, p2); |
| 173563 | + if( cmp>0 ){ |
| 173564 | + rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); |
| 173565 | + cmp = fts5NodeCompare(pExpr, p1, p2); |
| 173566 | + } |
| 173567 | + assert( rc!=SQLITE_OK || cmp<=0 ); |
| 173568 | + if( cmp || p2->bNomatch ) break; |
| 173569 | + rc = fts5ExprNodeNext(pExpr, p1, 0, 0); |
| 173570 | + } |
| 173571 | + pNode->bEof = p1->bEof; |
| 173572 | + pNode->bNomatch = p1->bNomatch; |
| 173573 | + pNode->iRowid = p1->iRowid; |
| 173574 | + if( p1->bEof ){ |
| 173575 | + fts5ExprNodeZeroPoslist(p2); |
| 173576 | + } |
| 173577 | + return rc; |
| 173578 | +} |
| 173579 | + |
| 173580 | +static int fts5ExprNodeNext_NOT( |
| 172884 | 173581 | Fts5Expr *pExpr, |
| 172885 | 173582 | Fts5ExprNode *pNode, |
| 172886 | 173583 | int bFromValid, |
| 172887 | 173584 | i64 iFrom |
| 172888 | 173585 | ){ |
| 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 | | - |
| 173586 | + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); |
| 173587 | + if( rc==SQLITE_OK ){ |
| 173588 | + rc = fts5ExprNodeTest_NOT(pExpr, pNode); |
| 173589 | + } |
| 173590 | + return rc; |
| 173591 | +} |
| 172966 | 173592 | |
| 172967 | 173593 | /* |
| 172968 | 173594 | ** If pNode currently points to a match, this function returns SQLITE_OK |
| 172969 | 173595 | ** without modifying it. Otherwise, pNode is advanced until it does point |
| 172970 | 173596 | ** to a match or EOF is reached. |
| 172971 | 173597 | */ |
| 172972 | | -static int fts5ExprNodeNextMatch( |
| 173598 | +static int fts5ExprNodeTest( |
| 172973 | 173599 | Fts5Expr *pExpr, /* Expression of which pNode is a part */ |
| 172974 | 173600 | Fts5ExprNode *pNode /* Expression node to test */ |
| 172975 | 173601 | ){ |
| 172976 | 173602 | int rc = SQLITE_OK; |
| 172977 | 173603 | if( pNode->bEof==0 ){ |
| 172978 | 173604 | switch( pNode->eType ){ |
| 172979 | 173605 | |
| 172980 | 173606 | case FTS5_STRING: { |
| 172981 | | - /* Advance the iterators until they all point to the same rowid */ |
| 172982 | | - rc = fts5ExprNearNextMatch(pExpr, pNode); |
| 173607 | + rc = fts5ExprNodeTest_STRING(pExpr, pNode); |
| 172983 | 173608 | break; |
| 172984 | 173609 | } |
| 172985 | 173610 | |
| 172986 | 173611 | case FTS5_TERM: { |
| 172987 | | - rc = fts5ExprTokenTest(pExpr, pNode); |
| 173612 | + rc = fts5ExprNodeTest_TERM(pExpr, pNode); |
| 172988 | 173613 | break; |
| 172989 | 173614 | } |
| 172990 | 173615 | |
| 172991 | 173616 | case FTS5_AND: { |
| 172992 | | - rc = fts5ExprAndNextRowid(pExpr, pNode); |
| 173617 | + rc = fts5ExprNodeTest_AND(pExpr, pNode); |
| 172993 | 173618 | break; |
| 172994 | 173619 | } |
| 172995 | 173620 | |
| 172996 | 173621 | 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; |
| 173622 | + fts5ExprNodeTest_OR(pExpr, pNode); |
| 173010 | 173623 | break; |
| 173011 | 173624 | } |
| 173012 | 173625 | |
| 173013 | 173626 | 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 | | - } |
| 173627 | + rc = fts5ExprNodeTest_NOT(pExpr, pNode); |
| 173033 | 173628 | break; |
| 173034 | 173629 | } |
| 173035 | 173630 | } |
| 173036 | 173631 | } |
| 173037 | 173632 | return rc; |
| | @@ -173046,24 +173641,44 @@ |
| 173046 | 173641 | ** It is not an error if there are no matches. |
| 173047 | 173642 | */ |
| 173048 | 173643 | static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ |
| 173049 | 173644 | int rc = SQLITE_OK; |
| 173050 | 173645 | pNode->bEof = 0; |
| 173646 | + pNode->bNomatch = 0; |
| 173051 | 173647 | |
| 173052 | 173648 | if( Fts5NodeIsString(pNode) ){ |
| 173053 | 173649 | /* Initialize all term iterators in the NEAR object. */ |
| 173054 | 173650 | rc = fts5ExprNearInitAll(pExpr, pNode); |
| 173055 | 173651 | }else{ |
| 173056 | 173652 | int i; |
| 173653 | + int nEof = 0; |
| 173057 | 173654 | for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){ |
| 173655 | + Fts5ExprNode *pChild = pNode->apChild[i]; |
| 173058 | 173656 | rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]); |
| 173657 | + assert( pChild->bEof==0 || pChild->bEof==1 ); |
| 173658 | + nEof += pChild->bEof; |
| 173059 | 173659 | } |
| 173060 | 173660 | pNode->iRowid = pNode->apChild[0]->iRowid; |
| 173661 | + |
| 173662 | + switch( pNode->eType ){ |
| 173663 | + case FTS5_AND: |
| 173664 | + if( nEof>0 ) fts5ExprSetEof(pNode); |
| 173665 | + break; |
| 173666 | + |
| 173667 | + case FTS5_OR: |
| 173668 | + if( pNode->nChild==nEof ) fts5ExprSetEof(pNode); |
| 173669 | + break; |
| 173670 | + |
| 173671 | + default: |
| 173672 | + assert( pNode->eType==FTS5_NOT ); |
| 173673 | + pNode->bEof = pNode->apChild[0]->bEof; |
| 173674 | + break; |
| 173675 | + } |
| 173061 | 173676 | } |
| 173062 | 173677 | |
| 173063 | 173678 | if( rc==SQLITE_OK ){ |
| 173064 | | - rc = fts5ExprNodeNextMatch(pExpr, pNode); |
| 173679 | + rc = fts5ExprNodeTest(pExpr, pNode); |
| 173065 | 173680 | } |
| 173066 | 173681 | return rc; |
| 173067 | 173682 | } |
| 173068 | 173683 | |
| 173069 | 173684 | |
| | @@ -173083,11 +173698,11 @@ |
| 173083 | 173698 | ** is not considered an error if the query does not match any documents. |
| 173084 | 173699 | */ |
| 173085 | 173700 | static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ |
| 173086 | 173701 | Fts5ExprNode *pRoot = p->pRoot; |
| 173087 | 173702 | int rc = SQLITE_OK; |
| 173088 | | - if( pRoot ){ |
| 173703 | + if( pRoot->xNext ){ |
| 173089 | 173704 | p->pIndex = pIdx; |
| 173090 | 173705 | p->bDesc = bDesc; |
| 173091 | 173706 | rc = fts5ExprNodeFirst(p, pRoot); |
| 173092 | 173707 | |
| 173093 | 173708 | /* If not at EOF but the current rowid occurs earlier than iFirst in |
| | @@ -173095,11 +173710,12 @@ |
| 173095 | 173710 | if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ |
| 173096 | 173711 | rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); |
| 173097 | 173712 | } |
| 173098 | 173713 | |
| 173099 | 173714 | /* If the iterator is not at a real match, skip forward until it is. */ |
| 173100 | | - while( pRoot->bNomatch && rc==SQLITE_OK && pRoot->bEof==0 ){ |
| 173715 | + while( pRoot->bNomatch ){ |
| 173716 | + assert( pRoot->bEof==0 && rc==SQLITE_OK ); |
| 173101 | 173717 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173102 | 173718 | } |
| 173103 | 173719 | } |
| 173104 | 173720 | return rc; |
| 173105 | 173721 | } |
| | @@ -173111,21 +173727,23 @@ |
| 173111 | 173727 | ** is not considered an error if the query does not match any documents. |
| 173112 | 173728 | */ |
| 173113 | 173729 | static int sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ |
| 173114 | 173730 | int rc; |
| 173115 | 173731 | Fts5ExprNode *pRoot = p->pRoot; |
| 173732 | + assert( pRoot->bEof==0 && pRoot->bNomatch==0 ); |
| 173116 | 173733 | do { |
| 173117 | 173734 | rc = fts5ExprNodeNext(p, pRoot, 0, 0); |
| 173118 | | - }while( pRoot->bNomatch && pRoot->bEof==0 && rc==SQLITE_OK ); |
| 173735 | + assert( pRoot->bNomatch==0 || (rc==SQLITE_OK && pRoot->bEof==0) ); |
| 173736 | + }while( pRoot->bNomatch ); |
| 173119 | 173737 | if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ |
| 173120 | 173738 | pRoot->bEof = 1; |
| 173121 | 173739 | } |
| 173122 | 173740 | return rc; |
| 173123 | 173741 | } |
| 173124 | 173742 | |
| 173125 | 173743 | static int sqlite3Fts5ExprEof(Fts5Expr *p){ |
| 173126 | | - return (p->pRoot==0 || p->pRoot->bEof); |
| 173744 | + return p->pRoot->bEof; |
| 173127 | 173745 | } |
| 173128 | 173746 | |
| 173129 | 173747 | static i64 sqlite3Fts5ExprRowid(Fts5Expr *p){ |
| 173130 | 173748 | return p->pRoot->iRowid; |
| 173131 | 173749 | } |
| | @@ -173146,14 +173764,14 @@ |
| 173146 | 173764 | Fts5ExprTerm *pSyn; |
| 173147 | 173765 | Fts5ExprTerm *pNext; |
| 173148 | 173766 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; |
| 173149 | 173767 | sqlite3_free(pTerm->zTerm); |
| 173150 | 173768 | sqlite3Fts5IterClose(pTerm->pIter); |
| 173151 | | - |
| 173152 | 173769 | for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ |
| 173153 | 173770 | pNext = pSyn->pSynonym; |
| 173154 | 173771 | sqlite3Fts5IterClose(pSyn->pIter); |
| 173772 | + fts5BufferFree((Fts5Buffer*)&pSyn[1]); |
| 173155 | 173773 | sqlite3_free(pSyn); |
| 173156 | 173774 | } |
| 173157 | 173775 | } |
| 173158 | 173776 | if( pPhrase->poslist.nSpace>0 ) fts5BufferFree(&pPhrase->poslist); |
| 173159 | 173777 | sqlite3_free(pPhrase); |
| | @@ -173230,24 +173848,26 @@ |
| 173230 | 173848 | ){ |
| 173231 | 173849 | int rc = SQLITE_OK; |
| 173232 | 173850 | const int SZALLOC = 8; |
| 173233 | 173851 | TokenCtx *pCtx = (TokenCtx*)pContext; |
| 173234 | 173852 | Fts5ExprPhrase *pPhrase = pCtx->pPhrase; |
| 173853 | + |
| 173854 | + UNUSED_PARAM2(iUnused1, iUnused2); |
| 173235 | 173855 | |
| 173236 | 173856 | /* If an error has already occurred, this is a no-op */ |
| 173237 | 173857 | if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; |
| 173238 | 173858 | |
| 173239 | 173859 | assert( pPhrase==0 || pPhrase->nTerm>0 ); |
| 173240 | 173860 | if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ |
| 173241 | 173861 | Fts5ExprTerm *pSyn; |
| 173242 | | - int nByte = sizeof(Fts5ExprTerm) + nToken+1; |
| 173862 | + int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; |
| 173243 | 173863 | pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); |
| 173244 | 173864 | if( pSyn==0 ){ |
| 173245 | 173865 | rc = SQLITE_NOMEM; |
| 173246 | 173866 | }else{ |
| 173247 | 173867 | memset(pSyn, 0, nByte); |
| 173248 | | - pSyn->zTerm = (char*)&pSyn[1]; |
| 173868 | + pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); |
| 173249 | 173869 | memcpy(pSyn->zTerm, pToken, nToken); |
| 173250 | 173870 | pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; |
| 173251 | 173871 | pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; |
| 173252 | 173872 | } |
| 173253 | 173873 | }else{ |
| | @@ -173366,26 +173986,21 @@ |
| 173366 | 173986 | /* |
| 173367 | 173987 | ** Create a new FTS5 expression by cloning phrase iPhrase of the |
| 173368 | 173988 | ** expression passed as the second argument. |
| 173369 | 173989 | */ |
| 173370 | 173990 | static int sqlite3Fts5ExprClonePhrase( |
| 173371 | | - Fts5Config *pConfig, |
| 173372 | 173991 | Fts5Expr *pExpr, |
| 173373 | 173992 | int iPhrase, |
| 173374 | 173993 | Fts5Expr **ppNew |
| 173375 | 173994 | ){ |
| 173376 | 173995 | int rc = SQLITE_OK; /* Return code */ |
| 173377 | 173996 | Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ |
| 173378 | 173997 | int i; /* Used to iterate through phrase terms */ |
| 173379 | | - |
| 173380 | 173998 | Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ |
| 173381 | | - |
| 173382 | 173999 | TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */ |
| 173383 | 174000 | |
| 173384 | | - |
| 173385 | 174001 | pOrig = pExpr->apExprPhrase[iPhrase]; |
| 173386 | | - |
| 173387 | 174002 | pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); |
| 173388 | 174003 | if( rc==SQLITE_OK ){ |
| 173389 | 174004 | pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, |
| 173390 | 174005 | sizeof(Fts5ExprPhrase*)); |
| 173391 | 174006 | } |
| | @@ -173422,12 +174037,14 @@ |
| 173422 | 174037 | pNew->pRoot->pNear->nPhrase = 1; |
| 173423 | 174038 | sCtx.pPhrase->pNode = pNew->pRoot; |
| 173424 | 174039 | |
| 173425 | 174040 | if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ |
| 173426 | 174041 | pNew->pRoot->eType = FTS5_TERM; |
| 174042 | + pNew->pRoot->xNext = fts5ExprNodeNext_TERM; |
| 173427 | 174043 | }else{ |
| 173428 | 174044 | pNew->pRoot->eType = FTS5_STRING; |
| 174045 | + pNew->pRoot->xNext = fts5ExprNodeNext_STRING; |
| 173429 | 174046 | } |
| 173430 | 174047 | }else{ |
| 173431 | 174048 | sqlite3Fts5ExprFree(pNew); |
| 173432 | 174049 | fts5ExprPhraseFree(sCtx.pPhrase); |
| 173433 | 174050 | pNew = 0; |
| | @@ -173570,10 +174187,42 @@ |
| 173570 | 174187 | pNear->pColset = pColset; |
| 173571 | 174188 | }else{ |
| 173572 | 174189 | sqlite3_free(pColset); |
| 173573 | 174190 | } |
| 173574 | 174191 | } |
| 174192 | + |
| 174193 | +static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ |
| 174194 | + switch( pNode->eType ){ |
| 174195 | + case FTS5_STRING: { |
| 174196 | + Fts5ExprNearset *pNear = pNode->pNear; |
| 174197 | + if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 |
| 174198 | + && pNear->apPhrase[0]->aTerm[0].pSynonym==0 |
| 174199 | + ){ |
| 174200 | + pNode->eType = FTS5_TERM; |
| 174201 | + pNode->xNext = fts5ExprNodeNext_TERM; |
| 174202 | + }else{ |
| 174203 | + pNode->xNext = fts5ExprNodeNext_STRING; |
| 174204 | + } |
| 174205 | + break; |
| 174206 | + }; |
| 174207 | + |
| 174208 | + case FTS5_OR: { |
| 174209 | + pNode->xNext = fts5ExprNodeNext_OR; |
| 174210 | + break; |
| 174211 | + }; |
| 174212 | + |
| 174213 | + case FTS5_AND: { |
| 174214 | + pNode->xNext = fts5ExprNodeNext_AND; |
| 174215 | + break; |
| 174216 | + }; |
| 174217 | + |
| 174218 | + default: assert( pNode->eType==FTS5_NOT ); { |
| 174219 | + pNode->xNext = fts5ExprNodeNext_NOT; |
| 174220 | + break; |
| 174221 | + }; |
| 174222 | + } |
| 174223 | +} |
| 173575 | 174224 | |
| 173576 | 174225 | static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ |
| 173577 | 174226 | if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){ |
| 173578 | 174227 | int nByte = sizeof(Fts5ExprNode*) * pSub->nChild; |
| 173579 | 174228 | memcpy(&p->apChild[p->nChild], pSub->apChild, nByte); |
| | @@ -173620,20 +174269,20 @@ |
| 173620 | 174269 | pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); |
| 173621 | 174270 | |
| 173622 | 174271 | if( pRet ){ |
| 173623 | 174272 | pRet->eType = eType; |
| 173624 | 174273 | pRet->pNear = pNear; |
| 174274 | + fts5ExprAssignXNext(pRet); |
| 173625 | 174275 | if( eType==FTS5_STRING ){ |
| 173626 | 174276 | int iPhrase; |
| 173627 | 174277 | for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){ |
| 173628 | 174278 | pNear->apPhrase[iPhrase]->pNode = pRet; |
| 173629 | 174279 | } |
| 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 ){ |
| 174280 | + |
| 174281 | + if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL |
| 174282 | + && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1) |
| 174283 | + ){ |
| 173635 | 174284 | assert( pParse->rc==SQLITE_OK ); |
| 173636 | 174285 | pParse->rc = SQLITE_ERROR; |
| 173637 | 174286 | assert( pParse->zErr==0 ); |
| 173638 | 174287 | pParse->zErr = sqlite3_mprintf( |
| 173639 | 174288 | "fts5: %s queries are not supported (detail!=full)", |
| | @@ -173640,10 +174289,11 @@ |
| 173640 | 174289 | pNear->nPhrase==1 ? "phrase": "NEAR" |
| 173641 | 174290 | ); |
| 173642 | 174291 | sqlite3_free(pRet); |
| 173643 | 174292 | pRet = 0; |
| 173644 | 174293 | } |
| 174294 | + |
| 173645 | 174295 | }else{ |
| 173646 | 174296 | fts5ExprAddChildren(pRet, pLeft); |
| 173647 | 174297 | fts5ExprAddChildren(pRet, pRight); |
| 173648 | 174298 | } |
| 173649 | 174299 | } |
| | @@ -173922,11 +174572,11 @@ |
| 173922 | 174572 | if( rc==SQLITE_OK ){ |
| 173923 | 174573 | rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr); |
| 173924 | 174574 | } |
| 173925 | 174575 | if( rc==SQLITE_OK ){ |
| 173926 | 174576 | char *zText; |
| 173927 | | - if( pExpr->pRoot==0 ){ |
| 174577 | + if( pExpr->pRoot->xNext==0 ){ |
| 173928 | 174578 | zText = sqlite3_mprintf(""); |
| 173929 | 174579 | }else if( bTcl ){ |
| 173930 | 174580 | zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot); |
| 173931 | 174581 | }else{ |
| 173932 | 174582 | zText = fts5ExprPrint(pConfig, pExpr->pRoot); |
| | @@ -174022,11 +174672,11 @@ |
| 174022 | 174672 | }; |
| 174023 | 174673 | int i; |
| 174024 | 174674 | int rc = SQLITE_OK; |
| 174025 | 174675 | void *pCtx = (void*)pGlobal; |
| 174026 | 174676 | |
| 174027 | | - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){ |
| 174677 | + for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){ |
| 174028 | 174678 | struct Fts5ExprFunc *p = &aFunc[i]; |
| 174029 | 174679 | rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); |
| 174030 | 174680 | } |
| 174031 | 174681 | |
| 174032 | 174682 | /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ |
| | @@ -174119,16 +174769,18 @@ |
| 174119 | 174769 | static int fts5ExprPopulatePoslistsCb( |
| 174120 | 174770 | void *pCtx, /* Copy of 2nd argument to xTokenize() */ |
| 174121 | 174771 | int tflags, /* Mask of FTS5_TOKEN_* flags */ |
| 174122 | 174772 | const char *pToken, /* Pointer to buffer containing token */ |
| 174123 | 174773 | int nToken, /* Size of token in bytes */ |
| 174124 | | - int iStart, /* Byte offset of token within input text */ |
| 174125 | | - int iEnd /* Byte offset of end of token within input text */ |
| 174774 | + int iUnused1, /* Byte offset of token within input text */ |
| 174775 | + int iUnused2 /* Byte offset of end of token within input text */ |
| 174126 | 174776 | ){ |
| 174127 | 174777 | Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx; |
| 174128 | 174778 | Fts5Expr *pExpr = p->pExpr; |
| 174129 | 174779 | int i; |
| 174780 | + |
| 174781 | + UNUSED_PARAM2(iUnused1, iUnused2); |
| 174130 | 174782 | |
| 174131 | 174783 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++; |
| 174132 | 174784 | for(i=0; i<pExpr->nPhrase; i++){ |
| 174133 | 174785 | Fts5ExprTerm *pTerm; |
| 174134 | 174786 | if( p->aPopulator[i].bOk==0 ) continue; |
| | @@ -174260,30 +174912,25 @@ |
| 174260 | 174912 | Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase]; |
| 174261 | 174913 | Fts5ExprNode *pNode = pPhrase->pNode; |
| 174262 | 174914 | int rc = SQLITE_OK; |
| 174263 | 174915 | |
| 174264 | 174916 | assert( iPhrase>=0 && iPhrase<pExpr->nPhrase ); |
| 174917 | + assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); |
| 174918 | + |
| 174265 | 174919 | if( pNode->bEof==0 |
| 174266 | 174920 | && pNode->iRowid==pExpr->pRoot->iRowid |
| 174267 | 174921 | && pPhrase->poslist.n>0 |
| 174268 | 174922 | ){ |
| 174269 | 174923 | Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; |
| 174270 | 174924 | if( pTerm->pSynonym ){ |
| 174271 | | - int bDel = 0; |
| 174272 | | - u8 *a; |
| 174925 | + Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1]; |
| 174273 | 174926 | rc = fts5ExprSynonymList( |
| 174274 | | - pTerm, 1, 0, pNode->iRowid, &bDel, &a, pnCollist |
| 174927 | + pTerm, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist |
| 174275 | 174928 | ); |
| 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); |
| 174929 | + }else{ |
| 174930 | + *ppCollist = pPhrase->aTerm[0].pIter->pData; |
| 174931 | + *pnCollist = pPhrase->aTerm[0].pIter->nData; |
| 174285 | 174932 | } |
| 174286 | 174933 | }else{ |
| 174287 | 174934 | *ppCollist = 0; |
| 174288 | 174935 | *pnCollist = 0; |
| 174289 | 174936 | } |
| | @@ -174354,14 +175001,14 @@ |
| 174354 | 175001 | Fts5HashEntry *pScanNext; /* Next entry in sorted order */ |
| 174355 | 175002 | |
| 174356 | 175003 | int nAlloc; /* Total size of allocation */ |
| 174357 | 175004 | int iSzPoslist; /* Offset of space for 4-byte poslist size */ |
| 174358 | 175005 | int nData; /* Total bytes of data (incl. structure) */ |
| 175006 | + int nKey; /* Length of zKey[] in bytes */ |
| 174359 | 175007 | u8 bDel; /* Set delete-flag @ iSzPoslist */ |
| 174360 | 175008 | u8 bContent; /* Set content-flag (detail=none mode) */ |
| 174361 | | - |
| 174362 | | - int iCol; /* Column of last value written */ |
| 175009 | + i16 iCol; /* Column of last value written */ |
| 174363 | 175010 | int iPos; /* Position of last value written */ |
| 174364 | 175011 | i64 iRowid; /* Rowid of last value written */ |
| 174365 | 175012 | char zKey[8]; /* Nul-terminated entry key */ |
| 174366 | 175013 | }; |
| 174367 | 175014 | |
| | @@ -174537,12 +175184,12 @@ |
| 174537 | 175184 | |
| 174538 | 175185 | /* Attempt to locate an existing hash entry */ |
| 174539 | 175186 | iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken); |
| 174540 | 175187 | for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ |
| 174541 | 175188 | if( p->zKey[0]==bByte |
| 175189 | + && p->nKey==nToken |
| 174542 | 175190 | && memcmp(&p->zKey[1], pToken, nToken)==0 |
| 174543 | | - && p->zKey[nToken+1]==0 |
| 174544 | 175191 | ){ |
| 174545 | 175192 | break; |
| 174546 | 175193 | } |
| 174547 | 175194 | } |
| 174548 | 175195 | |
| | @@ -174565,10 +175212,11 @@ |
| 174565 | 175212 | memset(p, 0, FTS5_HASHENTRYSIZE); |
| 174566 | 175213 | p->nAlloc = nByte; |
| 174567 | 175214 | p->zKey[0] = bByte; |
| 174568 | 175215 | memcpy(&p->zKey[1], pToken, nToken); |
| 174569 | 175216 | assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) ); |
| 175217 | + p->nKey = nToken; |
| 174570 | 175218 | p->zKey[nToken+1] = '\0'; |
| 174571 | 175219 | p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE; |
| 174572 | 175220 | p->pHashNext = pHash->aSlot[iHash]; |
| 174573 | 175221 | pHash->aSlot[iHash] = p; |
| 174574 | 175222 | pHash->nEntry++; |
| | @@ -175080,10 +175728,11 @@ |
| 175080 | 175728 | |
| 175081 | 175729 | typedef struct Fts5Data Fts5Data; |
| 175082 | 175730 | typedef struct Fts5DlidxIter Fts5DlidxIter; |
| 175083 | 175731 | typedef struct Fts5DlidxLvl Fts5DlidxLvl; |
| 175084 | 175732 | typedef struct Fts5DlidxWriter Fts5DlidxWriter; |
| 175733 | +typedef struct Fts5Iter Fts5Iter; |
| 175085 | 175734 | typedef struct Fts5PageWriter Fts5PageWriter; |
| 175086 | 175735 | typedef struct Fts5SegIter Fts5SegIter; |
| 175087 | 175736 | typedef struct Fts5DoclistIter Fts5DoclistIter; |
| 175088 | 175737 | typedef struct Fts5SegWriter Fts5SegWriter; |
| 175089 | 175738 | typedef struct Fts5Structure Fts5Structure; |
| | @@ -175322,20 +175971,24 @@ |
| 175322 | 175971 | ** |
| 175323 | 175972 | ** poslist: |
| 175324 | 175973 | ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. |
| 175325 | 175974 | ** There is no way to tell if this is populated or not. |
| 175326 | 175975 | */ |
| 175327 | | -struct Fts5IndexIter { |
| 175976 | +struct Fts5Iter { |
| 175977 | + Fts5IndexIter base; /* Base class containing output vars */ |
| 175978 | + |
| 175328 | 175979 | Fts5Index *pIndex; /* Index that owns this iterator */ |
| 175329 | 175980 | Fts5Structure *pStruct; /* Database structure for this iterator */ |
| 175330 | 175981 | Fts5Buffer poslist; /* Buffer containing current poslist */ |
| 175982 | + Fts5Colset *pColset; /* Restrict matches to these columns */ |
| 175983 | + |
| 175984 | + /* Invoked to set output variables. */ |
| 175985 | + void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*); |
| 175331 | 175986 | |
| 175332 | 175987 | int nSeg; /* Size of aSeg[] array */ |
| 175333 | 175988 | int bRev; /* True to iterate in reverse order */ |
| 175334 | 175989 | u8 bSkipEmpty; /* True to skip deleted entries */ |
| 175335 | | - u8 bEof; /* True at EOF */ |
| 175336 | | - u8 bFiltered; /* True if column-filter already applied */ |
| 175337 | 175990 | |
| 175338 | 175991 | i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ |
| 175339 | 175992 | Fts5CResult *aFirst; /* Current merge state (see above) */ |
| 175340 | 175993 | Fts5SegIter aSeg[1]; /* Array of segment iterators */ |
| 175341 | 175994 | }; |
| | @@ -175421,21 +176074,10 @@ |
| 175421 | 176074 | int nCmp = MIN(pLeft->n, pRight->n); |
| 175422 | 176075 | int res = memcmp(pLeft->p, pRight->p, nCmp); |
| 175423 | 176076 | return (res==0 ? (pLeft->n - pRight->n) : res); |
| 175424 | 176077 | } |
| 175425 | 176078 | |
| 175426 | | -#ifdef SQLITE_DEBUG |
| 175427 | | -static int fts5BlobCompare( |
| 175428 | | - const u8 *pLeft, int nLeft, |
| 175429 | | - const u8 *pRight, int nRight |
| 175430 | | -){ |
| 175431 | | - int nCmp = MIN(nLeft, nRight); |
| 175432 | | - int res = memcmp(pLeft, pRight, nCmp); |
| 175433 | | - return (res==0 ? (nLeft - nRight) : res); |
| 175434 | | -} |
| 175435 | | -#endif |
| 175436 | | - |
| 175437 | 176079 | static int fts5LeafFirstTermOff(Fts5Data *pLeaf){ |
| 175438 | 176080 | int ret; |
| 175439 | 176081 | fts5GetVarint32(&pLeaf->p[pLeaf->szLeaf], ret); |
| 175440 | 176082 | return ret; |
| 175441 | 176083 | } |
| | @@ -175693,28 +176335,37 @@ |
| 175693 | 176335 | for(iLvl=0; rc==SQLITE_OK && iLvl<nLevel; iLvl++){ |
| 175694 | 176336 | Fts5StructureLevel *pLvl = &pRet->aLevel[iLvl]; |
| 175695 | 176337 | int nTotal; |
| 175696 | 176338 | int iSeg; |
| 175697 | 176339 | |
| 175698 | | - i += fts5GetVarint32(&pData[i], pLvl->nMerge); |
| 175699 | | - i += fts5GetVarint32(&pData[i], nTotal); |
| 175700 | | - assert( nTotal>=pLvl->nMerge ); |
| 175701 | | - pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, |
| 175702 | | - nTotal * sizeof(Fts5StructureSegment) |
| 175703 | | - ); |
| 176340 | + if( i>=nData ){ |
| 176341 | + rc = FTS5_CORRUPT; |
| 176342 | + }else{ |
| 176343 | + i += fts5GetVarint32(&pData[i], pLvl->nMerge); |
| 176344 | + i += fts5GetVarint32(&pData[i], nTotal); |
| 176345 | + assert( nTotal>=pLvl->nMerge ); |
| 176346 | + pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, |
| 176347 | + nTotal * sizeof(Fts5StructureSegment) |
| 176348 | + ); |
| 176349 | + } |
| 175704 | 176350 | |
| 175705 | 176351 | if( rc==SQLITE_OK ){ |
| 175706 | 176352 | pLvl->nSeg = nTotal; |
| 175707 | 176353 | for(iSeg=0; iSeg<nTotal; iSeg++){ |
| 176354 | + if( i>=nData ){ |
| 176355 | + rc = FTS5_CORRUPT; |
| 176356 | + break; |
| 176357 | + } |
| 175708 | 176358 | i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid); |
| 175709 | 176359 | i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst); |
| 175710 | 176360 | i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast); |
| 175711 | 176361 | } |
| 175712 | | - }else{ |
| 175713 | | - fts5StructureRelease(pRet); |
| 175714 | | - pRet = 0; |
| 175715 | 176362 | } |
| 176363 | + } |
| 176364 | + if( rc!=SQLITE_OK ){ |
| 176365 | + fts5StructureRelease(pRet); |
| 176366 | + pRet = 0; |
| 175716 | 176367 | } |
| 175717 | 176368 | } |
| 175718 | 176369 | |
| 175719 | 176370 | *ppOut = pRet; |
| 175720 | 176371 | return rc; |
| | @@ -176378,10 +177029,14 @@ |
| 176378 | 177029 | u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ |
| 176379 | 177030 | int iOff = pIter->iLeafOffset; /* Offset to read at */ |
| 176380 | 177031 | int nNew; /* Bytes of new data */ |
| 176381 | 177032 | |
| 176382 | 177033 | iOff += fts5GetVarint32(&a[iOff], nNew); |
| 177034 | + if( iOff+nNew>pIter->pLeaf->nn ){ |
| 177035 | + p->rc = FTS5_CORRUPT; |
| 177036 | + return; |
| 177037 | + } |
| 176383 | 177038 | pIter->term.n = nKeep; |
| 176384 | 177039 | fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]); |
| 176385 | 177040 | iOff += nNew; |
| 176386 | 177041 | pIter->iTermLeafOffset = iOff; |
| 176387 | 177042 | pIter->iTermLeafPgno = pIter->iLeafPgno; |
| | @@ -176571,11 +177226,11 @@ |
| 176571 | 177226 | /* |
| 176572 | 177227 | ** Return true if the iterator passed as the second argument currently |
| 176573 | 177228 | ** points to a delete marker. A delete marker is an entry with a 0 byte |
| 176574 | 177229 | ** position-list. |
| 176575 | 177230 | */ |
| 176576 | | -static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){ |
| 177231 | +static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){ |
| 176577 | 177232 | Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; |
| 176578 | 177233 | return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0); |
| 176579 | 177234 | } |
| 176580 | 177235 | |
| 176581 | 177236 | /* |
| | @@ -176584,14 +177239,16 @@ |
| 176584 | 177239 | ** This version of fts5SegIterNext() is only used by reverse iterators. |
| 176585 | 177240 | */ |
| 176586 | 177241 | static void fts5SegIterNext_Reverse( |
| 176587 | 177242 | Fts5Index *p, /* FTS5 backend object */ |
| 176588 | 177243 | Fts5SegIter *pIter, /* Iterator to advance */ |
| 176589 | | - int *pbNewTerm /* OUT: Set for new term */ |
| 177244 | + int *pbUnused /* Unused */ |
| 176590 | 177245 | ){ |
| 176591 | 177246 | assert( pIter->flags & FTS5_SEGITER_REVERSE ); |
| 176592 | 177247 | assert( pIter->pNextLeaf==0 ); |
| 177248 | + UNUSED_PARAM(pbUnused); |
| 177249 | + |
| 176593 | 177250 | if( pIter->iRowidOffset>0 ){ |
| 176594 | 177251 | u8 *a = pIter->pLeaf->p; |
| 176595 | 177252 | int iOff; |
| 176596 | 177253 | i64 iDelta; |
| 176597 | 177254 | |
| | @@ -176843,13 +177500,10 @@ |
| 176843 | 177500 | iPoslist = pIter->iTermLeafOffset; |
| 176844 | 177501 | }else{ |
| 176845 | 177502 | iPoslist = 4; |
| 176846 | 177503 | } |
| 176847 | 177504 | fts5IndexSkipVarint(pLeaf->p, iPoslist); |
| 176848 | | - assert( p->pConfig->eDetail==FTS5_DETAIL_NONE || iPoslist==( |
| 176849 | | - pIter->iLeafOffset - sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel) |
| 176850 | | - )); |
| 176851 | 177505 | pIter->iLeafOffset = iPoslist; |
| 176852 | 177506 | |
| 176853 | 177507 | /* If this condition is true then the largest rowid for the current |
| 176854 | 177508 | ** term may not be stored on the current page. So search forward to |
| 176855 | 177509 | ** see where said rowid really is. */ |
| | @@ -177067,23 +177721,19 @@ |
| 177067 | 177721 | ** If an error occurs, Fts5Index.rc is set to an appropriate error code. If |
| 177068 | 177722 | ** an error has already occurred when this function is called, it is a no-op. |
| 177069 | 177723 | */ |
| 177070 | 177724 | static void fts5SegIterSeekInit( |
| 177071 | 177725 | Fts5Index *p, /* FTS5 backend */ |
| 177072 | | - Fts5Buffer *pBuf, /* Buffer to use for loading pages */ |
| 177073 | 177726 | const u8 *pTerm, int nTerm, /* Term to seek to */ |
| 177074 | 177727 | int flags, /* Mask of FTS5INDEX_XXX flags */ |
| 177075 | 177728 | Fts5StructureSegment *pSeg, /* Description of segment */ |
| 177076 | 177729 | Fts5SegIter *pIter /* Object to populate */ |
| 177077 | 177730 | ){ |
| 177078 | 177731 | int iPg = 1; |
| 177079 | 177732 | int bGe = (flags & FTS5INDEX_QUERY_SCAN); |
| 177080 | 177733 | int bDlidx = 0; /* True if there is a doclist-index */ |
| 177081 | 177734 | |
| 177082 | | - static int nCall = 0; |
| 177083 | | - nCall++; |
| 177084 | | - |
| 177085 | 177735 | assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); |
| 177086 | 177736 | assert( pTerm && nTerm ); |
| 177087 | 177737 | memset(pIter, 0, sizeof(*pIter)); |
| 177088 | 177738 | pIter->pSeg = pSeg; |
| 177089 | 177739 | |
| | @@ -177225,11 +177875,11 @@ |
| 177225 | 177875 | ** fts5AssertMultiIterSetup(). It ensures that the result currently stored |
| 177226 | 177876 | ** in *pRes is the correct result of comparing the current positions of the |
| 177227 | 177877 | ** two iterators. |
| 177228 | 177878 | */ |
| 177229 | 177879 | static void fts5AssertComparisonResult( |
| 177230 | | - Fts5IndexIter *pIter, |
| 177880 | + Fts5Iter *pIter, |
| 177231 | 177881 | Fts5SegIter *p1, |
| 177232 | 177882 | Fts5SegIter *p2, |
| 177233 | 177883 | Fts5CResult *pRes |
| 177234 | 177884 | ){ |
| 177235 | 177885 | int i1 = p1 - pIter->aSeg; |
| | @@ -177266,16 +177916,16 @@ |
| 177266 | 177916 | ** This function is a no-op unless SQLITE_DEBUG is defined when this module |
| 177267 | 177917 | ** is compiled. In that case, this function is essentially an assert() |
| 177268 | 177918 | ** statement used to verify that the contents of the pIter->aFirst[] array |
| 177269 | 177919 | ** are correct. |
| 177270 | 177920 | */ |
| 177271 | | -static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5IndexIter *pIter){ |
| 177921 | +static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){ |
| 177272 | 177922 | if( p->rc==SQLITE_OK ){ |
| 177273 | 177923 | Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177274 | 177924 | int i; |
| 177275 | 177925 | |
| 177276 | | - assert( (pFirst->pLeaf==0)==pIter->bEof ); |
| 177926 | + assert( (pFirst->pLeaf==0)==pIter->base.bEof ); |
| 177277 | 177927 | |
| 177278 | 177928 | /* Check that pIter->iSwitchRowid is set correctly. */ |
| 177279 | 177929 | for(i=0; i<pIter->nSeg; i++){ |
| 177280 | 177930 | Fts5SegIter *p1 = &pIter->aSeg[i]; |
| 177281 | 177931 | assert( p1==pFirst |
| | @@ -177311,11 +177961,11 @@ |
| 177311 | 177961 | ** If the returned value is non-zero, then it is the index of an entry |
| 177312 | 177962 | ** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing |
| 177313 | 177963 | ** to a key that is a duplicate of another, higher priority, |
| 177314 | 177964 | ** segment-iterator in the pSeg->aSeg[] array. |
| 177315 | 177965 | */ |
| 177316 | | -static int fts5MultiIterDoCompare(Fts5IndexIter *pIter, int iOut){ |
| 177966 | +static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ |
| 177317 | 177967 | int i1; /* Index of left-hand Fts5SegIter */ |
| 177318 | 177968 | int i2; /* Index of right-hand Fts5SegIter */ |
| 177319 | 177969 | int iRes; |
| 177320 | 177970 | Fts5SegIter *p1; /* Left-hand Fts5SegIter */ |
| 177321 | 177971 | Fts5SegIter *p2; /* Right-hand Fts5SegIter */ |
| | @@ -177457,11 +178107,11 @@ |
| 177457 | 178107 | |
| 177458 | 178108 | |
| 177459 | 178109 | /* |
| 177460 | 178110 | ** Free the iterator object passed as the second argument. |
| 177461 | 178111 | */ |
| 177462 | | -static void fts5MultiIterFree(Fts5Index *p, Fts5IndexIter *pIter){ |
| 178112 | +static void fts5MultiIterFree(Fts5Iter *pIter){ |
| 177463 | 178113 | if( pIter ){ |
| 177464 | 178114 | int i; |
| 177465 | 178115 | for(i=0; i<pIter->nSeg; i++){ |
| 177466 | 178116 | fts5SegIterClear(&pIter->aSeg[i]); |
| 177467 | 178117 | } |
| | @@ -177471,11 +178121,11 @@ |
| 177471 | 178121 | } |
| 177472 | 178122 | } |
| 177473 | 178123 | |
| 177474 | 178124 | static void fts5MultiIterAdvanced( |
| 177475 | 178125 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177476 | | - Fts5IndexIter *pIter, /* Iterator to update aFirst[] array for */ |
| 178126 | + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ |
| 177477 | 178127 | int iChanged, /* Index of sub-iterator just advanced */ |
| 177478 | 178128 | int iMinset /* Minimum entry in aFirst[] to set */ |
| 177479 | 178129 | ){ |
| 177480 | 178130 | int i; |
| 177481 | 178131 | for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){ |
| | @@ -177498,13 +178148,13 @@ |
| 177498 | 178148 | ** If non-zero is returned, the caller should call fts5MultiIterAdvanced() |
| 177499 | 178149 | ** on the iterator instead. That function does the same as this one, except |
| 177500 | 178150 | ** that it deals with more complicated cases as well. |
| 177501 | 178151 | */ |
| 177502 | 178152 | 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 */ |
| 178153 | + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ |
| 178154 | + int iChanged, /* Index of sub-iterator just advanced */ |
| 178155 | + Fts5SegIter **ppFirst |
| 177506 | 178156 | ){ |
| 177507 | 178157 | Fts5SegIter *pNew = &pIter->aSeg[iChanged]; |
| 177508 | 178158 | |
| 177509 | 178159 | if( pNew->iRowid==pIter->iSwitchRowid |
| 177510 | 178160 | || (pNew->iRowid<pIter->iSwitchRowid)==pIter->bRev |
| | @@ -177533,19 +178183,20 @@ |
| 177533 | 178183 | |
| 177534 | 178184 | pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ]; |
| 177535 | 178185 | } |
| 177536 | 178186 | } |
| 177537 | 178187 | |
| 178188 | + *ppFirst = pNew; |
| 177538 | 178189 | return 0; |
| 177539 | 178190 | } |
| 177540 | 178191 | |
| 177541 | 178192 | /* |
| 177542 | 178193 | ** Set the pIter->bEof variable based on the state of the sub-iterators. |
| 177543 | 178194 | */ |
| 177544 | | -static void fts5MultiIterSetEof(Fts5IndexIter *pIter){ |
| 178195 | +static void fts5MultiIterSetEof(Fts5Iter *pIter){ |
| 177545 | 178196 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 177546 | | - pIter->bEof = pSeg->pLeaf==0; |
| 178197 | + pIter->base.bEof = pSeg->pLeaf==0; |
| 177547 | 178198 | pIter->iSwitchRowid = pSeg->iRowid; |
| 177548 | 178199 | } |
| 177549 | 178200 | |
| 177550 | 178201 | /* |
| 177551 | 178202 | ** Move the iterator to the next entry. |
| | @@ -177554,43 +178205,48 @@ |
| 177554 | 178205 | ** considered an error if the iterator reaches EOF, or if it is already at |
| 177555 | 178206 | ** EOF when this function is called. |
| 177556 | 178207 | */ |
| 177557 | 178208 | static void fts5MultiIterNext( |
| 177558 | 178209 | Fts5Index *p, |
| 177559 | | - Fts5IndexIter *pIter, |
| 178210 | + Fts5Iter *pIter, |
| 177560 | 178211 | int bFrom, /* True if argument iFrom is valid */ |
| 177561 | 178212 | i64 iFrom /* Advance at least as far as this */ |
| 177562 | 178213 | ){ |
| 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) ); |
| 178214 | + int bUseFrom = bFrom; |
| 178215 | + while( p->rc==SQLITE_OK ){ |
| 178216 | + int iFirst = pIter->aFirst[1].iFirst; |
| 178217 | + int bNewTerm = 0; |
| 178218 | + Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; |
| 178219 | + assert( p->rc==SQLITE_OK ); |
| 178220 | + if( bUseFrom && pSeg->pDlidx ){ |
| 178221 | + fts5SegIterNextFrom(p, pSeg, iFrom); |
| 178222 | + }else{ |
| 178223 | + pSeg->xNext(p, pSeg, &bNewTerm); |
| 178224 | + } |
| 178225 | + |
| 178226 | + if( pSeg->pLeaf==0 || bNewTerm |
| 178227 | + || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) |
| 178228 | + ){ |
| 178229 | + fts5MultiIterAdvanced(p, pIter, iFirst, 1); |
| 178230 | + fts5MultiIterSetEof(pIter); |
| 178231 | + pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; |
| 178232 | + if( pSeg->pLeaf==0 ) return; |
| 178233 | + } |
| 178234 | + |
| 178235 | + fts5AssertMultiIterSetup(p, pIter); |
| 178236 | + assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); |
| 178237 | + if( pIter->bSkipEmpty==0 || pSeg->nPos ){ |
| 178238 | + pIter->xSetOutputs(pIter, pSeg); |
| 178239 | + return; |
| 178240 | + } |
| 178241 | + bUseFrom = 0; |
| 177586 | 178242 | } |
| 177587 | 178243 | } |
| 177588 | 178244 | |
| 177589 | 178245 | static void fts5MultiIterNext2( |
| 177590 | 178246 | Fts5Index *p, |
| 177591 | | - Fts5IndexIter *pIter, |
| 178247 | + Fts5Iter *pIter, |
| 177592 | 178248 | int *pbNewTerm /* OUT: True if *might* be new term */ |
| 177593 | 178249 | ){ |
| 177594 | 178250 | assert( pIter->bSkipEmpty ); |
| 177595 | 178251 | if( p->rc==SQLITE_OK ){ |
| 177596 | 178252 | do { |
| | @@ -177599,11 +178255,11 @@ |
| 177599 | 178255 | int bNewTerm = 0; |
| 177600 | 178256 | |
| 177601 | 178257 | assert( p->rc==SQLITE_OK ); |
| 177602 | 178258 | pSeg->xNext(p, pSeg, &bNewTerm); |
| 177603 | 178259 | if( pSeg->pLeaf==0 || bNewTerm |
| 177604 | | - || fts5MultiIterAdvanceRowid(p, pIter, iFirst) |
| 178260 | + || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) |
| 177605 | 178261 | ){ |
| 177606 | 178262 | fts5MultiIterAdvanced(p, pIter, iFirst, 1); |
| 177607 | 178263 | fts5MultiIterSetEof(pIter); |
| 177608 | 178264 | *pbNewTerm = 1; |
| 177609 | 178265 | }else{ |
| | @@ -177613,220 +178269,147 @@ |
| 177613 | 178269 | |
| 177614 | 178270 | }while( fts5MultiIterIsEmpty(p, pIter) ); |
| 177615 | 178271 | } |
| 177616 | 178272 | } |
| 177617 | 178273 | |
| 178274 | +static void fts5IterSetOutputs_Noop(Fts5Iter *pUnused1, Fts5SegIter *pUnused2){ |
| 178275 | + UNUSED_PARAM2(pUnused1, pUnused2); |
| 178276 | +} |
| 177618 | 178277 | |
| 177619 | | -static Fts5IndexIter *fts5MultiIterAlloc( |
| 178278 | +static Fts5Iter *fts5MultiIterAlloc( |
| 177620 | 178279 | Fts5Index *p, /* FTS5 backend to iterate within */ |
| 177621 | 178280 | int nSeg |
| 177622 | 178281 | ){ |
| 177623 | | - Fts5IndexIter *pNew; |
| 178282 | + Fts5Iter *pNew; |
| 177624 | 178283 | int nSlot; /* Power of two >= nSeg */ |
| 177625 | 178284 | |
| 177626 | 178285 | for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2); |
| 177627 | 178286 | pNew = fts5IdxMalloc(p, |
| 177628 | | - sizeof(Fts5IndexIter) + /* pNew */ |
| 178287 | + sizeof(Fts5Iter) + /* pNew */ |
| 177629 | 178288 | sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */ |
| 177630 | 178289 | sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ |
| 177631 | 178290 | ); |
| 177632 | 178291 | if( pNew ){ |
| 177633 | 178292 | pNew->nSeg = nSlot; |
| 177634 | 178293 | pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; |
| 177635 | 178294 | pNew->pIndex = p; |
| 178295 | + pNew->xSetOutputs = fts5IterSetOutputs_Noop; |
| 177636 | 178296 | } |
| 177637 | 178297 | return pNew; |
| 177638 | 178298 | } |
| 177639 | 178299 | |
| 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; |
| 178300 | +static void fts5PoslistCallback( |
| 178301 | + Fts5Index *pUnused, |
| 178302 | + void *pContext, |
| 178303 | + const u8 *pChunk, int nChunk |
| 178304 | +){ |
| 178305 | + UNUSED_PARAM(pUnused); |
| 178306 | + assert_nc( nChunk>=0 ); |
| 178307 | + if( nChunk>0 ){ |
| 178308 | + fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); |
| 178309 | + } |
| 178310 | +} |
| 178311 | + |
| 178312 | +typedef struct PoslistCallbackCtx PoslistCallbackCtx; |
| 178313 | +struct PoslistCallbackCtx { |
| 178314 | + Fts5Buffer *pBuf; /* Append to this buffer */ |
| 178315 | + Fts5Colset *pColset; /* Restrict matches to this column */ |
| 178316 | + int eState; /* See above */ |
| 178317 | +}; |
| 178318 | + |
| 178319 | +typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; |
| 178320 | +struct PoslistOffsetsCtx { |
| 178321 | + Fts5Buffer *pBuf; /* Append to this buffer */ |
| 178322 | + Fts5Colset *pColset; /* Restrict matches to this column */ |
| 178323 | + int iRead; |
| 178324 | + int iWrite; |
| 178325 | +}; |
| 178326 | + |
| 178327 | +/* |
| 178328 | +** TODO: Make this more efficient! |
| 178329 | +*/ |
| 178330 | +static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ |
| 178331 | + int i; |
| 178332 | + for(i=0; i<pColset->nCol; i++){ |
| 178333 | + if( pColset->aiCol[i]==iCol ) return 1; |
| 178334 | + } |
| 178335 | + return 0; |
| 178336 | +} |
| 178337 | + |
| 178338 | +static void fts5PoslistOffsetsCallback( |
| 178339 | + Fts5Index *pUnused, |
| 178340 | + void *pContext, |
| 178341 | + const u8 *pChunk, int nChunk |
| 178342 | +){ |
| 178343 | + PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; |
| 178344 | + UNUSED_PARAM(pUnused); |
| 178345 | + assert_nc( nChunk>=0 ); |
| 178346 | + if( nChunk>0 ){ |
| 178347 | + int i = 0; |
| 178348 | + while( i<nChunk ){ |
| 178349 | + int iVal; |
| 178350 | + i += fts5GetVarint32(&pChunk[i], iVal); |
| 178351 | + iVal += pCtx->iRead - 2; |
| 178352 | + pCtx->iRead = iVal; |
| 178353 | + if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ |
| 178354 | + fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); |
| 178355 | + pCtx->iWrite = iVal; |
| 178356 | + } |
| 178357 | + } |
| 178358 | + } |
| 178359 | +} |
| 178360 | + |
| 178361 | +static void fts5PoslistFilterCallback( |
| 178362 | + Fts5Index *pUnused, |
| 178363 | + void *pContext, |
| 178364 | + const u8 *pChunk, int nChunk |
| 178365 | +){ |
| 178366 | + PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; |
| 178367 | + UNUSED_PARAM(pUnused); |
| 178368 | + assert_nc( nChunk>=0 ); |
| 178369 | + if( nChunk>0 ){ |
| 178370 | + /* Search through to find the first varint with value 1. This is the |
| 178371 | + ** start of the next columns hits. */ |
| 178372 | + int i = 0; |
| 178373 | + int iStart = 0; |
| 178374 | + |
| 178375 | + if( pCtx->eState==2 ){ |
| 178376 | + int iCol; |
| 178377 | + fts5FastGetVarint32(pChunk, i, iCol); |
| 178378 | + if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ |
| 178379 | + pCtx->eState = 1; |
| 178380 | + fts5BufferSafeAppendVarint(pCtx->pBuf, 1); |
| 178381 | + }else{ |
| 178382 | + pCtx->eState = 0; |
| 178383 | + } |
| 178384 | + } |
| 178385 | + |
| 178386 | + do { |
| 178387 | + while( i<nChunk && pChunk[i]!=0x01 ){ |
| 178388 | + while( pChunk[i] & 0x80 ) i++; |
| 178389 | + i++; |
| 178390 | + } |
| 178391 | + if( pCtx->eState ){ |
| 178392 | + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 178393 | + } |
| 178394 | + if( i<nChunk ){ |
| 178395 | + int iCol; |
| 178396 | + iStart = i; |
| 178397 | + i++; |
| 178398 | + if( i>=nChunk ){ |
| 178399 | + pCtx->eState = 2; |
| 178400 | + }else{ |
| 178401 | + fts5FastGetVarint32(pChunk, i, iCol); |
| 178402 | + pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); |
| 178403 | + if( pCtx->eState ){ |
| 178404 | + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 178405 | + iStart = i; |
| 178406 | + } |
| 178407 | + } |
| 178408 | + } |
| 178409 | + }while( i<nChunk ); |
| 178410 | + } |
| 177828 | 178411 | } |
| 177829 | 178412 | |
| 177830 | 178413 | static void fts5ChunkIterate( |
| 177831 | 178414 | Fts5Index *p, /* Index object */ |
| 177832 | 178415 | Fts5SegIter *pSeg, /* Poslist of this iterator */ |
| | @@ -177866,11 +178449,459 @@ |
| 177866 | 178449 | } |
| 177867 | 178450 | } |
| 177868 | 178451 | } |
| 177869 | 178452 | } |
| 177870 | 178453 | |
| 178454 | +/* |
| 178455 | +** Iterator pIter currently points to a valid entry (not EOF). This |
| 178456 | +** function appends the position list data for the current entry to |
| 178457 | +** buffer pBuf. It does not make a copy of the position-list size |
| 178458 | +** field. |
| 178459 | +*/ |
| 178460 | +static void fts5SegiterPoslist( |
| 178461 | + Fts5Index *p, |
| 178462 | + Fts5SegIter *pSeg, |
| 178463 | + Fts5Colset *pColset, |
| 178464 | + Fts5Buffer *pBuf |
| 178465 | +){ |
| 178466 | + if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ |
| 178467 | + if( pColset==0 ){ |
| 178468 | + fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); |
| 178469 | + }else{ |
| 178470 | + if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 178471 | + PoslistCallbackCtx sCtx; |
| 178472 | + sCtx.pBuf = pBuf; |
| 178473 | + sCtx.pColset = pColset; |
| 178474 | + sCtx.eState = fts5IndexColsetTest(pColset, 0); |
| 178475 | + assert( sCtx.eState==0 || sCtx.eState==1 ); |
| 178476 | + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); |
| 178477 | + }else{ |
| 178478 | + PoslistOffsetsCtx sCtx; |
| 178479 | + memset(&sCtx, 0, sizeof(sCtx)); |
| 178480 | + sCtx.pBuf = pBuf; |
| 178481 | + sCtx.pColset = pColset; |
| 178482 | + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); |
| 178483 | + } |
| 178484 | + } |
| 178485 | + } |
| 178486 | +} |
| 177871 | 178487 | |
| 178488 | +/* |
| 178489 | +** IN/OUT parameter (*pa) points to a position list n bytes in size. If |
| 178490 | +** the position list contains entries for column iCol, then (*pa) is set |
| 178491 | +** to point to the sub-position-list for that column and the number of |
| 178492 | +** bytes in it returned. Or, if the argument position list does not |
| 178493 | +** contain any entries for column iCol, return 0. |
| 178494 | +*/ |
| 178495 | +static int fts5IndexExtractCol( |
| 178496 | + const u8 **pa, /* IN/OUT: Pointer to poslist */ |
| 178497 | + int n, /* IN: Size of poslist in bytes */ |
| 178498 | + int iCol /* Column to extract from poslist */ |
| 178499 | +){ |
| 178500 | + int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ |
| 178501 | + const u8 *p = *pa; |
| 178502 | + const u8 *pEnd = &p[n]; /* One byte past end of position list */ |
| 178503 | + |
| 178504 | + while( iCol>iCurrent ){ |
| 178505 | + /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 178506 | + ** not part of a varint. Note that it is not possible for a negative |
| 178507 | + ** or extremely large varint to occur within an uncorrupted position |
| 178508 | + ** list. So the last byte of each varint may be assumed to have a clear |
| 178509 | + ** 0x80 bit. */ |
| 178510 | + while( *p!=0x01 ){ |
| 178511 | + while( *p++ & 0x80 ); |
| 178512 | + if( p>=pEnd ) return 0; |
| 178513 | + } |
| 178514 | + *pa = p++; |
| 178515 | + iCurrent = *p++; |
| 178516 | + if( iCurrent & 0x80 ){ |
| 178517 | + p--; |
| 178518 | + p += fts5GetVarint32(p, iCurrent); |
| 178519 | + } |
| 178520 | + } |
| 178521 | + if( iCol!=iCurrent ) return 0; |
| 178522 | + |
| 178523 | + /* Advance pointer p until it points to pEnd or an 0x01 byte that is |
| 178524 | + ** not part of a varint */ |
| 178525 | + while( p<pEnd && *p!=0x01 ){ |
| 178526 | + while( *p++ & 0x80 ); |
| 178527 | + } |
| 178528 | + |
| 178529 | + return p - (*pa); |
| 178530 | +} |
| 178531 | + |
| 178532 | +static int fts5IndexExtractColset ( |
| 178533 | + Fts5Colset *pColset, /* Colset to filter on */ |
| 178534 | + const u8 *pPos, int nPos, /* Position list */ |
| 178535 | + Fts5Buffer *pBuf /* Output buffer */ |
| 178536 | +){ |
| 178537 | + int rc = SQLITE_OK; |
| 178538 | + int i; |
| 178539 | + |
| 178540 | + fts5BufferZero(pBuf); |
| 178541 | + for(i=0; i<pColset->nCol; i++){ |
| 178542 | + const u8 *pSub = pPos; |
| 178543 | + int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); |
| 178544 | + if( nSub ){ |
| 178545 | + fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); |
| 178546 | + } |
| 178547 | + } |
| 178548 | + return rc; |
| 178549 | +} |
| 178550 | + |
| 178551 | +/* |
| 178552 | +** xSetOutputs callback used by detail=none tables. |
| 178553 | +*/ |
| 178554 | +static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178555 | + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE ); |
| 178556 | + pIter->base.iRowid = pSeg->iRowid; |
| 178557 | + pIter->base.nData = pSeg->nPos; |
| 178558 | +} |
| 178559 | + |
| 178560 | +/* |
| 178561 | +** xSetOutputs callback used by detail=full and detail=col tables when no |
| 178562 | +** column filters are specified. |
| 178563 | +*/ |
| 178564 | +static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178565 | + pIter->base.iRowid = pSeg->iRowid; |
| 178566 | + pIter->base.nData = pSeg->nPos; |
| 178567 | + |
| 178568 | + assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); |
| 178569 | + assert( pIter->pColset==0 ); |
| 178570 | + |
| 178571 | + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ |
| 178572 | + /* All data is stored on the current page. Populate the output |
| 178573 | + ** variables to point into the body of the page object. */ |
| 178574 | + pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 178575 | + }else{ |
| 178576 | + /* The data is distributed over two or more pages. Copy it into the |
| 178577 | + ** Fts5Iter.poslist buffer and then set the output pointer to point |
| 178578 | + ** to this buffer. */ |
| 178579 | + fts5BufferZero(&pIter->poslist); |
| 178580 | + fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); |
| 178581 | + pIter->base.pData = pIter->poslist.p; |
| 178582 | + } |
| 178583 | +} |
| 178584 | + |
| 178585 | +/* |
| 178586 | +** xSetOutputs callback used by detail=col when there is a column filter |
| 178587 | +** and there are 100 or more columns. Also called as a fallback from |
| 178588 | +** fts5IterSetOutputs_Col100 if the column-list spans more than one page. |
| 178589 | +*/ |
| 178590 | +static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178591 | + fts5BufferZero(&pIter->poslist); |
| 178592 | + fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist); |
| 178593 | + pIter->base.iRowid = pSeg->iRowid; |
| 178594 | + pIter->base.pData = pIter->poslist.p; |
| 178595 | + pIter->base.nData = pIter->poslist.n; |
| 178596 | +} |
| 178597 | + |
| 178598 | +/* |
| 178599 | +** xSetOutputs callback used when: |
| 178600 | +** |
| 178601 | +** * detail=col, |
| 178602 | +** * there is a column filter, and |
| 178603 | +** * the table contains 100 or fewer columns. |
| 178604 | +** |
| 178605 | +** The last point is to ensure all column numbers are stored as |
| 178606 | +** single-byte varints. |
| 178607 | +*/ |
| 178608 | +static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178609 | + |
| 178610 | + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); |
| 178611 | + assert( pIter->pColset ); |
| 178612 | + |
| 178613 | + if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ |
| 178614 | + fts5IterSetOutputs_Col(pIter, pSeg); |
| 178615 | + }else{ |
| 178616 | + u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 178617 | + u8 *pEnd = (u8*)&a[pSeg->nPos]; |
| 178618 | + int iPrev = 0; |
| 178619 | + int *aiCol = pIter->pColset->aiCol; |
| 178620 | + int *aiColEnd = &aiCol[pIter->pColset->nCol]; |
| 178621 | + |
| 178622 | + u8 *aOut = pIter->poslist.p; |
| 178623 | + int iPrevOut = 0; |
| 178624 | + |
| 178625 | + pIter->base.iRowid = pSeg->iRowid; |
| 178626 | + |
| 178627 | + while( a<pEnd ){ |
| 178628 | + iPrev += (int)a++[0] - 2; |
| 178629 | + while( *aiCol<iPrev ){ |
| 178630 | + aiCol++; |
| 178631 | + if( aiCol==aiColEnd ) goto setoutputs_col_out; |
| 178632 | + } |
| 178633 | + if( *aiCol==iPrev ){ |
| 178634 | + *aOut++ = (iPrev - iPrevOut) + 2; |
| 178635 | + iPrevOut = iPrev; |
| 178636 | + } |
| 178637 | + } |
| 178638 | + |
| 178639 | +setoutputs_col_out: |
| 178640 | + pIter->base.pData = pIter->poslist.p; |
| 178641 | + pIter->base.nData = aOut - pIter->poslist.p; |
| 178642 | + } |
| 178643 | +} |
| 178644 | + |
| 178645 | +/* |
| 178646 | +** xSetOutputs callback used by detail=full when there is a column filter. |
| 178647 | +*/ |
| 178648 | +static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ |
| 178649 | + Fts5Colset *pColset = pIter->pColset; |
| 178650 | + pIter->base.iRowid = pSeg->iRowid; |
| 178651 | + |
| 178652 | + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); |
| 178653 | + assert( pColset ); |
| 178654 | + |
| 178655 | + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ |
| 178656 | + /* All data is stored on the current page. Populate the output |
| 178657 | + ** variables to point into the body of the page object. */ |
| 178658 | + const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; |
| 178659 | + if( pColset->nCol==1 ){ |
| 178660 | + pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); |
| 178661 | + pIter->base.pData = a; |
| 178662 | + }else{ |
| 178663 | + fts5BufferZero(&pIter->poslist); |
| 178664 | + fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist); |
| 178665 | + pIter->base.pData = pIter->poslist.p; |
| 178666 | + pIter->base.nData = pIter->poslist.n; |
| 178667 | + } |
| 178668 | + }else{ |
| 178669 | + /* The data is distributed over two or more pages. Copy it into the |
| 178670 | + ** Fts5Iter.poslist buffer and then set the output pointer to point |
| 178671 | + ** to this buffer. */ |
| 178672 | + fts5BufferZero(&pIter->poslist); |
| 178673 | + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); |
| 178674 | + pIter->base.pData = pIter->poslist.p; |
| 178675 | + pIter->base.nData = pIter->poslist.n; |
| 178676 | + } |
| 178677 | +} |
| 178678 | + |
| 178679 | +static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ |
| 178680 | + if( *pRc==SQLITE_OK ){ |
| 178681 | + Fts5Config *pConfig = pIter->pIndex->pConfig; |
| 178682 | + if( pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 178683 | + pIter->xSetOutputs = fts5IterSetOutputs_None; |
| 178684 | + } |
| 178685 | + |
| 178686 | + else if( pIter->pColset==0 ){ |
| 178687 | + pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; |
| 178688 | + } |
| 178689 | + |
| 178690 | + else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ |
| 178691 | + pIter->xSetOutputs = fts5IterSetOutputs_Full; |
| 178692 | + } |
| 178693 | + |
| 178694 | + else{ |
| 178695 | + assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); |
| 178696 | + if( pConfig->nCol<=100 ){ |
| 178697 | + pIter->xSetOutputs = fts5IterSetOutputs_Col100; |
| 178698 | + sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); |
| 178699 | + }else{ |
| 178700 | + pIter->xSetOutputs = fts5IterSetOutputs_Col; |
| 178701 | + } |
| 178702 | + } |
| 178703 | + } |
| 178704 | +} |
| 178705 | + |
| 178706 | + |
| 178707 | +/* |
| 178708 | +** Allocate a new Fts5Iter object. |
| 178709 | +** |
| 178710 | +** The new object will be used to iterate through data in structure pStruct. |
| 178711 | +** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel |
| 178712 | +** is zero or greater, data from the first nSegment segments on level iLevel |
| 178713 | +** is merged. |
| 178714 | +** |
| 178715 | +** The iterator initially points to the first term/rowid entry in the |
| 178716 | +** iterated data. |
| 178717 | +*/ |
| 178718 | +static void fts5MultiIterNew( |
| 178719 | + Fts5Index *p, /* FTS5 backend to iterate within */ |
| 178720 | + Fts5Structure *pStruct, /* Structure of specific index */ |
| 178721 | + int flags, /* FTS5INDEX_QUERY_XXX flags */ |
| 178722 | + Fts5Colset *pColset, /* Colset to filter on (or NULL) */ |
| 178723 | + const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ |
| 178724 | + int iLevel, /* Level to iterate (-1 for all) */ |
| 178725 | + int nSegment, /* Number of segments to merge (iLevel>=0) */ |
| 178726 | + Fts5Iter **ppOut /* New object */ |
| 178727 | +){ |
| 178728 | + int nSeg = 0; /* Number of segment-iters in use */ |
| 178729 | + int iIter = 0; /* */ |
| 178730 | + int iSeg; /* Used to iterate through segments */ |
| 178731 | + Fts5StructureLevel *pLvl; |
| 178732 | + Fts5Iter *pNew; |
| 178733 | + |
| 178734 | + assert( (pTerm==0 && nTerm==0) || iLevel<0 ); |
| 178735 | + |
| 178736 | + /* Allocate space for the new multi-seg-iterator. */ |
| 178737 | + if( p->rc==SQLITE_OK ){ |
| 178738 | + if( iLevel<0 ){ |
| 178739 | + assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); |
| 178740 | + nSeg = pStruct->nSegment; |
| 178741 | + nSeg += (p->pHash ? 1 : 0); |
| 178742 | + }else{ |
| 178743 | + nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); |
| 178744 | + } |
| 178745 | + } |
| 178746 | + *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); |
| 178747 | + if( pNew==0 ) return; |
| 178748 | + pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); |
| 178749 | + pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY)); |
| 178750 | + pNew->pStruct = pStruct; |
| 178751 | + pNew->pColset = pColset; |
| 178752 | + fts5StructureRef(pStruct); |
| 178753 | + if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){ |
| 178754 | + fts5IterSetOutputCb(&p->rc, pNew); |
| 178755 | + } |
| 178756 | + |
| 178757 | + /* Initialize each of the component segment iterators. */ |
| 178758 | + if( p->rc==SQLITE_OK ){ |
| 178759 | + if( iLevel<0 ){ |
| 178760 | + Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; |
| 178761 | + if( p->pHash ){ |
| 178762 | + /* Add a segment iterator for the current contents of the hash table. */ |
| 178763 | + Fts5SegIter *pIter = &pNew->aSeg[iIter++]; |
| 178764 | + fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); |
| 178765 | + } |
| 178766 | + for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){ |
| 178767 | + for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){ |
| 178768 | + Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; |
| 178769 | + Fts5SegIter *pIter = &pNew->aSeg[iIter++]; |
| 178770 | + if( pTerm==0 ){ |
| 178771 | + fts5SegIterInit(p, pSeg, pIter); |
| 178772 | + }else{ |
| 178773 | + fts5SegIterSeekInit(p, pTerm, nTerm, flags, pSeg, pIter); |
| 178774 | + } |
| 178775 | + } |
| 178776 | + } |
| 178777 | + }else{ |
| 178778 | + pLvl = &pStruct->aLevel[iLevel]; |
| 178779 | + for(iSeg=nSeg-1; iSeg>=0; iSeg--){ |
| 178780 | + fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); |
| 178781 | + } |
| 178782 | + } |
| 178783 | + assert( iIter==nSeg ); |
| 178784 | + } |
| 178785 | + |
| 178786 | + /* If the above was successful, each component iterators now points |
| 178787 | + ** to the first entry in its segment. In this case initialize the |
| 178788 | + ** aFirst[] array. Or, if an error has occurred, free the iterator |
| 178789 | + ** object and set the output variable to NULL. */ |
| 178790 | + if( p->rc==SQLITE_OK ){ |
| 178791 | + for(iIter=pNew->nSeg-1; iIter>0; iIter--){ |
| 178792 | + int iEq; |
| 178793 | + if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ |
| 178794 | + Fts5SegIter *pSeg = &pNew->aSeg[iEq]; |
| 178795 | + if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); |
| 178796 | + fts5MultiIterAdvanced(p, pNew, iEq, iIter); |
| 178797 | + } |
| 178798 | + } |
| 178799 | + fts5MultiIterSetEof(pNew); |
| 178800 | + fts5AssertMultiIterSetup(p, pNew); |
| 178801 | + |
| 178802 | + if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ |
| 178803 | + fts5MultiIterNext(p, pNew, 0, 0); |
| 178804 | + }else if( pNew->base.bEof==0 ){ |
| 178805 | + Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; |
| 178806 | + pNew->xSetOutputs(pNew, pSeg); |
| 178807 | + } |
| 178808 | + |
| 178809 | + }else{ |
| 178810 | + fts5MultiIterFree(pNew); |
| 178811 | + *ppOut = 0; |
| 178812 | + } |
| 178813 | +} |
| 178814 | + |
| 178815 | +/* |
| 178816 | +** Create an Fts5Iter that iterates through the doclist provided |
| 178817 | +** as the second argument. |
| 178818 | +*/ |
| 178819 | +static void fts5MultiIterNew2( |
| 178820 | + Fts5Index *p, /* FTS5 backend to iterate within */ |
| 178821 | + Fts5Data *pData, /* Doclist to iterate through */ |
| 178822 | + int bDesc, /* True for descending rowid order */ |
| 178823 | + Fts5Iter **ppOut /* New object */ |
| 178824 | +){ |
| 178825 | + Fts5Iter *pNew; |
| 178826 | + pNew = fts5MultiIterAlloc(p, 2); |
| 178827 | + if( pNew ){ |
| 178828 | + Fts5SegIter *pIter = &pNew->aSeg[1]; |
| 178829 | + |
| 178830 | + pIter->flags = FTS5_SEGITER_ONETERM; |
| 178831 | + if( pData->szLeaf>0 ){ |
| 178832 | + pIter->pLeaf = pData; |
| 178833 | + pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); |
| 178834 | + pIter->iEndofDoclist = pData->nn; |
| 178835 | + pNew->aFirst[1].iFirst = 1; |
| 178836 | + if( bDesc ){ |
| 178837 | + pNew->bRev = 1; |
| 178838 | + pIter->flags |= FTS5_SEGITER_REVERSE; |
| 178839 | + fts5SegIterReverseInitPage(p, pIter); |
| 178840 | + }else{ |
| 178841 | + fts5SegIterLoadNPos(p, pIter); |
| 178842 | + } |
| 178843 | + pData = 0; |
| 178844 | + }else{ |
| 178845 | + pNew->base.bEof = 1; |
| 178846 | + } |
| 178847 | + fts5SegIterSetNext(p, pIter); |
| 178848 | + |
| 178849 | + *ppOut = pNew; |
| 178850 | + } |
| 178851 | + |
| 178852 | + fts5DataRelease(pData); |
| 178853 | +} |
| 178854 | + |
| 178855 | +/* |
| 178856 | +** Return true if the iterator is at EOF or if an error has occurred. |
| 178857 | +** False otherwise. |
| 178858 | +*/ |
| 178859 | +static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){ |
| 178860 | + assert( p->rc |
| 178861 | + || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof |
| 178862 | + ); |
| 178863 | + return (p->rc || pIter->base.bEof); |
| 178864 | +} |
| 178865 | + |
| 178866 | +/* |
| 178867 | +** Return the rowid of the entry that the iterator currently points |
| 178868 | +** to. If the iterator points to EOF when this function is called the |
| 178869 | +** results are undefined. |
| 178870 | +*/ |
| 178871 | +static i64 fts5MultiIterRowid(Fts5Iter *pIter){ |
| 178872 | + assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); |
| 178873 | + return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; |
| 178874 | +} |
| 178875 | + |
| 178876 | +/* |
| 178877 | +** Move the iterator to the next entry at or following iMatch. |
| 178878 | +*/ |
| 178879 | +static void fts5MultiIterNextFrom( |
| 178880 | + Fts5Index *p, |
| 178881 | + Fts5Iter *pIter, |
| 178882 | + i64 iMatch |
| 178883 | +){ |
| 178884 | + while( 1 ){ |
| 178885 | + i64 iRowid; |
| 178886 | + fts5MultiIterNext(p, pIter, 1, iMatch); |
| 178887 | + if( fts5MultiIterEof(p, pIter) ) break; |
| 178888 | + iRowid = fts5MultiIterRowid(pIter); |
| 178889 | + if( pIter->bRev==0 && iRowid>=iMatch ) break; |
| 178890 | + if( pIter->bRev!=0 && iRowid<=iMatch ) break; |
| 178891 | + } |
| 178892 | +} |
| 178893 | + |
| 178894 | +/* |
| 178895 | +** Return a pointer to a buffer containing the term associated with the |
| 178896 | +** entry that the iterator currently points to. |
| 178897 | +*/ |
| 178898 | +static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){ |
| 178899 | + Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 178900 | + *pn = p->term.n; |
| 178901 | + return p->term.p; |
| 178902 | +} |
| 177872 | 178903 | |
| 177873 | 178904 | /* |
| 177874 | 178905 | ** Allocate a new segment-id for the structure pStruct. The new segment |
| 177875 | 178906 | ** id must be between 1 and 65335 inclusive, and must not be used by |
| 177876 | 178907 | ** any currently existing segment. If a free segment id cannot be found, |
| | @@ -177914,19 +178945,18 @@ |
| 177914 | 178945 | p->nPendingData = 0; |
| 177915 | 178946 | } |
| 177916 | 178947 | } |
| 177917 | 178948 | |
| 177918 | 178949 | /* |
| 177919 | | -** Return the size of the prefix, in bytes, that buffer (nNew/pNew) shares |
| 177920 | | -** with buffer (nOld/pOld). |
| 178950 | +** Return the size of the prefix, in bytes, that buffer |
| 178951 | +** (pNew/<length-unknown>) shares with buffer (pOld/nOld). |
| 178952 | +** |
| 178953 | +** Buffer (pNew/<length-unknown>) is guaranteed to be greater |
| 178954 | +** than buffer (pOld/nOld). |
| 177921 | 178955 | */ |
| 177922 | | -static int fts5PrefixCompress( |
| 177923 | | - int nOld, const u8 *pOld, |
| 177924 | | - int nNew, const u8 *pNew |
| 177925 | | -){ |
| 178956 | +static int fts5PrefixCompress(int nOld, const u8 *pOld, const u8 *pNew){ |
| 177926 | 178957 | int i; |
| 177927 | | - assert( fts5BlobCompare(pOld, nOld, pNew, nNew)<0 ); |
| 177928 | 178958 | for(i=0; i<nOld; i++){ |
| 177929 | 178959 | if( pOld[i]!=pNew[i] ) break; |
| 177930 | 178960 | } |
| 177931 | 178961 | return i; |
| 177932 | 178962 | } |
| | @@ -178232,17 +179262,17 @@ |
| 178232 | 179262 | ** In this case the previous term is not available, so just write a |
| 178233 | 179263 | ** copy of (pTerm/nTerm) into the parent node. This is slightly |
| 178234 | 179264 | ** inefficient, but still correct. */ |
| 178235 | 179265 | int n = nTerm; |
| 178236 | 179266 | if( pPage->term.n ){ |
| 178237 | | - n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, nTerm, pTerm); |
| 179267 | + n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); |
| 178238 | 179268 | } |
| 178239 | 179269 | fts5WriteBtreeTerm(p, pWriter, n, pTerm); |
| 178240 | 179270 | pPage = &pWriter->writer; |
| 178241 | 179271 | } |
| 178242 | 179272 | }else{ |
| 178243 | | - nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, nTerm, pTerm); |
| 179273 | + nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); |
| 178244 | 179274 | fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix); |
| 178245 | 179275 | } |
| 178246 | 179276 | |
| 178247 | 179277 | /* Append the number of bytes of new data, then the term data itself |
| 178248 | 179278 | ** to the page. */ |
| | @@ -178401,11 +179431,11 @@ |
| 178401 | 179431 | /* |
| 178402 | 179432 | ** Iterator pIter was used to iterate through the input segments of on an |
| 178403 | 179433 | ** incremental merge operation. This function is called if the incremental |
| 178404 | 179434 | ** merge step has finished but the input has not been completely exhausted. |
| 178405 | 179435 | */ |
| 178406 | | -static void fts5TrimSegments(Fts5Index *p, Fts5IndexIter *pIter){ |
| 179436 | +static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ |
| 178407 | 179437 | int i; |
| 178408 | 179438 | Fts5Buffer buf; |
| 178409 | 179439 | memset(&buf, 0, sizeof(Fts5Buffer)); |
| 178410 | 179440 | for(i=0; i<pIter->nSeg; i++){ |
| 178411 | 179441 | Fts5SegIter *pSeg = &pIter->aSeg[i]; |
| | @@ -178479,18 +179509,19 @@ |
| 178479 | 179509 | int *pnRem /* Write up to this many output leaves */ |
| 178480 | 179510 | ){ |
| 178481 | 179511 | Fts5Structure *pStruct = *ppStruct; |
| 178482 | 179512 | Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; |
| 178483 | 179513 | Fts5StructureLevel *pLvlOut; |
| 178484 | | - Fts5IndexIter *pIter = 0; /* Iterator to read input data */ |
| 179514 | + Fts5Iter *pIter = 0; /* Iterator to read input data */ |
| 178485 | 179515 | int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */ |
| 178486 | 179516 | int nInput; /* Number of input segments */ |
| 178487 | 179517 | Fts5SegWriter writer; /* Writer object */ |
| 178488 | 179518 | Fts5StructureSegment *pSeg; /* Output segment */ |
| 178489 | 179519 | Fts5Buffer term; |
| 178490 | 179520 | int bOldest; /* True if the output segment is the oldest */ |
| 178491 | 179521 | int eDetail = p->pConfig->eDetail; |
| 179522 | + const int flags = FTS5INDEX_QUERY_NOOUTPUT; |
| 178492 | 179523 | |
| 178493 | 179524 | assert( iLvl<pStruct->nLevel ); |
| 178494 | 179525 | assert( pLvl->nMerge<=pLvl->nSeg ); |
| 178495 | 179526 | |
| 178496 | 179527 | memset(&writer, 0, sizeof(Fts5SegWriter)); |
| | @@ -178531,11 +179562,11 @@ |
| 178531 | 179562 | nInput = pLvl->nSeg; |
| 178532 | 179563 | } |
| 178533 | 179564 | bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); |
| 178534 | 179565 | |
| 178535 | 179566 | assert( iLvl>=0 ); |
| 178536 | | - for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, iLvl, nInput, &pIter); |
| 179567 | + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter); |
| 178537 | 179568 | fts5MultiIterEof(p, pIter)==0; |
| 178538 | 179569 | fts5MultiIterNext(p, pIter, 0, 0) |
| 178539 | 179570 | ){ |
| 178540 | 179571 | Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 178541 | 179572 | int nPos; /* position-list size field value */ |
| | @@ -178603,11 +179634,11 @@ |
| 178603 | 179634 | assert( pSeg->pgnoLast>0 ); |
| 178604 | 179635 | fts5TrimSegments(p, pIter); |
| 178605 | 179636 | pLvl->nMerge = nInput; |
| 178606 | 179637 | } |
| 178607 | 179638 | |
| 178608 | | - fts5MultiIterFree(p, pIter); |
| 179639 | + fts5MultiIterFree(pIter); |
| 178609 | 179640 | fts5BufferFree(&term); |
| 178610 | 179641 | if( pnRem ) *pnRem -= writer.nLeafWritten; |
| 178611 | 179642 | } |
| 178612 | 179643 | |
| 178613 | 179644 | /* |
| | @@ -178976,279 +180007,33 @@ |
| 178976 | 180007 | fts5StructureRelease(pStruct); |
| 178977 | 180008 | |
| 178978 | 180009 | return fts5IndexReturn(p); |
| 178979 | 180010 | } |
| 178980 | 180011 | |
| 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; |
| 180012 | +static void fts5AppendRowid( |
| 180013 | + Fts5Index *p, |
| 180014 | + i64 iDelta, |
| 180015 | + Fts5Iter *pUnused, |
| 180016 | + Fts5Buffer *pBuf |
| 180017 | +){ |
| 180018 | + UNUSED_PARAM(pUnused); |
| 180019 | + fts5BufferAppendVarint(&p->rc, pBuf, iDelta); |
| 180020 | +} |
| 180021 | + |
| 180022 | +static void fts5AppendPoslist( |
| 180023 | + Fts5Index *p, |
| 180024 | + i64 iDelta, |
| 180025 | + Fts5Iter *pMulti, |
| 180026 | + Fts5Buffer *pBuf |
| 180027 | +){ |
| 180028 | + int nData = pMulti->base.nData; |
| 180029 | + assert( nData>0 ); |
| 180030 | + if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){ |
| 180031 | + fts5BufferSafeAppendVarint(pBuf, iDelta); |
| 180032 | + fts5BufferSafeAppendVarint(pBuf, nData*2); |
| 180033 | + fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData); |
| 180034 | + } |
| 179250 | 180035 | } |
| 179251 | 180036 | |
| 179252 | 180037 | |
| 179253 | 180038 | static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ |
| 179254 | 180039 | u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist; |
| | @@ -179388,73 +180173,107 @@ |
| 179388 | 180173 | ){ |
| 179389 | 180174 | if( p2->n ){ |
| 179390 | 180175 | i64 iLastRowid = 0; |
| 179391 | 180176 | Fts5DoclistIter i1; |
| 179392 | 180177 | Fts5DoclistIter i2; |
| 179393 | | - Fts5Buffer out; |
| 179394 | | - Fts5Buffer tmp; |
| 179395 | | - memset(&out, 0, sizeof(out)); |
| 179396 | | - memset(&tmp, 0, sizeof(tmp)); |
| 180178 | + Fts5Buffer out = {0, 0, 0}; |
| 180179 | + Fts5Buffer tmp = {0, 0, 0}; |
| 179397 | 180180 | |
| 179398 | | - sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n); |
| 180181 | + if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; |
| 179399 | 180182 | fts5DoclistIterInit(p1, &i1); |
| 179400 | 180183 | 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) ){ |
| 180184 | + |
| 180185 | + while( 1 ){ |
| 180186 | + if( i1.iRowid<i2.iRowid ){ |
| 179403 | 180187 | /* Copy entry from i1 */ |
| 179404 | 180188 | fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); |
| 179405 | 180189 | fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize); |
| 179406 | 180190 | fts5DoclistIterNext(&i1); |
| 180191 | + if( i1.aPoslist==0 ) break; |
| 179407 | 180192 | } |
| 179408 | | - else if( i1.aPoslist==0 || i2.iRowid!=i1.iRowid ){ |
| 180193 | + else if( i2.iRowid!=i1.iRowid ){ |
| 179409 | 180194 | /* Copy entry from i2 */ |
| 179410 | 180195 | fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 179411 | 180196 | fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize); |
| 179412 | 180197 | fts5DoclistIterNext(&i2); |
| 180198 | + if( i2.aPoslist==0 ) break; |
| 179413 | 180199 | } |
| 179414 | 180200 | else{ |
| 180201 | + /* Merge the two position lists. */ |
| 179415 | 180202 | i64 iPos1 = 0; |
| 179416 | 180203 | i64 iPos2 = 0; |
| 179417 | 180204 | int iOff1 = 0; |
| 179418 | 180205 | int iOff2 = 0; |
| 179419 | 180206 | u8 *a1 = &i1.aPoslist[i1.nSize]; |
| 179420 | 180207 | u8 *a2 = &i2.aPoslist[i2.nSize]; |
| 179421 | 180208 | |
| 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 | | - } |
| 180209 | + i64 iPrev = 0; |
| 180210 | + Fts5PoslistWriter writer; |
| 180211 | + memset(&writer, 0, sizeof(writer)); |
| 180212 | + |
| 180213 | + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 180214 | + fts5BufferZero(&tmp); |
| 180215 | + sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist); |
| 180216 | + if( p->rc ) break; |
| 180217 | + |
| 180218 | + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 180219 | + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 180220 | + assert( iPos1>=0 && iPos2>=0 ); |
| 180221 | + |
| 180222 | + if( iPos1<iPos2 ){ |
| 180223 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); |
| 180224 | + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 180225 | + }else{ |
| 180226 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); |
| 180227 | + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 180228 | + } |
| 180229 | + |
| 180230 | + if( iPos1>=0 && iPos2>=0 ){ |
| 180231 | + while( 1 ){ |
| 180232 | + if( iPos1<iPos2 ){ |
| 180233 | + if( iPos1!=iPrev ){ |
| 180234 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); |
| 180235 | + } |
| 180236 | + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); |
| 180237 | + if( iPos1<0 ) break; |
| 180238 | + }else{ |
| 180239 | + assert( iPos2!=iPrev ); |
| 180240 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); |
| 180241 | + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); |
| 180242 | + if( iPos2<0 ) break; |
| 180243 | + } |
| 180244 | + } |
| 180245 | + } |
| 180246 | + |
| 180247 | + if( iPos1>=0 ){ |
| 180248 | + if( iPos1!=iPrev ){ |
| 180249 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); |
| 180250 | + } |
| 180251 | + fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); |
| 180252 | + }else{ |
| 180253 | + assert( iPos2>=0 && iPos2!=iPrev ); |
| 180254 | + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); |
| 180255 | + fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); |
| 179447 | 180256 | } |
| 179448 | 180257 | |
| 179449 | 180258 | /* WRITEPOSLISTSIZE */ |
| 179450 | 180259 | fts5BufferSafeAppendVarint(&out, tmp.n * 2); |
| 179451 | 180260 | fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); |
| 179452 | 180261 | fts5DoclistIterNext(&i1); |
| 179453 | 180262 | fts5DoclistIterNext(&i2); |
| 180263 | + if( i1.aPoslist==0 || i2.aPoslist==0 ) break; |
| 179454 | 180264 | } |
| 179455 | 180265 | } |
| 180266 | + |
| 180267 | + if( i1.aPoslist ){ |
| 180268 | + fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); |
| 180269 | + fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist); |
| 180270 | + } |
| 180271 | + else if( i2.aPoslist ){ |
| 180272 | + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); |
| 180273 | + fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); |
| 180274 | + } |
| 179456 | 180275 | |
| 179457 | 180276 | fts5BufferSet(&p->rc, p1, out.n, out.p); |
| 179458 | 180277 | fts5BufferFree(&tmp); |
| 179459 | 180278 | fts5BufferFree(&out); |
| 179460 | 180279 | } |
| | @@ -179464,18 +180283,18 @@ |
| 179464 | 180283 | Fts5Index *p, /* Index to read from */ |
| 179465 | 180284 | int bDesc, /* True for "ORDER BY rowid DESC" */ |
| 179466 | 180285 | const u8 *pToken, /* Buffer containing prefix to match */ |
| 179467 | 180286 | int nToken, /* Size of buffer pToken in bytes */ |
| 179468 | 180287 | Fts5Colset *pColset, /* Restrict matches to these columns */ |
| 179469 | | - Fts5IndexIter **ppIter /* OUT: New iterator */ |
| 180288 | + Fts5Iter **ppIter /* OUT: New iterator */ |
| 179470 | 180289 | ){ |
| 179471 | 180290 | Fts5Structure *pStruct; |
| 179472 | 180291 | Fts5Buffer *aBuf; |
| 179473 | 180292 | const int nBuf = 32; |
| 179474 | 180293 | |
| 179475 | 180294 | void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); |
| 179476 | | - int (*xAppend)(Fts5Index*, i64, Fts5IndexIter*, Fts5Colset*, Fts5Buffer*); |
| 180295 | + void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*); |
| 179477 | 180296 | if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ |
| 179478 | 180297 | xMerge = fts5MergeRowidLists; |
| 179479 | 180298 | xAppend = fts5AppendRowid; |
| 179480 | 180299 | }else{ |
| 179481 | 180300 | xMerge = fts5MergePrefixLists; |
| | @@ -179484,32 +180303,40 @@ |
| 179484 | 180303 | |
| 179485 | 180304 | aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf); |
| 179486 | 180305 | pStruct = fts5StructureRead(p); |
| 179487 | 180306 | |
| 179488 | 180307 | if( aBuf && pStruct ){ |
| 179489 | | - const int flags = FTS5INDEX_QUERY_SCAN; |
| 180308 | + const int flags = FTS5INDEX_QUERY_SCAN |
| 180309 | + | FTS5INDEX_QUERY_SKIPEMPTY |
| 180310 | + | FTS5INDEX_QUERY_NOOUTPUT; |
| 179490 | 180311 | int i; |
| 179491 | 180312 | i64 iLastRowid = 0; |
| 179492 | | - Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */ |
| 180313 | + Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ |
| 179493 | 180314 | Fts5Data *pData; |
| 179494 | 180315 | Fts5Buffer doclist; |
| 179495 | 180316 | int bNewTerm = 1; |
| 179496 | 180317 | |
| 179497 | 180318 | memset(&doclist, 0, sizeof(doclist)); |
| 179498 | | - for(fts5MultiIterNew(p, pStruct, 1, flags, pToken, nToken, -1, 0, &p1); |
| 180319 | + fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1); |
| 180320 | + fts5IterSetOutputCb(&p->rc, p1); |
| 180321 | + for( /* no-op */ ; |
| 179499 | 180322 | fts5MultiIterEof(p, p1)==0; |
| 179500 | 180323 | fts5MultiIterNext2(p, p1, &bNewTerm) |
| 179501 | 180324 | ){ |
| 179502 | | - i64 iRowid = fts5MultiIterRowid(p1); |
| 179503 | | - int nTerm; |
| 179504 | | - const u8 *pTerm = fts5MultiIterTerm(p1, &nTerm); |
| 180325 | + Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ]; |
| 180326 | + int nTerm = pSeg->term.n; |
| 180327 | + const u8 *pTerm = pSeg->term.p; |
| 180328 | + p1->xSetOutputs(p1, pSeg); |
| 180329 | + |
| 179505 | 180330 | assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 ); |
| 179506 | 180331 | if( bNewTerm ){ |
| 179507 | 180332 | if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break; |
| 179508 | 180333 | } |
| 179509 | 180334 | |
| 179510 | | - if( doclist.n>0 && iRowid<=iLastRowid ){ |
| 180335 | + if( p1->base.nData==0 ) continue; |
| 180336 | + |
| 180337 | + if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){ |
| 179511 | 180338 | for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ |
| 179512 | 180339 | assert( i<nBuf ); |
| 179513 | 180340 | if( aBuf[i].n==0 ){ |
| 179514 | 180341 | fts5BufferSwap(&doclist, &aBuf[i]); |
| 179515 | 180342 | fts5BufferZero(&doclist); |
| | @@ -179519,22 +180346,21 @@ |
| 179519 | 180346 | } |
| 179520 | 180347 | } |
| 179521 | 180348 | iLastRowid = 0; |
| 179522 | 180349 | } |
| 179523 | 180350 | |
| 179524 | | - if( !xAppend(p, iRowid-iLastRowid, p1, pColset, &doclist) ){ |
| 179525 | | - iLastRowid = iRowid; |
| 179526 | | - } |
| 180351 | + xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist); |
| 180352 | + iLastRowid = p1->base.iRowid; |
| 179527 | 180353 | } |
| 179528 | 180354 | |
| 179529 | 180355 | for(i=0; i<nBuf; i++){ |
| 179530 | 180356 | if( p->rc==SQLITE_OK ){ |
| 179531 | 180357 | xMerge(p, &doclist, &aBuf[i]); |
| 179532 | 180358 | } |
| 179533 | 180359 | fts5BufferFree(&aBuf[i]); |
| 179534 | 180360 | } |
| 179535 | | - fts5MultiIterFree(p, p1); |
| 180361 | + fts5MultiIterFree(p1); |
| 179536 | 180362 | |
| 179537 | 180363 | pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n); |
| 179538 | 180364 | if( pData ){ |
| 179539 | 180365 | pData->p = (u8*)&pData[1]; |
| 179540 | 180366 | pData->nn = pData->szLeaf = doclist.n; |
| | @@ -179591,11 +180417,11 @@ |
| 179591 | 180417 | ** records must be invalidated. |
| 179592 | 180418 | */ |
| 179593 | 180419 | static int sqlite3Fts5IndexRollback(Fts5Index *p){ |
| 179594 | 180420 | fts5CloseReader(p); |
| 179595 | 180421 | fts5IndexDiscardData(p); |
| 179596 | | - assert( p->rc==SQLITE_OK ); |
| 180422 | + /* assert( p->rc==SQLITE_OK ); */ |
| 179597 | 180423 | return SQLITE_OK; |
| 179598 | 180424 | } |
| 179599 | 180425 | |
| 179600 | 180426 | /* |
| 179601 | 180427 | ** The %_data table is completely empty when this function is called. This |
| | @@ -179763,26 +180589,31 @@ |
| 179763 | 180589 | int flags, /* Mask of FTS5INDEX_QUERY_X flags */ |
| 179764 | 180590 | Fts5Colset *pColset, /* Match these columns only */ |
| 179765 | 180591 | Fts5IndexIter **ppIter /* OUT: New iterator object */ |
| 179766 | 180592 | ){ |
| 179767 | 180593 | Fts5Config *pConfig = p->pConfig; |
| 179768 | | - Fts5IndexIter *pRet = 0; |
| 179769 | | - int iIdx = 0; |
| 180594 | + Fts5Iter *pRet = 0; |
| 179770 | 180595 | Fts5Buffer buf = {0, 0, 0}; |
| 179771 | 180596 | |
| 179772 | 180597 | /* If the QUERY_SCAN flag is set, all other flags must be clear. */ |
| 179773 | 180598 | assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); |
| 179774 | 180599 | |
| 179775 | 180600 | if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ |
| 180601 | + int iIdx = 0; /* Index to search */ |
| 179776 | 180602 | memcpy(&buf.p[1], pToken, nToken); |
| 179777 | 180603 | |
| 179778 | | -#ifdef SQLITE_DEBUG |
| 179779 | | - /* If the QUERY_TEST_NOIDX flag was specified, then this must be a |
| 180604 | + /* Figure out which index to search and set iIdx accordingly. If this |
| 180605 | + ** is a prefix query for which there is no prefix index, set iIdx to |
| 180606 | + ** greater than pConfig->nPrefix to indicate that the query will be |
| 180607 | + ** satisfied by scanning multiple terms in the main index. |
| 180608 | + ** |
| 180609 | + ** If the QUERY_TEST_NOIDX flag was specified, then this must be a |
| 179780 | 180610 | ** prefix-query. Instead of using a prefix-index (if one exists), |
| 179781 | 180611 | ** evaluate the prefix query using the main FTS index. This is used |
| 179782 | 180612 | ** for internal sanity checking by the integrity-check in debug |
| 179783 | 180613 | ** mode only. */ |
| 180614 | +#ifdef SQLITE_DEBUG |
| 179784 | 180615 | if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ |
| 179785 | 180616 | assert( flags & FTS5INDEX_QUERY_PREFIX ); |
| 179786 | 180617 | iIdx = 1+pConfig->nPrefix; |
| 179787 | 180618 | }else |
| 179788 | 180619 | #endif |
| | @@ -179792,54 +180623,62 @@ |
| 179792 | 180623 | if( pConfig->aPrefix[iIdx-1]==nChar ) break; |
| 179793 | 180624 | } |
| 179794 | 180625 | } |
| 179795 | 180626 | |
| 179796 | 180627 | if( iIdx<=pConfig->nPrefix ){ |
| 180628 | + /* Straight index lookup */ |
| 179797 | 180629 | Fts5Structure *pStruct = fts5StructureRead(p); |
| 179798 | 180630 | buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); |
| 179799 | 180631 | if( pStruct ){ |
| 179800 | | - fts5MultiIterNew(p, pStruct, 1, flags, buf.p, nToken+1, -1, 0, &pRet); |
| 180632 | + fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, |
| 180633 | + pColset, buf.p, nToken+1, -1, 0, &pRet |
| 180634 | + ); |
| 179801 | 180635 | fts5StructureRelease(pStruct); |
| 179802 | 180636 | } |
| 179803 | 180637 | }else{ |
| 180638 | + /* Scan multiple terms in the main index */ |
| 179804 | 180639 | int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; |
| 179805 | 180640 | buf.p[0] = FTS5_MAIN_PREFIX; |
| 179806 | 180641 | fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); |
| 180642 | + assert( p->rc!=SQLITE_OK || pRet->pColset==0 ); |
| 180643 | + fts5IterSetOutputCb(&p->rc, pRet); |
| 180644 | + if( p->rc==SQLITE_OK ){ |
| 180645 | + Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; |
| 180646 | + if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); |
| 180647 | + } |
| 179807 | 180648 | } |
| 179808 | 180649 | |
| 179809 | 180650 | if( p->rc ){ |
| 179810 | | - sqlite3Fts5IterClose(pRet); |
| 180651 | + sqlite3Fts5IterClose(&pRet->base); |
| 179811 | 180652 | pRet = 0; |
| 179812 | 180653 | fts5CloseReader(p); |
| 179813 | 180654 | } |
| 179814 | | - *ppIter = pRet; |
| 180655 | + |
| 180656 | + *ppIter = &pRet->base; |
| 179815 | 180657 | sqlite3Fts5BufferFree(&buf); |
| 179816 | 180658 | } |
| 179817 | 180659 | return fts5IndexReturn(p); |
| 179818 | 180660 | } |
| 179819 | 180661 | |
| 179820 | 180662 | /* |
| 179821 | 180663 | ** Return true if the iterator passed as the only argument is at EOF. |
| 179822 | 180664 | */ |
| 179823 | | -static int sqlite3Fts5IterEof(Fts5IndexIter *pIter){ |
| 179824 | | - assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179825 | | - return pIter->bEof; |
| 179826 | | -} |
| 179827 | | - |
| 179828 | 180665 | /* |
| 179829 | 180666 | ** Move to the next matching rowid. |
| 179830 | 180667 | */ |
| 179831 | | -static int sqlite3Fts5IterNext(Fts5IndexIter *pIter){ |
| 180668 | +static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){ |
| 180669 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 179832 | 180670 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179833 | 180671 | fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); |
| 179834 | 180672 | return fts5IndexReturn(pIter->pIndex); |
| 179835 | 180673 | } |
| 179836 | 180674 | |
| 179837 | 180675 | /* |
| 179838 | 180676 | ** Move to the next matching term/rowid. Used by the fts5vocab module. |
| 179839 | 180677 | */ |
| 179840 | | -static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIter){ |
| 180678 | +static int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){ |
| 180679 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 179841 | 180680 | Fts5Index *p = pIter->pIndex; |
| 179842 | 180681 | |
| 179843 | 180682 | assert( pIter->pIndex->rc==SQLITE_OK ); |
| 179844 | 180683 | |
| 179845 | 180684 | fts5MultiIterNext(p, pIter, 0, 0); |
| | @@ -179846,11 +180685,11 @@ |
| 179846 | 180685 | if( p->rc==SQLITE_OK ){ |
| 179847 | 180686 | Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; |
| 179848 | 180687 | if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){ |
| 179849 | 180688 | fts5DataRelease(pSeg->pLeaf); |
| 179850 | 180689 | pSeg->pLeaf = 0; |
| 179851 | | - pIter->bEof = 1; |
| 180690 | + pIter->base.bEof = 1; |
| 179852 | 180691 | } |
| 179853 | 180692 | } |
| 179854 | 180693 | |
| 179855 | 180694 | return fts5IndexReturn(pIter->pIndex); |
| 179856 | 180695 | } |
| | @@ -179858,135 +180697,34 @@ |
| 179858 | 180697 | /* |
| 179859 | 180698 | ** Move to the next matching rowid that occurs at or after iMatch. The |
| 179860 | 180699 | ** definition of "at or after" depends on whether this iterator iterates |
| 179861 | 180700 | ** in ascending or descending rowid order. |
| 179862 | 180701 | */ |
| 179863 | | -static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIter, i64 iMatch){ |
| 180702 | +static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ |
| 180703 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 179864 | 180704 | fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); |
| 179865 | 180705 | return fts5IndexReturn(pIter->pIndex); |
| 179866 | 180706 | } |
| 179867 | 180707 | |
| 179868 | | -/* |
| 179869 | | -** Return the current rowid. |
| 179870 | | -*/ |
| 179871 | | -static i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIter){ |
| 179872 | | - return fts5MultiIterRowid(pIter); |
| 179873 | | -} |
| 179874 | | - |
| 179875 | 180708 | /* |
| 179876 | 180709 | ** Return the current term. |
| 179877 | 180710 | */ |
| 179878 | | -static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIter, int *pn){ |
| 180711 | +static const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ |
| 179879 | 180712 | int n; |
| 179880 | | - const char *z = (const char*)fts5MultiIterTerm(pIter, &n); |
| 180713 | + const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n); |
| 179881 | 180714 | *pn = n-1; |
| 179882 | 180715 | return &z[1]; |
| 179883 | 180716 | } |
| 179884 | 180717 | |
| 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 | 180718 | /* |
| 179982 | 180719 | ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). |
| 179983 | 180720 | */ |
| 179984 | | -static void sqlite3Fts5IterClose(Fts5IndexIter *pIter){ |
| 179985 | | - if( pIter ){ |
| 180721 | +static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ |
| 180722 | + if( pIndexIter ){ |
| 180723 | + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; |
| 179986 | 180724 | Fts5Index *pIndex = pIter->pIndex; |
| 179987 | | - fts5MultiIterFree(pIter->pIndex, pIter); |
| 180725 | + fts5MultiIterFree(pIter); |
| 179988 | 180726 | fts5CloseReader(pIndex); |
| 179989 | 180727 | } |
| 179990 | 180728 | } |
| 179991 | 180729 | |
| 179992 | 180730 | /* |
| | @@ -180147,39 +180885,34 @@ |
| 180147 | 180885 | int flags, /* Flags for Fts5IndexQuery */ |
| 180148 | 180886 | u64 *pCksum /* IN/OUT: Checksum value */ |
| 180149 | 180887 | ){ |
| 180150 | 180888 | int eDetail = p->pConfig->eDetail; |
| 180151 | 180889 | u64 cksum = *pCksum; |
| 180152 | | - Fts5IndexIter *pIdxIter = 0; |
| 180153 | | - Fts5Buffer buf = {0, 0, 0}; |
| 180154 | | - int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter); |
| 180890 | + Fts5IndexIter *pIter = 0; |
| 180891 | + int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); |
| 180155 | 180892 | |
| 180156 | | - while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){ |
| 180157 | | - i64 rowid = sqlite3Fts5IterRowid(pIdxIter); |
| 180893 | + while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){ |
| 180894 | + i64 rowid = pIter->iRowid; |
| 180158 | 180895 | |
| 180159 | 180896 | if( eDetail==FTS5_DETAIL_NONE ){ |
| 180160 | 180897 | cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); |
| 180161 | 180898 | }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 | | - } |
| 180899 | + Fts5PoslistReader sReader; |
| 180900 | + for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader); |
| 180901 | + sReader.bEof==0; |
| 180902 | + sqlite3Fts5PoslistReaderNext(&sReader) |
| 180903 | + ){ |
| 180904 | + int iCol = FTS5_POS2COLUMN(sReader.iPos); |
| 180905 | + int iOff = FTS5_POS2OFFSET(sReader.iPos); |
| 180906 | + cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); |
| 180173 | 180907 | } |
| 180174 | 180908 | } |
| 180175 | 180909 | if( rc==SQLITE_OK ){ |
| 180176 | | - rc = sqlite3Fts5IterNext(pIdxIter); |
| 180910 | + rc = sqlite3Fts5IterNext(pIter); |
| 180177 | 180911 | } |
| 180178 | 180912 | } |
| 180179 | | - sqlite3Fts5IterClose(pIdxIter); |
| 180180 | | - fts5BufferFree(&buf); |
| 180913 | + sqlite3Fts5IterClose(pIter); |
| 180181 | 180914 | |
| 180182 | 180915 | *pCksum = cksum; |
| 180183 | 180916 | return rc; |
| 180184 | 180917 | } |
| 180185 | 180918 | |
| | @@ -180480,18 +181213,19 @@ |
| 180480 | 181213 | */ |
| 180481 | 181214 | static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ |
| 180482 | 181215 | int eDetail = p->pConfig->eDetail; |
| 180483 | 181216 | u64 cksum2 = 0; /* Checksum based on contents of indexes */ |
| 180484 | 181217 | Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ |
| 180485 | | - Fts5IndexIter *pIter; /* Used to iterate through entire index */ |
| 181218 | + Fts5Iter *pIter; /* Used to iterate through entire index */ |
| 180486 | 181219 | Fts5Structure *pStruct; /* Index structure */ |
| 180487 | 181220 | |
| 180488 | 181221 | #ifdef SQLITE_DEBUG |
| 180489 | 181222 | /* Used by extra internal tests only run if NDEBUG is not defined */ |
| 180490 | 181223 | u64 cksum3 = 0; /* Checksum based on contents of indexes */ |
| 180491 | 181224 | Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ |
| 180492 | 181225 | #endif |
| 181226 | + const int flags = FTS5INDEX_QUERY_NOOUTPUT; |
| 180493 | 181227 | |
| 180494 | 181228 | /* Load the FTS index structure */ |
| 180495 | 181229 | pStruct = fts5StructureRead(p); |
| 180496 | 181230 | |
| 180497 | 181231 | /* Check that the internal nodes of each segment match the leaves */ |
| | @@ -180516,11 +181250,11 @@ |
| 180516 | 181250 | ** |
| 180517 | 181251 | ** As each term visited by the linear scans, a separate query for the |
| 180518 | 181252 | ** same term is performed. cksum3 is calculated based on the entries |
| 180519 | 181253 | ** extracted by these queries. |
| 180520 | 181254 | */ |
| 180521 | | - for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, -1, 0, &pIter); |
| 181255 | + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter); |
| 180522 | 181256 | fts5MultiIterEof(p, pIter)==0; |
| 180523 | 181257 | fts5MultiIterNext(p, pIter, 0, 0) |
| 180524 | 181258 | ){ |
| 180525 | 181259 | int n; /* Size of term in bytes */ |
| 180526 | 181260 | i64 iPos = 0; /* Position read from poslist */ |
| | @@ -180545,11 +181279,11 @@ |
| 180545 | 181279 | } |
| 180546 | 181280 | } |
| 180547 | 181281 | } |
| 180548 | 181282 | fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); |
| 180549 | 181283 | |
| 180550 | | - fts5MultiIterFree(p, pIter); |
| 181284 | + fts5MultiIterFree(pIter); |
| 180551 | 181285 | if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; |
| 180552 | 181286 | |
| 180553 | 181287 | fts5StructureRelease(pStruct); |
| 180554 | 181288 | #ifdef SQLITE_DEBUG |
| 180555 | 181289 | fts5BufferFree(&term); |
| | @@ -180782,10 +181516,11 @@ |
| 180782 | 181516 | int rc = SQLITE_OK; /* Return code */ |
| 180783 | 181517 | int nSpace = 0; |
| 180784 | 181518 | int eDetailNone = (sqlite3_user_data(pCtx)!=0); |
| 180785 | 181519 | |
| 180786 | 181520 | assert( nArg==2 ); |
| 181521 | + UNUSED_PARAM(nArg); |
| 180787 | 181522 | memset(&s, 0, sizeof(Fts5Buffer)); |
| 180788 | 181523 | iRowid = sqlite3_value_int64(apVal[0]); |
| 180789 | 181524 | |
| 180790 | 181525 | /* Make a copy of the second argument (a blob) in aBlob[]. The aBlob[] |
| 180791 | 181526 | ** copy is followed by FTS5_DATA_ZERO_PADDING 0x00 bytes, which prevents |
| | @@ -181234,14 +181969,14 @@ |
| 181234 | 181969 | #define FTS5_BI_ORDER_DESC 0x0080 |
| 181235 | 181970 | |
| 181236 | 181971 | /* |
| 181237 | 181972 | ** Values for Fts5Cursor.csrflags |
| 181238 | 181973 | */ |
| 181239 | | -#define FTS5CSR_REQUIRE_CONTENT 0x01 |
| 181240 | | -#define FTS5CSR_REQUIRE_DOCSIZE 0x02 |
| 181241 | | -#define FTS5CSR_REQUIRE_INST 0x04 |
| 181242 | | -#define FTS5CSR_EOF 0x08 |
| 181974 | +#define FTS5CSR_EOF 0x01 |
| 181975 | +#define FTS5CSR_REQUIRE_CONTENT 0x02 |
| 181976 | +#define FTS5CSR_REQUIRE_DOCSIZE 0x04 |
| 181977 | +#define FTS5CSR_REQUIRE_INST 0x08 |
| 181243 | 181978 | #define FTS5CSR_FREE_ZRANK 0x10 |
| 181244 | 181979 | #define FTS5CSR_REQUIRE_RESEEK 0x20 |
| 181245 | 181980 | #define FTS5CSR_REQUIRE_POSLIST 0x40 |
| 181246 | 181981 | |
| 181247 | 181982 | #define BitFlagAllTest(x,y) (((x) & (y))==(y)) |
| | @@ -181552,11 +182287,11 @@ |
| 181552 | 182287 | |
| 181553 | 182288 | /* Set idxFlags flags for all WHERE clause terms that will be used. */ |
| 181554 | 182289 | for(i=0; i<pInfo->nConstraint; i++){ |
| 181555 | 182290 | struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; |
| 181556 | 182291 | int j; |
| 181557 | | - for(j=0; j<(int)ArraySize(aConstraint); j++){ |
| 182292 | + for(j=0; j<ArraySize(aConstraint); j++){ |
| 181558 | 182293 | struct Constraint *pC = &aConstraint[j]; |
| 181559 | 182294 | if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){ |
| 181560 | 182295 | if( p->usable ){ |
| 181561 | 182296 | pC->iConsIndex = i; |
| 181562 | 182297 | idxFlags |= pC->fts5op; |
| | @@ -181599,11 +182334,11 @@ |
| 181599 | 182334 | pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; |
| 181600 | 182335 | } |
| 181601 | 182336 | |
| 181602 | 182337 | /* Assign argvIndex values to each constraint in use. */ |
| 181603 | 182338 | iNext = 1; |
| 181604 | | - for(i=0; i<(int)ArraySize(aConstraint); i++){ |
| 182339 | + for(i=0; i<ArraySize(aConstraint); i++){ |
| 181605 | 182340 | struct Constraint *pC = &aConstraint[i]; |
| 181606 | 182341 | if( pC->iConsIndex>=0 ){ |
| 181607 | 182342 | pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; |
| 181608 | 182343 | pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; |
| 181609 | 182344 | } |
| | @@ -181792,18 +182527,19 @@ |
| 181792 | 182527 | Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); |
| 181793 | 182528 | int bDesc = pCsr->bDesc; |
| 181794 | 182529 | i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); |
| 181795 | 182530 | |
| 181796 | 182531 | rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); |
| 181797 | | - if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ |
| 182532 | + if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ |
| 181798 | 182533 | *pbSkip = 1; |
| 181799 | 182534 | } |
| 181800 | 182535 | |
| 181801 | 182536 | CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); |
| 181802 | 182537 | fts5CsrNewrow(pCsr); |
| 181803 | 182538 | if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ |
| 181804 | 182539 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 182540 | + *pbSkip = 1; |
| 181805 | 182541 | } |
| 181806 | 182542 | } |
| 181807 | 182543 | return rc; |
| 181808 | 182544 | } |
| 181809 | 182545 | |
| | @@ -181816,28 +182552,28 @@ |
| 181816 | 182552 | ** even if we reach end-of-file. The fts5EofMethod() will be called |
| 181817 | 182553 | ** subsequently to determine whether or not an EOF was hit. |
| 181818 | 182554 | */ |
| 181819 | 182555 | static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ |
| 181820 | 182556 | Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; |
| 181821 | | - int rc = SQLITE_OK; |
| 182557 | + int rc; |
| 181822 | 182558 | |
| 181823 | 182559 | assert( (pCsr->ePlan<3)== |
| 181824 | 182560 | (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) |
| 181825 | 182561 | ); |
| 182562 | + assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) ); |
| 181826 | 182563 | |
| 181827 | 182564 | if( pCsr->ePlan<3 ){ |
| 181828 | 182565 | int bSkip = 0; |
| 181829 | 182566 | if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; |
| 181830 | 182567 | rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); |
| 181831 | | - if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ |
| 181832 | | - CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 181833 | | - } |
| 182568 | + CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr)); |
| 181834 | 182569 | fts5CsrNewrow(pCsr); |
| 181835 | 182570 | }else{ |
| 181836 | 182571 | switch( pCsr->ePlan ){ |
| 181837 | 182572 | case FTS5_PLAN_SPECIAL: { |
| 181838 | 182573 | CsrFlagSet(pCsr, FTS5CSR_EOF); |
| 182574 | + rc = SQLITE_OK; |
| 181839 | 182575 | break; |
| 181840 | 182576 | } |
| 181841 | 182577 | |
| 181842 | 182578 | case FTS5_PLAN_SORTED_MATCH: { |
| 181843 | 182579 | rc = fts5SorterNext(pCsr); |
| | @@ -182109,11 +182845,11 @@ |
| 182109 | 182845 | ** 3. A full-table scan. |
| 182110 | 182846 | */ |
| 182111 | 182847 | static int fts5FilterMethod( |
| 182112 | 182848 | sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ |
| 182113 | 182849 | int idxNum, /* Strategy index */ |
| 182114 | | - const char *idxStr, /* Unused */ |
| 182850 | + const char *zUnused, /* Unused */ |
| 182115 | 182851 | int nVal, /* Number of elements in apVal */ |
| 182116 | 182852 | sqlite3_value **apVal /* Arguments for the indexing scheme */ |
| 182117 | 182853 | ){ |
| 182118 | 182854 | Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); |
| 182119 | 182855 | Fts5Config *pConfig = pTab->pConfig; |
| | @@ -182126,10 +182862,13 @@ |
| 182126 | 182862 | sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */ |
| 182127 | 182863 | sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */ |
| 182128 | 182864 | sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */ |
| 182129 | 182865 | sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */ |
| 182130 | 182866 | char **pzErrmsg = pConfig->pzErrmsg; |
| 182867 | + |
| 182868 | + UNUSED_PARAM(zUnused); |
| 182869 | + UNUSED_PARAM(nVal); |
| 182131 | 182870 | |
| 182132 | 182871 | if( pCsr->ePlan ){ |
| 182133 | 182872 | fts5FreeCursorComponents(pCsr); |
| 182134 | 182873 | memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr)); |
| 182135 | 182874 | } |
| | @@ -182411,12 +183150,11 @@ |
| 182411 | 183150 | return rc; |
| 182412 | 183151 | } |
| 182413 | 183152 | |
| 182414 | 183153 | static int fts5SpecialDelete( |
| 182415 | 183154 | Fts5Table *pTab, |
| 182416 | | - sqlite3_value **apVal, |
| 182417 | | - sqlite3_int64 *piRowid |
| 183155 | + sqlite3_value **apVal |
| 182418 | 183156 | ){ |
| 182419 | 183157 | int rc = SQLITE_OK; |
| 182420 | 183158 | int eType1 = sqlite3_value_type(apVal[1]); |
| 182421 | 183159 | if( eType1==SQLITE_INTEGER ){ |
| 182422 | 183160 | sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]); |
| | @@ -182488,11 +183226,11 @@ |
| 182488 | 183226 | /* A "special" INSERT op. These are handled separately. */ |
| 182489 | 183227 | const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]); |
| 182490 | 183228 | if( pConfig->eContent!=FTS5_CONTENT_NORMAL |
| 182491 | 183229 | && 0==sqlite3_stricmp("delete", z) |
| 182492 | 183230 | ){ |
| 182493 | | - rc = fts5SpecialDelete(pTab, apVal, pRowid); |
| 183231 | + rc = fts5SpecialDelete(pTab, apVal); |
| 182494 | 183232 | }else{ |
| 182495 | 183233 | rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); |
| 182496 | 183234 | } |
| 182497 | 183235 | }else{ |
| 182498 | 183236 | /* A regular INSERT, UPDATE or DELETE statement. The trick here is that |
| | @@ -182589,10 +183327,11 @@ |
| 182589 | 183327 | |
| 182590 | 183328 | /* |
| 182591 | 183329 | ** Implementation of xBegin() method. |
| 182592 | 183330 | */ |
| 182593 | 183331 | static int fts5BeginMethod(sqlite3_vtab *pVtab){ |
| 183332 | + UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ |
| 182594 | 183333 | fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0); |
| 182595 | 183334 | return SQLITE_OK; |
| 182596 | 183335 | } |
| 182597 | 183336 | |
| 182598 | 183337 | /* |
| | @@ -182599,10 +183338,11 @@ |
| 182599 | 183338 | ** Implementation of xCommit() method. This is a no-op. The contents of |
| 182600 | 183339 | ** the pending-terms hash-table have already been flushed into the database |
| 182601 | 183340 | ** by fts5SyncMethod(). |
| 182602 | 183341 | */ |
| 182603 | 183342 | static int fts5CommitMethod(sqlite3_vtab *pVtab){ |
| 183343 | + UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ |
| 182604 | 183344 | fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0); |
| 182605 | 183345 | return SQLITE_OK; |
| 182606 | 183346 | } |
| 182607 | 183347 | |
| 182608 | 183348 | /* |
| | @@ -182852,16 +183592,18 @@ |
| 182852 | 183592 | } |
| 182853 | 183593 | |
| 182854 | 183594 | static int fts5ColumnSizeCb( |
| 182855 | 183595 | void *pContext, /* Pointer to int */ |
| 182856 | 183596 | int tflags, |
| 182857 | | - const char *pToken, /* Buffer containing token */ |
| 182858 | | - int nToken, /* Size of token in bytes */ |
| 182859 | | - int iStart, /* Start offset of token */ |
| 182860 | | - int iEnd /* End offset of token */ |
| 183597 | + const char *pUnused, /* Buffer containing token */ |
| 183598 | + int nUnused, /* Size of token in bytes */ |
| 183599 | + int iUnused1, /* Start offset of token */ |
| 183600 | + int iUnused2 /* End offset of token */ |
| 182861 | 183601 | ){ |
| 182862 | 183602 | int *pCnt = (int*)pContext; |
| 183603 | + UNUSED_PARAM2(pUnused, nUnused); |
| 183604 | + UNUSED_PARAM2(iUnused1, iUnused2); |
| 182863 | 183605 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 182864 | 183606 | (*pCnt)++; |
| 182865 | 183607 | } |
| 182866 | 183608 | return SQLITE_OK; |
| 182867 | 183609 | } |
| | @@ -182973,14 +183715,15 @@ |
| 182973 | 183715 | |
| 182974 | 183716 | return pRet; |
| 182975 | 183717 | } |
| 182976 | 183718 | |
| 182977 | 183719 | static void fts5ApiPhraseNext( |
| 182978 | | - Fts5Context *pCtx, |
| 183720 | + Fts5Context *pUnused, |
| 182979 | 183721 | Fts5PhraseIter *pIter, |
| 182980 | 183722 | int *piCol, int *piOff |
| 182981 | 183723 | ){ |
| 183724 | + UNUSED_PARAM(pUnused); |
| 182982 | 183725 | if( pIter->a>=pIter->b ){ |
| 182983 | 183726 | *piCol = -1; |
| 182984 | 183727 | *piOff = -1; |
| 182985 | 183728 | }else{ |
| 182986 | 183729 | int iVal; |
| | @@ -183128,16 +183871,15 @@ |
| 183128 | 183871 | int rc; |
| 183129 | 183872 | Fts5Cursor *pNew = 0; |
| 183130 | 183873 | |
| 183131 | 183874 | rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew); |
| 183132 | 183875 | if( rc==SQLITE_OK ){ |
| 183133 | | - Fts5Config *pConf = pTab->pConfig; |
| 183134 | 183876 | pNew->ePlan = FTS5_PLAN_MATCH; |
| 183135 | 183877 | pNew->iFirstRowid = SMALLEST_INT64; |
| 183136 | 183878 | pNew->iLastRowid = LARGEST_INT64; |
| 183137 | 183879 | pNew->base.pVtab = (sqlite3_vtab*)pTab; |
| 183138 | | - rc = sqlite3Fts5ExprClonePhrase(pConf, pCsr->pExpr, iPhrase, &pNew->pExpr); |
| 183880 | + rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr); |
| 183139 | 183881 | } |
| 183140 | 183882 | |
| 183141 | 183883 | if( rc==SQLITE_OK ){ |
| 183142 | 183884 | for(rc = fts5CursorFirst(pTab, pNew, 0); |
| 183143 | 183885 | rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0; |
| | @@ -183346,18 +184088,19 @@ |
| 183346 | 184088 | ** This routine implements the xFindFunction method for the FTS3 |
| 183347 | 184089 | ** virtual table. |
| 183348 | 184090 | */ |
| 183349 | 184091 | static int fts5FindFunctionMethod( |
| 183350 | 184092 | sqlite3_vtab *pVtab, /* Virtual table handle */ |
| 183351 | | - int nArg, /* Number of SQL function arguments */ |
| 184093 | + int nUnused, /* Number of SQL function arguments */ |
| 183352 | 184094 | const char *zName, /* Name of SQL function */ |
| 183353 | 184095 | void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ |
| 183354 | 184096 | void **ppArg /* OUT: User data for *pxFunc */ |
| 183355 | 184097 | ){ |
| 183356 | 184098 | Fts5Table *pTab = (Fts5Table*)pVtab; |
| 183357 | 184099 | Fts5Auxiliary *pAux; |
| 183358 | 184100 | |
| 184101 | + UNUSED_PARAM(nUnused); |
| 183359 | 184102 | pAux = fts5FindAuxiliary(pTab, zName); |
| 183360 | 184103 | if( pAux ){ |
| 183361 | 184104 | *pxFunc = fts5ApiCallback; |
| 183362 | 184105 | *ppArg = (void*)pAux; |
| 183363 | 184106 | return 1; |
| | @@ -183383,10 +184126,11 @@ |
| 183383 | 184126 | ** |
| 183384 | 184127 | ** Flush the contents of the pending-terms table to disk. |
| 183385 | 184128 | */ |
| 183386 | 184129 | static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ |
| 183387 | 184130 | Fts5Table *pTab = (Fts5Table*)pVtab; |
| 184131 | + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ |
| 183388 | 184132 | fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); |
| 183389 | 184133 | fts5TripCursors(pTab); |
| 183390 | 184134 | return sqlite3Fts5StorageSync(pTab->pStorage, 0); |
| 183391 | 184135 | } |
| 183392 | 184136 | |
| | @@ -183395,10 +184139,11 @@ |
| 183395 | 184139 | ** |
| 183396 | 184140 | ** This is a no-op. |
| 183397 | 184141 | */ |
| 183398 | 184142 | static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ |
| 183399 | 184143 | Fts5Table *pTab = (Fts5Table*)pVtab; |
| 184144 | + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ |
| 183400 | 184145 | fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); |
| 183401 | 184146 | fts5TripCursors(pTab); |
| 183402 | 184147 | return sqlite3Fts5StorageSync(pTab->pStorage, 0); |
| 183403 | 184148 | } |
| 183404 | 184149 | |
| | @@ -183407,10 +184152,11 @@ |
| 183407 | 184152 | ** |
| 183408 | 184153 | ** Discard the contents of the pending terms table. |
| 183409 | 184154 | */ |
| 183410 | 184155 | static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ |
| 183411 | 184156 | Fts5Table *pTab = (Fts5Table*)pVtab; |
| 184157 | + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ |
| 183412 | 184158 | fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); |
| 183413 | 184159 | fts5TripCursors(pTab); |
| 183414 | 184160 | return sqlite3Fts5StorageRollback(pTab->pStorage); |
| 183415 | 184161 | } |
| 183416 | 184162 | |
| | @@ -183586,14 +184332,15 @@ |
| 183586 | 184332 | } |
| 183587 | 184333 | |
| 183588 | 184334 | static void fts5Fts5Func( |
| 183589 | 184335 | sqlite3_context *pCtx, /* Function call context */ |
| 183590 | 184336 | int nArg, /* Number of args */ |
| 183591 | | - sqlite3_value **apVal /* Function arguments */ |
| 184337 | + sqlite3_value **apUnused /* Function arguments */ |
| 183592 | 184338 | ){ |
| 183593 | 184339 | Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx); |
| 183594 | 184340 | char buf[8]; |
| 184341 | + UNUSED_PARAM2(nArg, apUnused); |
| 183595 | 184342 | assert( nArg==0 ); |
| 183596 | 184343 | assert( sizeof(buf)>=sizeof(pGlobal) ); |
| 183597 | 184344 | memcpy(buf, (void*)&pGlobal, sizeof(pGlobal)); |
| 183598 | 184345 | sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT); |
| 183599 | 184346 | } |
| | @@ -183602,14 +184349,15 @@ |
| 183602 | 184349 | ** Implementation of fts5_source_id() function. |
| 183603 | 184350 | */ |
| 183604 | 184351 | static void fts5SourceIdFunc( |
| 183605 | 184352 | sqlite3_context *pCtx, /* Function call context */ |
| 183606 | 184353 | int nArg, /* Number of args */ |
| 183607 | | - sqlite3_value **apVal /* Function arguments */ |
| 184354 | + sqlite3_value **apUnused /* Function arguments */ |
| 183608 | 184355 | ){ |
| 183609 | 184356 | assert( nArg==0 ); |
| 183610 | | - sqlite3_result_text(pCtx, "fts5: 2016-01-20 14:22:41 204432ee72fda8e82d244c4aa18de7ec4811b8e1", -1, SQLITE_TRANSIENT); |
| 184357 | + UNUSED_PARAM2(nArg, apUnused); |
| 184358 | + sqlite3_result_text(pCtx, "fts5: 2016-02-15 17:29:24 3d862f207e3adc00f78066799ac5a8c282430a5f", -1, SQLITE_TRANSIENT); |
| 183611 | 184359 | } |
| 183612 | 184360 | |
| 183613 | 184361 | static int fts5Init(sqlite3 *db){ |
| 183614 | 184362 | static const sqlite3_module fts5Mod = { |
| 183615 | 184363 | /* iVersion */ 2, |
| | @@ -184050,11 +184798,11 @@ |
| 184050 | 184798 | int rc = SQLITE_OK; |
| 184051 | 184799 | if( p ){ |
| 184052 | 184800 | int i; |
| 184053 | 184801 | |
| 184054 | 184802 | /* Finalize all SQL statements */ |
| 184055 | | - for(i=0; i<(int)ArraySize(p->aStmt); i++){ |
| 184803 | + for(i=0; i<ArraySize(p->aStmt); i++){ |
| 184056 | 184804 | sqlite3_finalize(p->aStmt[i]); |
| 184057 | 184805 | } |
| 184058 | 184806 | |
| 184059 | 184807 | sqlite3_free(p); |
| 184060 | 184808 | } |
| | @@ -184074,15 +184822,16 @@ |
| 184074 | 184822 | static int fts5StorageInsertCallback( |
| 184075 | 184823 | void *pContext, /* Pointer to Fts5InsertCtx object */ |
| 184076 | 184824 | int tflags, |
| 184077 | 184825 | const char *pToken, /* Buffer containing token */ |
| 184078 | 184826 | int nToken, /* Size of token in bytes */ |
| 184079 | | - int iStart, /* Start offset of token */ |
| 184080 | | - int iEnd /* End offset of token */ |
| 184827 | + int iUnused1, /* Start offset of token */ |
| 184828 | + int iUnused2 /* End offset of token */ |
| 184081 | 184829 | ){ |
| 184082 | 184830 | Fts5InsertCtx *pCtx = (Fts5InsertCtx*)pContext; |
| 184083 | 184831 | Fts5Index *pIdx = pCtx->pStorage->pIndex; |
| 184832 | + UNUSED_PARAM2(iUnused1, iUnused2); |
| 184084 | 184833 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ |
| 184085 | 184834 | pCtx->szCol++; |
| 184086 | 184835 | } |
| 184087 | 184836 | return sqlite3Fts5IndexWrite(pIdx, pCtx->iCol, pCtx->szCol-1, pToken, nToken); |
| 184088 | 184837 | } |
| | @@ -184509,20 +185258,22 @@ |
| 184509 | 185258 | static int fts5StorageIntegrityCallback( |
| 184510 | 185259 | void *pContext, /* Pointer to Fts5IntegrityCtx object */ |
| 184511 | 185260 | int tflags, |
| 184512 | 185261 | const char *pToken, /* Buffer containing token */ |
| 184513 | 185262 | int nToken, /* Size of token in bytes */ |
| 184514 | | - int iStart, /* Start offset of token */ |
| 184515 | | - int iEnd /* End offset of token */ |
| 185263 | + int iUnused1, /* Start offset of token */ |
| 185264 | + int iUnused2 /* End offset of token */ |
| 184516 | 185265 | ){ |
| 184517 | 185266 | Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext; |
| 184518 | 185267 | Fts5Termset *pTermset = pCtx->pTermset; |
| 184519 | 185268 | int bPresent; |
| 184520 | 185269 | int ii; |
| 184521 | 185270 | int rc = SQLITE_OK; |
| 184522 | 185271 | int iPos; |
| 184523 | 185272 | int iCol; |
| 185273 | + |
| 185274 | + UNUSED_PARAM2(iUnused1, iUnused2); |
| 184524 | 185275 | |
| 184525 | 185276 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ |
| 184526 | 185277 | pCtx->szCol++; |
| 184527 | 185278 | } |
| 184528 | 185279 | |
| | @@ -184897,16 +185648,17 @@ |
| 184897 | 185648 | |
| 184898 | 185649 | /* |
| 184899 | 185650 | ** Create an "ascii" tokenizer. |
| 184900 | 185651 | */ |
| 184901 | 185652 | static int fts5AsciiCreate( |
| 184902 | | - void *pCtx, |
| 185653 | + void *pUnused, |
| 184903 | 185654 | const char **azArg, int nArg, |
| 184904 | 185655 | Fts5Tokenizer **ppOut |
| 184905 | 185656 | ){ |
| 184906 | 185657 | int rc = SQLITE_OK; |
| 184907 | 185658 | AsciiTokenizer *p = 0; |
| 185659 | + UNUSED_PARAM(pUnused); |
| 184908 | 185660 | if( nArg%2 ){ |
| 184909 | 185661 | rc = SQLITE_ERROR; |
| 184910 | 185662 | }else{ |
| 184911 | 185663 | p = sqlite3_malloc(sizeof(AsciiTokenizer)); |
| 184912 | 185664 | if( p==0 ){ |
| | @@ -184951,11 +185703,11 @@ |
| 184951 | 185703 | ** Tokenize some text using the ascii tokenizer. |
| 184952 | 185704 | */ |
| 184953 | 185705 | static int fts5AsciiTokenize( |
| 184954 | 185706 | Fts5Tokenizer *pTokenizer, |
| 184955 | 185707 | void *pCtx, |
| 184956 | | - int flags, |
| 185708 | + int iUnused, |
| 184957 | 185709 | const char *pText, int nText, |
| 184958 | 185710 | int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd) |
| 184959 | 185711 | ){ |
| 184960 | 185712 | AsciiTokenizer *p = (AsciiTokenizer*)pTokenizer; |
| 184961 | 185713 | int rc = SQLITE_OK; |
| | @@ -184964,10 +185716,12 @@ |
| 184964 | 185716 | |
| 184965 | 185717 | char aFold[64]; |
| 184966 | 185718 | int nFold = sizeof(aFold); |
| 184967 | 185719 | char *pFold = aFold; |
| 184968 | 185720 | unsigned char *a = p->aTokenChar; |
| 185721 | + |
| 185722 | + UNUSED_PARAM(iUnused); |
| 184969 | 185723 | |
| 184970 | 185724 | while( is<nText && rc==SQLITE_OK ){ |
| 184971 | 185725 | int nByte; |
| 184972 | 185726 | |
| 184973 | 185727 | /* Skip any leading divider characters. */ |
| | @@ -185158,16 +185912,18 @@ |
| 185158 | 185912 | |
| 185159 | 185913 | /* |
| 185160 | 185914 | ** Create a "unicode61" tokenizer. |
| 185161 | 185915 | */ |
| 185162 | 185916 | static int fts5UnicodeCreate( |
| 185163 | | - void *pCtx, |
| 185917 | + void *pUnused, |
| 185164 | 185918 | const char **azArg, int nArg, |
| 185165 | 185919 | Fts5Tokenizer **ppOut |
| 185166 | 185920 | ){ |
| 185167 | 185921 | int rc = SQLITE_OK; /* Return code */ |
| 185168 | 185922 | Unicode61Tokenizer *p = 0; /* New tokenizer object */ |
| 185923 | + |
| 185924 | + UNUSED_PARAM(pUnused); |
| 185169 | 185925 | |
| 185170 | 185926 | if( nArg%2 ){ |
| 185171 | 185927 | rc = SQLITE_ERROR; |
| 185172 | 185928 | }else{ |
| 185173 | 185929 | p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); |
| | @@ -185221,11 +185977,11 @@ |
| 185221 | 185977 | } |
| 185222 | 185978 | |
| 185223 | 185979 | static int fts5UnicodeTokenize( |
| 185224 | 185980 | Fts5Tokenizer *pTokenizer, |
| 185225 | 185981 | void *pCtx, |
| 185226 | | - int flags, |
| 185982 | + int iUnused, |
| 185227 | 185983 | const char *pText, int nText, |
| 185228 | 185984 | int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd) |
| 185229 | 185985 | ){ |
| 185230 | 185986 | Unicode61Tokenizer *p = (Unicode61Tokenizer*)pTokenizer; |
| 185231 | 185987 | int rc = SQLITE_OK; |
| | @@ -185236,10 +185992,12 @@ |
| 185236 | 185992 | |
| 185237 | 185993 | /* Output buffer */ |
| 185238 | 185994 | char *aFold = p->aFold; |
| 185239 | 185995 | int nFold = p->nFold; |
| 185240 | 185996 | const char *pEnd = &aFold[nFold-6]; |
| 185997 | + |
| 185998 | + UNUSED_PARAM(iUnused); |
| 185241 | 185999 | |
| 185242 | 186000 | /* Each iteration of this loop gobbles up a contiguous run of separators, |
| 185243 | 186001 | ** then the next token. */ |
| 185244 | 186002 | while( rc==SQLITE_OK ){ |
| 185245 | 186003 | int iCode; /* non-ASCII codepoint read from input */ |
| | @@ -186055,11 +186813,11 @@ |
| 186055 | 186813 | }; |
| 186056 | 186814 | |
| 186057 | 186815 | int rc = SQLITE_OK; /* Return code */ |
| 186058 | 186816 | int i; /* To iterate through builtin functions */ |
| 186059 | 186817 | |
| 186060 | | - for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){ |
| 186818 | + for(i=0; rc==SQLITE_OK && i<ArraySize(aBuiltin); i++){ |
| 186061 | 186819 | rc = pApi->xCreateTokenizer(pApi, |
| 186062 | 186820 | aBuiltin[i].zName, |
| 186063 | 186821 | (void*)pApi, |
| 186064 | 186822 | &aBuiltin[i].x, |
| 186065 | 186823 | 0 |
| | @@ -186196,13 +186954,13 @@ |
| 186196 | 186954 | }; |
| 186197 | 186955 | static const unsigned int aAscii[4] = { |
| 186198 | 186956 | 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, |
| 186199 | 186957 | }; |
| 186200 | 186958 | |
| 186201 | | - if( c<128 ){ |
| 186959 | + if( (unsigned int)c<128 ){ |
| 186202 | 186960 | return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); |
| 186203 | | - }else if( c<(1<<22) ){ |
| 186961 | + }else if( (unsigned int)c<(1<<22) ){ |
| 186204 | 186962 | unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; |
| 186205 | 186963 | int iRes = 0; |
| 186206 | 186964 | int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; |
| 186207 | 186965 | int iLo = 0; |
| 186208 | 186966 | while( iHi>=iLo ){ |
| | @@ -186765,11 +187523,14 @@ |
| 186765 | 187523 | return fts5PutVarint64(p,v); |
| 186766 | 187524 | } |
| 186767 | 187525 | |
| 186768 | 187526 | |
| 186769 | 187527 | static int sqlite3Fts5GetVarintLen(u32 iVal){ |
| 187528 | +#if 0 |
| 186770 | 187529 | if( iVal<(1 << 7 ) ) return 1; |
| 187530 | +#endif |
| 187531 | + assert( iVal>=(1 << 7) ); |
| 186771 | 187532 | if( iVal<(1 << 14) ) return 2; |
| 186772 | 187533 | if( iVal<(1 << 21) ) return 3; |
| 186773 | 187534 | if( iVal<(1 << 28) ) return 4; |
| 186774 | 187535 | return 5; |
| 186775 | 187536 | } |
| | @@ -186959,11 +187720,11 @@ |
| 186959 | 187720 | int nTab = (int)strlen(zTab)+1; |
| 186960 | 187721 | int eType = 0; |
| 186961 | 187722 | |
| 186962 | 187723 | rc = fts5VocabTableType(zType, pzErr, &eType); |
| 186963 | 187724 | if( rc==SQLITE_OK ){ |
| 186964 | | - assert( eType>=0 && eType<sizeof(azSchema)/sizeof(azSchema[0]) ); |
| 187725 | + assert( eType>=0 && eType<ArraySize(azSchema) ); |
| 186965 | 187726 | rc = sqlite3_declare_vtab(db, azSchema[eType]); |
| 186966 | 187727 | } |
| 186967 | 187728 | |
| 186968 | 187729 | nByte = sizeof(Fts5VocabTable) + nDb + nTab; |
| 186969 | 187730 | pRet = sqlite3Fts5MallocZero(&rc, nByte); |
| | @@ -187012,19 +187773,21 @@ |
| 187012 | 187773 | |
| 187013 | 187774 | /* |
| 187014 | 187775 | ** Implementation of the xBestIndex method. |
| 187015 | 187776 | */ |
| 187016 | 187777 | static int fts5VocabBestIndexMethod( |
| 187017 | | - sqlite3_vtab *pVTab, |
| 187778 | + sqlite3_vtab *pUnused, |
| 187018 | 187779 | sqlite3_index_info *pInfo |
| 187019 | 187780 | ){ |
| 187020 | 187781 | int i; |
| 187021 | 187782 | int iTermEq = -1; |
| 187022 | 187783 | int iTermGe = -1; |
| 187023 | 187784 | int iTermLe = -1; |
| 187024 | 187785 | int idxNum = 0; |
| 187025 | 187786 | int nArg = 0; |
| 187787 | + |
| 187788 | + UNUSED_PARAM(pUnused); |
| 187026 | 187789 | |
| 187027 | 187790 | for(i=0; i<pInfo->nConstraint; i++){ |
| 187028 | 187791 | struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; |
| 187029 | 187792 | if( p->usable==0 ) continue; |
| 187030 | 187793 | if( p->iColumn==0 ){ /* term column */ |
| | @@ -187182,59 +187945,54 @@ |
| 187182 | 187945 | memset(pCsr->aDoc, 0, nCol * sizeof(i64)); |
| 187183 | 187946 | pCsr->iCol = 0; |
| 187184 | 187947 | |
| 187185 | 187948 | assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); |
| 187186 | 187949 | while( rc==SQLITE_OK ){ |
| 187187 | | - i64 dummy; |
| 187188 | 187950 | const u8 *pPos; int nPos; /* Position list */ |
| 187189 | 187951 | i64 iPos = 0; /* 64-bit position read from poslist */ |
| 187190 | 187952 | int iOff = 0; /* Current offset within position list */ |
| 187191 | 187953 | |
| 187954 | + pPos = pCsr->pIter->pData; |
| 187955 | + nPos = pCsr->pIter->nData; |
| 187192 | 187956 | switch( pCsr->pConfig->eDetail ){ |
| 187193 | 187957 | 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 | | - } |
| 187958 | + pPos = pCsr->pIter->pData; |
| 187959 | + nPos = pCsr->pIter->nData; |
| 187960 | + if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 187961 | + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 187962 | + pCsr->aCnt[0]++; |
| 187963 | + } |
| 187964 | + pCsr->aDoc[0]++; |
| 187965 | + }else{ |
| 187966 | + int iCol = -1; |
| 187967 | + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
| 187968 | + int ii = FTS5_POS2COLUMN(iPos); |
| 187969 | + pCsr->aCnt[ii]++; |
| 187970 | + if( iCol!=ii ){ |
| 187971 | + if( ii>=nCol ){ |
| 187972 | + rc = FTS5_CORRUPT; |
| 187973 | + break; |
| 187974 | + } |
| 187975 | + pCsr->aDoc[ii]++; |
| 187976 | + iCol = ii; |
| 187214 | 187977 | } |
| 187215 | 187978 | } |
| 187216 | 187979 | } |
| 187217 | 187980 | break; |
| 187218 | 187981 | |
| 187219 | 187982 | case FTS5_DETAIL_COLUMNS: |
| 187220 | 187983 | if( pTab->eType==FTS5_VOCAB_ROW ){ |
| 187221 | 187984 | pCsr->aDoc[0]++; |
| 187222 | 187985 | }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); |
| 187986 | + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ |
| 187987 | + assert_nc( iPos>=0 && iPos<nCol ); |
| 187988 | + if( iPos>=nCol ){ |
| 187989 | + rc = FTS5_CORRUPT; |
| 187990 | + break; |
| 187991 | + } |
| 187992 | + pCsr->aDoc[iPos]++; |
| 187993 | + } |
| 187236 | 187994 | } |
| 187237 | 187995 | break; |
| 187238 | 187996 | |
| 187239 | 187997 | default: |
| 187240 | 187998 | assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); |
| | @@ -187268,12 +188026,12 @@ |
| 187268 | 188026 | ** This is the xFilter implementation for the virtual table. |
| 187269 | 188027 | */ |
| 187270 | 188028 | static int fts5VocabFilterMethod( |
| 187271 | 188029 | sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ |
| 187272 | 188030 | int idxNum, /* Strategy index */ |
| 187273 | | - const char *idxStr, /* Unused */ |
| 187274 | | - int nVal, /* Number of elements in apVal */ |
| 188031 | + const char *zUnused, /* Unused */ |
| 188032 | + int nUnused, /* Number of elements in apVal */ |
| 187275 | 188033 | sqlite3_value **apVal /* Arguments for the indexing scheme */ |
| 187276 | 188034 | ){ |
| 187277 | 188035 | Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; |
| 187278 | 188036 | int rc = SQLITE_OK; |
| 187279 | 188037 | |
| | @@ -187283,10 +188041,12 @@ |
| 187283 | 188041 | int nTerm = 0; |
| 187284 | 188042 | |
| 187285 | 188043 | sqlite3_value *pEq = 0; |
| 187286 | 188044 | sqlite3_value *pGe = 0; |
| 187287 | 188045 | sqlite3_value *pLe = 0; |
| 188046 | + |
| 188047 | + UNUSED_PARAM2(zUnused, nUnused); |
| 187288 | 188048 | |
| 187289 | 188049 | fts5VocabResetCursor(pCsr); |
| 187290 | 188050 | if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++]; |
| 187291 | 188051 | if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++]; |
| 187292 | 188052 | if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++]; |
| 187293 | 188053 | |