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

📄 rtree.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  }  rightbbox.iRowid = pRight->iNode;  leftbbox.iRowid = pLeft->iNode;  if( pNode->iNode==1 ){    rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1);    if( rc!=SQLITE_OK ){      goto splitnode_out;    }  }else{    RtreeNode *pParent = pLeft->pParent;    int iCell = nodeParentIndex(pRtree, pLeft);    nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);    AdjustTree(pRtree, pParent, &leftbbox);  }  if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){    goto splitnode_out;  }  for(i=0; i<NCELL(pRight); i++){    i64 iRowid = nodeGetRowid(pRtree, pRight, i);    rc = updateMapping(pRtree, iRowid, pRight, iHeight);    if( iRowid==pCell->iRowid ){      newCellIsRight = 1;    }    if( rc!=SQLITE_OK ){      goto splitnode_out;    }  }  if( pNode->iNode==1 ){    for(i=0; i<NCELL(pLeft); i++){      i64 iRowid = nodeGetRowid(pRtree, pLeft, i);      rc = updateMapping(pRtree, iRowid, pLeft, iHeight);      if( rc!=SQLITE_OK ){        goto splitnode_out;      }    }  }else if( newCellIsRight==0 ){    rc = updateMapping(pRtree, pCell->iRowid, pLeft, iHeight);  }  if( rc==SQLITE_OK ){    rc = nodeRelease(pRtree, pRight);    pRight = 0;  }  if( rc==SQLITE_OK ){    rc = nodeRelease(pRtree, pLeft);    pLeft = 0;  }splitnode_out:  nodeRelease(pRtree, pRight);  nodeRelease(pRtree, pLeft);  sqlite3_free(aCell);  return rc;}static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){  int rc = SQLITE_OK;  if( pLeaf->iNode!=1 && pLeaf->pParent==0 ){    sqlite3_bind_int64(pRtree->pReadParent, 1, pLeaf->iNode);    if( sqlite3_step(pRtree->pReadParent)==SQLITE_ROW ){      i64 iNode = sqlite3_column_int64(pRtree->pReadParent, 0);      rc = nodeAcquire(pRtree, iNode, 0, &pLeaf->pParent);    }else{      rc = SQLITE_ERROR;    }    sqlite3_reset(pRtree->pReadParent);    if( rc==SQLITE_OK ){      rc = fixLeafParent(pRtree, pLeaf->pParent);    }  }  return rc;}static int deleteCell(Rtree *, RtreeNode *, int, int);static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){  int rc;  RtreeNode *pParent;  int iCell;  assert( pNode->nRef==1 );  /* Remove the entry in the parent cell. */  iCell = nodeParentIndex(pRtree, pNode);  pParent = pNode->pParent;  pNode->pParent = 0;  if( SQLITE_OK!=(rc = deleteCell(pRtree, pParent, iCell, iHeight+1))    || SQLITE_OK!=(rc = nodeRelease(pRtree, pParent))  ){    return rc;  }  /* Remove the xxx_node entry. */  sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode);  sqlite3_step(pRtree->pDeleteNode);  if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){    return rc;  }  /* Remove the xxx_parent entry. */  sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode);  sqlite3_step(pRtree->pDeleteParent);  if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){    return rc;  }    /* Remove the node from the in-memory hash table and link it into  ** the Rtree.pDeleted list. Its contents will be re-inserted later on.  */  nodeHashDelete(pRtree, pNode);  pNode->iNode = iHeight;  pNode->pNext = pRtree->pDeleted;  pNode->nRef++;  pRtree->pDeleted = pNode;  return SQLITE_OK;}static void fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){  RtreeNode *pParent = pNode->pParent;  if( pParent ){    int ii;     int nCell = NCELL(pNode);    RtreeCell box;                            /* Bounding box for pNode */    nodeGetCell(pRtree, pNode, 0, &box);    for(ii=1; ii<nCell; ii++){      RtreeCell cell;      nodeGetCell(pRtree, pNode, ii, &cell);      cellUnion(pRtree, &box, &cell);    }    box.iRowid = pNode->iNode;    ii = nodeParentIndex(pRtree, pNode);    nodeOverwriteCell(pRtree, pParent, &box, ii);    fixBoundingBox(pRtree, pParent);  }}/*** Delete the cell at index iCell of node pNode. After removing the** cell, adjust the r-tree data structure if required.*/static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){  int rc;  if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){    return rc;  }  /* Remove the cell from the node. This call just moves bytes around  ** the in-memory node image, so it cannot fail.  */  nodeDeleteCell(pRtree, pNode, iCell);  /* If the node is not the tree root and now has less than the minimum  ** number of cells, remove it from the tree. Otherwise, update the  ** cell in the parent node so that it tightly contains the updated  ** node.  */  if( pNode->iNode!=1 ){    RtreeNode *pParent = pNode->pParent;    if( (pParent->iNode!=1 || NCELL(pParent)!=1)      && (NCELL(pNode)<RTREE_MINCELLS(pRtree))    ){      rc = removeNode(pRtree, pNode, iHeight);    }else{      fixBoundingBox(pRtree, pNode);    }  }  return rc;}static int Reinsert(  Rtree *pRtree,   RtreeNode *pNode,   RtreeCell *pCell,   int iHeight){  int *aOrder;  int *aSpare;  RtreeCell *aCell;  float *aDistance;  int nCell;  float aCenterCoord[RTREE_MAX_DIMENSIONS];  int iDim;  int ii;  int rc = SQLITE_OK;  memset(aCenterCoord, 0, sizeof(float)*RTREE_MAX_DIMENSIONS);  nCell = NCELL(pNode)+1;  /* Allocate the buffers used by this operation. The allocation is  ** relinquished before this function returns.  */  aCell = (RtreeCell *)sqlite3_malloc(nCell * (    sizeof(RtreeCell) +         /* aCell array */    sizeof(int)       +         /* aOrder array */    sizeof(int)       +         /* aSpare array */    sizeof(float)               /* aDistance array */  ));  if( !aCell ){    return SQLITE_NOMEM;  }  aOrder    = (int *)&aCell[nCell];  aSpare    = (int *)&aOrder[nCell];  aDistance = (float *)&aSpare[nCell];  for(ii=0; ii<nCell; ii++){    if( ii==(nCell-1) ){      memcpy(&aCell[ii], pCell, sizeof(RtreeCell));    }else{      nodeGetCell(pRtree, pNode, ii, &aCell[ii]);    }    aOrder[ii] = ii;    for(iDim=0; iDim<pRtree->nDim; iDim++){      aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);      aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);    }  }  for(iDim=0; iDim<pRtree->nDim; iDim++){    aCenterCoord[iDim] = aCenterCoord[iDim]/((float)nCell*2.0);  }  for(ii=0; ii<nCell; ii++){    aDistance[ii] = 0.0;    for(iDim=0; iDim<pRtree->nDim; iDim++){      float coord = DCOORD(aCell[ii].aCoord[iDim*2+1]) -           DCOORD(aCell[ii].aCoord[iDim*2]);      aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);    }  }  SortByDistance(aOrder, nCell, aDistance, aSpare);  nodeZero(pRtree, pNode);  for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){    RtreeCell *p = &aCell[aOrder[ii]];    nodeInsertCell(pRtree, pNode, p);    if( p->iRowid==pCell->iRowid ){      if( iHeight==0 ){        rc = rowidWrite(pRtree, p->iRowid, pNode->iNode);      }else{        rc = parentWrite(pRtree, p->iRowid, pNode->iNode);      }    }  }  if( rc==SQLITE_OK ){    fixBoundingBox(pRtree, pNode);  }  for(; rc==SQLITE_OK && ii<nCell; ii++){    /* Find a node to store this cell in. pNode->iNode currently contains    ** the height of the sub-tree headed by the cell.    */    RtreeNode *pInsert;    RtreeCell *p = &aCell[aOrder[ii]];    rc = ChooseLeaf(pRtree, p, iHeight, &pInsert);    if( rc==SQLITE_OK ){      int rc2;      rc = rtreeInsertCell(pRtree, pInsert, p, iHeight);      rc2 = nodeRelease(pRtree, pInsert);      if( rc==SQLITE_OK ){        rc = rc2;      }    }  }  sqlite3_free(aCell);  return rc;}/*** Insert cell pCell into node pNode. Node pNode is the head of a ** subtree iHeight high (leaf nodes have iHeight==0).*/static int rtreeInsertCell(  Rtree *pRtree,  RtreeNode *pNode,  RtreeCell *pCell,  int iHeight){  int rc = SQLITE_OK;  if( iHeight>0 ){    RtreeNode *pChild = nodeHashLookup(pRtree, pCell->iRowid);    if( pChild ){      nodeRelease(pRtree, pChild->pParent);      nodeReference(pNode);      pChild->pParent = pNode;    }  }  if( nodeInsertCell(pRtree, pNode, pCell) ){#if VARIANT_RSTARTREE_REINSERT    if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){      rc = SplitNode(pRtree, pNode, pCell, iHeight);    }else{      pRtree->iReinsertHeight = iHeight;      rc = Reinsert(pRtree, pNode, pCell, iHeight);    }#else    rc = SplitNode(pRtree, pNode, pCell, iHeight);#endif  }else{    AdjustTree(pRtree, pNode, pCell);    if( iHeight==0 ){      rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);    }else{      rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode);    }  }  return rc;}static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){  int ii;  int rc = SQLITE_OK;  int nCell = NCELL(pNode);  for(ii=0; rc==SQLITE_OK && ii<nCell; ii++){    RtreeNode *pInsert;    RtreeCell cell;    nodeGetCell(pRtree, pNode, ii, &cell);    /* Find a node to store this cell in. pNode->iNode currently contains    ** the height of the sub-tree headed by the cell.    */    rc = ChooseLeaf(pRtree, &cell, pNode->iNode, &pInsert);    if( rc==SQLITE_OK ){      int rc2;      rc = rtreeInsertCell(pRtree, pInsert, &cell, pNode->iNode);      rc2 = nodeRelease(pRtree, pInsert);      if( rc==SQLITE_OK ){        rc = rc2;      }    }  }  return rc;}/*** Select a currently unused rowid for a new r-tree record.*/static int newRowid(Rtree *pRtree, i64 *piRowid){  int rc;  sqlite3_bind_null(pRtree->pWriteRowid, 1);  sqlite3_bind_null(pRtree->pWriteRowid, 2);  sqlite3_step(pRtree->pWriteRowid);  rc = sqlite3_reset(pRtree->pWriteRowid);  *piRowid = sqlite3_last_insert_rowid(pRtree->db);  return rc;}#ifndef NDEBUGstatic int hashIsEmpty(Rtree *pRtree){  int ii;  for(ii=0; ii<HASHSIZE; ii++){    assert( !pRtree->aHash[ii] );  }  return 1;}#endif/*** The xUpdate method for rtree module virtual tables.*/int rtreeUpdate(  sqlite3_vtab *pVtab,   int nData,   sqlite3_value **azData,   sqlite_int64 *pRowid){  Rtree *pRtree = (Rtree *)pVtab;  int rc = SQLITE_OK;  rtreeReference(pRtree);  assert(nData>=1);  assert(hashIsEmpty(pRtree));  /* If azData[0] is not an SQL NULL value, it is the rowid of a  ** record to delete from the r-tree table. The following block does  ** just that.  */  if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){    i64 iDelete;                /* The rowid to delete */    RtreeNode *pLeaf;           /* Leaf node containing record iDelete */    int iCell;                  /* Index of iDelete cell in pLeaf */    RtreeNode *pRoot;    /* Obtain a reference to the root node to initialise Rtree.iDepth */    rc = nodeAcquire(pRtree, 1, 0, &pRoot);    /* Obtain a reference to the leaf node that contains the entry     ** about to be deleted.     */    if( rc==SQLITE_OK ){      iDelete = sqlite3_value_int64(azData[0]);      rc = findLeafNode(pRtree, iDelete, &pLeaf);    }    /* Delete the cell in question from the leaf node. */    if( rc==SQLITE_OK ){      int rc2;      iCell = nodeRowidIndex(pRtree, pLeaf, iDelete);      rc = deleteCell(pRtree, pLeaf, iCell, 0);      rc2 = nodeRelease(pRtree, pLeaf);      if( rc==SQLITE_OK ){        rc = rc2;      }    }    /* Delete the corresponding entry in the <rtree>_rowid table. */    if( rc==SQLITE_OK ){      sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete);      sqlite3_step(pRtree->pDeleteRowid);      rc = sqlite3_reset(pRtree->pDeleteRowid);    }    /* Check if the root node now has exactly one child. If so, remove    ** it, schedule the contents of the child for reinsertion and     ** reduce the tree height by one.    **    ** This is equivalent to copying the contents of the child into    ** the root node (the operation that Gutman's paper says to perform     ** in this scenario).    */    if( rc==SQLITE_OK && pRtree->iDepth>0 ){      if( rc==SQLITE_OK && NCELL(pRoot)==1 ){        RtreeNode *pChild;        i64 iChild = nodeGetRowid(pRtree, pRoot, 0);        rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);        if( rc==SQLITE_OK ){          rc = removeNode(pRtree, pChild, pRtree->iDepth-1);        }        if( rc==SQLITE_OK ){          pRtree->iDepth--;          writeInt16(pRoot->zData, pRtree->iDepth);          pRoot->isDirty = 1;        }      }    }    /* Re-insert the contents of any underfull nodes removed from the tree. */    for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){      if( rc==SQLITE_OK ){        rc = reinsertNodeContent(pRtree, pLeaf);      }      pRtree->pDeleted = pLeaf->pNext;      sqlite3_free(pLeaf);    }    /* Release the reference to the root node. */    if( rc==SQLITE_OK ){      rc = nodeRelease(pRtree, pRoot);    }else{      nodeRelease(pRtree, pRoot);    }  }  /* If the azData[] array contains more than one element, elements  ** (azData[2]..azData[argc-1]) contain a new record to insert into  ** the r-tree structure.  */  if( rc==SQLITE_OK && nData>1 ){    /* Insert a new record into the r-tree */    RtreeCell cell;    int ii;    RtreeNode *pLeaf;    /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */    assert( nData==(pRtree->nDim*2 + 3) );    if( pRtree->eCoordType==RTREE_COORD_REAL32 ){      for(ii=0; ii<(pRtree->nDim*2); ii+=2){        cell.aCoord[ii].f = (float)sqlite3_value_double(azData[ii+3]);        cell.aCoord[ii+1].f = (float)sqlite3_value_double(azData[ii+4]);        if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){          rc = SQLITE_CONSTRAINT;          goto constraint;        }      }    }else{      for(ii=0; ii<(pRtree->nDim*2); ii+=2){        cell.

⌨️ 快捷键说明

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