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

📄 rtree.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid);  if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){    i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0);    rc = nodeAcquire(pRtree, iNode, 0, ppLeaf);    sqlite3_reset(pRtree->pReadRowid);  }else{    rc = sqlite3_reset(pRtree->pReadRowid);  }  return rc;}/* ** Rtree virtual table module xFilter method.*/static int rtreeFilter(  sqlite3_vtab_cursor *pVtabCursor,   int idxNum, const char *idxStr,  int argc, sqlite3_value **argv){  Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;  RtreeNode *pRoot = 0;  int ii;  int rc = SQLITE_OK;  rtreeReference(pRtree);  sqlite3_free(pCsr->aConstraint);  pCsr->aConstraint = 0;  pCsr->iStrategy = idxNum;  if( idxNum==1 ){    /* Special case - lookup by rowid. */    RtreeNode *pLeaf;        /* Leaf on which the required cell resides */    i64 iRowid = sqlite3_value_int64(argv[0]);    rc = findLeafNode(pRtree, iRowid, &pLeaf);    pCsr->pNode = pLeaf;     if( pLeaf && rc==SQLITE_OK ){      pCsr->iCell = nodeRowidIndex(pRtree, pLeaf, iRowid);    }  }else{    /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array     ** with the configured constraints.     */    if( argc>0 ){      pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);      pCsr->nConstraint = argc;      if( !pCsr->aConstraint ){        rc = SQLITE_NOMEM;      }else{        assert( (idxStr==0 && argc==0) || strlen(idxStr)==argc*2 );        for(ii=0; ii<argc; ii++){          RtreeConstraint *p = &pCsr->aConstraint[ii];          p->op = idxStr[ii*2];          p->iCoord = idxStr[ii*2+1]-'a';          p->rValue = sqlite3_value_double(argv[ii]);        }      }    }      if( rc==SQLITE_OK ){      pCsr->pNode = 0;      rc = nodeAcquire(pRtree, 1, 0, &pRoot);    }    if( rc==SQLITE_OK ){      int isEof = 1;      int nCell = NCELL(pRoot);      pCsr->pNode = pRoot;      for(pCsr->iCell=0; rc==SQLITE_OK && pCsr->iCell<nCell; pCsr->iCell++){        assert( pCsr->pNode==pRoot );        rc = descendToCell(pRtree, pCsr, pRtree->iDepth, &isEof);        if( !isEof ){          break;        }      }      if( rc==SQLITE_OK && isEof ){        assert( pCsr->pNode==pRoot );        nodeRelease(pRtree, pRoot);        pCsr->pNode = 0;      }      assert( rc!=SQLITE_OK || !pCsr->pNode || pCsr->iCell<NCELL(pCsr->pNode) );    }  }  rtreeRelease(pRtree);  return rc;}/*** Rtree virtual table module xBestIndex method. There are three** table scan strategies to choose from (in order from most to ** least desirable):****   idxNum     idxStr        Strategy**   ------------------------------------------------**     1        Unused        Direct lookup by rowid.**     2        See below     R-tree query.**     3        Unused        Full table scan.**   ------------------------------------------------**** If strategy 1 or 3 is used, then idxStr is not meaningful. If strategy** 2 is used, idxStr is formatted to contain 2 bytes for each ** constraint used. The first two bytes of idxStr correspond to ** the constraint in sqlite3_index_info.aConstraintUsage[] with** (argvIndex==1) etc.**** The first of each pair of bytes in idxStr identifies the constraint** operator as follows:****   Operator    Byte Value**   ----------------------**      =        0x41 ('A')**     <=        0x42 ('B')**      <        0x43 ('C')**     >=        0x44 ('D')**      >        0x45 ('E')**   ----------------------**** The second of each pair of bytes identifies the coordinate column** to which the constraint applies. The leftmost coordinate column** is 'a', the second from the left 'b' etc.*/static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){  int rc = SQLITE_OK;  int ii, cCol;  int iIdx = 0;  char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];  memset(zIdxStr, 0, sizeof(zIdxStr));  assert( pIdxInfo->idxStr==0 );  for(ii=0; ii<pIdxInfo->nConstraint; ii++){    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];    if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){      /* We have an equality constraint on the rowid. Use strategy 1. */      int jj;      for(jj=0; jj<ii; jj++){        pIdxInfo->aConstraintUsage[jj].argvIndex = 0;        pIdxInfo->aConstraintUsage[jj].omit = 0;      }      pIdxInfo->idxNum = 1;      pIdxInfo->aConstraintUsage[ii].argvIndex = 1;      pIdxInfo->aConstraintUsage[jj].omit = 1;      return SQLITE_OK;    }    if( p->usable && p->iColumn>0 ){      u8 op = 0;      switch( p->op ){        case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;        case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;        case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;        case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;        case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;      }      if( op ){        /* Make sure this particular constraint has not been used before.        ** If it has been used before, ignore it.        **        ** A <= or < can be used if there is a prior >= or >.        ** A >= or > can be used if there is a prior < or <=.        ** A <= or < is disqualified if there is a prior <=, <, or ==.        ** A >= or > is disqualified if there is a prior >=, >, or ==.        ** A == is disqualifed if there is any prior constraint.        */        int j, opmsk;        static const unsigned char compatible[] = { 0, 0, 1, 1, 2, 2 };        assert( compatible[RTREE_EQ & 7]==0 );        assert( compatible[RTREE_LT & 7]==1 );        assert( compatible[RTREE_LE & 7]==1 );        assert( compatible[RTREE_GT & 7]==2 );        assert( compatible[RTREE_GE & 7]==2 );        cCol = p->iColumn - 1 + 'a';        opmsk = compatible[op & 7];        for(j=0; j<iIdx; j+=2){          if( zIdxStr[j+1]==cCol && (compatible[zIdxStr[j] & 7] & opmsk)!=0 ){            op = 0;            break;          }        }      }      if( op ){        assert( iIdx<sizeof(zIdxStr)-1 );        zIdxStr[iIdx++] = op;        zIdxStr[iIdx++] = cCol;        pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);        pIdxInfo->aConstraintUsage[ii].omit = 1;      }    }  }  pIdxInfo->idxNum = 2;  pIdxInfo->needToFreeIdxStr = 1;  if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){    return SQLITE_NOMEM;  }  return rc;}/*** Return the N-dimensional volumn of the cell stored in *p.*/static float cellArea(Rtree *pRtree, RtreeCell *p){  float area = 1.0;  int ii;  for(ii=0; ii<(pRtree->nDim*2); ii+=2){    area = area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));  }  return area;}/*** Return the margin length of cell p. The margin length is the sum** of the objects size in each dimension.*/static float cellMargin(Rtree *pRtree, RtreeCell *p){  float margin = 0.0;  int ii;  for(ii=0; ii<(pRtree->nDim*2); ii+=2){    margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]));  }  return margin;}/*** Store the union of cells p1 and p2 in p1.*/static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){  int ii;  if( pRtree->eCoordType==RTREE_COORD_REAL32 ){    for(ii=0; ii<(pRtree->nDim*2); ii+=2){      p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f);      p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f);    }  }else{    for(ii=0; ii<(pRtree->nDim*2); ii+=2){      p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);      p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);    }  }}/*** Return the amount cell p would grow by if it were unioned with pCell.*/static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){  float area;  RtreeCell cell;  memcpy(&cell, p, sizeof(RtreeCell));  area = cellArea(pRtree, &cell);  cellUnion(pRtree, &cell, pCell);  return (cellArea(pRtree, &cell)-area);}#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLITstatic float cellOverlap(  Rtree *pRtree,   RtreeCell *p,   RtreeCell *aCell,   int nCell,   int iExclude){  int ii;  float overlap = 0.0;  for(ii=0; ii<nCell; ii++){    if( ii!=iExclude ){      int jj;      float o = 1.0;      for(jj=0; jj<(pRtree->nDim*2); jj+=2){        double x1;        double x2;        x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj]));        x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1]));        if( x2<x1 ){          o = 0.0;          break;        }else{          o = o * (x2-x1);        }      }      overlap += o;    }  }  return overlap;}#endif#if VARIANT_RSTARTREE_CHOOSESUBTREEstatic float cellOverlapEnlargement(  Rtree *pRtree,   RtreeCell *p,   RtreeCell *pInsert,   RtreeCell *aCell,   int nCell,   int iExclude){  float before;  float after;  before = cellOverlap(pRtree, p, aCell, nCell, iExclude);  cellUnion(pRtree, p, pInsert);  after = cellOverlap(pRtree, p, aCell, nCell, iExclude);  return after-before;}#endif/*** This function implements the ChooseLeaf algorithm from Gutman[84].** ChooseSubTree in r*tree terminology.*/static int ChooseLeaf(  Rtree *pRtree,               /* Rtree table */  RtreeCell *pCell,            /* Cell to insert into rtree */  int iHeight,                 /* Height of sub-tree rooted at pCell */  RtreeNode **ppLeaf           /* OUT: Selected leaf page */){  int rc;  int ii;  RtreeNode *pNode;  rc = nodeAcquire(pRtree, 1, 0, &pNode);  for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){    int iCell;    sqlite3_int64 iBest;    float fMinGrowth;    float fMinArea;    float fMinOverlap;    int nCell = NCELL(pNode);    RtreeCell cell;    RtreeNode *pChild;    RtreeCell *aCell = 0;#if VARIANT_RSTARTREE_CHOOSESUBTREE    if( ii==(pRtree->iDepth-1) ){      int jj;      aCell = sqlite3_malloc(sizeof(RtreeCell)*nCell);      if( !aCell ){        rc = SQLITE_NOMEM;        nodeRelease(pRtree, pNode);        pNode = 0;        continue;      }      for(jj=0; jj<nCell; jj++){        nodeGetCell(pRtree, pNode, jj, &aCell[jj]);      }    }#endif    /* Select the child node which will be enlarged the least if pCell    ** is inserted into it. Resolve ties by choosing the entry with    ** the smallest area.    */    for(iCell=0; iCell<nCell; iCell++){      float growth;      float area;      float overlap = 0.0;      nodeGetCell(pRtree, pNode, iCell, &cell);      growth = cellGrowth(pRtree, &cell, pCell);      area = cellArea(pRtree, &cell);#if VARIANT_RSTARTREE_CHOOSESUBTREE      if( ii==(pRtree->iDepth-1) ){        overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell);      }#endif      if( (iCell==0)        || (overlap<fMinOverlap)        || (overlap==fMinOverlap && growth<fMinGrowth)       || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea)      ){        fMinOverlap = overlap;        fMinGrowth = growth;        fMinArea = area;        iBest = cell.iRowid;      }    }    sqlite3_free(aCell);    rc = nodeAcquire(pRtree, iBest, pNode, &pChild);    nodeRelease(pRtree, pNode);    pNode = pChild;  }  *ppLeaf = pNode;  return rc;}/*** A cell with the same content as pCell has just been inserted into** the node pNode. This function updates the bounding box cells in** all ancestor elements.*/static void AdjustTree(  Rtree *pRtree,                    /* Rtree table */  RtreeNode *pNode,                 /* Adjust ancestry of this node. */  RtreeCell *pCell                  /* This cell was just inserted */){  RtreeNode *p = pNode;  while( p->pParent ){    RtreeCell cell;    RtreeNode *pParent = p->pParent;    int iCell = nodeParentIndex(pRtree, p);    nodeGetCell(pRtree, pParent, iCell, &cell);    if( cellGrowth(pRtree, &cell, pCell)>0.0 ){      cellUnion(pRtree, &cell, pCell);      nodeOverwriteCell(pRtree, pParent, &cell, iCell);    }     p = pParent;  }}/*** Write mapping (iRowid->iNode) to the <rtree>_rowid table.*/static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){  sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid);  sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode);  sqlite3_step(pRtree->pWriteRowid);  return sqlite3_reset(pRtree->pWriteRowid);}/*** Write mapping (iNode->iPar) to the <rtree>_parent table.*/static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){  sqlite3_bind_int64(pRtree->pWriteParent, 1, iNode);  sqlite3_bind_int64(pRtree->pWriteParent, 2, iPar);  sqlite3_step(pRtree->pWriteParent);  return sqlite3_reset(pRtree->pWriteParent);}static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int);#if VARIANT_GUTTMAN_LINEAR_SPLIT/*** Implementation of the linear variant of the PickNext() function from** Guttman[84].*/static RtreeCell *LinearPickNext(  Rtree *pRtree,  RtreeCell *aCell,   int nCell,   RtreeCell *pLeftBox,   RtreeCell *pRightBox,  int *aiUsed){  int ii;  for(ii=0; aiUsed[ii]; ii++);  aiUsed[ii] = 1;  return &aCell[ii];}/*** Implementation of the linear variant of the PickSeeds() function from** Guttman[84].*/static void LinearPickSeeds(  Rtree *pRtree,  RtreeCell *aCell,   int nCell,   int *piLeftSeed,   int *piRightSeed){  int i;  int iLeftSeed = 0;  int iRightSeed = 1;  float maxNormalInnerWidth = 0.0;  /* Pick two "seed" cells from the array of cells. The algorithm used  ** here is the LinearPickSeeds algorithm from Gutman[1984]. The   ** indices of the two seed cells in the array are stored in local  ** variables iLeftSeek and iRightSeed.  */  for(i=0; i<pRtree->nDim; i++){    float x1 = aCell[0].aCoord[i*2];    float x2 = aCell[0].aCoord[i*2+1];    float x3 = x1;

⌨️ 快捷键说明

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