1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Improved implementation of the destructor on pointer-passing interfaces.

FossilOrigin-Name: 601ad6795927fff8c3cc1711a2fd90912499573e94aa5bc8f18cbd4b89778f58
This commit is contained in:
drh
2017-07-27 15:53:24 +00:00
parent 22930062d5
commit a0024e6c99
7 changed files with 60 additions and 41 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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