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

📄 fts1.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
  return pReader->iLastPos;}/* Skip past the end of a position list. */static void skipPositionList(DocListReader *pReader){  DocList *p = pReader->pDoclist;  if( p && p->iType>=DL_POSITIONS ){    int iColumn;    while( readPosition(pReader, &iColumn)!=-1 ){}  }}/* Skip over a docid, including its position list if the doclist has * positions. */static void skipDocument(DocListReader *pReader){  readDocid(pReader);  skipPositionList(pReader);}/* Skip past all docids which are less than [iDocid].  Returns 1 if a docid * matching [iDocid] was found.  */static int skipToDocid(DocListReader *pReader, sqlite_int64 iDocid){  sqlite_int64 d = 0;  while( !atEnd(pReader) && (d=peekDocid(pReader))<iDocid ){    skipDocument(pReader);  }  return !atEnd(pReader) && d==iDocid;}/* Return the first document in a document list.*/static sqlite_int64 firstDocid(DocList *d){  DocListReader r;  readerInit(&r, d);  return readDocid(&r);}#ifdef SQLITE_DEBUG/*** This routine is used for debugging purpose only.**** Write the content of a doclist to standard output.*/static void printDoclist(DocList *p){  DocListReader r;  const char *zSep = "";  readerInit(&r, p);  while( !atEnd(&r) ){    sqlite_int64 docid = readDocid(&r);    if( docid==0 ){      skipPositionList(&r);      continue;    }    printf("%s%lld", zSep, docid);    zSep =  ",";    if( p->iType>=DL_POSITIONS ){      int iPos, iCol;      const char *zDiv = "";      printf("(");      while( (iPos = readPosition(&r, &iCol))>=0 ){        printf("%s%d:%d", zDiv, iCol, iPos);        zDiv = ":";      }      printf(")");    }  }  printf("\n");  fflush(stdout);}#endif /* SQLITE_DEBUG *//* Trim the given doclist to contain only positions in column * [iRestrictColumn]. */static void docListRestrictColumn(DocList *in, int iRestrictColumn){  DocListReader r;  DocList out;  assert( in->iType>=DL_POSITIONS );  readerInit(&r, in);  docListInit(&out, DL_POSITIONS, NULL, 0);  while( !atEnd(&r) ){    sqlite_int64 iDocid = readDocid(&r);    int iPos, iColumn;    docListAddDocid(&out, iDocid);    while( (iPos = readPosition(&r, &iColumn)) != -1 ){      if( iColumn==iRestrictColumn ){        docListAddPos(&out, iColumn, iPos);      }    }  }  docListDestroy(in);  *in = out;}/* Trim the given doclist by discarding any docids without any remaining * positions. */static void docListDiscardEmpty(DocList *in) {  DocListReader r;  DocList out;  /* TODO: It would be nice to implement this operation in place; that   * could save a significant amount of memory in queries with long doclists. */  assert( in->iType>=DL_POSITIONS );  readerInit(&r, in);  docListInit(&out, DL_POSITIONS, NULL, 0);  while( !atEnd(&r) ){    sqlite_int64 iDocid = readDocid(&r);    int match = 0;    int iPos, iColumn;    while( (iPos = readPosition(&r, &iColumn)) != -1 ){      if( !match ){        docListAddDocid(&out, iDocid);        match = 1;      }      docListAddPos(&out, iColumn, iPos);    }  }  docListDestroy(in);  *in = out;}/* Helper function for docListUpdate() and docListAccumulate().** Splices a doclist element into the doclist represented by r,** leaving r pointing after the newly spliced element.*/static void docListSpliceElement(DocListReader *r, sqlite_int64 iDocid,                                 const char *pSource, int nSource){  DocList *d = r->pDoclist;  char *pTarget;  int nTarget, found;  found = skipToDocid(r, iDocid);  /* Describe slice in d to place pSource/nSource. */  pTarget = r->p;  if( found ){    skipDocument(r);    nTarget = r->p-pTarget;  }else{    nTarget = 0;  }  /* The sense of the following is that there are three possibilities.  ** If nTarget==nSource, we should not move any memory nor realloc.  ** If nTarget>nSource, trim target and realloc.  ** If nTarget<nSource, realloc then expand target.  */  if( nTarget>nSource ){    memmove(pTarget+nSource, pTarget+nTarget, docListEnd(d)-(pTarget+nTarget));  }  if( nTarget!=nSource ){    int iDoclist = pTarget-d->pData;    d->pData = realloc(d->pData, d->nData+nSource-nTarget);    pTarget = d->pData+iDoclist;  }  if( nTarget<nSource ){    memmove(pTarget+nSource, pTarget+nTarget, docListEnd(d)-(pTarget+nTarget));  }  memcpy(pTarget, pSource, nSource);  d->nData += nSource-nTarget;  r->p = pTarget+nSource;}/* Insert/update pUpdate into the doclist. */static void docListUpdate(DocList *d, DocList *pUpdate){  DocListReader reader;  assert( d!=NULL && pUpdate!=NULL );  assert( d->iType==pUpdate->iType);  readerInit(&reader, d);  docListSpliceElement(&reader, firstDocid(pUpdate),                       pUpdate->pData, pUpdate->nData);}/* Propagate elements from pUpdate to pAcc, overwriting elements with** matching docids.*/static void docListAccumulate(DocList *pAcc, DocList *pUpdate){  DocListReader accReader, updateReader;  /* Handle edge cases where one doclist is empty. */  assert( pAcc!=NULL );  if( pUpdate==NULL || pUpdate->nData==0 ) return;  if( pAcc->nData==0 ){    pAcc->pData = malloc(pUpdate->nData);    memcpy(pAcc->pData, pUpdate->pData, pUpdate->nData);    pAcc->nData = pUpdate->nData;    return;  }  readerInit(&accReader, pAcc);  readerInit(&updateReader, pUpdate);  while( !atEnd(&updateReader) ){    char *pSource = updateReader.p;    sqlite_int64 iDocid = readDocid(&updateReader);    skipPositionList(&updateReader);    docListSpliceElement(&accReader, iDocid, pSource, updateReader.p-pSource);  }}/*** Read the next docid off of pIn.  Return 0 if we reach the end.** TODO: This assumes that docids are never 0, but they may actually be 0 since* users can choose docids when inserting into a full-text table.  Fix this.*/static sqlite_int64 nextDocid(DocListReader *pIn){  skipPositionList(pIn);  return atEnd(pIn) ? 0 : readDocid(pIn);}/*** pLeft and pRight are two DocListReaders that are pointing to** positions lists of the same document: iDocid. **** If there are no instances in pLeft or pRight where the position** of pLeft is one less than the position of pRight, then this** routine adds nothing to pOut.**** If there are one or more instances where positions from pLeft** are exactly one less than positions from pRight, then add a new** document record to pOut.  If pOut wants to hold positions, then** include the positions from pRight that are one more than a** position in pLeft.  In other words:  pRight.iPos==pLeft.iPos+1.**** pLeft and pRight are left pointing at the next document record.*/static void mergePosList(  DocListReader *pLeft,    /* Left position list */  DocListReader *pRight,   /* Right position list */  sqlite_int64 iDocid,     /* The docid from pLeft and pRight */  DocList *pOut            /* Write the merged document record here */){  int iLeftCol, iLeftPos = readPosition(pLeft, &iLeftCol);  int iRightCol, iRightPos = readPosition(pRight, &iRightCol);  int match = 0;  /* Loop until we've reached the end of both position lists. */  while( iLeftPos!=-1 && iRightPos!=-1 ){    if( iLeftCol==iRightCol && iLeftPos+1==iRightPos ){      if( !match ){        docListAddDocid(pOut, iDocid);        match = 1;      }      if( pOut->iType>=DL_POSITIONS ){        docListAddPos(pOut, iRightCol, iRightPos);      }      iLeftPos = readPosition(pLeft, &iLeftCol);      iRightPos = readPosition(pRight, &iRightCol);    }else if( iRightCol<iLeftCol ||              (iRightCol==iLeftCol && iRightPos<iLeftPos+1) ){      iRightPos = readPosition(pRight, &iRightCol);    }else{      iLeftPos = readPosition(pLeft, &iLeftCol);    }  }  if( iLeftPos>=0 ) skipPositionList(pLeft);  if( iRightPos>=0 ) skipPositionList(pRight);}/* We have two doclists:  pLeft and pRight.** Write the phrase intersection of these two doclists into pOut.**** A phrase intersection means that two documents only match** if pLeft.iPos+1==pRight.iPos.**** The output pOut may or may not contain positions.  If pOut** does contain positions, they are the positions of pRight.*/static void docListPhraseMerge(  DocList *pLeft,    /* Doclist resulting from the words on the left */  DocList *pRight,   /* Doclist for the next word to the right */  DocList *pOut      /* Write the combined doclist here */){  DocListReader left, right;  sqlite_int64 docidLeft, docidRight;  readerInit(&left, pLeft);  readerInit(&right, pRight);  docidLeft = nextDocid(&left);  docidRight = nextDocid(&right);  while( docidLeft>0 && docidRight>0 ){    if( docidLeft<docidRight ){      docidLeft = nextDocid(&left);    }else if( docidRight<docidLeft ){      docidRight = nextDocid(&right);    }else{      mergePosList(&left, &right, docidLeft, pOut);      docidLeft = nextDocid(&left);      docidRight = nextDocid(&right);    }  }}/* We have two doclists:  pLeft and pRight.** Write the intersection of these two doclists into pOut.** Only docids are matched.  Position information is ignored.**** The output pOut never holds positions.*/static void docListAndMerge(  DocList *pLeft,    /* Doclist resulting from the words on the left */  DocList *pRight,   /* Doclist for the next word to the right */  DocList *pOut      /* Write the combined doclist here */){  DocListReader left, right;  sqlite_int64 docidLeft, docidRight;  assert( pOut->iType<DL_POSITIONS );  readerInit(&left, pLeft);  readerInit(&right, pRight);  docidLeft = nextDocid(&left);  docidRight = nextDocid(&right);  while( docidLeft>0 && docidRight>0 ){    if( docidLeft<docidRight ){      docidLeft = nextDocid(&left);    }else if( docidRight<docidLeft ){      docidRight = nextDocid(&right);    }else{      docListAddDocid(pOut, docidLeft);      docidLeft = nextDocid(&left);      docidRight = nextDocid(&right);    }  }}/* We have two doclists:  pLeft and pRight.** Write the union of these two doclists into pOut.** Only docids are matched.  Position information is ignored.**** The output pOut never holds positions.*/static void docListOrMerge(  DocList *pLeft,    /* Doclist resulting from the words on the left */  DocList *pRight,   /* Doclist for the next word to the right */  DocList *pOut      /* Write the combined doclist here */){  DocListReader left, right;  sqlite_int64 docidLeft, docidRight, priorLeft;  readerInit(&left, pLeft);  readerInit(&right, pRight);  docidLeft = nextDocid(&left);  docidRight = nextDocid(&right);  while( docidLeft>0 && docidRight>0 ){    if( docidLeft<=docidRight ){      docListAddDocid(pOut, docidLeft);    }else{      docListAddDocid(pOut, docidRight);    }    priorLeft = docidLeft;    if( docidLeft<=docidRight ){      docidLeft = nextDocid(&left);    }    if( docidRight>0 && docidRight<=priorLeft ){      docidRight = nextDocid(&right);    }  }  while( docidLeft>0 ){    docListAddDocid(pOut, docidLeft);    docidLeft = nextDocid(&left);  }  while( docidRight>0 ){    docListAddDocid(pOut, docidRight);    docidRight = nextDocid(&right);  }}/* We have two doclists:  pLeft and pRight.** Write into pOut all documents that occur in pLeft but not** in pRight.**** Only docids are matched.  Position information is ignored.**** The output pOut never holds positions.*/static void docListExceptMerge(  DocList *pLeft,    /* Doclist resulting from the words on the left */  DocList *pRight,   /* Doclist for the next word to the right */  DocList *pOut      /* Write the combined doclist here */){  DocListReader left, right;  sqlite_int64 docidLeft, docidRight, priorLeft;  readerInit(&left, pLeft);  readerInit(&right, pRight);  docidLeft = nextDocid(&left);  docidRight = nextDocid(&right);  while( docidLeft>0 && docidRight>0 ){    priorLeft = docidLeft;    if( docidLeft<docidRight ){      docListAddDocid(pOut, docidLeft);    }    if( docidLeft<=docidRight ){      docidLeft = nextDocid(&left);    }    if( docidRight>0 && docidRight<=priorLeft ){      docidRight = nextDocid(&right);    }  }  while( docidLeft>0 ){    docListAddDocid(pOut, docidLeft);    docidLeft = nextDocid(&left);  }}static char *string_dup_n(const char *s, int n){  char *str = malloc(n + 1);  memcpy(str, s, n);  str[n] = '\0';  return str;}/* Duplicate a string; the caller must free() the returned string. * (We don't use strdup() since it's not part of the standard C library and * may not be available everywhere.) */static char *string_dup(const char *s){  return string_dup_n(s, strlen(s));}

⌨️ 快捷键说明

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