📄 vdbeaux.c
字号:
** 3 3 signed integer** 4 4 signed integer** 5 6 signed integer** 6 8 signed integer** 7 8 IEEE float** 8 0 Integer constant 0** 9 0 Integer constant 1** 10,11 reserved for expansion** N>=12 and even (N-12)/2 BLOB** N>=13 and odd (N-13)/2 text**** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions** of SQLite will not understand those serial types.*//*** Return the serial-type for the value stored in pMem.*/u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){ int flags = pMem->flags; int n; if( flags&MEM_Null ){ return 0; } if( flags&MEM_Int ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */# define MAX_6BYTE ((((i64)0x00001000)<<32)-1) i64 i = pMem->u.i; u64 u; if( file_format>=4 && (i&1)==i ){ return 8+i; } u = i<0 ? -i : i; if( u<=127 ) return 1; if( u<=32767 ) return 2; if( u<=8388607 ) return 3; if( u<=2147483647 ) return 4; if( u<=MAX_6BYTE ) return 5; return 6; } if( flags&MEM_Real ){ return 7; } assert( flags&(MEM_Str|MEM_Blob) ); n = pMem->n; if( flags & MEM_Zero ){ n += pMem->u.i; } assert( n>=0 ); return ((n*2) + 12 + ((flags&MEM_Str)!=0));}/*** Return the length of the data corresponding to the supplied serial-type.*/int sqlite3VdbeSerialTypeLen(u32 serial_type){ if( serial_type>=12 ){ return (serial_type-12)/2; }else{ static const u8 aSize[] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 }; return aSize[serial_type]; }}/*** If we are on an architecture with mixed-endian floating ** points (ex: ARM7) then swap the lower 4 bytes with the ** upper 4 bytes. Return the result.**** For most architectures, this is a no-op.**** (later): It is reported to me that the mixed-endian problem** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems** that early versions of GCC stored the two words of a 64-bit** float in the wrong order. And that error has been propagated** ever since. The blame is not necessarily with GCC, though.** GCC might have just copying the problem from a prior compiler.** I am also told that newer versions of GCC that follow a different** ABI get the byte order right.**** Developers using SQLite on an ARM7 should compile and run their** application using -DSQLITE_DEBUG=1 at least once. With DEBUG** enabled, some asserts below will ensure that the byte order of** floating point values is correct.**** (2007-08-30) Frank van Vugt has studied this problem closely** and has send his findings to the SQLite developers. Frank** writes that some Linux kernels offer floating point hardware** emulation that uses only 32-bit mantissas instead of a full ** 48-bits as required by the IEEE standard. (This is the** CONFIG_FPE_FASTFPE option.) On such systems, floating point** byte swapping becomes very complicated. To avoid problems,** the necessary byte swapping is carried out using a 64-bit integer** rather than a 64-bit float. Frank assures us that the code here** works for him. We, the developers, have no way to independently** verify this, but Frank seems to know what he is talking about** so we trust him.*/#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOATstatic u64 floatSwap(u64 in){ union { u64 r; u32 i[2]; } u; u32 t; u.r = in; t = u.i[0]; u.i[0] = u.i[1]; u.i[1] = t; return u.r;}# define swapMixedEndianFloat(X) X = floatSwap(X)#else# define swapMixedEndianFloat(X)#endif/*** Write the serialized data blob for the value stored in pMem into ** buf. It is assumed that the caller has allocated sufficient space.** Return the number of bytes written.**** nBuf is the amount of space left in buf[]. nBuf must always be** large enough to hold the entire field. Except, if the field is** a blob with a zero-filled tail, then buf[] might be just the right** size to hold everything except for the zero-filled tail. If buf[]** is only big enough to hold the non-zero prefix, then only write that** prefix into buf[]. But if buf[] is large enough to hold both the** prefix and the tail then write the prefix and set the tail to all** zeros.**** Return the number of bytes actually written into buf[]. The number** of bytes in the zero-filled tail is included in the return value only** if those bytes were zeroed in buf[].*/ int sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){ u32 serial_type = sqlite3VdbeSerialType(pMem, file_format); int len; /* Integer and Real */ if( serial_type<=7 && serial_type>0 ){ u64 v; int i; if( serial_type==7 ){ assert( sizeof(v)==sizeof(pMem->r) ); memcpy(&v, &pMem->r, sizeof(v)); swapMixedEndianFloat(v); }else{ v = pMem->u.i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); assert( len<=nBuf ); while( i-- ){ buf[i] = (v&0xFF); v >>= 8; } return len; } /* String or blob */ if( serial_type>=12 ){ assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.i:0) == sqlite3VdbeSerialTypeLen(serial_type) ); assert( pMem->n<=nBuf ); len = pMem->n; memcpy(buf, pMem->z, len); if( pMem->flags & MEM_Zero ){ len += pMem->u.i; if( len>nBuf ){ len = nBuf; } memset(&buf[pMem->n], 0, len-pMem->n); } return len; } /* NULL or constants 0 or 1 */ return 0;}/*** Deserialize the data blob pointed to by buf as serial type serial_type** and store the result in pMem. Return the number of bytes read.*/ int sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */){ switch( serial_type ){ case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ case 0: { /* NULL */ pMem->flags = MEM_Null; break; } case 1: { /* 1-byte signed integer */ pMem->u.i = (signed char)buf[0]; pMem->flags = MEM_Int; return 1; } case 2: { /* 2-byte signed integer */ pMem->u.i = (((signed char)buf[0])<<8) | buf[1]; pMem->flags = MEM_Int; return 2; } case 3: { /* 3-byte signed integer */ pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2]; pMem->flags = MEM_Int; return 3; } case 4: { /* 4-byte signed integer */ pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; pMem->flags = MEM_Int; return 4; } case 5: { /* 6-byte signed integer */ u64 x = (((signed char)buf[0])<<8) | buf[1]; u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5]; x = (x<<32) | y; pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; return 6; } case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ u64 x; u32 y;#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) /* Verify that integers and floating point values use the same ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is ** defined that 64-bit floating point values really are mixed ** endian. */ static const u64 t1 = ((u64)0x3ff00000)<<32; static const double r1 = 1.0; u64 t2 = t1; swapMixedEndianFloat(t2); assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );#endif x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7]; x = (x<<32) | y; if( serial_type==6 ){ pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; }else{ assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); swapMixedEndianFloat(x); memcpy(&pMem->r, &x, sizeof(x)); pMem->flags = MEM_Real; } return 8; } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ pMem->u.i = serial_type-8; pMem->flags = MEM_Int; return 0; } default: { int len = (serial_type-12)/2; pMem->z = (char *)buf; pMem->n = len; pMem->xDel = 0; if( serial_type&0x01 ){ pMem->flags = MEM_Str | MEM_Ephem; }else{ pMem->flags = MEM_Blob | MEM_Ephem; } return len; } } return 0;}/*** The header of a record consists of a sequence variable-length integers.** These integers are almost always small and are encoded as a single byte.** The following macro takes advantage this fact to provide a fast decode** of the integers in a record header. It is faster for the common case** where the integer is a single byte. It is a little slower when the** integer is two or more bytes. But overall it is faster.**** The following expressions are equivalent:**** x = sqlite3GetVarint32( A, &B );**** x = GetVarint( A, B );***/#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))/*** This function compares the two table rows or index records specified by ** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero** or positive integer if {nKey1, pKey1} is less than, equal to or ** greater than {nKey2, pKey2}. Both Key1 and Key2 must be byte strings** composed by the OP_MakeRecord opcode of the VDBE.*/int sqlite3VdbeRecordCompare( void *userData, int nKey1, const void *pKey1, int nKey2, const void *pKey2){ KeyInfo *pKeyInfo = (KeyInfo*)userData; u32 d1, d2; /* Offset into aKey[] of next data element */ u32 idx1, idx2; /* Offset into aKey[] of next header element */ u32 szHdr1, szHdr2; /* Number of bytes in header */ int i = 0; int nField; int rc = 0; const unsigned char *aKey1 = (const unsigned char *)pKey1; const unsigned char *aKey2 = (const unsigned char *)pKey2; Mem mem1; Mem mem2; mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; mem2.enc = pKeyInfo->enc; mem2.db = pKeyInfo->db; idx1 = GetVarint(aKey1, szHdr1); d1 = szHdr1; idx2 = GetVarint(aKey2, szHdr2); d2 = szHdr2; nField = pKeyInfo->nField; while( idx1<szHdr1 && idx2<szHdr2 ){ u32 serial_type1; u32 serial_type2; /* Read the serial types for the next element in each key. */ idx1 += GetVarint( aKey1+idx1, serial_type1 ); if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; idx2 += GetVarint( aKey2+idx2, serial_type2 ); if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break; /* Extract the values to be compared. */ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2); /* Do the comparison */ rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0); if( mem1.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem1); if( mem2.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem2); if( rc!=0 ){ break; } i++; } /* One of the keys ran out of fields, but all the fields up to that point ** were equal. If the incrKey flag is true, then the second key is ** treated as larger. */ if( rc==0 ){ if( pKeyInfo->incrKey ){ rc = -1; }else if( !pKeyInfo->prefixIsEqual ){ if( d1<nKey1 ){ rc = 1; }else if( d2<nKey2 ){ rc = -1; } } }else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField && pKeyInfo->aSortOrder[i] ){ rc = -rc; } return rc;}/*** The argument is an index entry composed using the OP_MakeRecord opcode.** The last entry in this record should be an integer (specifically** an integer rowid). This routine returns the number of bytes in** that integer.*/int sqlite3VdbeIdxRowidLen(const u8 *aKey){ u32 szHdr; /* Size of the header */ u32 typeRowid; /* Serial type of the rowid */ sqlite3GetVarint32(aKey, &szHdr); sqlite3GetVarint32(&aKey[szHdr-1], &typeRowid); return sqlite3VdbeSerialTypeLen(typeRowid);} /*** pCur points at an index entry created using the OP_MakeRecord opcode.** Read the rowid (the last field in the record) and store it in *rowid.** Return SQLITE_OK if everything works, or an error code otherwise.*/int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ i64 nCellKey = 0; int rc; u32 szHdr; /* Size of the header */ u32 typeRowid; /* Serial type of the rowid */ u32 lenRowid; /* Size of the rowid */ Mem m, v; sqlite3BtreeKeySize(pCur, &nCellKey); if( nCellKey<=0 ){ return SQLITE_CORRUPT_BKPT; } rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m); if( rc ){ return rc; } sqlite3GetVarint32((u8*)m.z, &szHdr); sqlite3GetVarint32((u8*)&m.z[szHdr-1], &typeRowid); lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v); *rowid = v.u.i; sqlite3VdbeMemRelease(&m); return SQLITE_OK;}/*** Compare the key of the index entry that cursor pC is point to against** the key string in pKey (of length nKey). Write into *pRes a number** that is negative, zero, or positive if pC is less than, equal to,** or greater than pKey. Return SQLITE_OK on success.**** pKey is either created without a rowid or is truncated so that it** omits the rowid at the end. The rowid at the end of the index entry** is ignored as well.*/int sqlite3VdbeIdxKeyCompare( Cursor *pC, /* The cursor to compare against */ int nKey, const u8 *pKey, /* The key to compare */ int *res /* Write the comparison result here */){ i64 nCellKey = 0; int r
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -