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

📄 rtree.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell;  nCell = NCELL(pNode);  assert(nCell<=nMaxCell);  if( nCell<nMaxCell ){    nodeOverwriteCell(pRtree, pNode, pCell, nCell);    writeInt16(&pNode->zData[2], nCell+1);    pNode->isDirty = 1;  }  return (nCell==nMaxCell);}/*** If the node is dirty, write it out to the database.*/static intnodeWrite(Rtree *pRtree, RtreeNode *pNode){  int rc = SQLITE_OK;  if( pNode->isDirty ){    sqlite3_stmt *p = pRtree->pWriteNode;    if( pNode->iNode ){      sqlite3_bind_int64(p, 1, pNode->iNode);    }else{      sqlite3_bind_null(p, 1);    }    sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC);    sqlite3_step(p);    pNode->isDirty = 0;    rc = sqlite3_reset(p);    if( pNode->iNode==0 && rc==SQLITE_OK ){      pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);      nodeHashInsert(pRtree, pNode);    }  }  return rc;}/*** Release a reference to a node. If the node is dirty and the reference** count drops to zero, the node data is written to the database.*/static intnodeRelease(Rtree *pRtree, RtreeNode *pNode){  int rc = SQLITE_OK;  if( pNode ){    assert( pNode->nRef>0 );    pNode->nRef--;    if( pNode->nRef==0 ){      if( pNode->iNode==1 ){        pRtree->iDepth = -1;      }      if( pNode->pParent ){        rc = nodeRelease(pRtree, pNode->pParent);      }      if( rc==SQLITE_OK ){        rc = nodeWrite(pRtree, pNode);      }      nodeHashDelete(pRtree, pNode);      sqlite3_free(pNode);    }  }  return rc;}/*** Return the 64-bit integer value associated with cell iCell of** node pNode. If pNode is a leaf node, this is a rowid. If it is** an internal node, then the 64-bit integer is a child page number.*/static i64 nodeGetRowid(  Rtree *pRtree,   RtreeNode *pNode,   int iCell){  assert( iCell<NCELL(pNode) );  return readInt64(&pNode->zData[4 + pRtree->nBytesPerCell*iCell]);}/*** Return coordinate iCoord from cell iCell in node pNode.*/static void nodeGetCoord(  Rtree *pRtree,   RtreeNode *pNode,   int iCell,  int iCoord,  RtreeCoord *pCoord           /* Space to write result to */){  readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);}/*** Deserialize cell iCell of node pNode. Populate the structure pointed** to by pCell with the results.*/static void nodeGetCell(  Rtree *pRtree,   RtreeNode *pNode,   int iCell,  RtreeCell *pCell){  int ii;  pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell);  for(ii=0; ii<pRtree->nDim*2; ii++){    nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]);  }}/* Forward declaration for the function that does the work of** the virtual table module xCreate() and xConnect() methods.*/static int rtreeInit(  sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int, int);/* ** Rtree virtual table module xCreate method.*/static int rtreeCreate(  sqlite3 *db,  void *pAux,  int argc, const char *const*argv,  sqlite3_vtab **ppVtab,  char **pzErr){  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1, (int)pAux);}/* ** Rtree virtual table module xConnect method.*/static int rtreeConnect(  sqlite3 *db,  void *pAux,  int argc, const char *const*argv,  sqlite3_vtab **ppVtab,  char **pzErr){  return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0, (int)pAux);}/*** Increment the r-tree reference count.*/static void rtreeReference(Rtree *pRtree){  pRtree->nBusy++;}/*** Decrement the r-tree reference count. When the reference count reaches** zero the structure is deleted.*/static void rtreeRelease(Rtree *pRtree){  pRtree->nBusy--;  if( pRtree->nBusy==0 ){    sqlite3_finalize(pRtree->pReadNode);    sqlite3_finalize(pRtree->pWriteNode);    sqlite3_finalize(pRtree->pDeleteNode);    sqlite3_finalize(pRtree->pReadRowid);    sqlite3_finalize(pRtree->pWriteRowid);    sqlite3_finalize(pRtree->pDeleteRowid);    sqlite3_finalize(pRtree->pReadParent);    sqlite3_finalize(pRtree->pWriteParent);    sqlite3_finalize(pRtree->pDeleteParent);    sqlite3_free(pRtree);  }}/* ** Rtree virtual table module xDisconnect method.*/static int rtreeDisconnect(sqlite3_vtab *pVtab){  rtreeRelease((Rtree *)pVtab);  return SQLITE_OK;}/* ** Rtree virtual table module xDestroy method.*/static int rtreeDestroy(sqlite3_vtab *pVtab){  Rtree *pRtree = (Rtree *)pVtab;  int rc;  char *zCreate = sqlite3_mprintf(    "DROP TABLE '%q'.'%q_node';"    "DROP TABLE '%q'.'%q_rowid';"    "DROP TABLE '%q'.'%q_parent';",    pRtree->zDb, pRtree->zName,     pRtree->zDb, pRtree->zName,    pRtree->zDb, pRtree->zName  );  if( !zCreate ){    rc = SQLITE_NOMEM;  }else{    rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);    sqlite3_free(zCreate);  }  if( rc==SQLITE_OK ){    rtreeRelease(pRtree);  }  return rc;}/* ** Rtree virtual table module xOpen method.*/static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){  int rc = SQLITE_NOMEM;  RtreeCursor *pCsr;  pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));  if( pCsr ){    memset(pCsr, 0, sizeof(RtreeCursor));    pCsr->base.pVtab = pVTab;    rc = SQLITE_OK;  }  *ppCursor = (sqlite3_vtab_cursor *)pCsr;  return rc;}/* ** Rtree virtual table module xClose method.*/static int rtreeClose(sqlite3_vtab_cursor *cur){  Rtree *pRtree = (Rtree *)(cur->pVtab);  int rc;  RtreeCursor *pCsr = (RtreeCursor *)cur;  sqlite3_free(pCsr->aConstraint);  rc = nodeRelease(pRtree, pCsr->pNode);  sqlite3_free(pCsr);  return rc;}/*** Rtree virtual table module xEof method.**** Return non-zero if the cursor does not currently point to a valid ** record (i.e if the scan has finished), or zero otherwise.*/static int rtreeEof(sqlite3_vtab_cursor *cur){  RtreeCursor *pCsr = (RtreeCursor *)cur;  return (pCsr->pNode==0);}/* ** Cursor pCursor currently points to a cell in a non-leaf page.** Return true if the sub-tree headed by the cell is filtered** (excluded) by the constraints in the pCursor->aConstraint[] ** array, or false otherwise.*/static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor){  RtreeCell cell;  int ii;  int bRes = 0;  nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);  for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){    RtreeConstraint *p = &pCursor->aConstraint[ii];    double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]);    double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]);    assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE         || p->op==RTREE_GT || p->op==RTREE_EQ    );    switch( p->op ){      case RTREE_LE: case RTREE_LT: bRes = p->rValue<cell_min; break;      case RTREE_GE: case RTREE_GT: bRes = p->rValue>cell_max; break;      case RTREE_EQ:         bRes = (p->rValue>cell_max || p->rValue<cell_min);        break;    }  }  return bRes;}/* ** Return true if the cell that cursor pCursor currently points to** would be filtered (excluded) by the constraints in the ** pCursor->aConstraint[] array, or false otherwise.**** This function assumes that the cell is part of a leaf node.*/static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor){  RtreeCell cell;  int ii;  nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell);  for(ii=0; ii<pCursor->nConstraint; ii++){    RtreeConstraint *p = &pCursor->aConstraint[ii];    double coord = DCOORD(cell.aCoord[p->iCoord]);    int res;    assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE         || p->op==RTREE_GT || p->op==RTREE_EQ    );    switch( p->op ){      case RTREE_LE: res = (coord<=p->rValue); break;      case RTREE_LT: res = (coord<p->rValue);  break;      case RTREE_GE: res = (coord>=p->rValue); break;      case RTREE_GT: res = (coord>p->rValue);  break;      case RTREE_EQ: res = (coord==p->rValue); break;    }    if( !res ) return 1;  }  return 0;}/*** Cursor pCursor currently points at a node that heads a sub-tree of** height iHeight (if iHeight==0, then the node is a leaf). Descend** to point to the left-most cell of the sub-tree that matches the ** configured constraints.*/static int descendToCell(  Rtree *pRtree,   RtreeCursor *pCursor,   int iHeight,  int *pEof                 /* OUT: Set to true if cannot descend */){  int isEof;  int rc;  int ii;  RtreeNode *pChild;  sqlite3_int64 iRowid;  RtreeNode *pSavedNode = pCursor->pNode;  int iSavedCell = pCursor->iCell;  assert( iHeight>=0 );  if( iHeight==0 ){    isEof = testRtreeEntry(pRtree, pCursor);  }else{    isEof = testRtreeCell(pRtree, pCursor);  }  if( isEof || iHeight==0 ){    *pEof = isEof;    return SQLITE_OK;  }  iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell);  rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild);  if( rc!=SQLITE_OK ){    return rc;  }  nodeRelease(pRtree, pCursor->pNode);  pCursor->pNode = pChild;  isEof = 1;  for(ii=0; isEof && ii<NCELL(pChild); ii++){    pCursor->iCell = ii;    rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof);    if( rc!=SQLITE_OK ){      return rc;    }  }  if( isEof ){    assert( pCursor->pNode==pChild );    nodeReference(pSavedNode);    nodeRelease(pRtree, pChild);    pCursor->pNode = pSavedNode;    pCursor->iCell = iSavedCell;  }  *pEof = isEof;  return SQLITE_OK;}/*** One of the cells in node pNode is guaranteed to have a 64-bit ** integer value equal to iRowid. Return the index of this cell.*/static int nodeRowidIndex(Rtree *pRtree, RtreeNode *pNode, i64 iRowid){  int ii;  for(ii=0; nodeGetRowid(pRtree, pNode, ii)!=iRowid; ii++){    assert( ii<(NCELL(pNode)-1) );  }  return ii;}/*** Return the index of the cell containing a pointer to node pNode** in its parent. If pNode is the root node, return -1.*/static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode){  RtreeNode *pParent = pNode->pParent;  if( pParent ){    return nodeRowidIndex(pRtree, pParent, pNode->iNode);  }  return -1;}/* ** Rtree virtual table module xNext method.*/static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){  Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab);  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;  int rc = SQLITE_OK;  if( pCsr->iStrategy==1 ){    /* This "scan" is a direct lookup by rowid. There is no next entry. */    nodeRelease(pRtree, pCsr->pNode);    pCsr->pNode = 0;  }  else if( pCsr->pNode ){    /* Move to the next entry that matches the configured constraints. */    int iHeight = 0;    while( pCsr->pNode ){      RtreeNode *pNode = pCsr->pNode;      int nCell = NCELL(pNode);      for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){        int isEof;        rc = descendToCell(pRtree, pCsr, iHeight, &isEof);        if( rc!=SQLITE_OK || !isEof ){          return rc;        }      }      pCsr->pNode = pNode->pParent;      pCsr->iCell = nodeParentIndex(pRtree, pNode);      nodeReference(pCsr->pNode);      nodeRelease(pRtree, pNode);      iHeight++;    }  }  return rc;}/* ** Rtree virtual table module xRowid method.*/static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){  Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;  RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;  assert(pCsr->pNode);  *pRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);  return SQLITE_OK;}/* ** Rtree virtual table module xColumn method.*/static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){  Rtree *pRtree = (Rtree *)cur->pVtab;  RtreeCursor *pCsr = (RtreeCursor *)cur;  if( i==0 ){    i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell);    sqlite3_result_int64(ctx, iRowid);  }else{    RtreeCoord c;    nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c);    if( pRtree->eCoordType==RTREE_COORD_REAL32 ){      sqlite3_result_double(ctx, c.f);    }else{      assert( pRtree->eCoordType==RTREE_COORD_INT32 );      sqlite3_result_int(ctx, c.i);    }  }  return SQLITE_OK;}/* ** Use nodeAcquire() to obtain the leaf node containing the record with ** rowid iRowid. If successful, set *ppLeaf to point to the node and** return SQLITE_OK. If there is no such record in the table, set** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf** to zero and return an SQLite error code.*/static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){  int rc;  *ppLeaf = 0;

⌨️ 快捷键说明

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