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

📄 vdbe.c

📁 sqlite-source-2_8_16.zip 轻量级嵌入式数据库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  pTos->i = ~pTos->i;  pTos->flags = MEM_Int;  break;}/* Opcode: Noop * * ***** Do nothing.  This instruction is often useful as a jump** destination.*/case OP_Noop: {  break;}/* Opcode: If P1 P2 ***** Pop a single boolean from the stack.  If the boolean popped is** true, then jump to p2.  Otherwise continue to the next instruction.** An integer is false if zero and true otherwise.  A string is** false if it has zero length and true otherwise.**** If the value popped of the stack is NULL, then take the jump if P1** is true and fall through if P1 is false.*//* Opcode: IfNot P1 P2 ***** Pop a single boolean from the stack.  If the boolean popped is** false, then jump to p2.  Otherwise continue to the next instruction.** An integer is false if zero and true otherwise.  A string is** false if it has zero length and true otherwise.**** If the value popped of the stack is NULL, then take the jump if P1** is true and fall through if P1 is false.*/case OP_If:case OP_IfNot: {  int c;  assert( pTos>=p->aStack );  if( pTos->flags & MEM_Null ){    c = pOp->p1;  }else{    Integerify(pTos);    c = pTos->i;    if( pOp->opcode==OP_IfNot ) c = !c;  }  assert( (pTos->flags & MEM_Dyn)==0 );  pTos--;  if( c ) pc = pOp->p2-1;  break;}/* Opcode: IsNull P1 P2 ***** If any of the top abs(P1) values on the stack are NULL, then jump** to P2.  Pop the stack P1 times if P1>0.   If P1<0 leave the stack** unchanged.*/case OP_IsNull: {  int i, cnt;  Mem *pTerm;  cnt = pOp->p1;  if( cnt<0 ) cnt = -cnt;  pTerm = &pTos[1-cnt];  assert( pTerm>=p->aStack );  for(i=0; i<cnt; i++, pTerm++){    if( pTerm->flags & MEM_Null ){      pc = pOp->p2-1;      break;    }  }  if( pOp->p1>0 ) popStack(&pTos, cnt);  break;}/* Opcode: NotNull P1 P2 ***** Jump to P2 if the top P1 values on the stack are all not NULL.  Pop the** stack if P1 times if P1 is greater than zero.  If P1 is less than** zero then leave the stack unchanged.*/case OP_NotNull: {  int i, cnt;  cnt = pOp->p1;  if( cnt<0 ) cnt = -cnt;  assert( &pTos[1-cnt] >= p->aStack );  for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}  if( i>=cnt ) pc = pOp->p2-1;  if( pOp->p1>0 ) popStack(&pTos, cnt);  break;}/* Opcode: MakeRecord P1 P2 ***** Convert the top P1 entries of the stack into a single entry** suitable for use as a data record in a database table.  The** details of the format are irrelavant as long as the OP_Column** opcode can decode the record later.  Refer to source code** comments for the details of the record format.**** If P2 is true (non-zero) and one or more of the P1 entries** that go into building the record is NULL, then add some extra** bytes to the record to make it distinct for other entries created** during the same run of the VDBE.  The extra bytes added are a** counter that is reset with each run of the VDBE, so records** created this way will not necessarily be distinct across runs.** But they should be distinct for transient tables (created using** OP_OpenTemp) which is what they are intended for.**** (Later:) The P2==1 option was intended to make NULLs distinct** for the UNION operator.  But I have since discovered that NULLs** are indistinct for UNION.  So this option is never used.*/case OP_MakeRecord: {  char *zNewRecord;  int nByte;  int nField;  int i, j;  int idxWidth;  u32 addr;  Mem *pRec;  int addUnique = 0;   /* True to cause bytes to be added to make the                       ** generated record distinct */  char zTemp[NBFS];    /* Temp space for small records */  /* Assuming the record contains N fields, the record format looks  ** like this:  **  **   -------------------------------------------------------------------  **   | idx0 | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) |  **   -------------------------------------------------------------------  **  ** All data fields are converted to strings before being stored and  ** are stored with their null terminators.  NULL entries omit the  ** null terminator.  Thus an empty string uses 1 byte and a NULL uses  ** zero bytes.  Data(0) is taken from the lowest element of the stack  ** and data(N-1) is the top of the stack.  **  ** Each of the idx() entries is either 1, 2, or 3 bytes depending on  ** how big the total record is.  Idx(0) contains the offset to the start  ** of data(0).  Idx(k) contains the offset to the start of data(k).  ** Idx(N) contains the total number of bytes in the record.  */  nField = pOp->p1;  pRec = &pTos[1-nField];  assert( pRec>=p->aStack );  nByte = 0;  for(i=0; i<nField; i++, pRec++){    if( pRec->flags & MEM_Null ){      addUnique = pOp->p2;    }else{      Stringify(pRec);      nByte += pRec->n;    }  }  if( addUnique ) nByte += sizeof(p->uniqueCnt);  if( nByte + nField + 1 < 256 ){    idxWidth = 1;  }else if( nByte + 2*nField + 2 < 65536 ){    idxWidth = 2;  }else{    idxWidth = 3;  }  nByte += idxWidth*(nField + 1);  if( nByte>MAX_BYTES_PER_ROW ){    rc = SQLITE_TOOBIG;    goto abort_due_to_error;  }  if( nByte<=NBFS ){    zNewRecord = zTemp;  }else{    zNewRecord = sqliteMallocRaw( nByte );    if( zNewRecord==0 ) goto no_mem;  }  j = 0;  addr = idxWidth*(nField+1) + addUnique*sizeof(p->uniqueCnt);  for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){    zNewRecord[j++] = addr & 0xff;    if( idxWidth>1 ){      zNewRecord[j++] = (addr>>8)&0xff;      if( idxWidth>2 ){        zNewRecord[j++] = (addr>>16)&0xff;      }    }    if( (pRec->flags & MEM_Null)==0 ){      addr += pRec->n;    }  }  zNewRecord[j++] = addr & 0xff;  if( idxWidth>1 ){    zNewRecord[j++] = (addr>>8)&0xff;    if( idxWidth>2 ){      zNewRecord[j++] = (addr>>16)&0xff;    }  }  if( addUnique ){    memcpy(&zNewRecord[j], &p->uniqueCnt, sizeof(p->uniqueCnt));    p->uniqueCnt++;    j += sizeof(p->uniqueCnt);  }  for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){    if( (pRec->flags & MEM_Null)==0 ){      memcpy(&zNewRecord[j], pRec->z, pRec->n);      j += pRec->n;    }  }  popStack(&pTos, nField);  pTos++;  pTos->n = nByte;  if( nByte<=NBFS ){    assert( zNewRecord==zTemp );    memcpy(pTos->zShort, zTemp, nByte);    pTos->z = pTos->zShort;    pTos->flags = MEM_Str | MEM_Short;  }else{    assert( zNewRecord!=zTemp );    pTos->z = zNewRecord;    pTos->flags = MEM_Str | MEM_Dyn;  }  break;}/* Opcode: MakeKey P1 P2 P3**** Convert the top P1 entries of the stack into a single entry suitable** for use as the key in an index.  The top P1 records are** converted to strings and merged.  The null-terminators ** are retained and used as separators.** The lowest entry in the stack is the first field and the top of the** stack becomes the last.**** If P2 is not zero, then the original entries remain on the stack** and the new key is pushed on top.  If P2 is zero, the original** data is popped off the stack first then the new key is pushed** back in its place.**** P3 is a string that is P1 characters long.  Each character is either** an 'n' or a 't' to indicates if the argument should be intepreted as** numeric or text type.  The first character of P3 corresponds to the** lowest element on the stack.  If P3 is NULL then all arguments are** assumed to be of the numeric type.**** The type makes a difference in that text-type fields may not be ** introduced by 'b' (as described in the next paragraph).  The** first character of a text-type field must be either 'a' (if it is NULL)** or 'c'.  Numeric fields will be introduced by 'b' if their content** looks like a well-formed number.  Otherwise the 'a' or 'c' will be** used.**** The key is a concatenation of fields.  Each field is terminated by** a single 0x00 character.  A NULL field is introduced by an 'a' and** is followed immediately by its 0x00 terminator.  A numeric field is** introduced by a single character 'b' and is followed by a sequence** of characters that represent the number such that a comparison of** the character string using memcpy() sorts the numbers in numerical** order.  The character strings for numbers are generated using the** sqliteRealToSortable() function.  A text field is introduced by a** 'c' character and is followed by the exact text of the field.  The** use of an 'a', 'b', or 'c' character at the beginning of each field** guarantees that NULLs sort before numbers and that numbers sort** before text.  0x00 characters do not occur except as separators** between fields.**** See also: MakeIdxKey, SortMakeKey*//* Opcode: MakeIdxKey P1 P2 P3**** Convert the top P1 entries of the stack into a single entry suitable** for use as the key in an index.  In addition, take one additional integer** off of the stack, treat that integer as a four-byte record number, and** append the four bytes to the key.  Thus a total of P1+1 entries are** popped from the stack for this instruction and a single entry is pushed** back.  The first P1 entries that are popped are strings and the last** entry (the lowest on the stack) is an integer record number.**** The converstion of the first P1 string entries occurs just like in** MakeKey.  Each entry is separated from the others by a null.** The entire concatenation is null-terminated.  The lowest entry** in the stack is the first field and the top of the stack becomes the** last.**** If P2 is not zero and one or more of the P1 entries that go into the** generated key is NULL, then jump to P2 after the new key has been** pushed on the stack.  In other words, jump to P2 if the key is** guaranteed to be unique.  This jump can be used to skip a subsequent** uniqueness test.**** P3 is a string that is P1 characters long.  Each character is either** an 'n' or a 't' to indicates if the argument should be numeric or** text.  The first character corresponds to the lowest element on the** stack.  If P3 is null then all arguments are assumed to be numeric.**** See also:  MakeKey, SortMakeKey*/case OP_MakeIdxKey:case OP_MakeKey: {  char *zNewKey;  int nByte;  int nField;  int addRowid;  int i, j;  int containsNull = 0;  Mem *pRec;  char zTemp[NBFS];  addRowid = pOp->opcode==OP_MakeIdxKey;  nField = pOp->p1;  pRec = &pTos[1-nField];  assert( pRec>=p->aStack );  nByte = 0;  for(j=0, i=0; i<nField; i++, j++, pRec++){    int flags = pRec->flags;    int len;    char *z;    if( flags & MEM_Null ){      nByte += 2;      containsNull = 1;    }else if( pOp->p3 && pOp->p3[j]=='t' ){      Stringify(pRec);      pRec->flags &= ~(MEM_Int|MEM_Real);      nByte += pRec->n+1;    }else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(pRec->z) ){      if( (flags & (MEM_Real|MEM_Int))==MEM_Int ){        pRec->r = pRec->i;      }else if( (flags & (MEM_Real|MEM_Int))==0 ){        pRec->r = sqliteAtoF(pRec->z, 0);      }      Release(pRec);      z = pRec->zShort;      sqliteRealToSortable(pRec->r, z);      len = strlen(z);      pRec->z = 0;      pRec->flags = MEM_Real;      pRec->n = len+1;      nByte += pRec->n+1;    }else{      nByte += pRec->n+1;    }  }  if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){    rc = SQLITE_TOOBIG;    goto abort_due_to_error;  }  if( addRowid ) nByte += sizeof(u32);  if( nByte<=NBFS ){    zNewKey = zTemp;  }else{    zNewKey = sqliteMallocRaw( nByte );    if( zNewKey==0 ) goto no_mem;  }  j = 0;  pRec = &pTos[1-nField];  for(i=0; i<nField; i++, pRec++){    if( pRec->flags & MEM_Null ){      zNewKey[j++] = 'a';      zNewKey[j++] = 0;    }else if( pRec->flags==MEM_Real ){      zNewKey[j++] = 'b';      memcpy(&zNewKey[j], pRec->zShort, pRec->n);      j += pRec->n;    }else{      assert( pRec->flags & MEM_Str );      zNewKey[j++] = 'c';      memcpy(&zNewKey[j], pRec->z, pRec->n);      j += pRec->n;    }  }  if( addRowid ){    u32 iKey;    pRec = &pTos[-nField];    assert( pRec>=p->aStack );    Integerify(pRec);    iKey = intToKey(pRec->i);    memcpy(&zNewKey[j], &iKey, sizeof(u32));    popStack(&pTos, nField+1);    if( pOp->p2 && containsNull ) pc = pOp->p2 - 1;  }else{    if( pOp->p2==0 ) popStack(&pTos, nField);  }  pTos++;  pTos->n = nByte;  if( nByte<=NBFS ){    assert( zNewKey==zTemp );    pTos->z = pTos->zShort;    memcpy(pTos->zShort, zTemp, nByte);    pTos->flags = MEM_Str | MEM_Short;  }else{    pTos->z = zNewKey;    pTos->flags = MEM_Str | MEM_Dyn;  }  break;}/* Opcode: IncrKey * * ***** The top of the stack should contain an index key generated by** The MakeKey opcode.  This routine increases the least significant** byte of that key by one.  This is used so that the MoveTo opcode** will move to the first entry greater than the key rather than to** the key itself.*/case OP_IncrKey: {  assert( pTos>=p->aStack );  /* The IncrKey opcode is only applied to keys generated by  ** MakeKey or MakeIdxKey and the results of those operands  ** are always dynamic strings or zShort[] strings.  So we  ** are always free to modify the string in place.  */  assert( pTos->flags & (MEM_Dyn|MEM_Short) );  pTos->z[pTos->n-1]++;  break;}/* Opcode: Checkpoint P1 * ***** Begin a checkpoint.  A checkpoint is the beginning of a operation that** is part of a larger transaction but which might need to be rolled back** itself without effecting the containing transaction.  A checkpoint will** be automatically committed or rollback when the VDBE halts.**** The checkpoint is begun on the database file with index P1.  The main** database file has an index of 0 and the file used for temporary tables** has an index of 1.*/case OP_Checkpoint: {  int i = pOp->p1;  if( i>=0 && i<db->nDb && db->aDb[i].pBt && db->aDb[i].inTrans==1 ){    rc = sqliteBtreeBeginCkpt(db->aDb[i].pBt);    if( rc==SQLITE_OK ) db->aDb[i].inTrans = 2;  }  bre

⌨️ 快捷键说明

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