📄 fts2.c
字号:
DLWriter writer; int i, n; const char *pStart = 0; int nStart = 0; sqlite_int64 iFirstDocid = 0, iLastDocid = 0; assert( nReaders>0 ); if( nReaders==1 ){ dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders)); return; } assert( nReaders<=MERGE_COUNT ); n = 0; for(i=0; i<nReaders; i++){ assert( pReaders[i].iType==pReaders[0].iType ); readers[i].pReader = pReaders+i; readers[i].idx = i; n += dlrAllDataBytes(&pReaders[i]); } /* Conservatively size output to sum of inputs. Output should end ** up strictly smaller than input. */ dataBufferExpand(out, n); /* Get the readers into sorted order. */ while( i-->0 ){ orderedDLReaderReorder(readers+i, nReaders-i); } dlwInit(&writer, pReaders[0].iType, out); while( !dlrAtEnd(readers[0].pReader) ){ sqlite_int64 iDocid = dlrDocid(readers[0].pReader); /* If this is a continuation of the current buffer to copy, extend ** that buffer. memcpy() seems to be more efficient if it has a ** lots of data to copy. */ if( dlrDocData(readers[0].pReader)==pStart+nStart ){ nStart += dlrDocDataBytes(readers[0].pReader); }else{ if( pStart!=0 ){ dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); } pStart = dlrDocData(readers[0].pReader); nStart = dlrDocDataBytes(readers[0].pReader); iFirstDocid = iDocid; } iLastDocid = iDocid; dlrStep(readers[0].pReader); /* Drop all of the older elements with the same docid. */ for(i=1; i<nReaders && !dlrAtEnd(readers[i].pReader) && dlrDocid(readers[i].pReader)==iDocid; i++){ dlrStep(readers[i].pReader); } /* Get the readers back into order. */ while( i-->0 ){ orderedDLReaderReorder(readers+i, nReaders-i); } } /* Copy over any remaining elements. */ if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); dlwDestroy(&writer);}/* Helper function for posListUnion(). Compares the current position** between left and right, returning as standard C idiom of <0 if** left<right, >0 if left>right, and 0 if left==right. "End" always** compares greater.*/static int posListCmp(PLReader *pLeft, PLReader *pRight){ assert( pLeft->iType==pRight->iType ); if( pLeft->iType==DL_DOCIDS ) return 0; if( plrAtEnd(pLeft) ) return plrAtEnd(pRight) ? 0 : 1; if( plrAtEnd(pRight) ) return -1; if( plrColumn(pLeft)<plrColumn(pRight) ) return -1; if( plrColumn(pLeft)>plrColumn(pRight) ) return 1; if( plrPosition(pLeft)<plrPosition(pRight) ) return -1; if( plrPosition(pLeft)>plrPosition(pRight) ) return 1; if( pLeft->iType==DL_POSITIONS ) return 0; if( plrStartOffset(pLeft)<plrStartOffset(pRight) ) return -1; if( plrStartOffset(pLeft)>plrStartOffset(pRight) ) return 1; if( plrEndOffset(pLeft)<plrEndOffset(pRight) ) return -1; if( plrEndOffset(pLeft)>plrEndOffset(pRight) ) return 1; return 0;}/* Write the union of position lists in pLeft and pRight to pOut.** "Union" in this case meaning "All unique position tuples". Should** work with any doclist type, though both inputs and the output** should be the same type.*/static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ PLReader left, right; PLWriter writer; assert( dlrDocid(pLeft)==dlrDocid(pRight) ); assert( pLeft->iType==pRight->iType ); assert( pLeft->iType==pOut->iType ); plrInit(&left, pLeft); plrInit(&right, pRight); plwInit(&writer, pOut, dlrDocid(pLeft)); while( !plrAtEnd(&left) || !plrAtEnd(&right) ){ int c = posListCmp(&left, &right); if( c<0 ){ plwCopy(&writer, &left); plrStep(&left); }else if( c>0 ){ plwCopy(&writer, &right); plrStep(&right); }else{ plwCopy(&writer, &left); plrStep(&left); plrStep(&right); } } plwTerminate(&writer); plwDestroy(&writer); plrDestroy(&left); plrDestroy(&right);}/* Write the union of doclists in pLeft and pRight to pOut. For** docids in common between the inputs, the union of the position** lists is written. Inputs and outputs are always type DL_DEFAULT.*/static void docListUnion( const char *pLeft, int nLeft, const char *pRight, int nRight, DataBuffer *pOut /* Write the combined doclist here */){ DLReader left, right; DLWriter writer; if( nLeft==0 ){ dataBufferAppend(pOut, pRight, nRight); return; } if( nRight==0 ){ dataBufferAppend(pOut, pLeft, nLeft); return; } dlrInit(&left, DL_DEFAULT, pLeft, nLeft); dlrInit(&right, DL_DEFAULT, pRight, nRight); dlwInit(&writer, DL_DEFAULT, pOut); while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){ if( dlrAtEnd(&right) ){ dlwCopy(&writer, &left); dlrStep(&left); }else if( dlrAtEnd(&left) ){ dlwCopy(&writer, &right); dlrStep(&right); }else if( dlrDocid(&left)<dlrDocid(&right) ){ dlwCopy(&writer, &left); dlrStep(&left); }else if( dlrDocid(&left)>dlrDocid(&right) ){ dlwCopy(&writer, &right); dlrStep(&right); }else{ posListUnion(&left, &right, &writer); dlrStep(&left); dlrStep(&right); } } dlrDestroy(&left); dlrDestroy(&right); dlwDestroy(&writer);}/* pLeft and pRight are DLReaders positioned to the same docid.**** 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.*/static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ PLReader left, right; PLWriter writer; int match = 0; assert( dlrDocid(pLeft)==dlrDocid(pRight) ); assert( pOut->iType!=DL_POSITIONS_OFFSETS ); plrInit(&left, pLeft); plrInit(&right, pRight); while( !plrAtEnd(&left) && !plrAtEnd(&right) ){ if( plrColumn(&left)<plrColumn(&right) ){ plrStep(&left); }else if( plrColumn(&left)>plrColumn(&right) ){ plrStep(&right); }else if( plrPosition(&left)+1<plrPosition(&right) ){ plrStep(&left); }else if( plrPosition(&left)+1>plrPosition(&right) ){ plrStep(&right); }else{ if( !match ){ plwInit(&writer, pOut, dlrDocid(pLeft)); match = 1; } plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0); plrStep(&left); plrStep(&right); } } if( match ){ plwTerminate(&writer); plwDestroy(&writer); } plrDestroy(&left); plrDestroy(&right);}/* We have two doclists with positions: 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.**** iType controls the type of data written to pOut. If iType is** DL_POSITIONS, the positions are those from pRight.*/static void docListPhraseMerge( const char *pLeft, int nLeft, const char *pRight, int nRight, DocListType iType, DataBuffer *pOut /* Write the combined doclist here */){ DLReader left, right; DLWriter writer; if( nLeft==0 || nRight==0 ) return; assert( iType!=DL_POSITIONS_OFFSETS ); dlrInit(&left, DL_POSITIONS, pLeft, nLeft); dlrInit(&right, DL_POSITIONS, pRight, nRight); dlwInit(&writer, iType, pOut); while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){ if( dlrDocid(&left)<dlrDocid(&right) ){ dlrStep(&left); }else if( dlrDocid(&right)<dlrDocid(&left) ){ dlrStep(&right); }else{ posListPhraseMerge(&left, &right, &writer); dlrStep(&left); dlrStep(&right); } } dlrDestroy(&left); dlrDestroy(&right); dlwDestroy(&writer);}/* We have two DL_DOCIDS doclists: pLeft and pRight.** Write the intersection of these two doclists into pOut as a** DL_DOCIDS doclist.*/static void docListAndMerge( const char *pLeft, int nLeft, const char *pRight, int nRight, DataBuffer *pOut /* Write the combined doclist here */){ DLReader left, right; DLWriter writer; if( nLeft==0 || nRight==0 ) return; dlrInit(&left, DL_DOCIDS, pLeft, nLeft); dlrInit(&right, DL_DOCIDS, pRight, nRight); dlwInit(&writer, DL_DOCIDS, pOut); while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){ if( dlrDocid(&left)<dlrDocid(&right) ){ dlrStep(&left); }else if( dlrDocid(&right)<dlrDocid(&left) ){ dlrStep(&right); }else{ dlwAdd(&writer, dlrDocid(&left)); dlrStep(&left); dlrStep(&right); } } dlrDestroy(&left); dlrDestroy(&right); dlwDestroy(&writer);}/* We have two DL_DOCIDS doclists: pLeft and pRight.** Write the union of these two doclists into pOut as a** DL_DOCIDS doclist.*/static void docListOrMerge( const char *pLeft, int nLeft, const char *pRight, int nRight, DataBuffer *pOut /* Write the combined doclist here */){ DLReader left, right; DLWriter writer; if( nLeft==0 ){ dataBufferAppend(pOut, pRight, nRight); return; } if( nRight==0 ){ dataBufferAppend(pOut, pLeft, nLeft); return; } dlrInit(&left, DL_DOCIDS, pLeft, nLeft); dlrInit(&right, DL_DOCIDS, pRight, nRight); dlwInit(&writer, DL_DOCIDS, pOut); while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){ if( dlrAtEnd(&right) ){ dlwAdd(&writer, dlrDocid(&left)); dlrStep(&left); }else if( dlrAtEnd(&left) ){ dlwAdd(&writer, dlrDocid(&right)); dlrStep(&right); }else if( dlrDocid(&left)<dlrDocid(&right) ){ dlwAdd(&writer, dlrDocid(&left)); dlrStep(&left); }else if( dlrDocid(&right)<dlrDocid(&left) ){ dlwAdd(&writer, dlrDocid(&right)); dlrStep(&right); }else{ dlwAdd(&writer, dlrDocid(&left)); dlrStep(&left); dlrStep(&right); } } dlrDestroy(&left); dlrDestroy(&right); dlwDestroy(&writer);}/* We have two DL_DOCIDS doclists: pLeft and pRight.** Write into pOut as DL_DOCIDS doclist containing all documents that** occur in pLeft but not in pRight.*/static void docListExceptMerge( const char *pLeft, int nLeft, const char *pRight, int nRight, DataBuffer *pOut /* Write the combined doclist here */){ DLReader left, right; DLWriter writer; if( nLeft==0 ) return; if( nRight==0 ){ dataBufferAppend(pOut, pLeft, nLeft); return; } dlrInit(&left, DL_DOCIDS, pLeft, nLeft); dlrInit(&right, DL_DOCIDS, pRight, nRight); dlwInit(&writer, DL_DOCIDS, pOut); while( !dlrAtEnd(&left) ){ while( !dlrAtEnd(&right) && dlrDocid(&right)<dlrDocid(&left) ){ dlrStep(&right); } if( dlrAtEnd(&right) || dlrDocid(&left)<dlrDocid(&right) ){ dlwAdd(&writer, dlrDocid(&left)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -