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/vdbemem.c | |
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/vdbemem.c')
-rw-r--r-- | src/vdbemem.c | 50 |
1 files changed, 37 insertions, 13 deletions
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 |