|
|
@@ -1149,7 +1149,7 @@ extern "C" {
|
|
|
*/
|
|
|
#define SQLITE_VERSION "3.22.0"
|
|
|
#define SQLITE_VERSION_NUMBER 3022000
|
|
|
-#define SQLITE_SOURCE_ID "2018-01-11 18:15:40 a5d09dfaa337fa51d6e702c6aefe58824ab1e7d221c6e79166e2c6f9c7abalt1"
|
|
|
+#define SQLITE_SOURCE_ID "2018-01-13 02:07:16 bb196fcb677e962db4308c02097968615729a51fe4a1292e468aaf3e4bf5alt1"
|
|
|
|
|
|
/*
|
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
|
@@ -5842,6 +5842,9 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
|
|
** datatype of the value
|
|
|
** <tr><td><b>sqlite3_value_numeric_type </b>
|
|
|
** <td>→ <td>Best numeric datatype of the value
|
|
|
+** <tr><td><b>sqlite3_value_nochange </b>
|
|
|
+** <td>→ <td>True if the column is unchanged in an UPDATE
|
|
|
+** against a virtual table.
|
|
|
** </table></blockquote>
|
|
|
**
|
|
|
** <b>Details:</b>
|
|
|
@@ -5890,6 +5893,19 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
|
|
** 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). ^Within an [xUpdate] method, any value for which
|
|
|
+** sqlite3_value_nochange(X) is true will in all other respects appear
|
|
|
+** to be a NULL value. 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
|
|
|
@@ -5912,6 +5928,7 @@ SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
|
|
|
SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
|
|
|
SQLITE_API int sqlite3_value_type(sqlite3_value*);
|
|
|
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
|
|
|
+SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
|
|
|
|
|
|
/*
|
|
|
** CAPI3REF: Finding The Subtype Of SQL Values
|
|
|
@@ -9350,6 +9367,13 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
|
|
** column value will not change. Applications might use this to substitute
|
|
|
** a lighter-weight value to return that the corresponding [xUpdate] method
|
|
|
** understands as a "no-change" value.
|
|
|
+**
|
|
|
+** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
|
|
+** the column is not changed by the UPDATE statement, they the xColumn
|
|
|
+** method can optionally return without setting a result, without calling
|
|
|
+** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
|
|
+** In that case, [sqlite3_value_nochange(X)] will return true for the
|
|
|
+** same column in the [xUpdate] method.
|
|
|
*/
|
|
|
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
|
|
|
|
|
|
@@ -13764,6 +13788,7 @@ typedef struct VdbeOpList VdbeOpList;
|
|
|
#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */
|
|
|
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
|
|
|
#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */
|
|
|
+#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */
|
|
|
|
|
|
/* Error message codes for OP_Halt */
|
|
|
#define P5_ConstraintNotNull 1
|
|
|
@@ -16969,6 +16994,7 @@ struct AuthContext {
|
|
|
#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
|
|
|
@@ -18826,6 +18852,8 @@ struct sqlite3_value {
|
|
|
** If the MEM_Null flag is set, then the value is an SQL NULL value.
|
|
|
** For a pointer type created using sqlite3_bind_pointer() or
|
|
|
** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
|
|
|
+** If both MEM_Null and MEM_Zero are set, that means that the value is
|
|
|
+** an unchanging column value from VColumn.
|
|
|
**
|
|
|
** If the MEM_Str flag is set then Mem.z points at a string representation.
|
|
|
** Usually this is encoded in the same unicode encoding as the main
|
|
|
@@ -71311,7 +71339,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
|
|
|
if( p->flags & MEM_Null ){
|
|
|
/* Cannot be both MEM_Null and some other type */
|
|
|
assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
|
|
|
- |MEM_RowSet|MEM_Frame|MEM_Agg|MEM_Zero))==0 );
|
|
|
+ |MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
|
|
|
|
|
|
/* If MEM_Null is set, then either the value is a pure NULL (the usual
|
|
|
** case) or it is a pointer set using sqlite3_bind_pointer() or
|
|
|
@@ -73904,6 +73932,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
|
|
case P4_REAL:
|
|
|
case P4_INT64:
|
|
|
case P4_DYNAMIC:
|
|
|
+ case P4_DYNBLOB:
|
|
|
case P4_INTARRAY: {
|
|
|
sqlite3DbFree(db, p4);
|
|
|
break;
|
|
|
@@ -74445,6 +74474,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
|
|
sqlite3XPrintf(&x, "program");
|
|
|
break;
|
|
|
}
|
|
|
+ case P4_DYNBLOB:
|
|
|
case P4_ADVANCE: {
|
|
|
zTemp[0] = 0;
|
|
|
break;
|
|
|
@@ -76490,7 +76520,11 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
|
|
|
Mem *pMem /* Memory cell to write value into */
|
|
|
){
|
|
|
switch( serial_type ){
|
|
|
- case 10: /* Reserved for future use */
|
|
|
+ case 10: { /* Internal use only: NULL with virtual table
|
|
|
+ ** UPDATE no-change flag set */
|
|
|
+ pMem->flags = MEM_Null|MEM_Zero;
|
|
|
+ break;
|
|
|
+ }
|
|
|
case 11: /* Reserved for future use */
|
|
|
case 0: { /* Null */
|
|
|
/* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
|
|
|
@@ -78043,6 +78077,11 @@ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
|
|
|
return aType[pVal->flags&MEM_AffMask];
|
|
|
}
|
|
|
|
|
|
+/* Return true if a parameter to xUpdate represents an unchanged column */
|
|
|
+SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){
|
|
|
+ return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
|
|
|
+}
|
|
|
+
|
|
|
/* Make a copy of an sqlite3_value object
|
|
|
*/
|
|
|
SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
|
|
|
@@ -78536,7 +78575,7 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
|
|
|
*/
|
|
|
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){
|
|
|
assert( p );
|
|
|
- return p->bVtabNoChng;
|
|
|
+ return sqlite3_value_nochange(p->pOut);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -80420,7 +80459,7 @@ static void memTracePrint(Mem *p){
|
|
|
if( p->flags & MEM_Undefined ){
|
|
|
printf(" undefined");
|
|
|
}else if( p->flags & MEM_Null ){
|
|
|
- printf(" NULL");
|
|
|
+ printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
|
|
|
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
|
|
|
printf(" si:%lld", p->u.i);
|
|
|
}else if( p->flags & MEM_Int ){
|
|
|
@@ -82837,9 +82876,18 @@ case OP_MakeRecord: {
|
|
|
pRec = pLast;
|
|
|
do{
|
|
|
assert( memIsValid(pRec) );
|
|
|
- pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
|
|
|
+ serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
|
|
|
if( pRec->flags & MEM_Zero ){
|
|
|
- if( nData ){
|
|
|
+ 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;
|
|
|
@@ -82850,6 +82898,7 @@ case OP_MakeRecord: {
|
|
|
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);
|
|
|
@@ -84460,10 +84509,8 @@ case OP_InsertInt: {
|
|
|
int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
|
|
|
const char *zDb; /* database name - used by the update hook */
|
|
|
Table *pTab; /* Table structure - used by update and pre-update hooks */
|
|
|
- int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
|
|
|
BtreePayload x; /* Payload to be inserted */
|
|
|
|
|
|
- op = 0;
|
|
|
pData = &aMem[pOp->p2];
|
|
|
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
|
assert( memIsValid(pData) );
|
|
|
@@ -84491,19 +84538,21 @@ case OP_InsertInt: {
|
|
|
zDb = db->aDb[pC->iDb].zDbSName;
|
|
|
pTab = pOp->p4.pTab;
|
|
|
assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
|
|
|
- op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
|
|
|
}else{
|
|
|
- pTab = 0; /* Not needed. Silence a compiler warning. */
|
|
|
+ pTab = 0;
|
|
|
zDb = 0; /* Not needed. Silence a compiler warning. */
|
|
|
}
|
|
|
|
|
|
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
|
/* Invoke the pre-update hook, if any */
|
|
|
- if( db->xPreUpdateCallback
|
|
|
- && pOp->p4type==P4_TABLE
|
|
|
- && !(pOp->p5 & OPFLAG_ISUPDATE)
|
|
|
- ){
|
|
|
- sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2);
|
|
|
+ if( pTab ){
|
|
|
+ if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
|
|
|
+ sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
|
|
|
+ }
|
|
|
+ if( db->xUpdateCallback==0 || pTab->aCol==0 ){
|
|
|
+ /* Prevent post-update hook from running in cases when it should not */
|
|
|
+ pTab = 0;
|
|
|
+ }
|
|
|
}
|
|
|
if( pOp->p5 & OPFLAG_ISNOOP ) break;
|
|
|
#endif
|
|
|
@@ -84528,8 +84577,12 @@ case OP_InsertInt: {
|
|
|
|
|
|
/* Invoke the update-hook if required. */
|
|
|
if( rc ) goto abort_due_to_error;
|
|
|
- if( db->xUpdateCallback && op ){
|
|
|
- db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, x.nKey);
|
|
|
+ if( pTab ){
|
|
|
+ assert( db->xUpdateCallback!=0 );
|
|
|
+ assert( pTab->aCol!=0 );
|
|
|
+ db->xUpdateCallback(db->pUpdateArg,
|
|
|
+ (pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT,
|
|
|
+ zDb, pTab->zName, x.nKey);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
@@ -86738,15 +86791,15 @@ case OP_VFilter: { /* jump */
|
|
|
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
|
|
|
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
|
-/* Opcode: VColumn P1 P2 P3 P4 *
|
|
|
+/* Opcode: VColumn P1 P2 P3 * P5
|
|
|
** Synopsis: r[P3]=vcolumn(P2)
|
|
|
**
|
|
|
** Store in register P3 the value of the P2-th column of
|
|
|
** the current row of the virtual-table of cursor P1.
|
|
|
**
|
|
|
** If the VColumn opcode is being used to fetch the value of
|
|
|
-** an unchanging column during an UPDATE operation, then the P4
|
|
|
-** value is 1. Otherwise, P4 is 0. The P4 value is returned
|
|
|
+** an unchanging column during an UPDATE operation, then the P5
|
|
|
+** value is 1. Otherwise, P5 is 0. The P5 value is returned
|
|
|
** by sqlite3_vtab_nochange() routine can can be used
|
|
|
** by virtual table implementations to return special "no-change"
|
|
|
** marks which can be more efficient, depending on the virtual table.
|
|
|
@@ -86771,8 +86824,13 @@ case OP_VColumn: {
|
|
|
assert( pModule->xColumn );
|
|
|
memset(&sContext, 0, sizeof(sContext));
|
|
|
sContext.pOut = pDest;
|
|
|
- sContext.bVtabNoChng = pOp->p4.i!=0;
|
|
|
- MemSetTypeFlag(pDest, MEM_Null);
|
|
|
+ if( pOp->p5 ){
|
|
|
+ sqlite3VdbeMemSetNull(pDest);
|
|
|
+ pDest->flags = MEM_Null|MEM_Zero;
|
|
|
+ pDest->u.nZero = 0;
|
|
|
+ }else{
|
|
|
+ MemSetTypeFlag(pDest, MEM_Null);
|
|
|
+ }
|
|
|
rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
|
|
|
sqlite3VtabImportErrmsg(p, pVtab);
|
|
|
if( sContext.isError ){
|
|
|
@@ -99112,6 +99170,10 @@ static void openStatTable(
|
|
|
"DELETE FROM %Q.%s WHERE %s=%Q",
|
|
|
pDb->zDbSName, zTab, zWhereType, zWhere
|
|
|
);
|
|
|
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
|
+ }else if( db->xPreUpdateCallback ){
|
|
|
+ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab);
|
|
|
+#endif
|
|
|
}else{
|
|
|
/* The sqlite_stat[134] table already exists. Delete all rows. */
|
|
|
sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
|
|
|
@@ -99876,6 +99938,9 @@ static void analyzeOneTable(
|
|
|
int regIdxname = iMem++; /* Register containing index name */
|
|
|
int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
|
|
|
int regPrev = iMem; /* MUST BE LAST (see below) */
|
|
|
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
|
+ Table *pStat1 = 0;
|
|
|
+#endif
|
|
|
|
|
|
pParse->nMem = MAX(pParse->nMem, iMem);
|
|
|
v = sqlite3GetVdbe(pParse);
|
|
|
@@ -99901,6 +99966,18 @@ static void analyzeOneTable(
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
|
+ if( db->xPreUpdateCallback ){
|
|
|
+ pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13);
|
|
|
+ if( pStat1==0 ) return;
|
|
|
+ pStat1->zName = (char*)&pStat1[1];
|
|
|
+ memcpy(pStat1->zName, "sqlite_stat1", 13);
|
|
|
+ pStat1->nCol = 3;
|
|
|
+ pStat1->iPKey = -1;
|
|
|
+ sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
/* Establish a read-lock on the table at the shared-cache level.
|
|
|
** Open a read-only cursor on the table. Also allocate a cursor number
|
|
|
** to use for scanning indexes (iIdxCur). No index cursor is opened at
|
|
|
@@ -100102,6 +100179,9 @@ static void analyzeOneTable(
|
|
|
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
|
|
|
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
|
|
|
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
|
|
|
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
|
+ sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
|
|
|
+#endif
|
|
|
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
|
|
|
|
|
/* Add the entries to the stat3 or stat4 table. */
|
|
|
@@ -107358,7 +107438,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
|
|
|
u8 p5 = 0;
|
|
|
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
|
|
|
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
|
|
|
- if( pParse->nested==0 ){
|
|
|
+ if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
|
|
|
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
|
|
|
}
|
|
|
if( eMode!=ONEPASS_OFF ){
|
|
|
@@ -113667,6 +113747,8 @@ struct sqlite3_api_routines {
|
|
|
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
|
|
|
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
|
|
|
void *(*value_pointer)(sqlite3_value*,const char*);
|
|
|
+ int (*vtab_nochange)(sqlite3_context*);
|
|
|
+ int (*value_nochange)(sqlite3_value*);
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -113934,6 +114016,9 @@ typedef int (*sqlite3_loadext_entry)(
|
|
|
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
|
|
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
|
|
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
|
|
+/* Version 3.22.0 and later */
|
|
|
+#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
|
|
|
+#define sqlite3_value_nochange sqltie3_api->value_nochange
|
|
|
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
|
|
|
|
|
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
|
@@ -114370,7 +114455,10 @@ static const sqlite3_api_routines sqlite3Apis = {
|
|
|
sqlite3_prepare16_v3,
|
|
|
sqlite3_bind_pointer,
|
|
|
sqlite3_result_pointer,
|
|
|
- sqlite3_value_pointer
|
|
|
+ sqlite3_value_pointer,
|
|
|
+ /* Version 3.22.0 and later */
|
|
|
+ sqlite3_vtab_nochange,
|
|
|
+ sqlite3_value_nochange
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -127013,7 +127101,8 @@ static void updateVirtualTable(
|
|
|
if( aXRef[i]>=0 ){
|
|
|
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
|
|
}else{
|
|
|
- sqlite3VdbeAddOp4Int(v, OP_VColumn, iCsr, i, regArg+2+i, 1);
|
|
|
+ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
|
|
|
+ sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
|
|
|
}
|
|
|
}
|
|
|
if( HasRowid(pTab) ){
|
|
|
@@ -127048,6 +127137,11 @@ static void updateVirtualTable(
|
|
|
/* 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);
|
|
|
}
|
|
|
@@ -181224,9 +181318,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
|
|
|
|
|
|
/*
|
|
|
** This function queries the database for the names of the columns of table
|
|
|
-** zThis, in schema zDb. It is expected that the table has nCol columns. If
|
|
|
-** not, SQLITE_SCHEMA is returned and none of the output variables are
|
|
|
-** populated.
|
|
|
+** zThis, in schema zDb.
|
|
|
**
|
|
|
** Otherwise, if they are not NULL, variable *pnCol is set to the number
|
|
|
** of columns in the database table and variable *pzTab is set to point to a
|
|
|
@@ -181247,9 +181339,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
|
|
|
** *pabPK = {1, 0, 0, 1}
|
|
|
**
|
|
|
** All returned buffers are part of the same single allocation, which must
|
|
|
-** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then
|
|
|
-** pointer *pazCol should be freed to release all memory. Otherwise, pointer
|
|
|
-** *pabPK. It is illegal for both pazCol and pabPK to be NULL.
|
|
|
+** be freed using sqlite3_free() by the caller
|
|
|
*/
|
|
|
static int sessionTableInfo(
|
|
|
sqlite3 *db, /* Database connection */
|
|
|
@@ -181274,7 +181364,23 @@ static int sessionTableInfo(
|
|
|
assert( pazCol && pabPK );
|
|
|
|
|
|
nThis = sqlite3Strlen30(zThis);
|
|
|
- zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
|
|
|
+ if( nThis==12 && 0==sqlite3_stricmp("sqlite_stat1", zThis) ){
|
|
|
+ rc = sqlite3_table_column_metadata(db, zDb, zThis, 0, 0, 0, 0, 0, 0);
|
|
|
+ if( rc==SQLITE_OK ){
|
|
|
+ /* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */
|
|
|
+ zPragma = sqlite3_mprintf(
|
|
|
+ "SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
|
|
|
+ "SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
|
|
|
+ "SELECT 2, 'stat', '', 0, '', 0"
|
|
|
+ );
|
|
|
+ }else if( rc==SQLITE_ERROR ){
|
|
|
+ zPragma = sqlite3_mprintf("");
|
|
|
+ }else{
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
|
|
|
+ }
|
|
|
if( !zPragma ) return SQLITE_NOMEM;
|
|
|
|
|
|
rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0);
|
|
|
@@ -181831,7 +181937,6 @@ SQLITE_API int sqlite3session_diff(
|
|
|
if( abPK[i] ) bHasPk = 1;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
sqlite3_free((char*)azCol);
|
|
|
if( bMismatch ){
|
|
|
@@ -218720,9 +218825,9 @@ static void print_elem(void *e, sqlite_int64 c, void* p){
|
|
|
#endif
|
|
|
|
|
|
/************** End of extension-functions.c *********************************/
|
|
|
-#if __LINE__!=218723
|
|
|
+#if __LINE__!=218828
|
|
|
#undef SQLITE_SOURCE_ID
|
|
|
-#define SQLITE_SOURCE_ID "2018-01-11 18:15:40 a5d09dfaa337fa51d6e702c6aefe58824ab1e7d221c6e79166e2c6f9c7abalt2"
|
|
|
+#define SQLITE_SOURCE_ID "2018-01-13 02:07:16 bb196fcb677e962db4308c02097968615729a51fe4a1292e468aaf3e4bf5alt2"
|
|
|
#endif
|
|
|
/* Return the source-id for this library */
|
|
|
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
|