diff options
author | drh <drh@noemail.net> | 2017-07-27 15:53:24 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2017-07-27 15:53:24 +0000 |
commit | a0024e6c99dca51ebf12e4c49c17ac22a5e98f6b (patch) | |
tree | 9254828f7b020293baaf427056e0202081ef5525 /src | |
parent | 22930062d54a60193ee0624182961df0e6442e4b (diff) | |
download | sqlite-a0024e6c99dca51ebf12e4c49c17ac22a5e98f6b.tar.gz sqlite-a0024e6c99dca51ebf12e4c49c17ac22a5e98f6b.zip |
Improved implementation of the destructor on pointer-passing interfaces.
FossilOrigin-Name: 601ad6795927fff8c3cc1711a2fd90912499573e94aa5bc8f18cbd4b89778f58
Diffstat (limited to 'src')
-rw-r--r-- | src/vdbe.c | 6 | ||||
-rw-r--r-- | src/vdbeInt.h | 14 | ||||
-rw-r--r-- | src/vdbeapi.c | 4 | ||||
-rw-r--r-- | src/vdbeaux.c | 2 | ||||
-rw-r--r-- | src/vdbemem.c | 50 |
5 files changed, 49 insertions, 27 deletions
diff --git a/src/vdbe.c b/src/vdbe.c index 7e105940f..3e6231e0d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -416,7 +416,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ else *zCsr++ = z; } *(zCsr++) = ']'; - if( (f & (MEM_Zero|MEM_Blob))==(MEM_Zero|MEM_Blob) ){ + if( f & MEM_Zero ){ sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero); zCsr += sqlite3Strlen30(zCsr); } @@ -2735,7 +2735,7 @@ case OP_MakeRecord: { do{ assert( memIsValid(pRec) ); pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); - if( (pRec->flags & MEM_Zero)!=0 && (pRec->flags & MEM_Blob)!=0 ){ + if( pRec->flags & MEM_Zero ){ if( nData ){ if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; }else{ @@ -4411,7 +4411,7 @@ case OP_InsertInt: { x.nData = pData->n; } seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); - if( (pData->flags & MEM_Zero)!=0 && (pData->flags & MEM_Blob)!=0 ){ + if( pData->flags & MEM_Zero ){ x.nZero = pData->u.nZero; }else{ x.nZero = 0; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 366496bf6..d8e47be50 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -190,7 +190,7 @@ struct sqlite3_value { double r; /* Real value used when MEM_Real is set in flags */ i64 i; /* Integer value used when MEM_Int is set in flags */ int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */ - const char *zPType; /* Pointer type when MEM_Pointer and MEM_Null set */ + const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ @@ -222,7 +222,8 @@ struct sqlite3_value { ** representations of the value stored in the Mem struct. ** ** If the MEM_Null flag is set, then the value is an SQL NULL value. -** No other flags may be set in this case. +** For a pointer type created using sqlite3_bind_pointer() or +** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set. ** ** 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 @@ -230,7 +231,7 @@ struct sqlite3_value { ** set, then the string is nul terminated. The MEM_Int and MEM_Real ** flags may coexist with the MEM_Str flag. */ -#define MEM_Null 0x0001 /* Value is NULL */ +#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ @@ -247,18 +248,13 @@ struct sqlite3_value { ** the following flags must be set to determine the memory management ** policy for Mem.z. The MEM_Term flag tells us whether or not the ** string is \000 or \u0000 terminated -** -** NB: MEM_Zero and MEM_Pointer are the same value. But MEM_Zero is -** only value if MEM_Blob is also set, and MEM_Pointer is only valid -** if MEM_Null is also set. */ -#define MEM_Term 0x0200 /* String rep is nul terminated */ +#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */ #define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ #define MEM_Static 0x0800 /* Mem.z points to a static string */ #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ -#define MEM_Pointer 0x4000 /* Mem.z is an extension pointer */ #define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */ #ifdef SQLITE_OMIT_INCRBLOB #undef MEM_Zero diff --git a/src/vdbeapi.c b/src/vdbeapi.c index e82b12b71..f0537513f 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -201,8 +201,10 @@ unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ } void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){ Mem *p = (Mem*)pVal; - if( (p->flags&(MEM_AffMask|MEM_Pointer))==(MEM_Null|MEM_Pointer) + if( (p->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) == + (MEM_Null|MEM_Term|MEM_Subtype) && zPType!=0 + && p->eSubtype=='p' && strcmp(p->u.zPType, zPType)==0 ){ return (void*)p->z; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 82d59c5e6..7c2bd87ef 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3224,7 +3224,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) ); assert( pMem->n>=0 ); n = (u32)pMem->n; - if( (flags & MEM_Zero)!=0 && (flags & MEM_Blob)!=0 ){ + if( flags & MEM_Zero ){ n += pMem->u.nZero; } *pLen = n; diff --git a/src/vdbemem.c b/src/vdbemem.c index 451e06f41..45b0b38c1 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -27,7 +27,7 @@ */ int sqlite3VdbeCheckMemInvariants(Mem *p){ /* If MEM_Dyn is set then Mem.xDel!=0. - ** Mem.xDel is might not be initialized if MEM_Dyn is clear. + ** Mem.xDel might not be initialized if MEM_Dyn is clear. */ assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); @@ -40,9 +40,34 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){ /* Cannot be both MEM_Int and MEM_Real at the same time */ assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); - /* Cannot be both MEM_Null and some other type */ - assert( (p->flags & MEM_Null)==0 || - (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob))==0 ); + 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 ); + + /* 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 + ** sqlite3_result_pointer(). If a pointer, then MEM_Term must also be + ** set. + */ + if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){ + /* This is a pointer type. There may be a flag to indicate what to + ** do with the pointer. */ + assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + + ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 ); + + /* No other bits set */ + assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype + |MEM_Dyn|MEM_Ephem|MEM_Static))==0 ); + }else{ + /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn, + ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */ + } + }else{ + /* The MEM_Cleared bit is only allowed on NULLs */ + assert( (p->flags & MEM_Cleared)==0 ); + } /* The szMalloc field holds the correct memory allocation size */ assert( p->szMalloc==0 @@ -220,9 +245,9 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ int sqlite3VdbeMemExpandBlob(Mem *pMem){ int nByte; assert( pMem->flags & MEM_Zero ); + assert( pMem->flags&MEM_Blob ); assert( (pMem->flags&MEM_RowSet)==0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK; /* Set nByte to the number of bytes required to store the expanded blob. */ nByte = pMem->n + pMem->u.nZero; @@ -705,6 +730,9 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ } } +/* A no-op destructor */ +static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } + /* ** Set the value stored in *pMem should already be a NULL. ** Also store a pointer to go with it. @@ -716,15 +744,11 @@ void sqlite3VdbeMemSetPointer( void (*xDestructor)(void*) ){ assert( pMem->flags==MEM_Null ); - pMem->u.zPType = zPType; + pMem->u.zPType = zPType ? zPType : ""; pMem->z = pPtr; - if( zPType ){ - pMem->flags = MEM_Null|MEM_Pointer; - } - if( xDestructor ){ - pMem->xDel = xDestructor; - pMem->flags |= MEM_Dyn; - } + pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term; + pMem->eSubtype = 'p'; + pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor; } #ifndef SQLITE_OMIT_FLOATING_POINT |