/* ** Release an array of N Mem elements */ static void releaseMemArray(Mem *p, int N){ if( p ){ while( N-->0 ){ sqlite3VdbeMemRelease(p++); } } }
/* ** Convert pMem to type integer. Invalidate any prior representations. */ int sqlite3VdbeMemIntegerify(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); pMem->u.i = sqlite3VdbeIntValue(pMem); sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Int; return SQLITE_OK; }
/* ** Convert pMem so that it is of type MEM_Real. ** Invalidate any prior representations. */ int sqlite3VdbeMemRealify(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); pMem->r = sqlite3VdbeRealValue(pMem); sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Real; return SQLITE_OK; }
/* ** Unbind the value bound to variable i in virtual machine p. This is the ** the same as binding a NULL value to the column. If the "i" parameter is ** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. ** ** A successful evaluation of this routine acquires the mutex on p. ** the mutex is released if any kind of error occurs. ** ** The error code stored in database p->db is overwritten with the return ** value in any case. */ static int vdbeUnbind(Vdbe *p, int i){ Mem *pVar; if( vdbeSafetyNotNull(p) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(p->db->mutex); if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ sqlite3Error(p->db, SQLITE_MISUSE, 0); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); return SQLITE_MISUSE_BKPT; } if( i<1 || i>p->nVar ){ sqlite3Error(p->db, SQLITE_RANGE, 0); sqlite3_mutex_leave(p->db->mutex); return SQLITE_RANGE; } i--; pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; sqlite3Error(p->db, SQLITE_OK, 0); /* If the bit corresponding to this variable in Vdbe.expmask is set, then ** binding a new value to this variable invalidates the current query plan. */ if( p->isPrepareV2 && ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) ){ p->expired = 1; } return SQLITE_OK; }
static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem)); if( pRes->flags ){ sqlite3_result_value(context, pRes); } sqlite3VdbeMemRelease(pRes); }
/* ** Move data out of a btree key or data field and into a Mem structure. ** The data or key is taken from the entry that pCur is currently pointing ** to. offset and amt determine what portion of the data or key to retrieve. ** key is true to get the key or false to get data. The result is written ** into the pMem element. ** ** The pMem structure is assumed to be uninitialized. Any prior content ** is overwritten without being freed. ** ** If this routine fails for any reason (malloc returns NULL or unable ** to read from the disk) then the pMem is left in an inconsistent state. */ int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ int offset, /* Offset from the start of data to return bytes from. */ int amt, /* Number of bytes to return. */ int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ int available = 0; /* Number of bytes available on the local btree page */ int rc = SQLITE_OK; /* Return code */ assert( sqlite3BtreeCursorIsValid(pCur) ); /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } assert( zData!=0 ); if( offset+amt<=available && (pMem->flags&MEM_Dyn)==0 ){ sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; pMem->enc = 0; pMem->type = SQLITE_BLOB; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); }else{ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); } pMem->z[amt] = 0; pMem->z[amt+1] = 0; if( rc!=SQLITE_OK ){ sqlite3VdbeMemRelease(pMem); } } pMem->n = amt; return rc; }
/* ** Move data out of a btree key or data field and into a Mem structure. ** The data or key is taken from the entry that pCur is currently pointing ** to. offset and amt determine what portion of the data or key to retrieve. ** key is true to get the key or false to get data. The result is written ** into the pMem element. ** ** The pMem structure is assumed to be uninitialized. Any prior content ** is overwritten without being freed. ** ** If this routine fails for any reason (malloc returns NULL or unable ** to read from the disk) then the pMem is left in an inconsistent state. */ int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ int offset, /* Offset from the start of data to return bytes from. */ int amt, /* Number of bytes to return. */ int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ int available = 0; /* Number of bytes available on the local btree page */ sqlite3 *db; /* Database connection */ int rc = SQLITE_OK; db = sqlite3BtreeCursorDb(pCur); assert( sqlite3_mutex_held(db->mutex) ); assert( (pMem->flags & MEM_RowSet)==0 ); if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } assert( zData!=0 ); if( offset+amt<=available && ((pMem->flags&MEM_Dyn)==0 || pMem->xDel) ){ sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; pMem->enc = 0; pMem->type = SQLITE_BLOB; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); }else{ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); } pMem->z[amt] = 0; pMem->z[amt+1] = 0; if( rc!=SQLITE_OK ){ sqlite3VdbeMemRelease(pMem); } } pMem->n = amt; return rc; }
/* ** Remove any elements that remain on the sorter for the VDBE given. */ void sqlite3VdbeSorterReset(Vdbe *p){ while( p->pSort ){ Sorter *pSorter = p->pSort; p->pSort = pSorter->pNext; sqliteFree(pSorter->zKey); sqlite3VdbeMemRelease(&pSorter->data); sqliteFree(pSorter); } }
/* ** Delete any previous value and set the value to be a BLOB of length ** n containing all zeros. */ void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Blob|MEM_Zero; pMem->type = SQLITE_BLOB; pMem->n = 0; if( n<0 ) n = 0; pMem->u.nZero = n; pMem->enc = SQLITE_UTF8; }
/* ** Delete any previous value and set the value stored in *pMem to val, ** manifest type REAL. */ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ if( sqlite3IsNaN(val) ){ sqlite3VdbeMemSetNull(pMem); }else{ sqlite3VdbeMemRelease(pMem); pMem->r = val; pMem->flags = MEM_Real; pMem->type = SQLITE_FLOAT; } }
/* ** If the memory cell contains a string value that must be freed by ** invoking an external callback, free it now. Calling this function ** does not free any Mem.zMalloc buffer. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); if( p->flags&MEM_Agg ){ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); }else if( p->flags&MEM_Dyn && p->xDel ){ p->xDel((void *)p->z); p->xDel = 0; } }
/* ** Transfer the contents of pFrom to pTo. Any existing value in pTo is ** freed. If pFrom contains ephemeral data, a copy is made. ** ** pFrom contains an SQL NULL when this routine returns. */ void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) ); assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) ); assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db ); sqlite3VdbeMemRelease(pTo); memcpy(pTo, pFrom, sizeof(Mem)); pFrom->flags = MEM_Null; pFrom->xDel = 0; pFrom->zMalloc = 0; }
/* ** Make a full copy of pFrom into pTo. Prior contents of pTo are ** freed before the copy is made. */ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc; if( pTo->flags & MEM_Dyn ){ sqlite3VdbeMemRelease(pTo); } sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem); if( pTo->flags & MEM_Ephem ){ rc = sqlite3VdbeMemMakeWriteable(pTo); }else{ rc = SQLITE_OK; } return rc; }
/* ** Convert a UTF-16 string in the native encoding into a UTF-8 string. ** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must ** be freed by the calling function. ** ** NULL is returned if there is an allocation error. */ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){ Mem m; memset(&m, 0, sizeof(m)); m.db = db; sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); if( db->mallocFailed ){ sqlite3VdbeMemRelease(&m); m.z = 0; } assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z); }
/* ** Set all the parameters in the compiled SQL statement to NULL. */ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; #ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); for(i=0; i<p->nVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; } sqlite3_mutex_leave(mutex); return rc; }
/* ** Free all resources allociated with AggElem pElem, an element of ** aggregate pAgg. */ void freeAggElem(AggElem *pElem, Agg *pAgg){ int i; for(i=0; i<pAgg->nMem; i++){ Mem *pMem = &pElem->aMem[i]; if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){ sqlite3_context ctx; ctx.pFunc = pAgg->apFunc[i]; ctx.s.flags = MEM_Null; ctx.pAgg = pMem->z; ctx.cnt = (int) pMem->i; ctx.isStep = 0; ctx.isError = 0; (*pAgg->apFunc[i]->xFinalize)(&ctx); pMem->z = ctx.pAgg; if( pMem->z!=0 && pMem->z!=pMem->zShort ){ sqliteFree(pMem->z); } sqlite3VdbeMemRelease(&ctx.s); }else{ sqlite3VdbeMemRelease(pMem); } } sqliteFree(pElem); }
/* ** Convert a UTF-16 string in the native encoding into a UTF-8 string. ** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must ** be freed by the calling function. ** ** NULL is returned if there is an allocation error. */ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){ Mem m; memset(&m, 0, sizeof(m)); m.db = db; sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); if( db->mallocFailed ){ sqlite3VdbeMemRelease(&m); m.z = 0; } assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); assert( m.z || db->mallocFailed ); return m.z; }
/* ** Delete any previous value and set the value of pMem to be an ** empty boolean index. */ void sqlite3VdbeMemSetRowSet(Mem *pMem){ sqlite3 *db = pMem->db; assert( db!=0 ); assert( (pMem->flags & MEM_RowSet)==0 ); sqlite3VdbeMemRelease(pMem); pMem->zMalloc = sqlite3DbMallocRaw(db, 64); if( db->mallocFailed ){ pMem->flags = MEM_Null; }else{ assert( pMem->zMalloc ); pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, sqlite3DbMallocSize(db, pMem->zMalloc)); assert( pMem->u.pRowSet!=0 ); pMem->flags = MEM_RowSet; } }
/* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and ** (Mem.type==SQLITE_TEXT). */ void sqlite3VdbeMemRelease(Mem *p){ if( p->flags & (MEM_Dyn|MEM_Agg) ){ if( p->xDel ){ if( p->flags & MEM_Agg ){ sqlite3VdbeMemFinalize(p, *(FuncDef**)&p->i); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); }else{ p->xDel((void *)p->z); } }else{ sqliteFree(p->z); } p->z = 0; p->xDel = 0; } }
/* ** If pMem is an object with a valid string representation, this routine ** ensures the internal encoding for the string representation is ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. ** ** If pMem is not a string object, or the encoding of the string ** representation is already stored using the requested encoding, then this ** routine is a no-op. ** ** SQLITE_OK is returned if the conversion is successful (or not required). ** SQLITE_NOMEM may be returned if a malloc() fails during conversion ** between formats. */ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ int rc; if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ return SQLITE_OK; } #ifdef SQLITE_OMIT_UTF16 return SQLITE_ERROR; #else rc = sqlite3VdbeMemTranslate(pMem, desiredEnc); if( rc==SQLITE_NOMEM ){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Null; pMem->z = 0; } return rc; #endif }
/* ** Delete any previous value and set the value to be a BLOB of length ** n containing all zeros. */ void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Blob|MEM_Zero; pMem->type = SQLITE_BLOB; pMem->n = 0; if( n<0 ) n = 0; pMem->u.nZero = n; pMem->enc = SQLITE_UTF8; #ifdef SQLITE_OMIT_INCRBLOB sqlite3VdbeMemGrow(pMem, n, 0); if( pMem->z ){ pMem->n = n; memset(pMem->z, 0, n); } #endif }
/* ** If the memory cell contains a string value that must be freed by ** invoking an external callback, free it now. Calling this function ** does not free any Mem.zMalloc buffer. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); if( p->flags&MEM_Agg ){ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); }else if( p->flags&MEM_Dyn && p->xDel ){ assert( (p->flags&MEM_RowSet)==0 ); assert( p->xDel!=SQLITE_DYNAMIC ); p->xDel((void *)p->z); p->xDel = 0; }else if( p->flags&MEM_RowSet ){ sqlite3RowSetClear(p->u.pRowSet); }else if( p->flags&MEM_Frame ){ sqlite3VdbeMemSetNull(p); } }
/* ** Unbind the value bound to variable i in virtual machine p. This is the ** the same as binding a NULL value to the column. If the "i" parameter is ** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. ** ** The error code stored in database p->db is overwritten with the return ** value in any case. */ static int vdbeUnbind(Vdbe *p, int i){ Mem *pVar; if( p==0 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ if( p ) sqlite3Error(p->db, SQLITE_MISUSE, 0); return SQLITE_MISUSE; } if( i<1 || i>p->nVar ){ sqlite3Error(p->db, SQLITE_RANGE, 0); return SQLITE_RANGE; } i--; pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; sqlite3Error(p->db, SQLITE_OK, 0); return SQLITE_OK; }
/* ** Transfer the contents of pFrom to pTo. Any existing value in pTo is ** freed. If pFrom contains ephemeral data, a copy is made. ** ** pFrom contains an SQL NULL when this routine returns. SQLITE_NOMEM ** might be returned if pFrom held ephemeral data and we were unable ** to allocate enough space to make a copy. */ int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom) { int rc; if( pTo->flags & MEM_Dyn ) { sqlite3VdbeMemRelease(pTo); } memcpy(pTo, pFrom, sizeof(Mem)); if( pFrom->flags & MEM_Short ) { pTo->z = pTo->zShort; } pFrom->flags = MEM_Null; pFrom->xDel = 0; if( pTo->flags & MEM_Ephem ) { rc = sqlite3VdbeMemMakeWriteable(pTo); } else { rc = SQLITE_OK; } return rc; }
/* ** Set all the parameters in the compiled SQL statement to NULL. */ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); for(i=0; i<p->nVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; } if( p->isPrepareV2 && p->expmask ){ p->expired = 1; } sqlite3_mutex_leave(mutex); return rc; }
/* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and ** (Mem.type==SQLITE_TEXT). */ void sqlite3VdbeMemRelease(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); if( p->flags & (MEM_Dyn|MEM_Agg) ){ if( p->xDel ){ if( p->flags & MEM_Agg ){ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); }else{ p->xDel((void *)p->z); } }else{ sqlite3_free(p->z); } p->z = 0; p->xDel = 0; } }
/* ** Convert pMem so that it has types MEM_Real or MEM_Int or both. ** Invalidate any prior representations. */ int sqlite3VdbeMemNumerify(Mem *pMem){ double r1, r2; i64 i; assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); r1 = sqlite3VdbeRealValue(pMem); i = (i64)r1; r2 = (double)i; if( r1==r2 ){ sqlite3VdbeMemIntegerify(pMem); }else{ pMem->r = r1; pMem->flags = MEM_Real; sqlite3VdbeMemRelease(pMem); } return SQLITE_OK; }
/* ** Unbind the value bound to variable i in virtual machine p. This is the ** the same as binding a NULL value to the column. If the "i" parameter is ** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. ** ** A successful evaluation of this routine acquires the mutex on p. ** the mutex is released if any kind of error occurs. ** ** The error code stored in database p->db is overwritten with the return ** value in any case. */ static int vdbeUnbind(Vdbe *p, int i){ Mem *pVar; if( vdbeSafetyNotNull(p) ){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(p->db->mutex); if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ sqlite3Error(p->db, SQLITE_MISUSE); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); return SQLITE_MISUSE_BKPT; } if( i<1 || i>p->nVar ){ sqlite3Error(p->db, SQLITE_RANGE); sqlite3_mutex_leave(p->db->mutex); return SQLITE_RANGE; } i--; pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; sqlite3Error(p->db, SQLITE_OK); /* If the bit corresponding to this variable in Vdbe.expmask is set, then ** binding a new value to this variable invalidates the current query plan. ** ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host ** parameter in the WHERE clause might influence the choice of query plan ** for a statement, then the statement will be automatically recompiled, ** as if there had been a schema change, on the first sqlite3_step() call ** following any change to the bindings of that parameter. */ if( p->isPrepareV2 && ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) ){ p->expired = 1; } return SQLITE_OK; }
int sqlite3VdbeMemExpandBlob(Mem *pMem){ if( pMem->flags & MEM_Zero ){ char *pNew; int nByte; assert( (pMem->flags & MEM_Blob)!=0 ); nByte = pMem->n + pMem->u.i; if( nByte<=0 ) nByte = 1; assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); pNew = sqlite3DbMallocRaw(pMem->db, nByte); if( pNew==0 ){ return SQLITE_NOMEM; } memcpy(pNew, pMem->z, pMem->n); memset(&pNew[pMem->n], 0, pMem->u.i); sqlite3VdbeMemRelease(pMem); pMem->z = pNew; pMem->n += pMem->u.i; pMem->u.i = 0; pMem->flags &= ~(MEM_Zero|MEM_Static|MEM_Ephem|MEM_Short|MEM_Term); pMem->flags |= MEM_Dyn; } return SQLITE_OK; }
/* ** Compare the values contained by the two memory cells, returning ** negative, zero or positive if pMem1 is less than, equal to, or greater ** than pMem2. Sorting order is NULL's first, followed by numbers (integers ** and reals) sorted numerically, followed by text ordered by the collating ** sequence pColl and finally blob's ordered by memcmp(). ** ** Two NULL values are considered equal by this function. */ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ int rc; int f1, f2; int combined_flags; /* Interchange pMem1 and pMem2 if the collating sequence specifies ** DESC order. */ f1 = pMem1->flags; f2 = pMem2->flags; combined_flags = f1|f2; /* If one value is NULL, it is less than the other. If both values ** are NULL, return 0. */ if( combined_flags&MEM_Null ){ return (f2&MEM_Null) - (f1&MEM_Null); } /* If one value is a number and the other is not, the number is less. ** If both are numbers, compare as reals if one is a real, or as integers ** if both values are integers. */ if( combined_flags&(MEM_Int|MEM_Real) ){ if( !(f1&(MEM_Int|MEM_Real)) ){ return 1; } if( !(f2&(MEM_Int|MEM_Real)) ){ return -1; } if( (f1 & f2 & MEM_Int)==0 ){ double r1, r2; if( (f1&MEM_Real)==0 ){ r1 = pMem1->u.i; }else{ r1 = pMem1->r; } if( (f2&MEM_Real)==0 ){ r2 = pMem2->u.i; }else{ r2 = pMem2->r; } if( r1<r2 ) return -1; if( r1>r2 ) return 1; return 0; }else{ assert( f1&MEM_Int ); assert( f2&MEM_Int ); if( pMem1->u.i < pMem2->u.i ) return -1; if( pMem1->u.i > pMem2->u.i ) return 1; return 0; } } /* If one value is a string and the other is a blob, the string is less. ** If both are strings, compare using the collating functions. */ if( combined_flags&MEM_Str ){ if( (f1 & MEM_Str)==0 ){ return 1; } if( (f2 & MEM_Str)==0 ){ return -1; } assert( pMem1->enc==pMem2->enc ); assert( pMem1->enc==SQLITE_UTF8 || pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); /* The collation sequence must be defined at this point, even if ** the user deletes the collation sequence after the vdbe program is ** compiled (this was not always the case). */ assert( !pColl || pColl->xCmp ); if( pColl ){ if( pMem1->enc==pColl->enc ){ /* The strings are already in the correct encoding. Call the ** comparison function directly */ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); }else{ const void *v1, *v2; int n1, n2; Mem c1; Mem c2; memset(&c1, 0, sizeof(c1)); memset(&c2, 0, sizeof(c2)); sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); n1 = v1==0 ? 0 : c1.n; v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); n2 = v2==0 ? 0 : c2.n; rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); sqlite3VdbeMemRelease(&c1); sqlite3VdbeMemRelease(&c2); return rc; } } /* If a NULL pointer was passed as the collate function, fall through ** to the blob case and use memcmp(). */ } /* Both values must be blobs. Compare using memcmp(). */ rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); if( rc==0 ){ rc = pMem1->n - pMem2->n; } return rc; }