Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improved comments. Slightly tighter implementation, but no big changes. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sqlite3_value_nochange |
Files: | files | file ages | folders |
SHA3-256: |
a1b3f28569f2a8d82b2931527fdfe191 |
User & Date: | drh 2018-01-12 23:18:38.948 |
Context
2018-01-12
| ||
23:38 | Add the sqlite3_value_nochange() API, usable from within the xUpdate method of a virtual table to discover whether or not a column was unchanged at the SQL level. (check-in: dec3ea4e4e user: drh tags: trunk) | |
23:18 | Improved comments. Slightly tighter implementation, but no big changes. (Closed-Leaf check-in: a1b3f28569 user: drh tags: sqlite3_value_nochange) | |
21:00 | Add the experimental sqlite3_value_nochange() interface usable by xUpdate methods of virtual tables to see if a column has actually changed values. (check-in: 8b7be15ece user: drh tags: sqlite3_value_nochange) | |
Changes
Changes to src/sqlite.h.in.
︙ | ︙ | |||
4846 4847 4848 4849 4850 4851 4852 | ** words, if the value is a string that looks like a number) ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ ** ** ^Within the [xUpdate] method of a [virtual table], the ** sqlite3_value_nochange(X) interface returns true if and only if ** the column corresponding to X is unchanged by the UPDATE operation | > > > | > > | | 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 | ** words, if the value is a string that looks like a number) ** then the conversion is performed. Otherwise no conversion occurs. ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ ** ** ^Within the [xUpdate] method of a [virtual table], the ** sqlite3_value_nochange(X) interface returns true if and only if ** the column corresponding to X is unchanged by the UPDATE operation ** that the xUpdate method call was invoked to implement and if ** and the prior [xColumn] method call that was invoked to extracted ** the value for that column returned without setting a result (probably ** because it queried [sqlite3_vtab_nochange()] and found that the column ** was unchanging). If sqlite3_value_nochange(X) is invoked anywhere other ** than within an [xUpdate] method call for an UPDATE statement, then ** the return value is arbitrary and meaningless. ** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */ #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the | > | 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */ #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ #define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
824 825 826 827 828 829 830 | /* Populate the argument registers. */ for(i=0; i<pTab->nCol; i++){ if( aXRef[i]>=0 ){ sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); }else{ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); | | | 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 | /* Populate the argument registers. */ for(i=0; i<pTab->nCol; i++){ if( aXRef[i]>=0 ){ sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); }else{ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */ } } if( HasRowid(pTab) ){ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); if( pRowid ){ sqlite3ExprCode(pParse, pRowid, regArg+1); }else{ |
︙ | ︙ | |||
859 860 861 862 863 864 865 | if( sqlite3IsToplevel(pParse) ){ pParse->isMultiWrite = 0; } }else{ /* Create a record from the argument register contents and insert it into ** the ephemeral table. */ sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); | > > > | > | 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 | if( sqlite3IsToplevel(pParse) ){ pParse->isMultiWrite = 0; } }else{ /* Create a record from the argument register contents and insert it into ** the ephemeral table. */ sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); #ifdef SQLITE_DEBUG /* Signal an assert() within OP_MakeRecord that it is allowed to ** accept no-change records with serial_type 10 */ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); #endif sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); } if( bOnePass==0 ){ /* End the virtual table scan */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2788 2789 2790 2791 2792 2793 2794 | /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ pRec = pLast; do{ assert( memIsValid(pRec) ); | | > > > > > > | | < > | 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 | /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ pRec = pLast; do{ assert( memIsValid(pRec) ); serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); if( pRec->flags & MEM_Zero ){ if( serial_type==0 ){ /* Values with MEM_Null and MEM_Zero are created by xColumn virtual ** table methods that never invoke sqlite3_result_xxxxx() while ** computing an unchanging column value in an UPDATE statement. ** Give such values a special internal-use-only serial-type of 10 ** so that they can be passed through to xUpdate and have ** a true sqlite3_value_nochange(). */ assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB ); serial_type = 10; }else if( nData ){ if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; }else{ nZero += pRec->u.nZero; len -= pRec->u.nZero; } } nData += len; testcase( serial_type==127 ); testcase( serial_type==128 ); nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); pRec->uTemp = serial_type; if( pRec==pData0 ) break; pRec--; }while(1); /* EVIDENCE-OF: R-22564-11647 The header begins with a single varint ** which determines the total number of bytes in the header. The varint ** value is the size of the header in bytes including the size varint |
︙ | ︙ |