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

📄 expr.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** Generate code to copy content from registers iFrom...iFrom+nReg-1** over to iTo..iTo+nReg-1.*/void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){  int i;  if( iFrom==iTo ) return;  for(i=0; i<nReg; i++){    sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i);  }}/*** Return true if any register in the range iFrom..iTo (inclusive)** is used as part of the column cache.*/static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){  int i;  for(i=0; i<pParse->nColCache; i++){    int r = pParse->aColCache[i].iReg;    if( r>=iFrom && r<=iTo ) return 1;  }  return 0;}/*** Theres is a value in register iCurrent.  We ultimately want** the value to be in register iTarget.  It might be that** iCurrent and iTarget are the same register.**** We are going to modify the value, so we need to make sure it** is not a cached register.  If iCurrent is a cached register,** then try to move the value over to iTarget.  If iTarget is a** cached register, then clear the corresponding cache line.**** Return the register that the value ends up in.*/int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){  int i;  assert( pParse->pVdbe!=0 );  if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){    return iCurrent;  }  if( iCurrent!=iTarget ){    sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);  }  for(i=0; i<pParse->nColCache; i++){    if( pParse->aColCache[i].iReg==iTarget ){      pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];      pParse->iColCache = pParse->nColCache;    }  }  return iTarget;}/*** If the last instruction coded is an ephemeral copy of any of** the registers in the nReg registers beginning with iReg, then** convert the last instruction from OP_SCopy to OP_Copy.*/void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){  int addr;  VdbeOp *pOp;  Vdbe *v;  v = pParse->pVdbe;  addr = sqlite3VdbeCurrentAddr(v);  pOp = sqlite3VdbeGetOp(v, addr-1);  assert( pOp || pParse->db->mallocFailed );  if( pOp && pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){    pOp->opcode = OP_Copy;  }}/*** Generate code to store the value of the iAlias-th alias in register** target.  The first time this is called, pExpr is evaluated to compute** the value of the alias.  The value is stored in an auxiliary register** and the number of that register is returned.  On subsequent calls,** the register number is returned without generating any code.**** Note that in order for this to work, code must be generated in the** same order that it is executed.**** Aliases are numbered starting with 1.  So iAlias is in the range** of 1 to pParse->nAlias inclusive.  **** pParse->aAlias[iAlias-1] records the register number where the value** of the iAlias-th alias is stored.  If zero, that means that the** alias has not yet been computed.*/static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){  sqlite3 *db = pParse->db;  int iReg;  if( pParse->aAlias==0 ){    pParse->aAlias = sqlite3DbMallocZero(db,                                  sizeof(pParse->aAlias[0])*pParse->nAlias );    if( db->mallocFailed ) return 0;  }  assert( iAlias>0 && iAlias<=pParse->nAlias );  iReg = pParse->aAlias[iAlias-1];  if( iReg==0 ){    if( pParse->disableColCache ){      iReg = sqlite3ExprCodeTarget(pParse, pExpr, target);    }else{      iReg = ++pParse->nMem;      sqlite3ExprCode(pParse, pExpr, iReg);      pParse->aAlias[iAlias-1] = iReg;    }  }  return iReg;}/*** Generate code into the current Vdbe to evaluate the given** expression.  Attempt to store the results in register "target".** Return the register where results are stored.**** With this routine, there is no guarantee that results will** be stored in target.  The result might be stored in some other** register if it is convenient to do so.  The calling function** must check the return code and move the results to the desired** register.*/int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){  Vdbe *v = pParse->pVdbe;  /* The VM under construction */  int op;                   /* The opcode being coded */  int inReg = target;       /* Results stored in register inReg */  int regFree1 = 0;         /* If non-zero free this temporary register */  int regFree2 = 0;         /* If non-zero free this temporary register */  int r1, r2, r3, r4;       /* Various register numbers */  sqlite3 *db;  db = pParse->db;  assert( v!=0 || db->mallocFailed );  assert( target>0 && target<=pParse->nMem );  if( v==0 ) return 0;  if( pExpr==0 ){    op = TK_NULL;  }else{    op = pExpr->op;  }  switch( op ){    case TK_AGG_COLUMN: {      AggInfo *pAggInfo = pExpr->pAggInfo;      struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];      if( !pAggInfo->directMode ){        assert( pCol->iMem>0 );        inReg = pCol->iMem;        break;      }else if( pAggInfo->useSortingIdx ){        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,                              pCol->iSorterColumn, target);        break;      }      /* Otherwise, fall thru into the TK_COLUMN case */    }    case TK_COLUMN: {      if( pExpr->iTable<0 ){        /* This only happens when coding check constraints */        assert( pParse->ckBase>0 );        inReg = pExpr->iColumn + pParse->ckBase;      }else{        testcase( (pExpr->flags & EP_AnyAff)!=0 );        inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,                                 pExpr->iColumn, pExpr->iTable, target,                                 pExpr->flags & EP_AnyAff);      }      break;    }    case TK_INTEGER: {      codeInteger(v, pExpr, 0, target);      break;    }    case TK_FLOAT: {      codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target);      break;    }    case TK_STRING: {      sqlite3DequoteExpr(db, pExpr);      sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0,                        (char*)pExpr->token.z, pExpr->token.n);      break;    }    case TK_NULL: {      sqlite3VdbeAddOp2(v, OP_Null, 0, target);      break;    }#ifndef SQLITE_OMIT_BLOB_LITERAL    case TK_BLOB: {      int n;      const char *z;      char *zBlob;      assert( pExpr->token.n>=3 );      assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' );      assert( pExpr->token.z[1]=='\'' );      assert( pExpr->token.z[pExpr->token.n-1]=='\'' );      n = pExpr->token.n - 3;      z = (char*)pExpr->token.z + 2;      zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);      sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);      break;    }#endif    case TK_VARIABLE: {      sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iTable, target);      if( pExpr->token.n>1 ){        sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n);      }      break;    }    case TK_REGISTER: {      inReg = pExpr->iTable;      break;    }    case TK_AS: {      inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft, target);      break;    }#ifndef SQLITE_OMIT_CAST    case TK_CAST: {      /* Expressions of the form:   CAST(pLeft AS token) */      int aff, to_op;      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);      aff = sqlite3AffinityType(&pExpr->token);      to_op = aff - SQLITE_AFF_TEXT + OP_ToText;      assert( to_op==OP_ToText    || aff!=SQLITE_AFF_TEXT    );      assert( to_op==OP_ToBlob    || aff!=SQLITE_AFF_NONE    );      assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC );      assert( to_op==OP_ToInt     || aff!=SQLITE_AFF_INTEGER );      assert( to_op==OP_ToReal    || aff!=SQLITE_AFF_REAL    );      testcase( to_op==OP_ToText );      testcase( to_op==OP_ToBlob );      testcase( to_op==OP_ToNumeric );      testcase( to_op==OP_ToInt );      testcase( to_op==OP_ToReal );      if( inReg!=target ){        sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);        inReg = target;      }      sqlite3VdbeAddOp1(v, to_op, inReg);      testcase( usedAsColumnCache(pParse, inReg, inReg) );      sqlite3ExprCacheAffinityChange(pParse, inReg, 1);      break;    }#endif /* SQLITE_OMIT_CAST */    case TK_LT:    case TK_LE:    case TK_GT:    case TK_GE:    case TK_NE:    case TK_EQ: {      assert( TK_LT==OP_Lt );      assert( TK_LE==OP_Le );      assert( TK_GT==OP_Gt );      assert( TK_GE==OP_Ge );      assert( TK_EQ==OP_Eq );      assert( TK_NE==OP_Ne );      testcase( op==TK_LT );      testcase( op==TK_LE );      testcase( op==TK_GT );      testcase( op==TK_GE );      testcase( op==TK_EQ );      testcase( op==TK_NE );      codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,                                  pExpr->pRight, &r2, &regFree2);      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,                  r1, r2, inReg, SQLITE_STOREP2);      testcase( regFree1==0 );      testcase( regFree2==0 );      break;    }    case TK_AND:    case TK_OR:    case TK_PLUS:    case TK_STAR:    case TK_MINUS:    case TK_REM:    case TK_BITAND:    case TK_BITOR:    case TK_SLASH:    case TK_LSHIFT:    case TK_RSHIFT:     case TK_CONCAT: {      assert( TK_AND==OP_And );      assert( TK_OR==OP_Or );      assert( TK_PLUS==OP_Add );      assert( TK_MINUS==OP_Subtract );      assert( TK_REM==OP_Remainder );      assert( TK_BITAND==OP_BitAnd );      assert( TK_BITOR==OP_BitOr );      assert( TK_SLASH==OP_Divide );      assert( TK_LSHIFT==OP_ShiftLeft );      assert( TK_RSHIFT==OP_ShiftRight );      assert( TK_CONCAT==OP_Concat );      testcase( op==TK_AND );      testcase( op==TK_OR );      testcase( op==TK_PLUS );      testcase( op==TK_MINUS );      testcase( op==TK_REM );      testcase( op==TK_BITAND );      testcase( op==TK_BITOR );      testcase( op==TK_SLASH );      testcase( op==TK_LSHIFT );      testcase( op==TK_RSHIFT );      testcase( op==TK_CONCAT );      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);      sqlite3VdbeAddOp3(v, op, r2, r1, target);      testcase( regFree1==0 );      testcase( regFree2==0 );      break;    }    case TK_UMINUS: {      Expr *pLeft = pExpr->pLeft;      assert( pLeft );      if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){        if( pLeft->op==TK_FLOAT ){          codeReal(v, (char*)pLeft->token.z, pLeft->token.n, 1, target);        }else{          codeInteger(v, pLeft, 1, target);        }      }else{        regFree1 = r1 = sqlite3GetTempReg(pParse);        sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);        r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);        sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);        testcase( regFree2==0 );      }      inReg = target;      break;    }    case TK_BITNOT:    case TK_NOT: {      assert( TK_BITNOT==OP_BitNot );      assert( TK_NOT==OP_Not );      testcase( op==TK_BITNOT );      testcase( op==TK_NOT );      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);      testcase( inReg==target );      testcase( usedAsColumnCache(pParse, inReg, inReg) );      inReg = sqlite3ExprWritableRegister(pParse, inReg, target);      sqlite3VdbeAddOp1(v, op, inReg);      break;    }    case TK_ISNULL:    case TK_NOTNULL: {      int addr;      assert( TK_ISNULL==OP_IsNull );      assert( TK_NOTNULL==OP_NotNull );      testcase( op==TK_ISNULL );      testcase( op==TK_NOTNULL );      sqlite3VdbeAddOp2(v, OP_Integer, 1, target);      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);      testcase( regFree1==0 );      addr = sqlite3VdbeAddOp1(v, op, r1);      sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);      sqlite3VdbeJumpHere(v, addr);      break;    }    case TK_AGG_FUNCTION: {      AggInfo *pInfo = pExpr->pAggInfo;      if( pInfo==0 ){        sqlite3ErrorMsg(pParse, "misuse of aggregate: %T",            &pExpr->span);      }else{        inReg = pInfo->aFunc[pExpr->iAgg].iMem;      }      break;    }    case TK_CONST_FUNC:    case TK_FUNCTION: {      ExprList *pList = pExpr->pList;      int nExpr = pList ? pList->nExpr : 0;      FuncDef *pDef;      int nId;      const char *zId;      int constMask = 0;      int i;      u8 enc = ENC(db);      CollSeq *pColl = 0;      testcase( op==TK_CONST_FUNC );      testcase( op==TK_FUNCTION );      zId = (char*)pExpr->token.z;      nId = pExpr->token.n;      pDef = sqlite3FindFunction(db, zId, nId, nExpr, enc, 0);      assert( pDef!=0 );      if( pList ){        nExpr = pList->nExpr;        r1 = sqlite3GetTempRange(pParse, nExpr);        sqlite3ExprCodeExprList(pParse, pList, r1, 1);      }else{        nExpr = r1 = 0;      }#ifndef SQLITE_OMIT_VIRTUALTABLE      /* Possibly overload the function if the first argument is      ** a virtual table column.      **      ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the      ** second argument, not the first, as the argument to test to      ** see if it is a column in a virtual table.  This is done because      ** the left operand of infix functions (the operand we want to      ** control overloading) ends up as the second argument to the      ** function.  Th

⌨️ 快捷键说明

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