/ Hex Artifact Content
Login

Artifact daa57fb45216491814520bbb587e97bf81ced458:


0000: 2f 2a 0a 2a 2a 20 32 30 31 34 20 4d 61 79 20 33  /*.** 2014 May 3
0010: 31 0a 2a 2a 0a 2a 2a 20 54 68 65 20 61 75 74 68  1.**.** The auth
0020: 6f 72 20 64 69 73 63 6c 61 69 6d 73 20 63 6f 70  or disclaims cop
0030: 79 72 69 67 68 74 20 74 6f 20 74 68 69 73 20 73  yright to this s
0040: 6f 75 72 63 65 20 63 6f 64 65 2e 20 20 49 6e 20  ource code.  In 
0050: 70 6c 61 63 65 20 6f 66 0a 2a 2a 20 61 20 6c 65  place of.** a le
0060: 67 61 6c 20 6e 6f 74 69 63 65 2c 20 68 65 72 65  gal notice, here
0070: 20 69 73 20 61 20 62 6c 65 73 73 69 6e 67 3a 0a   is a blessing:.
0080: 2a 2a 0a 2a 2a 20 20 20 20 4d 61 79 20 79 6f 75  **.**    May you
0090: 20 64 6f 20 67 6f 6f 64 20 61 6e 64 20 6e 6f 74   do good and not
00a0: 20 65 76 69 6c 2e 0a 2a 2a 20 20 20 20 4d 61 79   evil..**    May
00b0: 20 79 6f 75 20 66 69 6e 64 20 66 6f 72 67 69 76   you find forgiv
00c0: 65 6e 65 73 73 20 66 6f 72 20 79 6f 75 72 73 65  eness for yourse
00d0: 6c 66 20 61 6e 64 20 66 6f 72 67 69 76 65 20 6f  lf and forgive o
00e0: 74 68 65 72 73 2e 0a 2a 2a 20 20 20 20 4d 61 79  thers..**    May
00f0: 20 79 6f 75 20 73 68 61 72 65 20 66 72 65 65 6c   you share freel
0100: 79 2c 20 6e 65 76 65 72 20 74 61 6b 69 6e 67 20  y, never taking 
0110: 6d 6f 72 65 20 74 68 61 6e 20 79 6f 75 20 67 69  more than you gi
0120: 76 65 2e 0a 2a 2a 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ve..**.*********
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0170: 2a 2a 2a 2a 2a 0a 2a 2f 0a 0a 0a 23 69 6e 63 6c  *****.*/...#incl
0180: 75 64 65 20 22 66 74 73 35 49 6e 74 2e 68 22 0a  ude "fts5Int.h".
0190: 23 69 6e 63 6c 75 64 65 20 3c 6d 61 74 68 2e 68  #include <math.h
01a0: 3e 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  >               
01b0: 20 20 2f 2a 20 61 6d 61 6c 67 61 6d 61 74 6f 72    /* amalgamator
01c0: 3a 20 6b 65 65 70 20 2a 2f 0a 0a 2f 2a 0a 2a 2a  : keep */../*.**
01d0: 20 4f 62 6a 65 63 74 20 75 73 65 64 20 74 6f 20   Object used to 
01e0: 69 74 65 72 61 74 65 20 74 68 72 6f 75 67 68 20  iterate through 
01f0: 61 6c 6c 20 22 63 6f 61 6c 65 73 63 65 64 20 70  all "coalesced p
0200: 68 72 61 73 65 20 69 6e 73 74 61 6e 63 65 73 22  hrase instances"
0210: 20 69 6e 20 0a 2a 2a 20 61 20 73 69 6e 67 6c 65   in .** a single
0220: 20 63 6f 6c 75 6d 6e 20 6f 66 20 74 68 65 20 63   column of the c
0230: 75 72 72 65 6e 74 20 72 6f 77 2e 20 49 66 20 74  urrent row. If t
0240: 68 65 20 70 68 72 61 73 65 20 69 6e 73 74 61 6e  he phrase instan
0250: 63 65 73 20 69 6e 20 74 68 65 0a 2a 2a 20 63 6f  ces in the.** co
0260: 6c 75 6d 6e 20 62 65 69 6e 67 20 63 6f 6e 73 69  lumn being consi
0270: 64 65 72 65 64 20 64 6f 20 6e 6f 74 20 6f 76 65  dered do not ove
0280: 72 6c 61 70 2c 20 74 68 69 73 20 6f 62 6a 65 63  rlap, this objec
0290: 74 20 73 69 6d 70 6c 79 20 69 74 65 72 61 74 65  t simply iterate
02a0: 73 0a 2a 2a 20 74 68 72 6f 75 67 68 20 74 68 65  s.** through the
02b0: 6d 2e 20 4f 72 2c 20 69 66 20 74 68 65 79 20 64  m. Or, if they d
02c0: 6f 20 6f 76 65 72 6c 61 70 20 28 73 68 61 72 65  o overlap (share
02d0: 20 6f 6e 65 20 6f 72 20 6d 6f 72 65 20 74 6f 6b   one or more tok
02e0: 65 6e 73 20 69 6e 0a 2a 2a 20 63 6f 6d 6d 6f 6e  ens in.** common
02f0: 29 2c 20 65 61 63 68 20 73 65 74 20 6f 66 20 6f  ), each set of o
0300: 76 65 72 6c 61 70 70 69 6e 67 20 69 6e 73 74 61  verlapping insta
0310: 6e 63 65 73 20 69 73 20 74 72 65 61 74 65 64 20  nces is treated 
0320: 61 73 20 61 20 73 69 6e 67 6c 65 0a 2a 2a 20 6d  as a single.** m
0330: 61 74 63 68 2e 20 53 65 65 20 64 6f 63 75 6d 65  atch. See docume
0340: 6e 74 61 74 69 6f 6e 20 66 6f 72 20 74 68 65 20  ntation for the 
0350: 68 69 67 68 6c 69 67 68 74 28 29 20 61 75 78 69  highlight() auxi
0360: 6c 69 61 72 79 20 66 75 6e 63 74 69 6f 6e 20 66  liary function f
0370: 6f 72 0a 2a 2a 20 64 65 74 61 69 6c 73 2e 0a 2a  or.** details..*
0380: 2a 0a 2a 2a 20 55 73 61 67 65 20 69 73 3a 0a 2a  *.** Usage is:.*
0390: 2a 0a 2a 2a 20 20 20 66 6f 72 28 72 63 20 3d 20  *.**   for(rc = 
03a0: 66 74 73 35 43 49 6e 73 74 49 74 65 72 4e 65 78  fts5CInstIterNex
03b0: 74 28 70 41 70 69 2c 20 70 46 74 73 2c 20 69 43  t(pApi, pFts, iC
03c0: 6f 6c 2c 20 26 69 74 65 72 29 3b 0a 2a 2a 20 20  ol, &iter);.**  
03d0: 20 20 20 20 28 72 63 3d 3d 53 51 4c 49 54 45 5f      (rc==SQLITE_
03e0: 4f 4b 20 26 26 20 30 3d 3d 66 74 73 35 43 49 6e  OK && 0==fts5CIn
03f0: 73 74 49 74 65 72 45 6f 66 28 26 69 74 65 72 29  stIterEof(&iter)
0400: 3b 0a 2a 2a 20 20 20 20 20 20 72 63 20 3d 20 66  ;.**      rc = f
0410: 74 73 35 43 49 6e 73 74 49 74 65 72 4e 65 78 74  ts5CInstIterNext
0420: 28 26 69 74 65 72 29 0a 2a 2a 20 20 20 29 7b 0a  (&iter).**   ){.
0430: 2a 2a 20 20 20 20 20 70 72 69 6e 74 66 28 22 69  **     printf("i
0440: 6e 73 74 61 6e 63 65 20 73 74 61 72 74 73 20 61  nstance starts a
0450: 74 20 25 64 2c 20 65 6e 64 73 20 61 74 20 25 64  t %d, ends at %d
0460: 5c 6e 22 2c 20 69 74 65 72 2e 69 53 74 61 72 74  \n", iter.iStart
0470: 2c 20 69 74 65 72 2e 69 45 6e 64 29 3b 0a 2a 2a  , iter.iEnd);.**
0480: 20 20 20 7d 0a 2a 2a 0a 2a 2f 0a 74 79 70 65 64     }.**.*/.typed
0490: 65 66 20 73 74 72 75 63 74 20 43 49 6e 73 74 49  ef struct CInstI
04a0: 74 65 72 20 43 49 6e 73 74 49 74 65 72 3b 0a 73  ter CInstIter;.s
04b0: 74 72 75 63 74 20 43 49 6e 73 74 49 74 65 72 20  truct CInstIter 
04c0: 7b 0a 20 20 63 6f 6e 73 74 20 46 74 73 35 45 78  {.  const Fts5Ex
04d0: 74 65 6e 73 69 6f 6e 41 70 69 20 2a 70 41 70 69  tensionApi *pApi
04e0: 3b 20 20 20 2f 2a 20 41 50 49 20 6f 66 66 65 72  ;   /* API offer
04f0: 65 64 20 62 79 20 63 75 72 72 65 6e 74 20 46 54  ed by current FT
0500: 53 20 76 65 72 73 69 6f 6e 20 2a 2f 0a 20 20 46  S version */.  F
0510: 74 73 35 43 6f 6e 74 65 78 74 20 2a 70 46 74 73  ts5Context *pFts
0520: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f  ;              /
0530: 2a 20 46 69 72 73 74 20 61 72 67 20 74 6f 20 70  * First arg to p
0540: 61 73 73 20 74 6f 20 70 41 70 69 20 66 75 6e 63  ass to pApi func
0550: 74 69 6f 6e 73 20 2a 2f 0a 20 20 69 6e 74 20 69  tions */.  int i
0560: 43 6f 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20  Col;            
0570: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f             /* Co
0580: 6c 75 6d 6e 20 74 6f 20 73 65 61 72 63 68 20 2a  lumn to search *
0590: 2f 0a 20 20 69 6e 74 20 69 49 6e 73 74 3b 20 20  /.  int iInst;  
05a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
05b0: 20 20 20 20 2f 2a 20 4e 65 78 74 20 70 68 72 61      /* Next phra
05c0: 73 65 20 69 6e 73 74 61 6e 63 65 20 69 6e 64 65  se instance inde
05d0: 78 20 2a 2f 0a 20 20 69 6e 74 20 6e 49 6e 73 74  x */.  int nInst
05e0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
05f0: 20 20 20 20 20 20 20 2f 2a 20 54 6f 74 61 6c 20         /* Total 
0600: 6e 75 6d 62 65 72 20 6f 66 20 70 68 72 61 73 65  number of phrase
0610: 20 69 6e 73 74 61 6e 63 65 73 20 2a 2f 0a 0a 20   instances */.. 
0620: 20 2f 2a 20 4f 75 74 70 75 74 20 76 61 72 69 61   /* Output varia
0630: 62 6c 65 73 20 2a 2f 0a 20 20 69 6e 74 20 69 53  bles */.  int iS
0640: 74 61 72 74 3b 20 20 20 20 20 20 20 20 20 20 20  tart;           
0650: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 69 72            /* Fir
0660: 73 74 20 74 6f 6b 65 6e 20 69 6e 20 63 6f 61 6c  st token in coal
0670: 65 73 63 65 64 20 70 68 72 61 73 65 20 69 6e 73  esced phrase ins
0680: 74 61 6e 63 65 20 2a 2f 0a 20 20 69 6e 74 20 69  tance */.  int i
0690: 45 6e 64 3b 20 20 20 20 20 20 20 20 20 20 20 20  End;            
06a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 61             /* La
06b0: 73 74 20 74 6f 6b 65 6e 20 69 6e 20 63 6f 61 6c  st token in coal
06c0: 65 73 63 65 64 20 70 68 72 61 73 65 20 69 6e 73  esced phrase ins
06d0: 74 61 6e 63 65 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a  tance */.};../*.
06e0: 2a 2a 20 41 64 76 61 6e 63 65 20 74 68 65 20 69  ** Advance the i
06f0: 74 65 72 61 74 6f 72 20 74 6f 20 74 68 65 20 6e  terator to the n
0700: 65 78 74 20 63 6f 61 6c 65 73 63 65 64 20 70 68  ext coalesced ph
0710: 72 61 73 65 20 69 6e 73 74 61 6e 63 65 2e 20 52  rase instance. R
0720: 65 74 75 72 6e 0a 2a 2a 20 61 6e 20 53 51 4c 69  eturn.** an SQLi
0730: 74 65 20 65 72 72 6f 72 20 63 6f 64 65 20 69 66  te error code if
0740: 20 61 6e 20 65 72 72 6f 72 20 6f 63 63 75 72 73   an error occurs
0750: 2c 20 6f 72 20 53 51 4c 49 54 45 5f 4f 4b 20 6f  , or SQLITE_OK o
0760: 74 68 65 72 77 69 73 65 2e 0a 2a 2f 0a 73 74 61  therwise..*/.sta
0770: 74 69 63 20 69 6e 74 20 66 74 73 35 43 49 6e 73  tic int fts5CIns
0780: 74 49 74 65 72 4e 65 78 74 28 43 49 6e 73 74 49  tIterNext(CInstI
0790: 74 65 72 20 2a 70 49 74 65 72 29 7b 0a 20 20 69  ter *pIter){.  i
07a0: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f  nt rc = SQLITE_O
07b0: 4b 3b 0a 20 20 70 49 74 65 72 2d 3e 69 53 74 61  K;.  pIter->iSta
07c0: 72 74 20 3d 20 2d 31 3b 0a 20 20 70 49 74 65 72  rt = -1;.  pIter
07d0: 2d 3e 69 45 6e 64 20 3d 20 2d 31 3b 0a 0a 20 20  ->iEnd = -1;..  
07e0: 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54  while( rc==SQLIT
07f0: 45 5f 4f 4b 20 26 26 20 70 49 74 65 72 2d 3e 69  E_OK && pIter->i
0800: 49 6e 73 74 3c 70 49 74 65 72 2d 3e 6e 49 6e 73  Inst<pIter->nIns
0810: 74 20 29 7b 0a 20 20 20 20 69 6e 74 20 69 70 3b  t ){.    int ip;
0820: 20 69 6e 74 20 69 63 3b 20 69 6e 74 20 69 6f 3b   int ic; int io;
0830: 0a 20 20 20 20 72 63 20 3d 20 70 49 74 65 72 2d  .    rc = pIter-
0840: 3e 70 41 70 69 2d 3e 78 49 6e 73 74 28 70 49 74  >pApi->xInst(pIt
0850: 65 72 2d 3e 70 46 74 73 2c 20 70 49 74 65 72 2d  er->pFts, pIter-
0860: 3e 69 49 6e 73 74 2c 20 26 69 70 2c 20 26 69 63  >iInst, &ip, &ic
0870: 2c 20 26 69 6f 29 3b 0a 20 20 20 20 69 66 28 20  , &io);.    if( 
0880: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
0890: 0a 20 20 20 20 20 20 69 66 28 20 69 63 3d 3d 70  .      if( ic==p
08a0: 49 74 65 72 2d 3e 69 43 6f 6c 20 29 7b 0a 20 20  Iter->iCol ){.  
08b0: 20 20 20 20 20 20 69 6e 74 20 69 45 6e 64 20 3d        int iEnd =
08c0: 20 69 6f 20 2d 20 31 20 2b 20 70 49 74 65 72 2d   io - 1 + pIter-
08d0: 3e 70 41 70 69 2d 3e 78 50 68 72 61 73 65 53 69  >pApi->xPhraseSi
08e0: 7a 65 28 70 49 74 65 72 2d 3e 70 46 74 73 2c 20  ze(pIter->pFts, 
08f0: 69 70 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28  ip);.        if(
0900: 20 70 49 74 65 72 2d 3e 69 53 74 61 72 74 3c 30   pIter->iStart<0
0910: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 70 49   ){.          pI
0920: 74 65 72 2d 3e 69 53 74 61 72 74 20 3d 20 69 6f  ter->iStart = io
0930: 3b 0a 20 20 20 20 20 20 20 20 20 20 70 49 74 65  ;.          pIte
0940: 72 2d 3e 69 45 6e 64 20 3d 20 69 45 6e 64 3b 0a  r->iEnd = iEnd;.
0950: 20 20 20 20 20 20 20 20 7d 65 6c 73 65 20 69 66          }else if
0960: 28 20 69 6f 3c 3d 70 49 74 65 72 2d 3e 69 45 6e  ( io<=pIter->iEn
0970: 64 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 69  d ){.          i
0980: 66 28 20 69 45 6e 64 3e 70 49 74 65 72 2d 3e 69  f( iEnd>pIter->i
0990: 45 6e 64 20 29 20 70 49 74 65 72 2d 3e 69 45 6e  End ) pIter->iEn
09a0: 64 20 3d 20 69 45 6e 64 3b 0a 20 20 20 20 20 20  d = iEnd;.      
09b0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
09c0: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
09d0: 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20    }.      }.    
09e0: 20 20 70 49 74 65 72 2d 3e 69 49 6e 73 74 2b 2b    pIter->iInst++
09f0: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72  ;.    }.  }..  r
0a00: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a  eturn rc;.}../*.
0a10: 2a 2a 20 49 6e 69 74 69 61 6c 69 7a 65 20 74 68  ** Initialize th
0a20: 65 20 69 74 65 72 61 74 6f 72 20 6f 62 6a 65 63  e iterator objec
0a30: 74 20 69 6e 64 69 63 61 74 65 64 20 62 79 20 74  t indicated by t
0a40: 68 65 20 66 69 6e 61 6c 20 70 61 72 61 6d 65 74  he final paramet
0a50: 65 72 20 74 6f 20 0a 2a 2a 20 69 74 65 72 61 74  er to .** iterat
0a60: 65 20 74 68 72 6f 75 67 68 20 63 6f 61 6c 65 73  e through coales
0a70: 63 65 64 20 70 68 72 61 73 65 20 69 6e 73 74 61  ced phrase insta
0a80: 6e 63 65 73 20 69 6e 20 63 6f 6c 75 6d 6e 20 69  nces in column i
0a90: 43 6f 6c 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  Col..*/.static i
0aa0: 6e 74 20 66 74 73 35 43 49 6e 73 74 49 74 65 72  nt fts5CInstIter
0ab0: 49 6e 69 74 28 0a 20 20 63 6f 6e 73 74 20 46 74  Init(.  const Ft
0ac0: 73 35 45 78 74 65 6e 73 69 6f 6e 41 70 69 20 2a  s5ExtensionApi *
0ad0: 70 41 70 69 2c 0a 20 20 46 74 73 35 43 6f 6e 74  pApi,.  Fts5Cont
0ae0: 65 78 74 20 2a 70 46 74 73 2c 0a 20 20 69 6e 74  ext *pFts,.  int
0af0: 20 69 43 6f 6c 2c 0a 20 20 43 49 6e 73 74 49 74   iCol,.  CInstIt
0b00: 65 72 20 2a 70 49 74 65 72 0a 29 7b 0a 20 20 69  er *pIter.){.  i
0b10: 6e 74 20 72 63 3b 0a 0a 20 20 6d 65 6d 73 65 74  nt rc;..  memset
0b20: 28 70 49 74 65 72 2c 20 30 2c 20 73 69 7a 65 6f  (pIter, 0, sizeo
0b30: 66 28 43 49 6e 73 74 49 74 65 72 29 29 3b 0a 20  f(CInstIter));. 
0b40: 20 70 49 74 65 72 2d 3e 70 41 70 69 20 3d 20 70   pIter->pApi = p
0b50: 41 70 69 3b 0a 20 20 70 49 74 65 72 2d 3e 70 46  Api;.  pIter->pF
0b60: 74 73 20 3d 20 70 46 74 73 3b 0a 20 20 70 49 74  ts = pFts;.  pIt
0b70: 65 72 2d 3e 69 43 6f 6c 20 3d 20 69 43 6f 6c 3b  er->iCol = iCol;
0b80: 0a 20 20 72 63 20 3d 20 70 41 70 69 2d 3e 78 49  .  rc = pApi->xI
0b90: 6e 73 74 43 6f 75 6e 74 28 70 46 74 73 2c 20 26  nstCount(pFts, &
0ba0: 70 49 74 65 72 2d 3e 6e 49 6e 73 74 29 3b 0a 0a  pIter->nInst);..
0bb0: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
0bc0: 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d 20  _OK ){.    rc = 
0bd0: 66 74 73 35 43 49 6e 73 74 49 74 65 72 4e 65 78  fts5CInstIterNex
0be0: 74 28 70 49 74 65 72 29 3b 0a 20 20 7d 0a 0a 20  t(pIter);.  }.. 
0bf0: 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a   return rc;.}...
0c00: 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ./**************
0c10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0c20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0c30: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0c40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 2a 2a 20 53  ***********.** S
0c50: 74 61 72 74 20 6f 66 20 68 69 67 68 6c 69 67 68  tart of highligh
0c60: 74 28 29 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69  t() implementati
0c70: 6f 6e 2e 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73  on..*/.typedef s
0c80: 74 72 75 63 74 20 48 69 67 68 6c 69 67 68 74 43  truct HighlightC
0c90: 6f 6e 74 65 78 74 20 48 69 67 68 6c 69 67 68 74  ontext Highlight
0ca0: 43 6f 6e 74 65 78 74 3b 0a 73 74 72 75 63 74 20  Context;.struct 
0cb0: 48 69 67 68 6c 69 67 68 74 43 6f 6e 74 65 78 74  HighlightContext
0cc0: 20 7b 0a 20 20 43 49 6e 73 74 49 74 65 72 20 69   {.  CInstIter i
0cd0: 74 65 72 3b 20 20 20 20 20 20 20 20 20 20 20 20  ter;            
0ce0: 20 20 20 20 20 2f 2a 20 43 6f 61 6c 65 73 63 65       /* Coalesce
0cf0: 64 20 49 6e 73 74 61 6e 63 65 20 49 74 65 72 61  d Instance Itera
0d00: 74 6f 72 20 2a 2f 0a 20 20 69 6e 74 20 69 50 6f  tor */.  int iPo
0d10: 73 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s;              
0d20: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 75 72 72           /* Curr
0d30: 65 6e 74 20 74 6f 6b 65 6e 20 6f 66 66 73 65 74  ent token offset
0d40: 20 69 6e 20 7a 49 6e 5b 5d 20 2a 2f 0a 20 20 69   in zIn[] */.  i
0d50: 6e 74 20 69 52 61 6e 67 65 53 74 61 72 74 3b 20  nt iRangeStart; 
0d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0d70: 2a 20 46 69 72 73 74 20 74 6f 6b 65 6e 20 74 6f  * First token to
0d80: 20 69 6e 63 6c 75 64 65 20 2a 2f 0a 20 20 69 6e   include */.  in
0d90: 74 20 69 52 61 6e 67 65 45 6e 64 3b 20 20 20 20  t iRangeEnd;    
0da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
0db0: 20 49 66 20 6e 6f 6e 2d 7a 65 72 6f 2c 20 6c 61   If non-zero, la
0dc0: 73 74 20 74 6f 6b 65 6e 20 74 6f 20 69 6e 63 6c  st token to incl
0dd0: 75 64 65 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  ude */.  const c
0de0: 68 61 72 20 2a 7a 4f 70 65 6e 3b 20 20 20 20 20  har *zOpen;     
0df0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 70 65 6e           /* Open
0e00: 69 6e 67 20 68 69 67 68 6c 69 67 68 74 20 2a 2f  ing highlight */
0e10: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
0e20: 43 6c 6f 73 65 3b 20 20 20 20 20 20 20 20 20 20  Close;          
0e30: 20 20 20 2f 2a 20 43 6c 6f 73 69 6e 67 20 68 69     /* Closing hi
0e40: 67 68 6c 69 67 68 74 20 2a 2f 0a 20 20 63 6f 6e  ghlight */.  con
0e50: 73 74 20 63 68 61 72 20 2a 7a 49 6e 3b 20 20 20  st char *zIn;   
0e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
0e70: 49 6e 70 75 74 20 74 65 78 74 20 2a 2f 0a 20 20  Input text */.  
0e80: 69 6e 74 20 6e 49 6e 3b 20 20 20 20 20 20 20 20  int nIn;        
0e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ea0: 2f 2a 20 53 69 7a 65 20 6f 66 20 69 6e 70 75 74  /* Size of input
0eb0: 20 74 65 78 74 20 69 6e 20 62 79 74 65 73 20 2a   text in bytes *
0ec0: 2f 0a 20 20 69 6e 74 20 69 4f 66 66 3b 20 20 20  /.  int iOff;   
0ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ee0: 20 20 20 20 2f 2a 20 43 75 72 72 65 6e 74 20 6f      /* Current o
0ef0: 66 66 73 65 74 20 77 69 74 68 69 6e 20 7a 49 6e  ffset within zIn
0f00: 5b 5d 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 4f  [] */.  char *zO
0f10: 75 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  ut;             
0f20: 20 20 20 20 20 20 20 20 2f 2a 20 4f 75 74 70 75          /* Outpu
0f30: 74 20 76 61 6c 75 65 20 2a 2f 0a 7d 3b 0a 0a 2f  t value */.};../
0f40: 2a 0a 2a 2a 20 41 70 70 65 6e 64 20 74 65 78 74  *.** Append text
0f50: 20 74 6f 20 74 68 65 20 48 69 67 68 6c 69 67 68   to the Highligh
0f60: 74 43 6f 6e 74 65 78 74 20 6f 75 74 70 75 74 20  tContext output 
0f70: 73 74 72 69 6e 67 20 2d 20 70 2d 3e 7a 4f 75 74  string - p->zOut
0f80: 2e 20 41 72 67 75 6d 65 6e 74 0a 2a 2a 20 7a 20  . Argument.** z 
0f90: 70 6f 69 6e 74 73 20 74 6f 20 61 20 62 75 66 66  points to a buff
0fa0: 65 72 20 63 6f 6e 74 61 69 6e 69 6e 67 20 6e 20  er containing n 
0fb0: 62 79 74 65 73 20 6f 66 20 74 65 78 74 20 74 6f  bytes of text to
0fc0: 20 61 70 70 65 6e 64 2e 20 49 66 20 6e 20 69 73   append. If n is
0fd0: 20 0a 2a 2a 20 6e 65 67 61 74 69 76 65 2c 20 65   .** negative, e
0fe0: 76 65 72 79 74 68 69 6e 67 20 75 70 20 75 6e 74  verything up unt
0ff0: 69 6c 20 74 68 65 20 66 69 72 73 74 20 27 5c 30  il the first '\0
1000: 27 20 69 73 20 61 70 70 65 6e 64 65 64 20 74 6f  ' is appended to
1010: 20 74 68 65 20 6f 75 74 70 75 74 2e 0a 2a 2a 0a   the output..**.
1020: 2a 2a 20 49 66 20 2a 70 52 63 20 69 73 20 73 65  ** If *pRc is se
1030: 74 20 74 6f 20 61 6e 79 20 76 61 6c 75 65 20 6f  t to any value o
1040: 74 68 65 72 20 74 68 61 6e 20 53 51 4c 49 54 45  ther than SQLITE
1050: 5f 4f 4b 20 77 68 65 6e 20 74 68 69 73 20 66 75  _OK when this fu
1060: 6e 63 74 69 6f 6e 20 69 73 20 0a 2a 2a 20 63 61  nction is .** ca
1070: 6c 6c 65 64 2c 20 69 74 20 69 73 20 61 20 6e 6f  lled, it is a no
1080: 2d 6f 70 2e 20 49 66 20 61 6e 20 65 72 72 6f 72  -op. If an error
1090: 20 28 69 2e 65 2e 20 61 6e 20 4f 4f 4d 20 63 6f   (i.e. an OOM co
10a0: 6e 64 69 74 69 6f 6e 29 20 69 73 20 65 6e 63 6f  ndition) is enco
10b0: 75 6e 74 65 72 65 64 2c 20 0a 2a 2a 20 2a 70 52  untered, .** *pR
10c0: 63 20 69 73 20 73 65 74 20 74 6f 20 61 6e 20 65  c is set to an e
10d0: 72 72 6f 72 20 63 6f 64 65 20 62 65 66 6f 72 65  rror code before
10e0: 20 72 65 74 75 72 6e 69 6e 67 2e 20 0a 2a 2f 0a   returning. .*/.
10f0: 73 74 61 74 69 63 20 76 6f 69 64 20 66 74 73 35  static void fts5
1100: 48 69 67 68 6c 69 67 68 74 41 70 70 65 6e 64 28  HighlightAppend(
1110: 0a 20 20 69 6e 74 20 2a 70 52 63 2c 20 0a 20 20  .  int *pRc, .  
1120: 48 69 67 68 6c 69 67 68 74 43 6f 6e 74 65 78 74  HighlightContext
1130: 20 2a 70 2c 20 0a 20 20 63 6f 6e 73 74 20 63 68   *p, .  const ch
1140: 61 72 20 2a 7a 2c 20 69 6e 74 20 6e 0a 29 7b 0a  ar *z, int n.){.
1150: 20 20 69 66 28 20 2a 70 52 63 3d 3d 53 51 4c 49    if( *pRc==SQLI
1160: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 69 66 28  TE_OK ){.    if(
1170: 20 6e 3c 30 20 29 20 6e 20 3d 20 28 69 6e 74 29   n<0 ) n = (int)
1180: 73 74 72 6c 65 6e 28 7a 29 3b 0a 20 20 20 20 70  strlen(z);.    p
1190: 2d 3e 7a 4f 75 74 20 3d 20 73 71 6c 69 74 65 33  ->zOut = sqlite3
11a0: 5f 6d 70 72 69 6e 74 66 28 22 25 7a 25 2e 2a 73  _mprintf("%z%.*s
11b0: 22 2c 20 70 2d 3e 7a 4f 75 74 2c 20 6e 2c 20 7a  ", p->zOut, n, z
11c0: 29 3b 0a 20 20 20 20 69 66 28 20 70 2d 3e 7a 4f  );.    if( p->zO
11d0: 75 74 3d 3d 30 20 29 20 2a 70 52 63 20 3d 20 53  ut==0 ) *pRc = S
11e0: 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 7d  QLITE_NOMEM;.  }
11f0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 6f 6b 65 6e 69  .}../*.** Tokeni
1200: 7a 65 72 20 63 61 6c 6c 62 61 63 6b 20 75 73 65  zer callback use
1210: 64 20 62 79 20 69 6d 70 6c 65 6d 65 6e 74 61 74  d by implementat
1220: 69 6f 6e 20 6f 66 20 68 69 67 68 6c 69 67 68 74  ion of highlight
1230: 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a  () function..*/.
1240: 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 35 48  static int fts5H
1250: 69 67 68 6c 69 67 68 74 43 62 28 0a 20 20 76 6f  ighlightCb(.  vo
1260: 69 64 20 2a 70 43 6f 6e 74 65 78 74 2c 20 20 20  id *pContext,   
1270: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
1280: 20 50 6f 69 6e 74 65 72 20 74 6f 20 48 69 67 68   Pointer to High
1290: 6c 69 67 68 74 43 6f 6e 74 65 78 74 20 6f 62 6a  lightContext obj
12a0: 65 63 74 20 2a 2f 0a 20 20 69 6e 74 20 74 66 6c  ect */.  int tfl
12b0: 61 67 73 2c 20 20 20 20 20 20 20 20 20 20 20 20  ags,            
12c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4d 61 73 6b           /* Mask
12d0: 20 6f 66 20 46 54 53 35 5f 54 4f 4b 45 4e 5f 2a   of FTS5_TOKEN_*
12e0: 20 66 6c 61 67 73 20 2a 2f 0a 20 20 63 6f 6e 73   flags */.  cons
12f0: 74 20 63 68 61 72 20 2a 70 54 6f 6b 65 6e 2c 20  t char *pToken, 
1300: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 42              /* B
1310: 75 66 66 65 72 20 63 6f 6e 74 61 69 6e 69 6e 67  uffer containing
1320: 20 74 6f 6b 65 6e 20 2a 2f 0a 20 20 69 6e 74 20   token */.  int 
1330: 6e 54 6f 6b 65 6e 2c 20 20 20 20 20 20 20 20 20  nToken,         
1340: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53              /* S
1350: 69 7a 65 20 6f 66 20 74 6f 6b 65 6e 20 69 6e 20  ize of token in 
1360: 62 79 74 65 73 20 2a 2f 0a 20 20 69 6e 74 20 69  bytes */.  int i
1370: 53 74 61 72 74 4f 66 66 2c 20 20 20 20 20 20 20  StartOff,       
1380: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 74             /* St
1390: 61 72 74 20 6f 66 66 73 65 74 20 6f 66 20 74 6f  art offset of to
13a0: 6b 65 6e 20 2a 2f 0a 20 20 69 6e 74 20 69 45 6e  ken */.  int iEn
13b0: 64 4f 66 66 20 20 20 20 20 20 20 20 20 20 20 20  dOff            
13c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 45 6e 64 20           /* End 
13d0: 6f 66 66 73 65 74 20 6f 66 20 74 6f 6b 65 6e 20  offset of token 
13e0: 2a 2f 0a 29 7b 0a 20 20 48 69 67 68 6c 69 67 68  */.){.  Highligh
13f0: 74 43 6f 6e 74 65 78 74 20 2a 70 20 3d 20 28 48  tContext *p = (H
1400: 69 67 68 6c 69 67 68 74 43 6f 6e 74 65 78 74 2a  ighlightContext*
1410: 29 70 43 6f 6e 74 65 78 74 3b 0a 20 20 69 6e 74  )pContext;.  int
1420: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
1430: 0a 20 20 69 6e 74 20 69 50 6f 73 3b 0a 0a 20 20  .  int iPos;..  
1440: 55 4e 55 53 45 44 5f 50 41 52 41 4d 32 28 70 54  UNUSED_PARAM2(pT
1450: 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 29 3b 0a 0a  oken, nToken);..
1460: 20 20 69 66 28 20 74 66 6c 61 67 73 20 26 20 46    if( tflags & F
1470: 54 53 35 5f 54 4f 4b 45 4e 5f 43 4f 4c 4f 43 41  TS5_TOKEN_COLOCA
1480: 54 45 44 20 29 20 72 65 74 75 72 6e 20 53 51 4c  TED ) return SQL
1490: 49 54 45 5f 4f 4b 3b 0a 20 20 69 50 6f 73 20 3d  ITE_OK;.  iPos =
14a0: 20 70 2d 3e 69 50 6f 73 2b 2b 3b 0a 0a 20 20 69   p->iPos++;..  i
14b0: 66 28 20 70 2d 3e 69 52 61 6e 67 65 45 6e 64 3e  f( p->iRangeEnd>
14c0: 30 20 29 7b 0a 20 20 20 20 69 66 28 20 69 50 6f  0 ){.    if( iPo
14d0: 73 3c 70 2d 3e 69 52 61 6e 67 65 53 74 61 72 74  s<p->iRangeStart
14e0: 20 7c 7c 20 69 50 6f 73 3e 70 2d 3e 69 52 61 6e   || iPos>p->iRan
14f0: 67 65 45 6e 64 20 29 20 72 65 74 75 72 6e 20 53  geEnd ) return S
1500: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 69 66  QLITE_OK;.    if
1510: 28 20 70 2d 3e 69 52 61 6e 67 65 53 74 61 72 74  ( p->iRangeStart
1520: 20 26 26 20 69 50 6f 73 3d 3d 70 2d 3e 69 52 61   && iPos==p->iRa
1530: 6e 67 65 53 74 61 72 74 20 29 20 70 2d 3e 69 4f  ngeStart ) p->iO
1540: 66 66 20 3d 20 69 53 74 61 72 74 4f 66 66 3b 0a  ff = iStartOff;.
1550: 20 20 7d 0a 0a 20 20 69 66 28 20 69 50 6f 73 3d    }..  if( iPos=
1560: 3d 70 2d 3e 69 74 65 72 2e 69 53 74 61 72 74 20  =p->iter.iStart 
1570: 29 7b 0a 20 20 20 20 66 74 73 35 48 69 67 68 6c  ){.    fts5Highl
1580: 69 67 68 74 41 70 70 65 6e 64 28 26 72 63 2c 20  ightAppend(&rc, 
1590: 70 2c 20 26 70 2d 3e 7a 49 6e 5b 70 2d 3e 69 4f  p, &p->zIn[p->iO
15a0: 66 66 5d 2c 20 69 53 74 61 72 74 4f 66 66 20 2d  ff], iStartOff -
15b0: 20 70 2d 3e 69 4f 66 66 29 3b 0a 20 20 20 20 66   p->iOff);.    f
15c0: 74 73 35 48 69 67 68 6c 69 67 68 74 41 70 70 65  ts5HighlightAppe
15d0: 6e 64 28 26 72 63 2c 20 70 2c 20 70 2d 3e 7a 4f  nd(&rc, p, p->zO
15e0: 70 65 6e 2c 20 2d 31 29 3b 0a 20 20 20 20 70 2d  pen, -1);.    p-
15f0: 3e 69 4f 66 66 20 3d 20 69 53 74 61 72 74 4f 66  >iOff = iStartOf
1600: 66 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20 69 50  f;.  }..  if( iP
1610: 6f 73 3d 3d 70 2d 3e 69 74 65 72 2e 69 45 6e 64  os==p->iter.iEnd
1620: 20 29 7b 0a 20 20 20 20 69 66 28 20 70 2d 3e 69   ){.    if( p->i
1630: 52 61 6e 67 65 45 6e 64 20 26 26 20 70 2d 3e 69  RangeEnd && p->i
1640: 74 65 72 2e 69 53 74 61 72 74 3c 70 2d 3e 69 52  ter.iStart<p->iR
1650: 61 6e 67 65 53 74 61 72 74 20 29 7b 0a 20 20 20  angeStart ){.   
1660: 20 20 20 66 74 73 35 48 69 67 68 6c 69 67 68 74     fts5Highlight
1670: 41 70 70 65 6e 64 28 26 72 63 2c 20 70 2c 20 70  Append(&rc, p, p
1680: 2d 3e 7a 4f 70 65 6e 2c 20 2d 31 29 3b 0a 20 20  ->zOpen, -1);.  
1690: 20 20 7d 0a 20 20 20 20 66 74 73 35 48 69 67 68    }.    fts5High
16a0: 6c 69 67 68 74 41 70 70 65 6e 64 28 26 72 63 2c  lightAppend(&rc,
16b0: 20 70 2c 20 26 70 2d 3e 7a 49 6e 5b 70 2d 3e 69   p, &p->zIn[p->i
16c0: 4f 66 66 5d 2c 20 69 45 6e 64 4f 66 66 20 2d 20  Off], iEndOff - 
16d0: 70 2d 3e 69 4f 66 66 29 3b 0a 20 20 20 20 66 74  p->iOff);.    ft
16e0: 73 35 48 69 67 68 6c 69 67 68 74 41 70 70 65 6e  s5HighlightAppen
16f0: 64 28 26 72 63 2c 20 70 2c 20 70 2d 3e 7a 43 6c  d(&rc, p, p->zCl
1700: 6f 73 65 2c 20 2d 31 29 3b 0a 20 20 20 20 70 2d  ose, -1);.    p-
1710: 3e 69 4f 66 66 20 3d 20 69 45 6e 64 4f 66 66 3b  >iOff = iEndOff;
1720: 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  .    if( rc==SQL
1730: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  ITE_OK ){.      
1740: 72 63 20 3d 20 66 74 73 35 43 49 6e 73 74 49 74  rc = fts5CInstIt
1750: 65 72 4e 65 78 74 28 26 70 2d 3e 69 74 65 72 29  erNext(&p->iter)
1760: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 69  ;.    }.  }..  i
1770: 66 28 20 70 2d 3e 69 52 61 6e 67 65 45 6e 64 3e  f( p->iRangeEnd>
1780: 30 20 26 26 20 69 50 6f 73 3d 3d 70 2d 3e 69 52  0 && iPos==p->iR
1790: 61 6e 67 65 45 6e 64 20 29 7b 0a 20 20 20 20 66  angeEnd ){.    f
17a0: 74 73 35 48 69 67 68 6c 69 67 68 74 41 70 70 65  ts5HighlightAppe
17b0: 6e 64 28 26 72 63 2c 20 70 2c 20 26 70 2d 3e 7a  nd(&rc, p, &p->z
17c0: 49 6e 5b 70 2d 3e 69 4f 66 66 5d 2c 20 69 45 6e  In[p->iOff], iEn
17d0: 64 4f 66 66 20 2d 20 70 2d 3e 69 4f 66 66 29 3b  dOff - p->iOff);
17e0: 0a 20 20 20 20 70 2d 3e 69 4f 66 66 20 3d 20 69  .    p->iOff = i
17f0: 45 6e 64 4f 66 66 3b 0a 20 20 20 20 69 66 28 20  EndOff;.    if( 
1800: 69 50 6f 73 3c 70 2d 3e 69 74 65 72 2e 69 45 6e  iPos<p->iter.iEn
1810: 64 20 29 7b 0a 20 20 20 20 20 20 66 74 73 35 48  d ){.      fts5H
1820: 69 67 68 6c 69 67 68 74 41 70 70 65 6e 64 28 26  ighlightAppend(&
1830: 72 63 2c 20 70 2c 20 70 2d 3e 7a 43 6c 6f 73 65  rc, p, p->zClose
1840: 2c 20 2d 31 29 3b 0a 20 20 20 20 7d 0a 20 20 7d  , -1);.    }.  }
1850: 0a 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  ..  return rc;.}
1860: 0a 0a 2f 2a 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e  ../*.** Implemen
1870: 74 61 74 69 6f 6e 20 6f 66 20 68 69 67 68 6c 69  tation of highli
1880: 67 68 74 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a  ght() function..
1890: 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 66  */.static void f
18a0: 74 73 35 48 69 67 68 6c 69 67 68 74 46 75 6e 63  ts5HighlightFunc
18b0: 74 69 6f 6e 28 0a 20 20 63 6f 6e 73 74 20 46 74  tion(.  const Ft
18c0: 73 35 45 78 74 65 6e 73 69 6f 6e 41 70 69 20 2a  s5ExtensionApi *
18d0: 70 41 70 69 2c 20 20 20 2f 2a 20 41 50 49 20 6f  pApi,   /* API o
18e0: 66 66 65 72 65 64 20 62 79 20 63 75 72 72 65 6e  ffered by curren
18f0: 74 20 46 54 53 20 76 65 72 73 69 6f 6e 20 2a 2f  t FTS version */
1900: 0a 20 20 46 74 73 35 43 6f 6e 74 65 78 74 20 2a  .  Fts5Context *
1910: 70 46 74 73 2c 20 20 20 20 20 20 20 20 20 20 20  pFts,           
1920: 20 20 20 2f 2a 20 46 69 72 73 74 20 61 72 67 20     /* First arg 
1930: 74 6f 20 70 61 73 73 20 74 6f 20 70 41 70 69 20  to pass to pApi 
1940: 66 75 6e 63 74 69 6f 6e 73 20 2a 2f 0a 20 20 73  functions */.  s
1950: 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74 20 2a  qlite3_context *
1960: 70 43 74 78 2c 20 20 20 20 20 20 20 20 20 20 2f  pCtx,          /
1970: 2a 20 43 6f 6e 74 65 78 74 20 66 6f 72 20 72 65  * Context for re
1980: 74 75 72 6e 69 6e 67 20 72 65 73 75 6c 74 2f 65  turning result/e
1990: 72 72 6f 72 20 2a 2f 0a 20 20 69 6e 74 20 6e 56  rror */.  int nV
19a0: 61 6c 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  al,             
19b0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d            /* Num
19c0: 62 65 72 20 6f 66 20 76 61 6c 75 65 73 20 69 6e  ber of values in
19d0: 20 61 70 56 61 6c 5b 5d 20 61 72 72 61 79 20 2a   apVal[] array *
19e0: 2f 0a 20 20 73 71 6c 69 74 65 33 5f 76 61 6c 75  /.  sqlite3_valu
19f0: 65 20 2a 2a 61 70 56 61 6c 20 20 20 20 20 20 20  e **apVal       
1a00: 20 20 20 20 2f 2a 20 41 72 72 61 79 20 6f 66 20      /* Array of 
1a10: 74 72 61 69 6c 69 6e 67 20 61 72 67 75 6d 65 6e  trailing argumen
1a20: 74 73 20 2a 2f 0a 29 7b 0a 20 20 48 69 67 68 6c  ts */.){.  Highl
1a30: 69 67 68 74 43 6f 6e 74 65 78 74 20 63 74 78 3b  ightContext ctx;
1a40: 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 69 6e 74  .  int rc;.  int
1a50: 20 69 43 6f 6c 3b 0a 0a 20 20 69 66 28 20 6e 56   iCol;..  if( nV
1a60: 61 6c 21 3d 33 20 29 7b 0a 20 20 20 20 63 6f 6e  al!=3 ){.    con
1a70: 73 74 20 63 68 61 72 20 2a 7a 45 72 72 20 3d 20  st char *zErr = 
1a80: 22 77 72 6f 6e 67 20 6e 75 6d 62 65 72 20 6f 66  "wrong number of
1a90: 20 61 72 67 75 6d 65 6e 74 73 20 74 6f 20 66 75   arguments to fu
1aa0: 6e 63 74 69 6f 6e 20 68 69 67 68 6c 69 67 68 74  nction highlight
1ab0: 28 29 22 3b 0a 20 20 20 20 73 71 6c 69 74 65 33  ()";.    sqlite3
1ac0: 5f 72 65 73 75 6c 74 5f 65 72 72 6f 72 28 70 43  _result_error(pC
1ad0: 74 78 2c 20 7a 45 72 72 2c 20 2d 31 29 3b 0a 20  tx, zErr, -1);. 
1ae0: 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 0a     return;.  }..
1af0: 20 20 69 43 6f 6c 20 3d 20 73 71 6c 69 74 65 33    iCol = sqlite3
1b00: 5f 76 61 6c 75 65 5f 69 6e 74 28 61 70 56 61 6c  _value_int(apVal
1b10: 5b 30 5d 29 3b 0a 20 20 6d 65 6d 73 65 74 28 26  [0]);.  memset(&
1b20: 63 74 78 2c 20 30 2c 20 73 69 7a 65 6f 66 28 48  ctx, 0, sizeof(H
1b30: 69 67 68 6c 69 67 68 74 43 6f 6e 74 65 78 74 29  ighlightContext)
1b40: 29 3b 0a 20 20 63 74 78 2e 7a 4f 70 65 6e 20 3d  );.  ctx.zOpen =
1b50: 20 28 63 6f 6e 73 74 20 63 68 61 72 2a 29 73 71   (const char*)sq
1b60: 6c 69 74 65 33 5f 76 61 6c 75 65 5f 74 65 78 74  lite3_value_text
1b70: 28 61 70 56 61 6c 5b 31 5d 29 3b 0a 20 20 63 74  (apVal[1]);.  ct
1b80: 78 2e 7a 43 6c 6f 73 65 20 3d 20 28 63 6f 6e 73  x.zClose = (cons
1b90: 74 20 63 68 61 72 2a 29 73 71 6c 69 74 65 33 5f  t char*)sqlite3_
1ba0: 76 61 6c 75 65 5f 74 65 78 74 28 61 70 56 61 6c  value_text(apVal
1bb0: 5b 32 5d 29 3b 0a 20 20 72 63 20 3d 20 70 41 70  [2]);.  rc = pAp
1bc0: 69 2d 3e 78 43 6f 6c 75 6d 6e 54 65 78 74 28 70  i->xColumnText(p
1bd0: 46 74 73 2c 20 69 43 6f 6c 2c 20 26 63 74 78 2e  Fts, iCol, &ctx.
1be0: 7a 49 6e 2c 20 26 63 74 78 2e 6e 49 6e 29 3b 0a  zIn, &ctx.nIn);.
1bf0: 0a 20 20 69 66 28 20 63 74 78 2e 7a 49 6e 20 29  .  if( ctx.zIn )
1c00: 7b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51  {.    if( rc==SQ
1c10: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20  LITE_OK ){.     
1c20: 20 72 63 20 3d 20 66 74 73 35 43 49 6e 73 74 49   rc = fts5CInstI
1c30: 74 65 72 49 6e 69 74 28 70 41 70 69 2c 20 70 46  terInit(pApi, pF
1c40: 74 73 2c 20 69 43 6f 6c 2c 20 26 63 74 78 2e 69  ts, iCol, &ctx.i
1c50: 74 65 72 29 3b 0a 20 20 20 20 7d 0a 0a 20 20 20  ter);.    }..   
1c60: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
1c70: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d  OK ){.      rc =
1c80: 20 70 41 70 69 2d 3e 78 54 6f 6b 65 6e 69 7a 65   pApi->xTokenize
1c90: 28 70 46 74 73 2c 20 63 74 78 2e 7a 49 6e 2c 20  (pFts, ctx.zIn, 
1ca0: 63 74 78 2e 6e 49 6e 2c 20 28 76 6f 69 64 2a 29  ctx.nIn, (void*)
1cb0: 26 63 74 78 2c 66 74 73 35 48 69 67 68 6c 69 67  &ctx,fts5Highlig
1cc0: 68 74 43 62 29 3b 0a 20 20 20 20 7d 0a 20 20 20  htCb);.    }.   
1cd0: 20 66 74 73 35 48 69 67 68 6c 69 67 68 74 41 70   fts5HighlightAp
1ce0: 70 65 6e 64 28 26 72 63 2c 20 26 63 74 78 2c 20  pend(&rc, &ctx, 
1cf0: 26 63 74 78 2e 7a 49 6e 5b 63 74 78 2e 69 4f 66  &ctx.zIn[ctx.iOf
1d00: 66 5d 2c 20 63 74 78 2e 6e 49 6e 20 2d 20 63 74  f], ctx.nIn - ct
1d10: 78 2e 69 4f 66 66 29 3b 0a 0a 20 20 20 20 69 66  x.iOff);..    if
1d20: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
1d30: 29 7b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33  ){.      sqlite3
1d40: 5f 72 65 73 75 6c 74 5f 74 65 78 74 28 70 43 74  _result_text(pCt
1d50: 78 2c 20 28 63 6f 6e 73 74 20 63 68 61 72 2a 29  x, (const char*)
1d60: 63 74 78 2e 7a 4f 75 74 2c 20 2d 31 2c 20 53 51  ctx.zOut, -1, SQ
1d70: 4c 49 54 45 5f 54 52 41 4e 53 49 45 4e 54 29 3b  LITE_TRANSIENT);
1d80: 0a 20 20 20 20 7d 0a 20 20 20 20 73 71 6c 69 74  .    }.    sqlit
1d90: 65 33 5f 66 72 65 65 28 63 74 78 2e 7a 4f 75 74  e3_free(ctx.zOut
1da0: 29 3b 0a 20 20 7d 0a 20 20 69 66 28 20 72 63 21  );.  }.  if( rc!
1db0: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
1dc0: 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74    sqlite3_result
1dd0: 5f 65 72 72 6f 72 5f 63 6f 64 65 28 70 43 74 78  _error_code(pCtx
1de0: 2c 20 72 63 29 3b 0a 20 20 7d 0a 7d 0a 2f 2a 0a  , rc);.  }.}./*.
1df0: 2a 2a 20 45 6e 64 20 6f 66 20 68 69 67 68 6c 69  ** End of highli
1e00: 67 68 74 28 29 20 69 6d 70 6c 65 6d 65 6e 74 61  ght() implementa
1e10: 74 69 6f 6e 2e 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  tion..**********
1e20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1e30: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1e40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1e50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1e60: 2f 0a 0a 2f 2a 0a 2a 2a 20 49 6d 70 6c 65 6d 65  /../*.** Impleme
1e70: 6e 74 61 74 69 6f 6e 20 6f 66 20 73 6e 69 70 70  ntation of snipp
1e80: 65 74 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a  et() function..*
1e90: 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 66 74  /.static void ft
1ea0: 73 35 53 6e 69 70 70 65 74 46 75 6e 63 74 69 6f  s5SnippetFunctio
1eb0: 6e 28 0a 20 20 63 6f 6e 73 74 20 46 74 73 35 45  n(.  const Fts5E
1ec0: 78 74 65 6e 73 69 6f 6e 41 70 69 20 2a 70 41 70  xtensionApi *pAp
1ed0: 69 2c 20 20 20 2f 2a 20 41 50 49 20 6f 66 66 65  i,   /* API offe
1ee0: 72 65 64 20 62 79 20 63 75 72 72 65 6e 74 20 46  red by current F
1ef0: 54 53 20 76 65 72 73 69 6f 6e 20 2a 2f 0a 20 20  TS version */.  
1f00: 46 74 73 35 43 6f 6e 74 65 78 74 20 2a 70 46 74  Fts5Context *pFt
1f10: 73 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s,              
1f20: 2f 2a 20 46 69 72 73 74 20 61 72 67 20 74 6f 20  /* First arg to 
1f30: 70 61 73 73 20 74 6f 20 70 41 70 69 20 66 75 6e  pass to pApi fun
1f40: 63 74 69 6f 6e 73 20 2a 2f 0a 20 20 73 71 6c 69  ctions */.  sqli
1f50: 74 65 33 5f 63 6f 6e 74 65 78 74 20 2a 70 43 74  te3_context *pCt
1f60: 78 2c 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43  x,          /* C
1f70: 6f 6e 74 65 78 74 20 66 6f 72 20 72 65 74 75 72  ontext for retur
1f80: 6e 69 6e 67 20 72 65 73 75 6c 74 2f 65 72 72 6f  ning result/erro
1f90: 72 20 2a 2f 0a 20 20 69 6e 74 20 6e 56 61 6c 2c  r */.  int nVal,
1fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fb0: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
1fc0: 20 6f 66 20 76 61 6c 75 65 73 20 69 6e 20 61 70   of values in ap
1fd0: 56 61 6c 5b 5d 20 61 72 72 61 79 20 2a 2f 0a 20  Val[] array */. 
1fe0: 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 20 2a   sqlite3_value *
1ff0: 2a 61 70 56 61 6c 20 20 20 20 20 20 20 20 20 20  *apVal          
2000: 20 2f 2a 20 41 72 72 61 79 20 6f 66 20 74 72 61   /* Array of tra
2010: 69 6c 69 6e 67 20 61 72 67 75 6d 65 6e 74 73 20  iling arguments 
2020: 2a 2f 0a 29 7b 0a 20 20 48 69 67 68 6c 69 67 68  */.){.  Highligh
2030: 74 43 6f 6e 74 65 78 74 20 63 74 78 3b 0a 20 20  tContext ctx;.  
2040: 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f  int rc = SQLITE_
2050: 4f 4b 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  OK;             
2060: 2f 2a 20 52 65 74 75 72 6e 20 63 6f 64 65 20 2a  /* Return code *
2070: 2f 0a 20 20 69 6e 74 20 69 43 6f 6c 3b 20 20 20  /.  int iCol;   
2080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2090: 20 20 20 20 2f 2a 20 31 73 74 20 61 72 67 75 6d      /* 1st argum
20a0: 65 6e 74 20 74 6f 20 73 6e 69 70 70 65 74 28 29  ent to snippet()
20b0: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
20c0: 20 2a 7a 45 6c 6c 69 70 73 3b 20 20 20 20 20 20   *zEllips;      
20d0: 20 20 20 20 20 20 2f 2a 20 34 74 68 20 61 72 67        /* 4th arg
20e0: 75 6d 65 6e 74 20 74 6f 20 73 6e 69 70 70 65 74  ument to snippet
20f0: 28 29 20 2a 2f 0a 20 20 69 6e 74 20 6e 54 6f 6b  () */.  int nTok
2100: 65 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  en;             
2110: 20 20 20 20 20 20 20 20 2f 2a 20 35 74 68 20 61          /* 5th a
2120: 72 67 75 6d 65 6e 74 20 74 6f 20 73 6e 69 70 70  rgument to snipp
2130: 65 74 28 29 20 2a 2f 0a 20 20 69 6e 74 20 6e 49  et() */.  int nI
2140: 6e 73 74 20 3d 20 30 3b 20 20 20 20 20 20 20 20  nst = 0;        
2150: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d            /* Num
2160: 62 65 72 20 6f 66 20 69 6e 73 74 61 6e 63 65 20  ber of instance 
2170: 6d 61 74 63 68 65 73 20 74 68 69 73 20 72 6f 77  matches this row
2180: 20 2a 2f 0a 20 20 69 6e 74 20 69 3b 20 20 20 20   */.  int i;    
2190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21a0: 20 20 20 20 20 20 2f 2a 20 55 73 65 64 20 74 6f        /* Used to
21b0: 20 69 74 65 72 61 74 65 20 74 68 72 6f 75 67 68   iterate through
21c0: 20 69 6e 73 74 61 6e 63 65 73 20 2a 2f 0a 20 20   instances */.  
21d0: 69 6e 74 20 6e 50 68 72 61 73 65 3b 20 20 20 20  int nPhrase;    
21e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21f0: 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 70 68 72  /* Number of phr
2200: 61 73 65 73 20 69 6e 20 71 75 65 72 79 20 2a 2f  ases in query */
2210: 0a 20 20 75 6e 73 69 67 6e 65 64 20 63 68 61 72  .  unsigned char
2220: 20 2a 61 53 65 65 6e 3b 20 20 20 20 20 20 20 20   *aSeen;        
2230: 20 20 20 2f 2a 20 41 72 72 61 79 20 6f 66 20 22     /* Array of "
2240: 73 65 65 6e 20 69 6e 73 74 61 6e 63 65 22 20 66  seen instance" f
2250: 6c 61 67 73 20 2a 2f 0a 20 20 69 6e 74 20 69 42  lags */.  int iB
2260: 65 73 74 43 6f 6c 3b 20 20 20 20 20 20 20 20 20  estCol;         
2270: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6c            /* Col
2280: 75 6d 6e 20 63 6f 6e 74 61 69 6e 69 6e 67 20 62  umn containing b
2290: 65 73 74 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20  est snippet */. 
22a0: 20 69 6e 74 20 69 42 65 73 74 53 74 61 72 74 20   int iBestStart 
22b0: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
22c0: 20 2f 2a 20 46 69 72 73 74 20 74 6f 6b 65 6e 20   /* First token 
22d0: 6f 66 20 62 65 73 74 20 73 6e 69 70 70 65 74 20  of best snippet 
22e0: 2a 2f 0a 20 20 69 6e 74 20 69 42 65 73 74 4c 61  */.  int iBestLa
22f0: 73 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  st;             
2300: 20 20 20 20 20 2f 2a 20 4c 61 73 74 20 74 6f 6b       /* Last tok
2310: 65 6e 20 6f 66 20 62 65 73 74 20 73 6e 69 70 70  en of best snipp
2320: 65 74 20 2a 2f 0a 20 20 69 6e 74 20 6e 42 65 73  et */.  int nBes
2330: 74 53 63 6f 72 65 20 3d 20 30 3b 20 20 20 20 20  tScore = 0;     
2340: 20 20 20 20 20 20 20 20 2f 2a 20 53 63 6f 72 65          /* Score
2350: 20 6f 66 20 62 65 73 74 20 73 6e 69 70 70 65 74   of best snippet
2360: 20 2a 2f 0a 20 20 69 6e 74 20 6e 43 6f 6c 53 69   */.  int nColSi
2370: 7a 65 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  ze = 0;         
2380: 20 20 20 20 20 20 2f 2a 20 54 6f 74 61 6c 20 73        /* Total s
2390: 69 7a 65 20 6f 66 20 69 42 65 73 74 43 6f 6c 20  ize of iBestCol 
23a0: 69 6e 20 74 6f 6b 65 6e 73 20 2a 2f 0a 0a 20 20  in tokens */..  
23b0: 69 66 28 20 6e 56 61 6c 21 3d 35 20 29 7b 0a 20  if( nVal!=5 ){. 
23c0: 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a     const char *z
23d0: 45 72 72 20 3d 20 22 77 72 6f 6e 67 20 6e 75 6d  Err = "wrong num
23e0: 62 65 72 20 6f 66 20 61 72 67 75 6d 65 6e 74 73  ber of arguments
23f0: 20 74 6f 20 66 75 6e 63 74 69 6f 6e 20 73 6e 69   to function sni
2400: 70 70 65 74 28 29 22 3b 0a 20 20 20 20 73 71 6c  ppet()";.    sql
2410: 69 74 65 33 5f 72 65 73 75 6c 74 5f 65 72 72 6f  ite3_result_erro
2420: 72 28 70 43 74 78 2c 20 7a 45 72 72 2c 20 2d 31  r(pCtx, zErr, -1
2430: 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a 20  );.    return;. 
2440: 20 7d 0a 0a 20 20 6d 65 6d 73 65 74 28 26 63 74   }..  memset(&ct
2450: 78 2c 20 30 2c 20 73 69 7a 65 6f 66 28 48 69 67  x, 0, sizeof(Hig
2460: 68 6c 69 67 68 74 43 6f 6e 74 65 78 74 29 29 3b  hlightContext));
2470: 0a 20 20 69 43 6f 6c 20 3d 20 73 71 6c 69 74 65  .  iCol = sqlite
2480: 33 5f 76 61 6c 75 65 5f 69 6e 74 28 61 70 56 61  3_value_int(apVa
2490: 6c 5b 30 5d 29 3b 0a 20 20 63 74 78 2e 7a 4f 70  l[0]);.  ctx.zOp
24a0: 65 6e 20 3d 20 28 63 6f 6e 73 74 20 63 68 61 72  en = (const char
24b0: 2a 29 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f  *)sqlite3_value_
24c0: 74 65 78 74 28 61 70 56 61 6c 5b 31 5d 29 3b 0a  text(apVal[1]);.
24d0: 20 20 63 74 78 2e 7a 43 6c 6f 73 65 20 3d 20 28    ctx.zClose = (
24e0: 63 6f 6e 73 74 20 63 68 61 72 2a 29 73 71 6c 69  const char*)sqli
24f0: 74 65 33 5f 76 61 6c 75 65 5f 74 65 78 74 28 61  te3_value_text(a
2500: 70 56 61 6c 5b 32 5d 29 3b 0a 20 20 7a 45 6c 6c  pVal[2]);.  zEll
2510: 69 70 73 20 3d 20 28 63 6f 6e 73 74 20 63 68 61  ips = (const cha
2520: 72 2a 29 73 71 6c 69 74 65 33 5f 76 61 6c 75 65  r*)sqlite3_value
2530: 5f 74 65 78 74 28 61 70 56 61 6c 5b 33 5d 29 3b  _text(apVal[3]);
2540: 0a 20 20 6e 54 6f 6b 65 6e 20 3d 20 73 71 6c 69  .  nToken = sqli
2550: 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74 28 61 70  te3_value_int(ap
2560: 56 61 6c 5b 34 5d 29 3b 0a 20 20 69 42 65 73 74  Val[4]);.  iBest
2570: 4c 61 73 74 20 3d 20 6e 54 6f 6b 65 6e 2d 31 3b  Last = nToken-1;
2580: 0a 0a 20 20 69 42 65 73 74 43 6f 6c 20 3d 20 28  ..  iBestCol = (
2590: 69 43 6f 6c 3e 3d 30 20 3f 20 69 43 6f 6c 20 3a  iCol>=0 ? iCol :
25a0: 20 30 29 3b 0a 20 20 6e 50 68 72 61 73 65 20 3d   0);.  nPhrase =
25b0: 20 70 41 70 69 2d 3e 78 50 68 72 61 73 65 43 6f   pApi->xPhraseCo
25c0: 75 6e 74 28 70 46 74 73 29 3b 0a 20 20 61 53 65  unt(pFts);.  aSe
25d0: 65 6e 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c  en = sqlite3_mal
25e0: 6c 6f 63 28 6e 50 68 72 61 73 65 29 3b 0a 20 20  loc(nPhrase);.  
25f0: 69 66 28 20 61 53 65 65 6e 3d 3d 30 20 29 7b 0a  if( aSeen==0 ){.
2600: 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f      rc = SQLITE_
2610: 4e 4f 4d 45 4d 3b 0a 20 20 7d 0a 0a 20 20 69 66  NOMEM;.  }..  if
2620: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
2630: 29 7b 0a 20 20 20 20 72 63 20 3d 20 70 41 70 69  ){.    rc = pApi
2640: 2d 3e 78 49 6e 73 74 43 6f 75 6e 74 28 70 46 74  ->xInstCount(pFt
2650: 73 2c 20 26 6e 49 6e 73 74 29 3b 0a 20 20 7d 0a  s, &nInst);.  }.
2660: 20 20 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 53    for(i=0; rc==S
2670: 51 4c 49 54 45 5f 4f 4b 20 26 26 20 69 3c 6e 49  QLITE_OK && i<nI
2680: 6e 73 74 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 69  nst; i++){.    i
2690: 6e 74 20 69 70 2c 20 69 53 6e 69 70 70 65 74 43  nt ip, iSnippetC
26a0: 6f 6c 2c 20 69 53 74 61 72 74 3b 0a 20 20 20 20  ol, iStart;.    
26b0: 6d 65 6d 73 65 74 28 61 53 65 65 6e 2c 20 30 2c  memset(aSeen, 0,
26c0: 20 6e 50 68 72 61 73 65 29 3b 0a 20 20 20 20 72   nPhrase);.    r
26d0: 63 20 3d 20 70 41 70 69 2d 3e 78 49 6e 73 74 28  c = pApi->xInst(
26e0: 70 46 74 73 2c 20 69 2c 20 26 69 70 2c 20 26 69  pFts, i, &ip, &i
26f0: 53 6e 69 70 70 65 74 43 6f 6c 2c 20 26 69 53 74  SnippetCol, &iSt
2700: 61 72 74 29 3b 0a 20 20 20 20 69 66 28 20 72 63  art);.    if( rc
2710: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 28  ==SQLITE_OK && (
2720: 69 43 6f 6c 3c 30 20 7c 7c 20 69 53 6e 69 70 70  iCol<0 || iSnipp
2730: 65 74 43 6f 6c 3d 3d 69 43 6f 6c 29 20 29 7b 0a  etCol==iCol) ){.
2740: 20 20 20 20 20 20 69 6e 74 20 6e 53 63 6f 72 65        int nScore
2750: 20 3d 20 31 30 30 30 3b 0a 20 20 20 20 20 20 69   = 1000;.      i
2760: 6e 74 20 69 4c 61 73 74 20 3d 20 69 53 74 61 72  nt iLast = iStar
2770: 74 20 2d 20 31 20 2b 20 70 41 70 69 2d 3e 78 50  t - 1 + pApi->xP
2780: 68 72 61 73 65 53 69 7a 65 28 70 46 74 73 2c 20  hraseSize(pFts, 
2790: 69 70 29 3b 0a 20 20 20 20 20 20 69 6e 74 20 6a  ip);.      int j
27a0: 3b 0a 20 20 20 20 20 20 61 53 65 65 6e 5b 69 70  ;.      aSeen[ip
27b0: 5d 20 3d 20 31 3b 0a 0a 20 20 20 20 20 20 66 6f  ] = 1;..      fo
27c0: 72 28 6a 3d 69 2b 31 3b 20 72 63 3d 3d 53 51 4c  r(j=i+1; rc==SQL
27d0: 49 54 45 5f 4f 4b 20 26 26 20 6a 3c 6e 49 6e 73  ITE_OK && j<nIns
27e0: 74 3b 20 6a 2b 2b 29 7b 0a 20 20 20 20 20 20 20  t; j++){.       
27f0: 20 69 6e 74 20 69 63 3b 20 69 6e 74 20 69 6f 3b   int ic; int io;
2800: 20 69 6e 74 20 69 46 69 6e 61 6c 3b 0a 20 20 20   int iFinal;.   
2810: 20 20 20 20 20 72 63 20 3d 20 70 41 70 69 2d 3e       rc = pApi->
2820: 78 49 6e 73 74 28 70 46 74 73 2c 20 6a 2c 20 26  xInst(pFts, j, &
2830: 69 70 2c 20 26 69 63 2c 20 26 69 6f 29 3b 0a 20  ip, &ic, &io);. 
2840: 20 20 20 20 20 20 20 69 46 69 6e 61 6c 20 3d 20         iFinal = 
2850: 69 6f 20 2b 20 70 41 70 69 2d 3e 78 50 68 72 61  io + pApi->xPhra
2860: 73 65 53 69 7a 65 28 70 46 74 73 2c 20 69 70 29  seSize(pFts, ip)
2870: 20 2d 20 31 3b 0a 20 20 20 20 20 20 20 20 69 66   - 1;.        if
2880: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
2890: 26 26 20 69 63 3d 3d 69 53 6e 69 70 70 65 74 43  && ic==iSnippetC
28a0: 6f 6c 20 26 26 20 69 4c 61 73 74 3c 69 53 74 61  ol && iLast<iSta
28b0: 72 74 2b 6e 54 6f 6b 65 6e 20 29 7b 0a 20 20 20  rt+nToken ){.   
28c0: 20 20 20 20 20 20 20 6e 53 63 6f 72 65 20 2b 3d         nScore +=
28d0: 20 61 53 65 65 6e 5b 69 70 5d 20 3f 20 31 30 30   aSeen[ip] ? 100
28e0: 30 20 3a 20 31 3b 0a 20 20 20 20 20 20 20 20 20  0 : 1;.         
28f0: 20 61 53 65 65 6e 5b 69 70 5d 20 3d 20 31 3b 0a   aSeen[ip] = 1;.
2900: 20 20 20 20 20 20 20 20 20 20 69 66 28 20 69 46            if( iF
2910: 69 6e 61 6c 3e 69 4c 61 73 74 20 29 20 69 4c 61  inal>iLast ) iLa
2920: 73 74 20 3d 20 69 46 69 6e 61 6c 3b 0a 20 20 20  st = iFinal;.   
2930: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 0a       }.      }..
2940: 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51        if( rc==SQ
2950: 4c 49 54 45 5f 4f 4b 20 26 26 20 6e 53 63 6f 72  LITE_OK && nScor
2960: 65 3e 6e 42 65 73 74 53 63 6f 72 65 20 29 7b 0a  e>nBestScore ){.
2970: 20 20 20 20 20 20 20 20 69 42 65 73 74 43 6f 6c          iBestCol
2980: 20 3d 20 69 53 6e 69 70 70 65 74 43 6f 6c 3b 0a   = iSnippetCol;.
2990: 20 20 20 20 20 20 20 20 69 42 65 73 74 53 74 61          iBestSta
29a0: 72 74 20 3d 20 69 53 74 61 72 74 3b 0a 20 20 20  rt = iStart;.   
29b0: 20 20 20 20 20 69 42 65 73 74 4c 61 73 74 20 3d       iBestLast =
29c0: 20 69 4c 61 73 74 3b 0a 20 20 20 20 20 20 20 20   iLast;.        
29d0: 6e 42 65 73 74 53 63 6f 72 65 20 3d 20 6e 53 63  nBestScore = nSc
29e0: 6f 72 65 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  ore;.      }.   
29f0: 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20 72 63   }.  }..  if( rc
2a00: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20  ==SQLITE_OK ){. 
2a10: 20 20 20 72 63 20 3d 20 70 41 70 69 2d 3e 78 43     rc = pApi->xC
2a20: 6f 6c 75 6d 6e 53 69 7a 65 28 70 46 74 73 2c 20  olumnSize(pFts, 
2a30: 69 42 65 73 74 43 6f 6c 2c 20 26 6e 43 6f 6c 53  iBestCol, &nColS
2a40: 69 7a 65 29 3b 0a 20 20 7d 0a 20 20 69 66 28 20  ize);.  }.  if( 
2a50: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
2a60: 0a 20 20 20 20 72 63 20 3d 20 70 41 70 69 2d 3e  .    rc = pApi->
2a70: 78 43 6f 6c 75 6d 6e 54 65 78 74 28 70 46 74 73  xColumnText(pFts
2a80: 2c 20 69 42 65 73 74 43 6f 6c 2c 20 26 63 74 78  , iBestCol, &ctx
2a90: 2e 7a 49 6e 2c 20 26 63 74 78 2e 6e 49 6e 29 3b  .zIn, &ctx.nIn);
2aa0: 0a 20 20 7d 0a 20 20 69 66 28 20 63 74 78 2e 7a  .  }.  if( ctx.z
2ab0: 49 6e 20 29 7b 0a 20 20 20 20 69 66 28 20 72 63  In ){.    if( rc
2ac0: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20  ==SQLITE_OK ){. 
2ad0: 20 20 20 20 20 72 63 20 3d 20 66 74 73 35 43 49       rc = fts5CI
2ae0: 6e 73 74 49 74 65 72 49 6e 69 74 28 70 41 70 69  nstIterInit(pApi
2af0: 2c 20 70 46 74 73 2c 20 69 42 65 73 74 43 6f 6c  , pFts, iBestCol
2b00: 2c 20 26 63 74 78 2e 69 74 65 72 29 3b 0a 20 20  , &ctx.iter);.  
2b10: 20 20 7d 0a 0a 20 20 20 20 69 66 28 20 28 69 42    }..    if( (iB
2b20: 65 73 74 53 74 61 72 74 2b 6e 54 6f 6b 65 6e 2d  estStart+nToken-
2b30: 31 29 3e 69 42 65 73 74 4c 61 73 74 20 29 7b 0a  1)>iBestLast ){.
2b40: 20 20 20 20 20 20 69 42 65 73 74 53 74 61 72 74        iBestStart
2b50: 20 2d 3d 20 28 69 42 65 73 74 53 74 61 72 74 2b   -= (iBestStart+
2b60: 6e 54 6f 6b 65 6e 2d 31 2d 69 42 65 73 74 4c 61  nToken-1-iBestLa
2b70: 73 74 29 20 2f 20 32 3b 0a 20 20 20 20 7d 0a 20  st) / 2;.    }. 
2b80: 20 20 20 69 66 28 20 69 42 65 73 74 53 74 61 72     if( iBestStar
2b90: 74 2b 6e 54 6f 6b 65 6e 3e 6e 43 6f 6c 53 69 7a  t+nToken>nColSiz
2ba0: 65 20 29 7b 0a 20 20 20 20 20 20 69 42 65 73 74  e ){.      iBest
2bb0: 53 74 61 72 74 20 3d 20 6e 43 6f 6c 53 69 7a 65  Start = nColSize
2bc0: 20 2d 20 6e 54 6f 6b 65 6e 3b 0a 20 20 20 20 7d   - nToken;.    }
2bd0: 0a 20 20 20 20 69 66 28 20 69 42 65 73 74 53 74  .    if( iBestSt
2be0: 61 72 74 3c 30 20 29 20 69 42 65 73 74 53 74 61  art<0 ) iBestSta
2bf0: 72 74 20 3d 20 30 3b 0a 0a 20 20 20 20 63 74 78  rt = 0;..    ctx
2c00: 2e 69 52 61 6e 67 65 53 74 61 72 74 20 3d 20 69  .iRangeStart = i
2c10: 42 65 73 74 53 74 61 72 74 3b 0a 20 20 20 20 63  BestStart;.    c
2c20: 74 78 2e 69 52 61 6e 67 65 45 6e 64 20 3d 20 69  tx.iRangeEnd = i
2c30: 42 65 73 74 53 74 61 72 74 20 2b 20 6e 54 6f 6b  BestStart + nTok
2c40: 65 6e 20 2d 20 31 3b 0a 0a 20 20 20 20 69 66 28  en - 1;..    if(
2c50: 20 69 42 65 73 74 53 74 61 72 74 3e 30 20 29 7b   iBestStart>0 ){
2c60: 0a 20 20 20 20 20 20 66 74 73 35 48 69 67 68 6c  .      fts5Highl
2c70: 69 67 68 74 41 70 70 65 6e 64 28 26 72 63 2c 20  ightAppend(&rc, 
2c80: 26 63 74 78 2c 20 7a 45 6c 6c 69 70 73 2c 20 2d  &ctx, zEllips, -
2c90: 31 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66  1);.    }.    if
2ca0: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
2cb0: 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70 41  ){.      rc = pA
2cc0: 70 69 2d 3e 78 54 6f 6b 65 6e 69 7a 65 28 70 46  pi->xTokenize(pF
2cd0: 74 73 2c 20 63 74 78 2e 7a 49 6e 2c 20 63 74 78  ts, ctx.zIn, ctx
2ce0: 2e 6e 49 6e 2c 20 28 76 6f 69 64 2a 29 26 63 74  .nIn, (void*)&ct
2cf0: 78 2c 66 74 73 35 48 69 67 68 6c 69 67 68 74 43  x,fts5HighlightC
2d00: 62 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66  b);.    }.    if
2d10: 28 20 63 74 78 2e 69 52 61 6e 67 65 45 6e 64 3e  ( ctx.iRangeEnd>
2d20: 3d 28 6e 43 6f 6c 53 69 7a 65 2d 31 29 20 29 7b  =(nColSize-1) ){
2d30: 0a 20 20 20 20 20 20 66 74 73 35 48 69 67 68 6c  .      fts5Highl
2d40: 69 67 68 74 41 70 70 65 6e 64 28 26 72 63 2c 20  ightAppend(&rc, 
2d50: 26 63 74 78 2c 20 26 63 74 78 2e 7a 49 6e 5b 63  &ctx, &ctx.zIn[c
2d60: 74 78 2e 69 4f 66 66 5d 2c 20 63 74 78 2e 6e 49  tx.iOff], ctx.nI
2d70: 6e 20 2d 20 63 74 78 2e 69 4f 66 66 29 3b 0a 20  n - ctx.iOff);. 
2d80: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
2d90: 66 74 73 35 48 69 67 68 6c 69 67 68 74 41 70 70  fts5HighlightApp
2da0: 65 6e 64 28 26 72 63 2c 20 26 63 74 78 2c 20 7a  end(&rc, &ctx, z
2db0: 45 6c 6c 69 70 73 2c 20 2d 31 29 3b 0a 20 20 20  Ellips, -1);.   
2dc0: 20 7d 0a 0a 20 20 20 20 69 66 28 20 72 63 3d 3d   }..    if( rc==
2dd0: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
2de0: 20 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c     sqlite3_resul
2df0: 74 5f 74 65 78 74 28 70 43 74 78 2c 20 28 63 6f  t_text(pCtx, (co
2e00: 6e 73 74 20 63 68 61 72 2a 29 63 74 78 2e 7a 4f  nst char*)ctx.zO
2e10: 75 74 2c 20 2d 31 2c 20 53 51 4c 49 54 45 5f 54  ut, -1, SQLITE_T
2e20: 52 41 4e 53 49 45 4e 54 29 3b 0a 20 20 20 20 7d  RANSIENT);.    }
2e30: 65 6c 73 65 7b 0a 20 20 20 20 20 20 73 71 6c 69  else{.      sqli
2e40: 74 65 33 5f 72 65 73 75 6c 74 5f 65 72 72 6f 72  te3_result_error
2e50: 5f 63 6f 64 65 28 70 43 74 78 2c 20 72 63 29 3b  _code(pCtx, rc);
2e60: 0a 20 20 20 20 7d 0a 20 20 20 20 73 71 6c 69 74  .    }.    sqlit
2e70: 65 33 5f 66 72 65 65 28 63 74 78 2e 7a 4f 75 74  e3_free(ctx.zOut
2e80: 29 3b 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33  );.  }.  sqlite3
2e90: 5f 66 72 65 65 28 61 53 65 65 6e 29 3b 0a 7d 0a  _free(aSeen);.}.
2ea0: 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ./**************
2eb0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
2ec0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
2ed0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
2ee0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 0a  **********/../*.
2ef0: 2a 2a 20 54 68 65 20 66 69 72 73 74 20 74 69 6d  ** The first tim
2f00: 65 20 74 68 65 20 62 6d 32 35 28 29 20 66 75 6e  e the bm25() fun
2f10: 63 74 69 6f 6e 20 69 73 20 63 61 6c 6c 65 64 20  ction is called 
2f20: 66 6f 72 20 61 20 71 75 65 72 79 2c 20 61 6e 20  for a query, an 
2f30: 69 6e 73 74 61 6e 63 65 0a 2a 2a 20 6f 66 20 74  instance.** of t
2f40: 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 73 74 72  he following str
2f50: 75 63 74 75 72 65 20 69 73 20 61 6c 6c 6f 63 61  ucture is alloca
2f60: 74 65 64 20 61 6e 64 20 70 6f 70 75 6c 61 74 65  ted and populate
2f70: 64 2e 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73 74  d..*/.typedef st
2f80: 72 75 63 74 20 46 74 73 35 42 6d 32 35 44 61 74  ruct Fts5Bm25Dat
2f90: 61 20 46 74 73 35 42 6d 32 35 44 61 74 61 3b 0a  a Fts5Bm25Data;.
2fa0: 73 74 72 75 63 74 20 46 74 73 35 42 6d 32 35 44  struct Fts5Bm25D
2fb0: 61 74 61 20 7b 0a 20 20 69 6e 74 20 6e 50 68 72  ata {.  int nPhr
2fc0: 61 73 65 3b 20 20 20 20 20 20 20 20 20 20 20 20  ase;            
2fd0: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
2fe0: 72 20 6f 66 20 70 68 72 61 73 65 73 20 69 6e 20  r of phrases in 
2ff0: 71 75 65 72 79 20 2a 2f 0a 20 20 64 6f 75 62 6c  query */.  doubl
3000: 65 20 61 76 67 64 6c 3b 20 20 20 20 20 20 20 20  e avgdl;        
3010: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 41 76             /* Av
3020: 65 72 61 67 65 20 6e 75 6d 62 65 72 20 6f 66 20  erage number of 
3030: 74 6f 6b 65 6e 73 20 69 6e 20 65 61 63 68 20 72  tokens in each r
3040: 6f 77 20 2a 2f 0a 20 20 64 6f 75 62 6c 65 20 2a  ow */.  double *
3050: 61 49 44 46 3b 20 20 20 20 20 20 20 20 20 20 20  aIDF;           
3060: 20 20 20 20 20 20 20 20 2f 2a 20 49 44 46 20 66          /* IDF f
3070: 6f 72 20 65 61 63 68 20 70 68 72 61 73 65 20 2a  or each phrase *
3080: 2f 0a 20 20 64 6f 75 62 6c 65 20 2a 61 46 72 65  /.  double *aFre
3090: 71 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  q;              
30a0: 20 20 20 20 2f 2a 20 41 72 72 61 79 20 75 73 65      /* Array use
30b0: 64 20 74 6f 20 63 61 6c 63 75 6c 61 74 65 20 70  d to calculate p
30c0: 68 72 61 73 65 20 66 72 65 71 2e 20 2a 2f 0a 7d  hrase freq. */.}
30d0: 3b 0a 0a 2f 2a 0a 2a 2a 20 43 61 6c 6c 62 61 63  ;../*.** Callbac
30e0: 6b 20 75 73 65 64 20 62 79 20 66 74 73 35 42 6d  k used by fts5Bm
30f0: 32 35 47 65 74 44 61 74 61 28 29 20 74 6f 20 63  25GetData() to c
3100: 6f 75 6e 74 20 74 68 65 20 6e 75 6d 62 65 72 20  ount the number 
3110: 6f 66 20 72 6f 77 73 20 69 6e 20 74 68 65 0a 2a  of rows in the.*
3120: 2a 20 74 61 62 6c 65 20 6d 61 74 63 68 65 64 20  * table matched 
3130: 62 79 20 65 61 63 68 20 69 6e 64 69 76 69 64 75  by each individu
3140: 61 6c 20 70 68 72 61 73 65 20 77 69 74 68 69 6e  al phrase within
3150: 20 74 68 65 20 71 75 65 72 79 2e 0a 2a 2f 0a 73   the query..*/.s
3160: 74 61 74 69 63 20 69 6e 74 20 66 74 73 35 43 6f  tatic int fts5Co
3170: 75 6e 74 43 62 28 0a 20 20 63 6f 6e 73 74 20 46  untCb(.  const F
3180: 74 73 35 45 78 74 65 6e 73 69 6f 6e 41 70 69 20  ts5ExtensionApi 
3190: 2a 70 41 70 69 2c 20 0a 20 20 46 74 73 35 43 6f  *pApi, .  Fts5Co
31a0: 6e 74 65 78 74 20 2a 70 46 74 73 2c 0a 20 20 76  ntext *pFts,.  v
31b0: 6f 69 64 20 2a 70 55 73 65 72 44 61 74 61 20 20  oid *pUserData  
31c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
31d0: 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20 73 71 6c  * Pointer to sql
31e0: 69 74 65 33 5f 69 6e 74 36 34 20 76 61 72 69 61  ite3_int64 varia
31f0: 62 6c 65 20 2a 2f 0a 29 7b 0a 20 20 73 71 6c 69  ble */.){.  sqli
3200: 74 65 33 5f 69 6e 74 36 34 20 2a 70 6e 20 3d 20  te3_int64 *pn = 
3210: 28 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 2a 29  (sqlite3_int64*)
3220: 70 55 73 65 72 44 61 74 61 3b 0a 20 20 55 4e 55  pUserData;.  UNU
3230: 53 45 44 5f 50 41 52 41 4d 32 28 70 41 70 69 2c  SED_PARAM2(pApi,
3240: 20 70 46 74 73 29 3b 0a 20 20 28 2a 70 6e 29 2b   pFts);.  (*pn)+
3250: 2b 3b 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49  +;.  return SQLI
3260: 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  TE_OK;.}../*.** 
3270: 53 65 74 20 2a 70 70 44 61 74 61 20 74 6f 20 70  Set *ppData to p
3280: 6f 69 6e 74 20 74 6f 20 74 68 65 20 46 74 73 35  oint to the Fts5
3290: 42 6d 32 35 44 61 74 61 20 6f 62 6a 65 63 74 20  Bm25Data object 
32a0: 66 6f 72 20 74 68 65 20 63 75 72 72 65 6e 74 20  for the current 
32b0: 71 75 65 72 79 2e 20 0a 2a 2a 20 49 66 20 74 68  query. .** If th
32c0: 65 20 6f 62 6a 65 63 74 20 68 61 73 20 6e 6f 74  e object has not
32d0: 20 61 6c 72 65 61 64 79 20 62 65 65 6e 20 61 6c   already been al
32e0: 6c 6f 63 61 74 65 64 2c 20 61 6c 6c 6f 63 61 74  located, allocat
32f0: 65 20 61 6e 64 20 70 6f 70 75 6c 61 74 65 20 69  e and populate i
3300: 74 0a 2a 2a 20 6e 6f 77 2e 0a 2a 2f 0a 73 74 61  t.** now..*/.sta
3310: 74 69 63 20 69 6e 74 20 66 74 73 35 42 6d 32 35  tic int fts5Bm25
3320: 47 65 74 44 61 74 61 28 0a 20 20 63 6f 6e 73 74  GetData(.  const
3330: 20 46 74 73 35 45 78 74 65 6e 73 69 6f 6e 41 70   Fts5ExtensionAp
3340: 69 20 2a 70 41 70 69 2c 20 0a 20 20 46 74 73 35  i *pApi, .  Fts5
3350: 43 6f 6e 74 65 78 74 20 2a 70 46 74 73 2c 0a 20  Context *pFts,. 
3360: 20 46 74 73 35 42 6d 32 35 44 61 74 61 20 2a 2a   Fts5Bm25Data **
3370: 70 70 44 61 74 61 20 20 20 20 20 20 20 20 20 20  ppData          
3380: 20 2f 2a 20 4f 55 54 3a 20 62 6d 32 35 2d 64 61   /* OUT: bm25-da
3390: 74 61 20 6f 62 6a 65 63 74 20 66 6f 72 20 74 68  ta object for th
33a0: 69 73 20 71 75 65 72 79 20 2a 2f 0a 29 7b 0a 20  is query */.){. 
33b0: 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45   int rc = SQLITE
33c0: 5f 4f 4b 3b 20 20 20 20 20 20 20 20 20 20 20 20  _OK;            
33d0: 20 2f 2a 20 52 65 74 75 72 6e 20 63 6f 64 65 20   /* Return code 
33e0: 2a 2f 0a 20 20 46 74 73 35 42 6d 32 35 44 61 74  */.  Fts5Bm25Dat
33f0: 61 20 2a 70 3b 20 20 20 20 20 20 20 20 20 20 20  a *p;           
3400: 20 20 20 20 20 2f 2a 20 4f 62 6a 65 63 74 20 74       /* Object t
3410: 6f 20 72 65 74 75 72 6e 20 2a 2f 0a 0a 20 20 70  o return */..  p
3420: 20 3d 20 70 41 70 69 2d 3e 78 47 65 74 41 75 78   = pApi->xGetAux
3430: 64 61 74 61 28 70 46 74 73 2c 20 30 29 3b 0a 20  data(pFts, 0);. 
3440: 20 69 66 28 20 70 3d 3d 30 20 29 7b 0a 20 20 20   if( p==0 ){.   
3450: 20 69 6e 74 20 6e 50 68 72 61 73 65 3b 20 20 20   int nPhrase;   
3460: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
3470: 2a 20 4e 75 6d 62 65 72 20 6f 66 20 70 68 72 61  * Number of phra
3480: 73 65 73 20 69 6e 20 71 75 65 72 79 20 2a 2f 0a  ses in query */.
3490: 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36      sqlite3_int6
34a0: 34 20 6e 52 6f 77 20 3d 20 30 3b 20 20 20 20 20  4 nRow = 0;     
34b0: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 72    /* Number of r
34c0: 6f 77 73 20 69 6e 20 74 61 62 6c 65 20 2a 2f 0a  ows in table */.
34d0: 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36      sqlite3_int6
34e0: 34 20 6e 54 6f 6b 65 6e 20 3d 20 30 3b 20 20 20  4 nToken = 0;   
34f0: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 74    /* Number of t
3500: 6f 6b 65 6e 73 20 69 6e 20 74 61 62 6c 65 20 2a  okens in table *
3510: 2f 0a 20 20 20 20 69 6e 74 20 6e 42 79 74 65 3b  /.    int nByte;
3520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3530: 20 20 20 20 2f 2a 20 42 79 74 65 73 20 6f 66 20      /* Bytes of 
3540: 73 70 61 63 65 20 74 6f 20 61 6c 6c 6f 63 61 74  space to allocat
3550: 65 20 2a 2f 0a 20 20 20 20 69 6e 74 20 69 3b 0a  e */.    int i;.
3560: 0a 20 20 20 20 2f 2a 20 41 6c 6c 6f 63 61 74 65  .    /* Allocate
3570: 20 74 68 65 20 46 74 73 35 42 6d 32 35 44 61 74   the Fts5Bm25Dat
3580: 61 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 20 20  a object */.    
3590: 6e 50 68 72 61 73 65 20 3d 20 70 41 70 69 2d 3e  nPhrase = pApi->
35a0: 78 50 68 72 61 73 65 43 6f 75 6e 74 28 70 46 74  xPhraseCount(pFt
35b0: 73 29 3b 0a 20 20 20 20 6e 42 79 74 65 20 3d 20  s);.    nByte = 
35c0: 73 69 7a 65 6f 66 28 46 74 73 35 42 6d 32 35 44  sizeof(Fts5Bm25D
35d0: 61 74 61 29 20 2b 20 6e 50 68 72 61 73 65 2a 32  ata) + nPhrase*2
35e0: 2a 73 69 7a 65 6f 66 28 64 6f 75 62 6c 65 29 3b  *sizeof(double);
35f0: 0a 20 20 20 20 70 20 3d 20 28 46 74 73 35 42 6d  .    p = (Fts5Bm
3600: 32 35 44 61 74 61 2a 29 73 71 6c 69 74 65 33 5f  25Data*)sqlite3_
3610: 6d 61 6c 6c 6f 63 28 6e 42 79 74 65 29 3b 0a 20  malloc(nByte);. 
3620: 20 20 20 69 66 28 20 70 3d 3d 30 20 29 7b 0a 20     if( p==0 ){. 
3630: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
3640: 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 65 6c 73  _NOMEM;.    }els
3650: 65 7b 0a 20 20 20 20 20 20 6d 65 6d 73 65 74 28  e{.      memset(
3660: 70 2c 20 30 2c 20 6e 42 79 74 65 29 3b 0a 20 20  p, 0, nByte);.  
3670: 20 20 20 20 70 2d 3e 6e 50 68 72 61 73 65 20 3d      p->nPhrase =
3680: 20 6e 50 68 72 61 73 65 3b 0a 20 20 20 20 20 20   nPhrase;.      
3690: 70 2d 3e 61 49 44 46 20 3d 20 28 64 6f 75 62 6c  p->aIDF = (doubl
36a0: 65 2a 29 26 70 5b 31 5d 3b 0a 20 20 20 20 20 20  e*)&p[1];.      
36b0: 70 2d 3e 61 46 72 65 71 20 3d 20 26 70 2d 3e 61  p->aFreq = &p->a
36c0: 49 44 46 5b 6e 50 68 72 61 73 65 5d 3b 0a 20 20  IDF[nPhrase];.  
36d0: 20 20 7d 0a 0a 20 20 20 20 2f 2a 20 43 61 6c 63    }..    /* Calc
36e0: 75 6c 61 74 65 20 74 68 65 20 61 76 65 72 61 67  ulate the averag
36f0: 65 20 64 6f 63 75 6d 65 6e 74 20 6c 65 6e 67 74  e document lengt
3700: 68 20 66 6f 72 20 74 68 69 73 20 46 54 53 35 20  h for this FTS5 
3710: 74 61 62 6c 65 20 2a 2f 0a 20 20 20 20 69 66 28  table */.    if(
3720: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29   rc==SQLITE_OK )
3730: 20 72 63 20 3d 20 70 41 70 69 2d 3e 78 52 6f 77   rc = pApi->xRow
3740: 43 6f 75 6e 74 28 70 46 74 73 2c 20 26 6e 52 6f  Count(pFts, &nRo
3750: 77 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d  w);.    if( rc==
3760: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63 20 3d  SQLITE_OK ) rc =
3770: 20 70 41 70 69 2d 3e 78 43 6f 6c 75 6d 6e 54 6f   pApi->xColumnTo
3780: 74 61 6c 53 69 7a 65 28 70 46 74 73 2c 20 2d 31  talSize(pFts, -1
3790: 2c 20 26 6e 54 6f 6b 65 6e 29 3b 0a 20 20 20 20  , &nToken);.    
37a0: 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f  if( rc==SQLITE_O
37b0: 4b 20 29 20 70 2d 3e 61 76 67 64 6c 20 3d 20 28  K ) p->avgdl = (
37c0: 64 6f 75 62 6c 65 29 6e 54 6f 6b 65 6e 20 20 2f  double)nToken  /
37d0: 20 28 64 6f 75 62 6c 65 29 6e 52 6f 77 3b 0a 0a   (double)nRow;..
37e0: 20 20 20 20 2f 2a 20 43 61 6c 63 75 6c 61 74 65      /* Calculate
37f0: 20 61 6e 20 49 44 46 20 66 6f 72 20 65 61 63 68   an IDF for each
3800: 20 70 68 72 61 73 65 20 69 6e 20 74 68 65 20 71   phrase in the q
3810: 75 65 72 79 20 2a 2f 0a 20 20 20 20 66 6f 72 28  uery */.    for(
3820: 69 3d 30 3b 20 72 63 3d 3d 53 51 4c 49 54 45 5f  i=0; rc==SQLITE_
3830: 4f 4b 20 26 26 20 69 3c 6e 50 68 72 61 73 65 3b  OK && i<nPhrase;
3840: 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 73 71 6c   i++){.      sql
3850: 69 74 65 33 5f 69 6e 74 36 34 20 6e 48 69 74 20  ite3_int64 nHit 
3860: 3d 20 30 3b 0a 20 20 20 20 20 20 72 63 20 3d 20  = 0;.      rc = 
3870: 70 41 70 69 2d 3e 78 51 75 65 72 79 50 68 72 61  pApi->xQueryPhra
3880: 73 65 28 70 46 74 73 2c 20 69 2c 20 28 76 6f 69  se(pFts, i, (voi
3890: 64 2a 29 26 6e 48 69 74 2c 20 66 74 73 35 43 6f  d*)&nHit, fts5Co
38a0: 75 6e 74 43 62 29 3b 0a 20 20 20 20 20 20 69 66  untCb);.      if
38b0: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
38c0: 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20 43 61  ){.        /* Ca
38d0: 6c 63 75 6c 61 74 65 20 74 68 65 20 49 44 46 20  lculate the IDF 
38e0: 28 49 6e 76 65 72 73 65 20 44 6f 63 75 6d 65 6e  (Inverse Documen
38f0: 74 20 46 72 65 71 75 65 6e 63 79 29 20 66 6f 72  t Frequency) for
3900: 20 70 68 72 61 73 65 20 69 2e 0a 20 20 20 20 20   phrase i..     
3910: 20 20 20 2a 2a 20 54 68 69 73 20 69 73 20 64 6f     ** This is do
3920: 6e 65 20 75 73 69 6e 67 20 74 68 65 20 73 74 61  ne using the sta
3930: 6e 64 61 72 64 20 42 4d 32 35 20 66 6f 72 6d 75  ndard BM25 formu
3940: 6c 61 20 61 73 20 66 6f 75 6e 64 20 6f 6e 20 77  la as found on w
3950: 69 6b 69 70 65 64 69 61 3a 0a 20 20 20 20 20 20  ikipedia:.      
3960: 20 20 2a 2a 0a 20 20 20 20 20 20 20 20 2a 2a 20    **.        ** 
3970: 20 20 49 44 46 20 3d 20 6c 6f 67 28 20 28 4e 20    IDF = log( (N 
3980: 2d 20 6e 48 69 74 20 2b 20 30 2e 35 29 20 2f 20  - nHit + 0.5) / 
3990: 28 6e 48 69 74 20 2b 20 30 2e 35 29 20 29 0a 20  (nHit + 0.5) ). 
39a0: 20 20 20 20 20 20 20 2a 2a 0a 20 20 20 20 20 20         **.      
39b0: 20 20 2a 2a 20 77 68 65 72 65 20 22 4e 22 20 69    ** where "N" i
39c0: 73 20 74 68 65 20 74 6f 74 61 6c 20 6e 75 6d 62  s the total numb
39d0: 65 72 20 6f 66 20 64 6f 63 75 6d 65 6e 74 73 20  er of documents 
39e0: 69 6e 20 74 68 65 20 73 65 74 20 61 6e 64 20 6e  in the set and n
39f0: 48 69 74 0a 20 20 20 20 20 20 20 20 2a 2a 20 69  Hit.        ** i
3a00: 73 20 74 68 65 20 6e 75 6d 62 65 72 20 74 68 61  s the number tha
3a10: 74 20 63 6f 6e 74 61 69 6e 20 61 74 20 6c 65 61  t contain at lea
3a20: 73 74 20 6f 6e 65 20 69 6e 73 74 61 6e 63 65 20  st one instance 
3a30: 6f 66 20 74 68 65 20 70 68 72 61 73 65 0a 20 20  of the phrase.  
3a40: 20 20 20 20 20 20 2a 2a 20 75 6e 64 65 72 20 63        ** under c
3a50: 6f 6e 73 69 64 65 72 61 74 69 6f 6e 2e 0a 20 20  onsideration..  
3a60: 20 20 20 20 20 20 2a 2a 0a 20 20 20 20 20 20 20        **.       
3a70: 20 2a 2a 20 54 68 65 20 70 72 6f 62 6c 65 6d 20   ** The problem 
3a80: 77 69 74 68 20 74 68 69 73 20 69 73 20 74 68 61  with this is tha
3a90: 74 20 69 66 20 28 4e 20 3c 20 32 2a 6e 48 69 74  t if (N < 2*nHit
3aa0: 29 2c 20 74 68 65 20 49 44 46 20 69 73 20 0a 20  ), the IDF is . 
3ab0: 20 20 20 20 20 20 20 2a 2a 20 6e 65 67 61 74 69         ** negati
3ac0: 76 65 2e 20 57 68 69 63 68 20 69 73 20 75 6e 64  ve. Which is und
3ad0: 65 73 69 72 61 62 6c 65 2e 20 53 6f 20 74 68 65  esirable. So the
3ae0: 20 6d 69 6d 69 6d 75 6d 20 61 6c 6c 6f 77 61 62   mimimum allowab
3af0: 6c 65 20 49 44 46 20 69 73 0a 20 20 20 20 20 20  le IDF is.      
3b00: 20 20 2a 2a 20 28 31 65 2d 36 29 20 2d 20 72 6f    ** (1e-6) - ro
3b10: 75 67 68 6c 79 20 74 68 65 20 73 61 6d 65 20 61  ughly the same a
3b20: 73 20 61 20 74 65 72 6d 20 74 68 61 74 20 61 70  s a term that ap
3b30: 70 65 61 72 73 20 69 6e 20 6a 75 73 74 20 6f 76  pears in just ov
3b40: 65 72 0a 20 20 20 20 20 20 20 20 2a 2a 20 68 61  er.        ** ha
3b50: 6c 66 20 6f 66 20 73 65 74 20 6f 66 20 35 2c 30  lf of set of 5,0
3b60: 30 30 2c 30 30 30 20 64 6f 63 75 6d 65 6e 74 73  00,000 documents
3b70: 2e 20 20 2a 2f 0a 20 20 20 20 20 20 20 20 64 6f  .  */.        do
3b80: 75 62 6c 65 20 69 64 66 20 3d 20 6c 6f 67 28 20  uble idf = log( 
3b90: 28 6e 52 6f 77 20 2d 20 6e 48 69 74 20 2b 20 30  (nRow - nHit + 0
3ba0: 2e 35 29 20 2f 20 28 6e 48 69 74 20 2b 20 30 2e  .5) / (nHit + 0.
3bb0: 35 29 20 29 3b 0a 20 20 20 20 20 20 20 20 69 66  5) );.        if
3bc0: 28 20 69 64 66 3c 3d 30 2e 30 20 29 20 69 64 66  ( idf<=0.0 ) idf
3bd0: 20 3d 20 31 65 2d 36 3b 0a 20 20 20 20 20 20 20   = 1e-6;.       
3be0: 20 70 2d 3e 61 49 44 46 5b 69 5d 20 3d 20 69 64   p->aIDF[i] = id
3bf0: 66 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d  f;.      }.    }
3c00: 0a 0a 20 20 20 20 69 66 28 20 72 63 21 3d 53 51  ..    if( rc!=SQ
3c10: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20  LITE_OK ){.     
3c20: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 29   sqlite3_free(p)
3c30: 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20  ;.    }else{.   
3c40: 20 20 20 72 63 20 3d 20 70 41 70 69 2d 3e 78 53     rc = pApi->xS
3c50: 65 74 41 75 78 64 61 74 61 28 70 46 74 73 2c 20  etAuxdata(pFts, 
3c60: 70 2c 20 73 71 6c 69 74 65 33 5f 66 72 65 65 29  p, sqlite3_free)
3c70: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20  ;.    }.    if( 
3c80: 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20  rc!=SQLITE_OK ) 
3c90: 70 20 3d 20 30 3b 0a 20 20 7d 0a 20 20 2a 70 70  p = 0;.  }.  *pp
3ca0: 44 61 74 61 20 3d 20 70 3b 0a 20 20 72 65 74 75  Data = p;.  retu
3cb0: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  rn rc;.}../*.** 
3cc0: 49 6d 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 20 6f  Implementation o
3cd0: 66 20 62 6d 32 35 28 29 20 66 75 6e 63 74 69 6f  f bm25() functio
3ce0: 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  n..*/.static voi
3cf0: 64 20 66 74 73 35 42 6d 32 35 46 75 6e 63 74 69  d fts5Bm25Functi
3d00: 6f 6e 28 0a 20 20 63 6f 6e 73 74 20 46 74 73 35  on(.  const Fts5
3d10: 45 78 74 65 6e 73 69 6f 6e 41 70 69 20 2a 70 41  ExtensionApi *pA
3d20: 70 69 2c 20 20 20 2f 2a 20 41 50 49 20 6f 66 66  pi,   /* API off
3d30: 65 72 65 64 20 62 79 20 63 75 72 72 65 6e 74 20  ered by current 
3d40: 46 54 53 20 76 65 72 73 69 6f 6e 20 2a 2f 0a 20  FTS version */. 
3d50: 20 46 74 73 35 43 6f 6e 74 65 78 74 20 2a 70 46   Fts5Context *pF
3d60: 74 73 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  ts,             
3d70: 20 2f 2a 20 46 69 72 73 74 20 61 72 67 20 74 6f   /* First arg to
3d80: 20 70 61 73 73 20 74 6f 20 70 41 70 69 20 66 75   pass to pApi fu
3d90: 6e 63 74 69 6f 6e 73 20 2a 2f 0a 20 20 73 71 6c  nctions */.  sql
3da0: 69 74 65 33 5f 63 6f 6e 74 65 78 74 20 2a 70 43  ite3_context *pC
3db0: 74 78 2c 20 20 20 20 20 20 20 20 20 20 2f 2a 20  tx,          /* 
3dc0: 43 6f 6e 74 65 78 74 20 66 6f 72 20 72 65 74 75  Context for retu
3dd0: 72 6e 69 6e 67 20 72 65 73 75 6c 74 2f 65 72 72  rning result/err
3de0: 6f 72 20 2a 2f 0a 20 20 69 6e 74 20 6e 56 61 6c  or */.  int nVal
3df0: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
3e00: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
3e10: 72 20 6f 66 20 76 61 6c 75 65 73 20 69 6e 20 61  r of values in a
3e20: 70 56 61 6c 5b 5d 20 61 72 72 61 79 20 2a 2f 0a  pVal[] array */.
3e30: 20 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 20    sqlite3_value 
3e40: 2a 2a 61 70 56 61 6c 20 20 20 20 20 20 20 20 20  **apVal         
3e50: 20 20 2f 2a 20 41 72 72 61 79 20 6f 66 20 74 72    /* Array of tr
3e60: 61 69 6c 69 6e 67 20 61 72 67 75 6d 65 6e 74 73  ailing arguments
3e70: 20 2a 2f 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 64   */.){.  const d
3e80: 6f 75 62 6c 65 20 6b 31 20 3d 20 31 2e 32 3b 20  ouble k1 = 1.2; 
3e90: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6e 73           /* Cons
3ea0: 74 61 6e 74 20 22 6b 31 22 20 66 72 6f 6d 20 42  tant "k1" from B
3eb0: 4d 32 35 20 66 6f 72 6d 75 6c 61 20 2a 2f 0a 20  M25 formula */. 
3ec0: 20 63 6f 6e 73 74 20 64 6f 75 62 6c 65 20 62 20   const double b 
3ed0: 3d 20 30 2e 37 35 3b 20 20 20 20 20 20 20 20 20  = 0.75;         
3ee0: 20 2f 2a 20 43 6f 6e 73 74 61 6e 74 20 22 62 22   /* Constant "b"
3ef0: 20 66 72 6f 6d 20 42 4d 32 35 20 66 6f 72 6d 75   from BM25 formu
3f00: 6c 61 20 2a 2f 0a 20 20 69 6e 74 20 72 63 20 3d  la */.  int rc =
3f10: 20 53 51 4c 49 54 45 5f 4f 4b 3b 20 20 20 20 20   SQLITE_OK;     
3f20: 20 20 20 20 20 20 20 20 2f 2a 20 45 72 72 6f 72          /* Error
3f30: 20 63 6f 64 65 20 2a 2f 0a 20 20 64 6f 75 62 6c   code */.  doubl
3f40: 65 20 73 63 6f 72 65 20 3d 20 30 2e 30 3b 20 20  e score = 0.0;  
3f50: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 51             /* SQ
3f60: 4c 20 66 75 6e 63 74 69 6f 6e 20 72 65 74 75 72  L function retur
3f70: 6e 20 76 61 6c 75 65 20 2a 2f 0a 20 20 46 74 73  n value */.  Fts
3f80: 35 42 6d 32 35 44 61 74 61 20 2a 70 44 61 74 61  5Bm25Data *pData
3f90: 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20  ;            /* 
3fa0: 56 61 6c 75 65 73 20 61 6c 6c 6f 63 61 74 65 64  Values allocated
3fb0: 2f 63 61 6c 63 75 6c 61 74 65 64 20 6f 6e 63 65  /calculated once
3fc0: 20 6f 6e 6c 79 20 2a 2f 0a 20 20 69 6e 74 20 69   only */.  int i
3fd0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
3fe0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49 74             /* It
3ff0: 65 72 61 74 6f 72 20 76 61 72 69 61 62 6c 65 20  erator variable 
4000: 2a 2f 0a 20 20 69 6e 74 20 6e 49 6e 73 74 20 3d  */.  int nInst =
4010: 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   0;             
4020: 20 20 20 20 20 2f 2a 20 56 61 6c 75 65 20 72 65       /* Value re
4030: 74 75 72 6e 65 64 20 62 79 20 78 49 6e 73 74 43  turned by xInstC
4040: 6f 75 6e 74 28 29 20 2a 2f 0a 20 20 64 6f 75 62  ount() */.  doub
4050: 6c 65 20 44 20 3d 20 30 2e 30 3b 20 20 20 20 20  le D = 0.0;     
4060: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54              /* T
4070: 6f 74 61 6c 20 6e 75 6d 62 65 72 20 6f 66 20 74  otal number of t
4080: 6f 6b 65 6e 73 20 69 6e 20 72 6f 77 20 2a 2f 0a  okens in row */.
4090: 20 20 64 6f 75 62 6c 65 20 2a 61 46 72 65 71 20    double *aFreq 
40a0: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
40b0: 20 20 2f 2a 20 41 72 72 61 79 20 6f 66 20 70 68    /* Array of ph
40c0: 72 61 73 65 20 66 72 65 71 2e 20 66 6f 72 20 63  rase freq. for c
40d0: 75 72 72 65 6e 74 20 72 6f 77 20 2a 2f 0a 0a 20  urrent row */.. 
40e0: 20 2f 2a 20 43 61 6c 63 75 6c 61 74 65 20 74 68   /* Calculate th
40f0: 65 20 70 68 72 61 73 65 20 66 72 65 71 75 65 6e  e phrase frequen
4100: 63 79 20 28 73 79 6d 62 6f 6c 20 22 66 28 71 69  cy (symbol "f(qi
4110: 2c 44 29 22 20 69 6e 20 74 68 65 20 64 6f 63 75  ,D)" in the docu
4120: 6d 65 6e 74 61 74 69 6f 6e 29 0a 20 20 2a 2a 20  mentation).  ** 
4130: 66 6f 72 20 65 61 63 68 20 70 68 72 61 73 65 20  for each phrase 
4140: 69 6e 20 74 68 65 20 71 75 65 72 79 20 66 6f 72  in the query for
4150: 20 74 68 65 20 63 75 72 72 65 6e 74 20 72 6f 77   the current row
4160: 2e 20 2a 2f 0a 20 20 72 63 20 3d 20 66 74 73 35  . */.  rc = fts5
4170: 42 6d 32 35 47 65 74 44 61 74 61 28 70 41 70 69  Bm25GetData(pApi
4180: 2c 20 70 46 74 73 2c 20 26 70 44 61 74 61 29 3b  , pFts, &pData);
4190: 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54  .  if( rc==SQLIT
41a0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 61 46 72 65  E_OK ){.    aFre
41b0: 71 20 3d 20 70 44 61 74 61 2d 3e 61 46 72 65 71  q = pData->aFreq
41c0: 3b 0a 20 20 20 20 6d 65 6d 73 65 74 28 61 46 72  ;.    memset(aFr
41d0: 65 71 2c 20 30 2c 20 73 69 7a 65 6f 66 28 64 6f  eq, 0, sizeof(do
41e0: 75 62 6c 65 29 20 2a 20 70 44 61 74 61 2d 3e 6e  uble) * pData->n
41f0: 50 68 72 61 73 65 29 3b 0a 20 20 20 20 72 63 20  Phrase);.    rc 
4200: 3d 20 70 41 70 69 2d 3e 78 49 6e 73 74 43 6f 75  = pApi->xInstCou
4210: 6e 74 28 70 46 74 73 2c 20 26 6e 49 6e 73 74 29  nt(pFts, &nInst)
4220: 3b 0a 20 20 7d 0a 20 20 66 6f 72 28 69 3d 30 3b  ;.  }.  for(i=0;
4230: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
4240: 26 20 69 3c 6e 49 6e 73 74 3b 20 69 2b 2b 29 7b  & i<nInst; i++){
4250: 0a 20 20 20 20 69 6e 74 20 69 70 3b 20 69 6e 74  .    int ip; int
4260: 20 69 63 3b 20 69 6e 74 20 69 6f 3b 0a 20 20 20   ic; int io;.   
4270: 20 72 63 20 3d 20 70 41 70 69 2d 3e 78 49 6e 73   rc = pApi->xIns
4280: 74 28 70 46 74 73 2c 20 69 2c 20 26 69 70 2c 20  t(pFts, i, &ip, 
4290: 26 69 63 2c 20 26 69 6f 29 3b 0a 20 20 20 20 69  &ic, &io);.    i
42a0: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
42b0: 20 29 7b 0a 20 20 20 20 20 20 64 6f 75 62 6c 65   ){.      double
42c0: 20 77 20 3d 20 28 6e 56 61 6c 20 3e 20 69 63 29   w = (nVal > ic)
42d0: 20 3f 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65   ? sqlite3_value
42e0: 5f 64 6f 75 62 6c 65 28 61 70 56 61 6c 5b 69 63  _double(apVal[ic
42f0: 5d 29 20 3a 20 31 2e 30 3b 0a 20 20 20 20 20 20  ]) : 1.0;.      
4300: 61 46 72 65 71 5b 69 70 5d 20 2b 3d 20 77 3b 0a  aFreq[ip] += w;.
4310: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f 2a 20      }.  }..  /* 
4320: 46 69 67 75 72 65 20 6f 75 74 20 74 68 65 20 74  Figure out the t
4330: 6f 74 61 6c 20 73 69 7a 65 20 6f 66 20 74 68 65  otal size of the
4340: 20 63 75 72 72 65 6e 74 20 72 6f 77 20 69 6e 20   current row in 
4350: 74 6f 6b 65 6e 73 2e 20 2a 2f 0a 20 20 69 66 28  tokens. */.  if(
4360: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29   rc==SQLITE_OK )
4370: 7b 0a 20 20 20 20 69 6e 74 20 6e 54 6f 6b 3b 0a  {.    int nTok;.
4380: 20 20 20 20 72 63 20 3d 20 70 41 70 69 2d 3e 78      rc = pApi->x
4390: 43 6f 6c 75 6d 6e 53 69 7a 65 28 70 46 74 73 2c  ColumnSize(pFts,
43a0: 20 2d 31 2c 20 26 6e 54 6f 6b 29 3b 0a 20 20 20   -1, &nTok);.   
43b0: 20 44 20 3d 20 28 64 6f 75 62 6c 65 29 6e 54 6f   D = (double)nTo
43c0: 6b 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 44 65 74  k;.  }..  /* Det
43d0: 65 72 6d 69 6e 65 20 74 68 65 20 42 4d 32 35 20  ermine the BM25 
43e0: 73 63 6f 72 65 20 66 6f 72 20 74 68 65 20 63 75  score for the cu
43f0: 72 72 65 6e 74 20 72 6f 77 2e 20 2a 2f 0a 20 20  rrent row. */.  
4400: 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 53 51 4c  for(i=0; rc==SQL
4410: 49 54 45 5f 4f 4b 20 26 26 20 69 3c 70 44 61 74  ITE_OK && i<pDat
4420: 61 2d 3e 6e 50 68 72 61 73 65 3b 20 69 2b 2b 29  a->nPhrase; i++)
4430: 7b 0a 20 20 20 20 73 63 6f 72 65 20 2b 3d 20 70  {.    score += p
4440: 44 61 74 61 2d 3e 61 49 44 46 5b 69 5d 20 2a 20  Data->aIDF[i] * 
4450: 28 0a 20 20 20 20 20 20 28 20 61 46 72 65 71 5b  (.      ( aFreq[
4460: 69 5d 20 2a 20 28 6b 31 20 2b 20 31 2e 30 29 20  i] * (k1 + 1.0) 
4470: 29 20 2f 20 0a 20 20 20 20 20 20 28 20 61 46 72  ) / .      ( aFr
4480: 65 71 5b 69 5d 20 2b 20 6b 31 20 2a 20 28 31 20  eq[i] + k1 * (1 
4490: 2d 20 62 20 2b 20 62 20 2a 20 44 20 2f 20 70 44  - b + b * D / pD
44a0: 61 74 61 2d 3e 61 76 67 64 6c 29 20 29 0a 20 20  ata->avgdl) ).  
44b0: 20 20 29 3b 0a 20 20 7d 0a 20 20 0a 20 20 2f 2a    );.  }.  .  /*
44c0: 20 49 66 20 6e 6f 20 65 72 72 6f 72 20 68 61 73   If no error has
44d0: 20 6f 63 63 75 72 72 65 64 2c 20 72 65 74 75 72   occurred, retur
44e0: 6e 20 74 68 65 20 63 61 6c 63 75 6c 61 74 65 64  n the calculated
44f0: 20 73 63 6f 72 65 2e 20 4f 74 68 65 72 77 69 73   score. Otherwis
4500: 65 2c 0a 20 20 2a 2a 20 74 68 72 6f 77 20 61 6e  e,.  ** throw an
4510: 20 53 51 4c 20 65 78 63 65 70 74 69 6f 6e 2e 20   SQL exception. 
4520: 20 2a 2f 0a 20 20 69 66 28 20 72 63 3d 3d 53 51   */.  if( rc==SQ
4530: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 73  LITE_OK ){.    s
4540: 71 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 64 6f  qlite3_result_do
4550: 75 62 6c 65 28 70 43 74 78 2c 20 2d 31 2e 30 20  uble(pCtx, -1.0 
4560: 2a 20 73 63 6f 72 65 29 3b 0a 20 20 7d 65 6c 73  * score);.  }els
4570: 65 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 72  e{.    sqlite3_r
4580: 65 73 75 6c 74 5f 65 72 72 6f 72 5f 63 6f 64 65  esult_error_code
4590: 28 70 43 74 78 2c 20 72 63 29 3b 0a 20 20 7d 0a  (pCtx, rc);.  }.
45a0: 7d 0a 0a 69 6e 74 20 73 71 6c 69 74 65 33 46 74  }..int sqlite3Ft
45b0: 73 35 41 75 78 49 6e 69 74 28 66 74 73 35 5f 61  s5AuxInit(fts5_a
45c0: 70 69 20 2a 70 41 70 69 29 7b 0a 20 20 73 74 72  pi *pApi){.  str
45d0: 75 63 74 20 42 75 69 6c 74 69 6e 20 7b 0a 20 20  uct Builtin {.  
45e0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 46    const char *zF
45f0: 75 6e 63 3b 20 20 20 20 20 20 20 20 20 20 20 20  unc;            
4600: 2f 2a 20 46 75 6e 63 74 69 6f 6e 20 6e 61 6d 65  /* Function name
4610: 20 28 6e 75 6c 2d 74 65 72 6d 69 6e 61 74 65 64   (nul-terminated
4620: 29 20 2a 2f 0a 20 20 20 20 76 6f 69 64 20 2a 70  ) */.    void *p
4630: 55 73 65 72 44 61 74 61 3b 20 20 20 20 20 20 20  UserData;       
4640: 20 20 20 20 20 20 20 2f 2a 20 55 73 65 72 2d 64         /* User-d
4650: 61 74 61 20 70 6f 69 6e 74 65 72 20 2a 2f 0a 20  ata pointer */. 
4660: 20 20 20 66 74 73 35 5f 65 78 74 65 6e 73 69 6f     fts5_extensio
4670: 6e 5f 66 75 6e 63 74 69 6f 6e 20 78 46 75 6e 63  n_function xFunc
4680: 3b 2f 2a 20 43 61 6c 6c 62 61 63 6b 20 66 75 6e  ;/* Callback fun
4690: 63 74 69 6f 6e 20 2a 2f 0a 20 20 20 20 76 6f 69  ction */.    voi
46a0: 64 20 28 2a 78 44 65 73 74 72 6f 79 29 28 76 6f  d (*xDestroy)(vo
46b0: 69 64 2a 29 3b 20 20 20 20 20 20 2f 2a 20 44 65  id*);      /* De
46c0: 73 74 72 75 63 74 6f 72 20 66 75 6e 63 74 69 6f  structor functio
46d0: 6e 20 2a 2f 0a 20 20 7d 20 61 42 75 69 6c 74 69  n */.  } aBuilti
46e0: 6e 20 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22  n [] = {.    { "
46f0: 73 6e 69 70 70 65 74 22 2c 20 20 20 30 2c 20 66  snippet",   0, f
4700: 74 73 35 53 6e 69 70 70 65 74 46 75 6e 63 74 69  ts5SnippetFuncti
4710: 6f 6e 2c 20 30 20 7d 2c 0a 20 20 20 20 7b 20 22  on, 0 },.    { "
4720: 68 69 67 68 6c 69 67 68 74 22 2c 20 30 2c 20 66  highlight", 0, f
4730: 74 73 35 48 69 67 68 6c 69 67 68 74 46 75 6e 63  ts5HighlightFunc
4740: 74 69 6f 6e 2c 20 30 20 7d 2c 0a 20 20 20 20 7b  tion, 0 },.    {
4750: 20 22 62 6d 32 35 22 2c 20 20 20 20 20 20 30 2c   "bm25",      0,
4760: 20 66 74 73 35 42 6d 32 35 46 75 6e 63 74 69 6f   fts5Bm25Functio
4770: 6e 2c 20 20 20 20 30 20 7d 2c 0a 20 20 7d 3b 0a  n,    0 },.  };.
4780: 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54    int rc = SQLIT
4790: 45 5f 4f 4b 3b 20 20 20 20 20 20 20 20 20 20 20  E_OK;           
47a0: 20 20 2f 2a 20 52 65 74 75 72 6e 20 63 6f 64 65    /* Return code
47b0: 20 2a 2f 0a 20 20 69 6e 74 20 69 3b 20 20 20 20   */.  int i;    
47c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
47d0: 20 20 20 20 20 20 2f 2a 20 54 6f 20 69 74 65 72        /* To iter
47e0: 61 74 65 20 74 68 72 6f 75 67 68 20 62 75 69 6c  ate through buil
47f0: 74 69 6e 20 66 75 6e 63 74 69 6f 6e 73 20 2a 2f  tin functions */
4800: 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 72 63 3d  ..  for(i=0; rc=
4810: 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 69 3c  =SQLITE_OK && i<
4820: 41 72 72 61 79 53 69 7a 65 28 61 42 75 69 6c 74  ArraySize(aBuilt
4830: 69 6e 29 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 72  in); i++){.    r
4840: 63 20 3d 20 70 41 70 69 2d 3e 78 43 72 65 61 74  c = pApi->xCreat
4850: 65 46 75 6e 63 74 69 6f 6e 28 70 41 70 69 2c 0a  eFunction(pApi,.
4860: 20 20 20 20 20 20 20 20 61 42 75 69 6c 74 69 6e          aBuiltin
4870: 5b 69 5d 2e 7a 46 75 6e 63 2c 0a 20 20 20 20 20  [i].zFunc,.     
4880: 20 20 20 61 42 75 69 6c 74 69 6e 5b 69 5d 2e 70     aBuiltin[i].p
4890: 55 73 65 72 44 61 74 61 2c 0a 20 20 20 20 20 20  UserData,.      
48a0: 20 20 61 42 75 69 6c 74 69 6e 5b 69 5d 2e 78 46    aBuiltin[i].xF
48b0: 75 6e 63 2c 0a 20 20 20 20 20 20 20 20 61 42 75  unc,.        aBu
48c0: 69 6c 74 69 6e 5b 69 5d 2e 78 44 65 73 74 72 6f  iltin[i].xDestro
48d0: 79 0a 20 20 20 20 29 3b 0a 20 20 7d 0a 0a 20 20  y.    );.  }..  
48e0: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a     return rc;.}...