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

📄 select.c

📁 1.编译色情sqlite源代码为dll;2.运用sqlite3数据库存储二进制数据到数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
  Vdbe *v = pParse->pVdbe;  int nExpr = pOrderBy->nExpr;  int regBase = sqlite3GetTempRange(pParse, nExpr+2);  int regRecord = sqlite3GetTempReg(pParse);  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);  sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1);  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);  sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);  sqlite3ReleaseTempReg(pParse, regRecord);  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);  if( pSelect->iLimit>=0 ){    int addr1, addr2;    int iLimit;    if( pSelect->pOffset ){      iLimit = pSelect->iOffset+1;    }else{      iLimit = pSelect->iLimit;    }    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);    sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);    addr2 = sqlite3VdbeAddOp0(v, OP_Goto);    sqlite3VdbeJumpHere(v, addr1);    sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);    sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);    sqlite3VdbeJumpHere(v, addr2);    pSelect->iLimit = -1;  }}/*** Add code to implement the OFFSET*/static void codeOffset(  Vdbe *v,          /* Generate code into this VM */  Select *p,        /* The SELECT statement being coded */  int iContinue     /* Jump here to skip the current record */){  if( p->iOffset>=0 && iContinue!=0 ){    int addr;    sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);    addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset);    sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);    VdbeComment((v, "skip OFFSET records"));    sqlite3VdbeJumpHere(v, addr);  }}/*** Add code that will check to make sure the N registers starting at iMem** form a distinct entry.  iTab is a sorting index that holds previously** seen combinations of the N values.  A new entry is made in iTab** if the current N values are new.**** A jump to addrRepeat is made and the N+1 values are popped from the** stack if the top N elements are not distinct.*/static void codeDistinct(  Parse *pParse,     /* Parsing and code generating context */  int iTab,          /* A sorting index used to test for distinctness */  int addrRepeat,    /* Jump to here if not distinct */  int N,             /* Number of elements */  int iMem           /* First element */){  Vdbe *v;  int r1;  v = pParse->pVdbe;  r1 = sqlite3GetTempReg(pParse);  sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);  sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1);  sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);  sqlite3ReleaseTempReg(pParse, r1);}/*** Generate an error message when a SELECT is used within a subexpression** (example:  "a IN (SELECT * FROM table)") but it has more than 1 result** column.  We do this in a subroutine because the error occurs in multiple** places.*/static int checkForMultiColumnSelectError(  Parse *pParse,       /* Parse context. */  SelectDest *pDest,   /* Destination of SELECT results */  int nExpr            /* Number of result columns returned by SELECT */){  int eDest = pDest->eDest;  if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){    sqlite3ErrorMsg(pParse, "only a single result allowed for "       "a SELECT that is part of an expression");    return 1;  }else{    return 0;  }}/*** This routine generates the code for the inside of the inner loop** of a SELECT.**** If srcTab and nColumn are both zero, then the pEList expressions** are evaluated in order to get the data for this row.  If nColumn>0** then data is pulled from srcTab and pEList is used only to get the** datatypes for each column.*/static void selectInnerLoop(  Parse *pParse,          /* The parser context */  Select *p,              /* The complete select statement being coded */  ExprList *pEList,       /* List of values being extracted */  int srcTab,             /* Pull data from this table */  int nColumn,            /* Number of columns in the source table */  ExprList *pOrderBy,     /* If not NULL, sort results using this key */  int distinct,           /* If >=0, make sure results are distinct */  SelectDest *pDest,      /* How to dispose of the results */  int iContinue,          /* Jump here to continue with next row */  int iBreak,             /* Jump here to break out of the inner loop */  char *aff               /* affinity string if eDest is SRT_Union */){  Vdbe *v = pParse->pVdbe;  int i;  int hasDistinct;        /* True if the DISTINCT keyword is present */  int regResult;              /* Start of memory holding result set */  int eDest = pDest->eDest;   /* How to dispose of results */  int iParm = pDest->iParm;   /* First argument to disposal method */  int nResultCol;             /* Number of result columns */  int nToFree;                /* Number of result columns to release */  if( v==0 ) return;  assert( pEList!=0 );  /* If there was a LIMIT clause on the SELECT statement, then do the check  ** to see if this row should be output.  */  hasDistinct = distinct>=0 && pEList->nExpr>0;  if( pOrderBy==0 && !hasDistinct ){    codeOffset(v, p, iContinue);  }  /* Pull the requested columns.  */  if( nColumn>0 ){    nResultCol = nColumn;  }else{    nResultCol = pEList->nExpr;  }  if( pDest->iMem>0 ){    regResult = pDest->iMem;    nToFree = 0;  }else{    pDest->iMem = regResult = sqlite3GetTempRange(pParse, nResultCol);    nToFree = nResultCol;  }  if( nColumn>0 ){    for(i=0; i<nColumn; i++){      sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);    }  }else if( eDest!=SRT_Exists ){    /* If the destination is an EXISTS(...) expression, the actual    ** values returned by the SELECT are not required.    */    for(i=0; i<nResultCol; i++){      sqlite3ExprCode(pParse, pEList->a[i].pExpr, regResult+i);    }  }  nColumn = nResultCol;  /* If the DISTINCT keyword was present on the SELECT statement  ** and this row has been seen before, then do not make this row  ** part of the result.  */  if( hasDistinct ){    assert( pEList!=0 );    assert( pEList->nExpr==nColumn );    codeDistinct(pParse, distinct, iContinue, nColumn, regResult);    if( pOrderBy==0 ){      codeOffset(v, p, iContinue);    }  }  if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){    return;  }  switch( eDest ){    /* In this mode, write each query result to the key of the temporary    ** table iParm.    */#ifndef SQLITE_OMIT_COMPOUND_SELECT    case SRT_Union: {      int r1;      r1 = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);      if( aff ){        sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);      }      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);      sqlite3ReleaseTempReg(pParse, r1);      break;    }    /* Construct a record from the query result, but instead of    ** saving that record, use it as a key to delete elements from    ** the temporary table iParm.    */    case SRT_Except: {      int r1;      r1 = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);      sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);      sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1);      sqlite3ReleaseTempReg(pParse, r1);      break;    }#endif    /* Store the result as data using a unique key.    */    case SRT_Table:    case SRT_EphemTab: {      int r1 = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);      if( pOrderBy ){        pushOntoSorter(pParse, pOrderBy, p, r1);      }else{        int r2 = sqlite3GetTempReg(pParse);        sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);        sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);        sqlite3VdbeChangeP5(v, OPFLAG_APPEND);        sqlite3ReleaseTempReg(pParse, r2);      }      sqlite3ReleaseTempReg(pParse, r1);      break;    }#ifndef SQLITE_OMIT_SUBQUERY    /* If we are creating a set for an "expr IN (SELECT ...)" construct,    ** then there should be a single item on the stack.  Write this    ** item into the set table with bogus data.    */    case SRT_Set: {      int addr2;      assert( nColumn==1 );      addr2 = sqlite3VdbeAddOp1(v, OP_IsNull, regResult);      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);      if( pOrderBy ){        /* At first glance you would think we could optimize out the        ** ORDER BY in this case since the order of entries in the set        ** does not matter.  But there might be a LIMIT clause, in which        ** case the order does matter */        pushOntoSorter(pParse, pOrderBy, p, regResult);      }else{        int r1 = sqlite3GetTempReg(pParse);        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);        sqlite3ReleaseTempReg(pParse, r1);      }      sqlite3VdbeJumpHere(v, addr2);      break;    }    /* If any row exist in the result set, record that fact and abort.    */    case SRT_Exists: {      sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);      /* The LIMIT clause will terminate the loop for us */      break;    }    /* If this is a scalar select that is part of an expression, then    ** store the results in the appropriate memory cell and break out    ** of the scan loop.    */    case SRT_Mem: {      assert( nColumn==1 );      if( pOrderBy ){        pushOntoSorter(pParse, pOrderBy, p, regResult);      }else{        sqlite3VdbeAddOp2(v, OP_Move, regResult, iParm);        /* The LIMIT clause will jump out of the loop for us */      }      break;    }#endif /* #ifndef SQLITE_OMIT_SUBQUERY */    /* Send the data to the callback function or to a subroutine.  In the    ** case of a subroutine, the subroutine itself is responsible for    ** popping the data from the stack.    */    case SRT_Subroutine:    case SRT_Callback: {      if( pOrderBy ){        int r1 = sqlite3GetTempReg(pParse);        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);        pushOntoSorter(pParse, pOrderBy, p, r1);        sqlite3ReleaseTempReg(pParse, r1);      }else if( eDest==SRT_Subroutine ){        nToFree = 0;  /* Preserve registers. Subroutine will need them. */        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);      }else{        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);      }      break;    }#if !defined(SQLITE_OMIT_TRIGGER)    /* Discard the results.  This is used for SELECT statements inside    ** the body of a TRIGGER.  The purpose of such selects is to call    ** user-defined functions that have side effects.  We do not care    ** about the actual results of the select.    */    default: {      assert( eDest==SRT_Discard );      break;    }#endif  }  /* Jump to the end of the loop if the LIMIT is reached.  */  if( p->iLimit>=0 && pOrderBy==0 ){    sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);    sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);  }  sqlite3ReleaseTempRange(pParse, regResult, nToFree);}/*** Given an expression list, generate a KeyInfo structure that records** the collating sequence for each expression in that expression list.**** If the ExprList is an ORDER BY or GROUP BY clause then the resulting** KeyInfo structure is appropriate for initializing a virtual index to** implement that clause.  If the ExprList is the result set of a SELECT** then the KeyInfo structure is appropriate for initializing a virtual** index to implement a DISTINCT test.**** Space to hold the KeyInfo structure is obtain from malloc.  The calling** function is responsible for seeing that this structure is eventually** freed.  Add the KeyInfo structure to the P4 field of an opcode using** P4_KEYINFO_HANDOFF is the usual way of dealing with this.*/static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){  sqlite3 *db = pParse->db;  int nExpr;  KeyInfo *pInfo;  struct ExprList_item *pItem;  int i;  nExpr = pList->nExpr;  pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );  if( pInfo ){    pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];    pInfo->nField = nExpr;    pInfo->enc = ENC(db);    for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){      CollSeq *pColl;      pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);      if( !pColl ){        pColl = db->pDfltColl;      }      pInfo->aColl[i] = pColl;      pInfo->aSortOrder[i] = pItem->sortOrder;    }  }  return pInfo;}/*** If the inner loop was generated using a non-null pOrderBy argument,** then the results were placed in a sorter.  After the loop is terminated** we need to run the sorter and output the results.  The following** routine generates the code needed to do that.*/static void generateSortTail(  Parse *pParse,    /* Parsing context */  Select *p,        /* The SELECT statement */  Vdbe *v,          /* Generate code into this VDBE */  int nColumn,      /* Number of columns of data */  SelectDest *pDest /* Write the sorted results here */){  int brk = sqlite3VdbeMakeLabel(v);  int cont = sqlite3VdbeMakeLabel(v);  int addr;  int iTab;  int pseudoTab = 0;  ExprList *pOrderBy = p->pOrderBy;  int eDest = pDest->eDest;  int iParm = pDest->iParm;  int regRow;  int regRowid;  iTab = pOrderBy->iECursor;  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){    pseudoTab = pParse->nTab++;    sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, 0);

⌨️ 快捷键说明

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