📄 vdbemem.c
字号:
|| enc==SQLITE_UTF16BE ); switch( enc ){ case 0: pMem->flags |= MEM_Blob; break; case SQLITE_UTF8: pMem->flags |= MEM_Str; if( n<0 ){ pMem->n = strlen(z); pMem->flags |= MEM_Term; } break;#ifndef SQLITE_OMIT_UTF16 case SQLITE_UTF16LE: case SQLITE_UTF16BE: pMem->flags |= MEM_Str; if( pMem->n<0 ){ pMem->n = sqlite3utf16ByteLen(pMem->z,-1); pMem->flags |= MEM_Term; } if( sqlite3VdbeMemHandleBom(pMem) ){ return SQLITE_NOMEM; }#endif /* SQLITE_OMIT_UTF16 */ } if( pMem->flags&MEM_Ephem ){ return sqlite3VdbeMemMakeWriteable(pMem); } 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->i; }else{ r1 = pMem1->r; } if( (f2&MEM_Real)==0 ){ r2 = pMem2->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->i < pMem2->i ) return -1; if( pMem1->i > pMem2->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 ); /* This assert may fail if the collation sequence is deleted after this ** vdbe program is compiled. The documentation defines this as an ** undefined condition. A crash is usual result. */ assert( !pColl || pColl->xCmp ); if( pColl ){ if( pMem1->enc==pColl->enc ){ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); }else{ u8 origEnc = pMem1->enc; rc = pColl->xCmp( pColl->pUser, sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc), sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc), sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc), sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc) ); sqlite3ValueBytes((sqlite3_value*)pMem1, origEnc); sqlite3ValueText((sqlite3_value*)pMem1, origEnc); sqlite3ValueBytes((sqlite3_value*)pMem2, origEnc); sqlite3ValueText((sqlite3_value*)pMem2, origEnc); 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;}/*** 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; /* Number of bytes available on the local btree page */ if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } pMem->n = amt; if( offset+amt<=available ){ pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; }else{ int rc; if( amt>NBFS-2 ){ zData = (char *)sqliteMallocRaw(amt+2); if( !zData ){ return SQLITE_NOMEM; } pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; pMem->xDel = 0; }else{ zData = &(pMem->zShort[0]); pMem->flags = MEM_Blob|MEM_Short|MEM_Term; } pMem->z = zData; pMem->enc = 0; pMem->type = SQLITE_BLOB; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, zData); }else{ rc = sqlite3BtreeData(pCur, offset, amt, zData); } zData[amt] = 0; zData[amt+1] = 0; if( rc!=SQLITE_OK ){ if( amt>NBFS-2 ){ assert( zData!=pMem->zShort ); assert( pMem->flags & MEM_Dyn ); sqliteFree(zData); } else { assert( zData==pMem->zShort ); assert( pMem->flags & MEM_Short ); } return rc; } } return SQLITE_OK;}#ifndef NDEBUG/*** Perform various checks on the memory cell pMem. An assert() will** fail if pMem is internally inconsistent.*/void sqlite3VdbeMemSanity(Mem *pMem, u8 db_enc){ int flags = pMem->flags; assert( flags!=0 ); /* Must define some type */ if( pMem->flags & (MEM_Str|MEM_Blob) ){ int x = pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short); assert( x!=0 ); /* Strings must define a string subtype */ assert( (x & (x-1))==0 ); /* Only one string subtype can be defined */ assert( pMem->z!=0 ); /* Strings must have a value */ /* Mem.z points to Mem.zShort iff the subtype is MEM_Short */ assert( (pMem->flags & MEM_Short)==0 || pMem->z==pMem->zShort ); assert( (pMem->flags & MEM_Short)!=0 || pMem->z!=pMem->zShort ); /* No destructor unless there is MEM_Dyn */ assert( pMem->xDel==0 || (pMem->flags & MEM_Dyn)!=0 ); if( (flags & MEM_Str) ){ assert( pMem->enc==SQLITE_UTF8 || pMem->enc==SQLITE_UTF16BE || pMem->enc==SQLITE_UTF16LE ); /* If the string is UTF-8 encoded and nul terminated, then pMem->n ** must be the length of the string. (Later:) If the database file ** has been corrupted, '\000' characters might have been inserted ** into the middle of the string. In that case, the strlen() might ** be less. */ if( pMem->enc==SQLITE_UTF8 && (flags & MEM_Term) ){ assert( strlen(pMem->z)<=pMem->n ); assert( pMem->z[pMem->n]==0 ); } } }else{ /* Cannot define a string subtype for non-string objects */ assert( (pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 ); assert( pMem->xDel==0 ); } /* MEM_Null excludes all other types */ assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0 || (pMem->flags&MEM_Null)==0 ); if( (pMem->flags & (MEM_Int|MEM_Real))==(MEM_Int|MEM_Real) ){ assert( pMem->r==pMem->i ); }}#endif/* This function is only available internally, it is not part of the** external API. It works in a similar way to sqlite3_value_text(),** except the data returned is in the encoding specified by the second** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or** SQLITE_UTF8.*/const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ if( !pVal ) return 0; assert( enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE || enc==SQLITE_UTF8); if( pVal->flags&MEM_Null ){ return 0; } if( pVal->flags&MEM_Str ){ sqlite3VdbeChangeEncoding(pVal, enc); }else if( !(pVal->flags&MEM_Blob) ){ sqlite3VdbeMemStringify(pVal, enc); } return (const void *)(pVal->z);}/*** Create a new sqlite3_value object.*/sqlite3_value* sqlite3ValueNew(){ Mem *p = sqliteMalloc(sizeof(*p)); if( p ){ p->flags = MEM_Null; p->type = SQLITE_NULL; } return p;}/*** Create a new sqlite3_value object, containing the value of pExpr.**** This only works for very simple expressions that consist of one constant** token (i.e. "5", "5.1", "NULL", "'a string'"). If the expression can** be converted directly into a value, then the value is allocated and** a pointer written to *ppVal. The caller is responsible for deallocating** the value by passing it to sqlite3ValueFree() later on. If the expression** cannot be converted to a value, then *ppVal is set to NULL.*/int sqlite3ValueFromExpr( Expr *pExpr, u8 enc, u8 affinity, sqlite3_value **ppVal){ int op; char *zVal = 0; sqlite3_value *pVal = 0; if( !pExpr ){ *ppVal = 0; return SQLITE_OK; } op = pExpr->op; if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ zVal = sqliteStrNDup(pExpr->token.z, pExpr->token.n); pVal = sqlite3ValueNew(); if( !zVal || !pVal ) goto no_mem; sqlite3Dequote(zVal); sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3FreeX); if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc); }else{ sqlite3ValueApplyAffinity(pVal, affinity, enc); } }else if( op==TK_UMINUS ) { if( SQLITE_OK==sqlite3ValueFromExpr(pExpr->pLeft, enc, affinity, &pVal) ){ pVal->i = -1 * pVal->i; pVal->r = -1.0 * pVal->r; } }#ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; pVal = sqlite3ValueNew(); zVal = sqliteStrNDup(pExpr->token.z+1, pExpr->token.n-1); if( !zVal || !pVal ) goto no_mem; sqlite3Dequote(zVal); nVal = strlen(zVal)/2; sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(zVal), nVal, 0, sqlite3FreeX); sqliteFree(zVal); }#endif *ppVal = pVal; return SQLITE_OK;no_mem: sqliteFree(zVal); sqlite3ValueFree(pVal); *ppVal = 0; return SQLITE_NOMEM;}/*** Change the string value of an sqlite3_value object*/void sqlite3ValueSetStr( sqlite3_value *v, int n, const void *z, u8 enc, void (*xDel)(void*)){ if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel);}/*** Free an sqlite3_value object*/void sqlite3ValueFree(sqlite3_value *v){ if( !v ) return; sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC); sqliteFree(v);}/*** Return the number of bytes in the sqlite3_value object assuming** that it uses the encoding "enc"*/int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ Mem *p = (Mem*)pVal; if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ return p->n; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -