⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdbemem.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** 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;}/*** Change the value of a Mem to be a string or a BLOB.*/int sqlite3VdbeMemSetStr(  Mem *pMem,          /* Memory cell to set to string value */  const char *z,      /* String pointer */  int n,              /* Bytes in string, or negative */  u8 enc,             /* Encoding of z.  0 for BLOBs */  void (*xDel)(void*) /* Destructor function */){  sqlite3VdbeMemRelease(pMem);  if( !z ){    pMem->flags = MEM_Null;    pMem->type = SQLITE_NULL;    return SQLITE_OK;  }  pMem->z = (char *)z;  if( xDel==SQLITE_STATIC ){    pMem->flags = MEM_Static;  }else if( xDel==SQLITE_TRANSIENT ){    pMem->flags = MEM_Ephem;  }else{    pMem->flags = MEM_Dyn;    pMem->xDel = xDel;  }  pMem->enc = enc;  pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT;  pMem->n = n;  assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE       || enc==SQLITE_UTF16BE );  switch( enc ){    case 0:      pMem->flags |= MEM_Blob;      pMem->enc = SQLITE_UTF8;      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->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{        u8 origEnc = pMem1->enc;        const void *v1, *v2;        int n1, n2;        /* Convert the strings into the encoding that the comparison        ** function expects */        v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc);        n1 = v1==0 ? 0 : pMem1->n;        assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) );        v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc);        n2 = v2==0 ? 0 : pMem2->n;        assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) );        /* Do the comparison */        rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);        /* Convert the strings back into the database encoding */        sqlite3ValueText((sqlite3_value*)pMem1, 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 = 0; /* Number of bytes available on the local btree page */  if( key ){    zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);  }else{    zData = (char *)sqlite3BtreeDataFetch(pCur, &available);  }  assert( zData!=0 );  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){  int flags = pMem->flags;  assert( flags!=0 );  /* Must define some type */  if( flags & (MEM_Str|MEM_Blob) ){    int x = 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( (x & MEM_Short)==0 || pMem->z==pMem->zShort );    assert( (x & 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 the MEM is both real and integer, the values are equal */  assert( (pMem->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real)           || pMem->r==pMem->u.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.**** (2006-02-16:)  The enc value can be or-ed with SQLITE_UTF16_ALIGNED.** If that is the case, then the result must be aligned on an even byte** boundary.*/const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){  if( !pVal ) return 0;  assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );  if( pVal->flags&MEM_Null ){    return 0;  }  assert( (MEM_Blob>>3) == MEM_Str );  pVal->flags |= (pVal->flags & MEM_Blob)>>3;  expandBlob(pVal);  if( pVal->flags&MEM_Str ){    sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);    if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){      assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );      if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){        return 0;      }    }    sqlite3VdbeMemNulTerminate(pVal);  }else{    assert( (pVal->flags&MEM_Blob)==0 );    sqlite3VdbeMemStringify(pVal, enc);    assert( 0==(1&(int)pVal->z) );  }  assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || sqlite3MallocFailed() );  if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){    return pVal->z;  }else{    return 0;  }}/*** Create a new sqlite3_value object.*/sqlite3_value *sqlite3ValueNew(void){  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((char*)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->u.i = -1 * pVal->u.i;      pVal->r = -1.0 * pVal->r;    }  }#ifndef SQLITE_OMIT_BLOB_LITERAL  else if( op==TK_BLOB ){    int nVal;    pVal = sqlite3ValueNew();    zVal = sqliteStrNDup((char*)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) ){    if( p->flags & MEM_Zero ){      return p->n+p->u.i;    }else{      return p->n;    }  }  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -