/ Hex Artifact Content
Login

Artifact f6ebb3536069ceaa27e9f178f4a59379db44ac10:


0000: 2f 2a 0a 2a 2a 20 32 30 30 39 20 4f 63 74 20 32  /*.** 2009 Oct 2
0010: 33 0a 2a 2a 0a 2a 2a 20 54 68 65 20 61 75 74 68  3.**.** 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 23 69 6e 63 6c 75  *****.*/..#inclu
0180: 64 65 20 22 66 74 73 33 49 6e 74 2e 68 22 0a 23  de "fts3Int.h".#
0190: 69 66 20 21 64 65 66 69 6e 65 64 28 53 51 4c 49  if !defined(SQLI
01a0: 54 45 5f 43 4f 52 45 29 20 7c 7c 20 64 65 66 69  TE_CORE) || defi
01b0: 6e 65 64 28 53 51 4c 49 54 45 5f 45 4e 41 42 4c  ned(SQLITE_ENABL
01c0: 45 5f 46 54 53 33 29 0a 0a 23 69 6e 63 6c 75 64  E_FTS3)..#includ
01d0: 65 20 3c 73 74 72 69 6e 67 2e 68 3e 0a 23 69 6e  e <string.h>.#in
01e0: 63 6c 75 64 65 20 3c 61 73 73 65 72 74 2e 68 3e  clude <assert.h>
01f0: 0a 0a 2f 2a 0a 2a 2a 20 43 68 61 72 61 63 74 65  ../*.** Characte
0200: 72 73 20 74 68 61 74 20 6d 61 79 20 61 70 70 65  rs that may appe
0210: 61 72 20 69 6e 20 74 68 65 20 73 65 63 6f 6e 64  ar in the second
0220: 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 6d 61 74   argument to mat
0230: 63 68 69 6e 66 6f 28 29 2e 0a 2a 2f 0a 23 64 65  chinfo()..*/.#de
0240: 66 69 6e 65 20 46 54 53 33 5f 4d 41 54 43 48 49  fine FTS3_MATCHI
0250: 4e 46 4f 5f 4e 50 48 52 41 53 45 20 20 20 27 70  NFO_NPHRASE   'p
0260: 27 20 20 20 20 20 20 20 20 2f 2a 20 31 20 76 61  '        /* 1 va
0270: 6c 75 65 20 2a 2f 0a 23 64 65 66 69 6e 65 20 46  lue */.#define F
0280: 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e 43  TS3_MATCHINFO_NC
0290: 4f 4c 20 20 20 20 20 20 27 63 27 20 20 20 20 20  OL      'c'     
02a0: 20 20 20 2f 2a 20 31 20 76 61 6c 75 65 20 2a 2f     /* 1 value */
02b0: 0a 23 64 65 66 69 6e 65 20 46 54 53 33 5f 4d 41  .#define FTS3_MA
02c0: 54 43 48 49 4e 46 4f 5f 4e 44 4f 43 20 20 20 20  TCHINFO_NDOC    
02d0: 20 20 27 6e 27 20 20 20 20 20 20 20 20 2f 2a 20    'n'        /* 
02e0: 31 20 76 61 6c 75 65 20 2a 2f 0a 23 64 65 66 69  1 value */.#defi
02f0: 6e 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  ne FTS3_MATCHINF
0300: 4f 5f 41 56 47 4c 45 4e 47 54 48 20 27 61 27 20  O_AVGLENGTH 'a' 
0310: 20 20 20 20 20 20 20 2f 2a 20 6e 43 6f 6c 20 76         /* nCol v
0320: 61 6c 75 65 73 20 2a 2f 0a 23 64 65 66 69 6e 65  alues */.#define
0330: 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f   FTS3_MATCHINFO_
0340: 4c 45 4e 47 54 48 20 20 20 20 27 6c 27 20 20 20  LENGTH    'l'   
0350: 20 20 20 20 20 2f 2a 20 6e 43 6f 6c 20 76 61 6c       /* nCol val
0360: 75 65 73 20 2a 2f 0a 23 64 65 66 69 6e 65 20 46  ues */.#define F
0370: 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c 43  TS3_MATCHINFO_LC
0380: 53 20 20 20 20 20 20 20 27 73 27 20 20 20 20 20  S       's'     
0390: 20 20 20 2f 2a 20 6e 43 6f 6c 20 76 61 6c 75 65     /* nCol value
03a0: 73 20 2a 2f 0a 23 64 65 66 69 6e 65 20 46 54 53  s */.#define FTS
03b0: 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 48 49 54 53  3_MATCHINFO_HITS
03c0: 20 20 20 20 20 20 27 78 27 20 20 20 20 20 20 20        'x'       
03d0: 20 2f 2a 20 33 2a 6e 43 6f 6c 2a 6e 50 68 72 61   /* 3*nCol*nPhra
03e0: 73 65 20 76 61 6c 75 65 73 20 2a 2f 0a 0a 2f 2a  se values */../*
03f0: 0a 2a 2a 20 54 68 65 20 64 65 66 61 75 6c 74 20  .** The default 
0400: 76 61 6c 75 65 20 66 6f 72 20 74 68 65 20 73 65  value for the se
0410: 63 6f 6e 64 20 61 72 67 75 6d 65 6e 74 20 74 6f  cond argument to
0420: 20 6d 61 74 63 68 69 6e 66 6f 28 29 2e 20 0a 2a   matchinfo(). .*
0430: 2f 0a 23 64 65 66 69 6e 65 20 46 54 53 33 5f 4d  /.#define FTS3_M
0440: 41 54 43 48 49 4e 46 4f 5f 44 45 46 41 55 4c 54  ATCHINFO_DEFAULT
0450: 20 20 20 22 70 63 78 22 0a 0a 0a 2f 2a 0a 2a 2a     "pcx".../*.**
0460: 20 55 73 65 64 20 61 73 20 61 6e 20 66 74 73 33   Used as an fts3
0470: 45 78 70 72 49 74 65 72 61 74 65 28 29 20 63 6f  ExprIterate() co
0480: 6e 74 65 78 74 20 77 68 65 6e 20 6c 6f 61 64 69  ntext when loadi
0490: 6e 67 20 70 68 72 61 73 65 20 64 6f 63 6c 69 73  ng phrase doclis
04a0: 74 73 20 74 6f 0a 2a 2a 20 46 74 73 33 45 78 70  ts to.** Fts3Exp
04b0: 72 2e 61 44 6f 63 6c 69 73 74 5b 5d 2f 6e 44 6f  r.aDoclist[]/nDo
04c0: 63 6c 69 73 74 2e 0a 2a 2f 0a 74 79 70 65 64 65  clist..*/.typede
04d0: 66 20 73 74 72 75 63 74 20 4c 6f 61 64 44 6f 63  f struct LoadDoc
04e0: 6c 69 73 74 43 74 78 20 4c 6f 61 64 44 6f 63 6c  listCtx LoadDocl
04f0: 69 73 74 43 74 78 3b 0a 73 74 72 75 63 74 20 4c  istCtx;.struct L
0500: 6f 61 64 44 6f 63 6c 69 73 74 43 74 78 20 7b 0a  oadDoclistCtx {.
0510: 20 20 46 74 73 33 43 75 72 73 6f 72 20 2a 70 43    Fts3Cursor *pC
0520: 73 72 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  sr;             
0530: 20 20 2f 2a 20 46 54 53 33 20 43 75 72 73 6f 72    /* FTS3 Cursor
0540: 20 2a 2f 0a 20 20 69 6e 74 20 6e 50 68 72 61 73   */.  int nPhras
0550: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
0560: 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20        /* Number 
0570: 6f 66 20 70 68 72 61 73 65 73 20 73 65 65 6e 20  of phrases seen 
0580: 73 6f 20 66 61 72 20 2a 2f 0a 20 20 69 6e 74 20  so far */.  int 
0590: 6e 54 6f 6b 65 6e 3b 20 20 20 20 20 20 20 20 20  nToken;         
05a0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
05b0: 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20  umber of tokens 
05c0: 73 65 65 6e 20 73 6f 20 66 61 72 20 2a 2f 0a 7d  seen so far */.}
05d0: 3b 0a 0a 2f 2a 0a 2a 2a 20 54 68 65 20 66 6f 6c  ;../*.** The fol
05e0: 6c 6f 77 69 6e 67 20 74 79 70 65 73 20 61 72 65  lowing types are
05f0: 20 75 73 65 64 20 61 73 20 70 61 72 74 20 6f 66   used as part of
0600: 20 74 68 65 20 69 6d 70 6c 65 6d 65 6e 74 61 74   the implementat
0610: 69 6f 6e 20 6f 66 20 74 68 65 20 0a 2a 2a 20 66  ion of the .** f
0620: 74 73 33 42 65 73 74 53 6e 69 70 70 65 74 28 29  ts3BestSnippet()
0630: 20 72 6f 75 74 69 6e 65 2e 0a 2a 2f 0a 74 79 70   routine..*/.typ
0640: 65 64 65 66 20 73 74 72 75 63 74 20 53 6e 69 70  edef struct Snip
0650: 70 65 74 49 74 65 72 20 53 6e 69 70 70 65 74 49  petIter SnippetI
0660: 74 65 72 3b 0a 74 79 70 65 64 65 66 20 73 74 72  ter;.typedef str
0670: 75 63 74 20 53 6e 69 70 70 65 74 50 68 72 61 73  uct SnippetPhras
0680: 65 20 53 6e 69 70 70 65 74 50 68 72 61 73 65 3b  e SnippetPhrase;
0690: 0a 74 79 70 65 64 65 66 20 73 74 72 75 63 74 20  .typedef struct 
06a0: 53 6e 69 70 70 65 74 46 72 61 67 6d 65 6e 74 20  SnippetFragment 
06b0: 53 6e 69 70 70 65 74 46 72 61 67 6d 65 6e 74 3b  SnippetFragment;
06c0: 0a 0a 73 74 72 75 63 74 20 53 6e 69 70 70 65 74  ..struct Snippet
06d0: 49 74 65 72 20 7b 0a 20 20 46 74 73 33 43 75 72  Iter {.  Fts3Cur
06e0: 73 6f 72 20 2a 70 43 73 72 3b 20 20 20 20 20 20  sor *pCsr;      
06f0: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 75 72 73           /* Curs
0700: 6f 72 20 73 6e 69 70 70 65 74 20 69 73 20 62 65  or snippet is be
0710: 69 6e 67 20 67 65 6e 65 72 61 74 65 64 20 66 72  ing generated fr
0720: 6f 6d 20 2a 2f 0a 20 20 69 6e 74 20 69 43 6f 6c  om */.  int iCol
0730: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
0740: 20 20 20 20 20 20 20 20 2f 2a 20 45 78 74 72 61          /* Extra
0750: 63 74 20 73 6e 69 70 70 65 74 20 66 72 6f 6d 20  ct snippet from 
0760: 74 68 69 73 20 63 6f 6c 75 6d 6e 20 2a 2f 0a 20  this column */. 
0770: 20 69 6e 74 20 6e 53 6e 69 70 70 65 74 3b 20 20   int nSnippet;  
0780: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0790: 20 2f 2a 20 52 65 71 75 65 73 74 65 64 20 73 6e   /* Requested sn
07a0: 69 70 70 65 74 20 6c 65 6e 67 74 68 20 28 69 6e  ippet length (in
07b0: 20 74 6f 6b 65 6e 73 29 20 2a 2f 0a 20 20 69 6e   tokens) */.  in
07c0: 74 20 6e 50 68 72 61 73 65 3b 20 20 20 20 20 20  t nPhrase;      
07d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
07e0: 20 4e 75 6d 62 65 72 20 6f 66 20 70 68 72 61 73   Number of phras
07f0: 65 73 20 69 6e 20 71 75 65 72 79 20 2a 2f 0a 20  es in query */. 
0800: 20 53 6e 69 70 70 65 74 50 68 72 61 73 65 20 2a   SnippetPhrase *
0810: 61 50 68 72 61 73 65 3b 20 20 20 20 20 20 20 20  aPhrase;        
0820: 20 2f 2a 20 41 72 72 61 79 20 6f 66 20 73 69 7a   /* Array of siz
0830: 65 20 6e 50 68 72 61 73 65 20 2a 2f 0a 20 20 69  e nPhrase */.  i
0840: 6e 74 20 69 43 75 72 72 65 6e 74 3b 20 20 20 20  nt iCurrent;    
0850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0860: 2a 20 46 69 72 73 74 20 74 6f 6b 65 6e 20 6f 66  * First token of
0870: 20 63 75 72 72 65 6e 74 20 73 6e 69 70 70 65 74   current snippet
0880: 20 2a 2f 0a 7d 3b 0a 0a 73 74 72 75 63 74 20 53   */.};..struct S
0890: 6e 69 70 70 65 74 50 68 72 61 73 65 20 7b 0a 20  nippetPhrase {. 
08a0: 20 69 6e 74 20 6e 54 6f 6b 65 6e 3b 20 20 20 20   int nToken;    
08b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
08c0: 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 74 6f   /* Number of to
08d0: 6b 65 6e 73 20 69 6e 20 70 68 72 61 73 65 20 2a  kens in phrase *
08e0: 2f 0a 20 20 63 68 61 72 20 2a 70 4c 69 73 74 3b  /.  char *pList;
08f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0900: 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65 72 20 74      /* Pointer t
0910: 6f 20 73 74 61 72 74 20 6f 66 20 70 68 72 61 73  o start of phras
0920: 65 20 70 6f 73 69 74 69 6f 6e 20 6c 69 73 74 20  e position list 
0930: 2a 2f 0a 20 20 69 6e 74 20 69 48 65 61 64 3b 20  */.  int iHead; 
0940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0950: 20 20 20 20 20 2f 2a 20 4e 65 78 74 20 76 61 6c       /* Next val
0960: 75 65 20 69 6e 20 70 6f 73 69 74 69 6f 6e 20 6c  ue in position l
0970: 69 73 74 20 2a 2f 0a 20 20 63 68 61 72 20 2a 70  ist */.  char *p
0980: 48 65 61 64 3b 20 20 20 20 20 20 20 20 20 20 20  Head;           
0990: 20 20 20 20 20 20 20 20 20 2f 2a 20 50 6f 73 69           /* Posi
09a0: 74 69 6f 6e 20 6c 69 73 74 20 64 61 74 61 20 66  tion list data f
09b0: 6f 6c 6c 6f 77 69 6e 67 20 69 48 65 61 64 20 2a  ollowing iHead *
09c0: 2f 0a 20 20 69 6e 74 20 69 54 61 69 6c 3b 20 20  /.  int iTail;  
09d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
09e0: 20 20 20 20 2f 2a 20 4e 65 78 74 20 76 61 6c 75      /* Next valu
09f0: 65 20 69 6e 20 74 72 61 69 6c 69 6e 67 20 70 6f  e in trailing po
0a00: 73 69 74 69 6f 6e 20 6c 69 73 74 20 2a 2f 0a 20  sition list */. 
0a10: 20 63 68 61 72 20 2a 70 54 61 69 6c 3b 20 20 20   char *pTail;   
0a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0a30: 20 2f 2a 20 50 6f 73 69 74 69 6f 6e 20 6c 69 73   /* Position lis
0a40: 74 20 64 61 74 61 20 66 6f 6c 6c 6f 77 69 6e 67  t data following
0a50: 20 69 54 61 69 6c 20 2a 2f 0a 7d 3b 0a 0a 73 74   iTail */.};..st
0a60: 72 75 63 74 20 53 6e 69 70 70 65 74 46 72 61 67  ruct SnippetFrag
0a70: 6d 65 6e 74 20 7b 0a 20 20 69 6e 74 20 69 43 6f  ment {.  int iCo
0a80: 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  l;              
0a90: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6c 75           /* Colu
0aa0: 6d 6e 20 73 6e 69 70 70 65 74 20 69 73 20 65 78  mn snippet is ex
0ab0: 74 72 61 63 74 65 64 20 66 72 6f 6d 20 2a 2f 0a  tracted from */.
0ac0: 20 20 69 6e 74 20 69 50 6f 73 3b 20 20 20 20 20    int iPos;     
0ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ae0: 20 20 2f 2a 20 49 6e 64 65 78 20 6f 66 20 66 69    /* Index of fi
0af0: 72 73 74 20 74 6f 6b 65 6e 20 69 6e 20 73 6e 69  rst token in sni
0b00: 70 70 65 74 20 2a 2f 0a 20 20 75 36 34 20 63 6f  ppet */.  u64 co
0b10: 76 65 72 65 64 3b 20 20 20 20 20 20 20 20 20 20  vered;          
0b20: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4d 61 73            /* Mas
0b30: 6b 20 6f 66 20 71 75 65 72 79 20 70 68 72 61 73  k of query phras
0b40: 65 73 20 63 6f 76 65 72 65 64 20 2a 2f 0a 20 20  es covered */.  
0b50: 75 36 34 20 68 6c 6d 61 73 6b 3b 20 20 20 20 20  u64 hlmask;     
0b60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b70: 2f 2a 20 4d 61 73 6b 20 6f 66 20 73 6e 69 70 70  /* Mask of snipp
0b80: 65 74 20 74 65 72 6d 73 20 74 6f 20 68 69 67 68  et terms to high
0b90: 6c 69 67 68 74 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a  light */.};../*.
0ba0: 2a 2a 20 54 68 69 73 20 74 79 70 65 20 69 73 20  ** This type is 
0bb0: 75 73 65 64 20 61 73 20 61 6e 20 66 74 73 33 45  used as an fts3E
0bc0: 78 70 72 49 74 65 72 61 74 65 28 29 20 63 6f 6e  xprIterate() con
0bd0: 74 65 78 74 20 6f 62 6a 65 63 74 20 77 68 69 6c  text object whil
0be0: 65 20 0a 2a 2a 20 61 63 63 75 6d 75 6c 61 74 69  e .** accumulati
0bf0: 6e 67 20 74 68 65 20 64 61 74 61 20 72 65 74 75  ng the data retu
0c00: 72 6e 65 64 20 62 79 20 74 68 65 20 6d 61 74 63  rned by the matc
0c10: 68 69 6e 66 6f 28 29 20 66 75 6e 63 74 69 6f 6e  hinfo() function
0c20: 2e 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73 74 72  ..*/.typedef str
0c30: 75 63 74 20 4d 61 74 63 68 49 6e 66 6f 20 4d 61  uct MatchInfo Ma
0c40: 74 63 68 49 6e 66 6f 3b 0a 73 74 72 75 63 74 20  tchInfo;.struct 
0c50: 4d 61 74 63 68 49 6e 66 6f 20 7b 0a 20 20 46 74  MatchInfo {.  Ft
0c60: 73 33 43 75 72 73 6f 72 20 2a 70 43 75 72 73 6f  s3Cursor *pCurso
0c70: 72 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  r;            /*
0c80: 20 46 54 53 33 20 43 75 72 73 6f 72 20 2a 2f 0a   FTS3 Cursor */.
0c90: 20 20 69 6e 74 20 6e 43 6f 6c 3b 20 20 20 20 20    int nCol;     
0ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0cb0: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 63    /* Number of c
0cc0: 6f 6c 75 6d 6e 73 20 69 6e 20 74 61 62 6c 65 20  olumns in table 
0cd0: 2a 2f 0a 20 20 69 6e 74 20 6e 50 68 72 61 73 65  */.  int nPhrase
0ce0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
0cf0: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
0d00: 66 20 6d 61 74 63 68 61 62 6c 65 20 70 68 72 61  f matchable phra
0d10: 73 65 73 20 69 6e 20 71 75 65 72 79 20 2a 2f 0a  ses in query */.
0d20: 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20    sqlite3_int64 
0d30: 6e 44 6f 63 3b 20 20 20 20 20 20 20 20 20 20 20  nDoc;           
0d40: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 64    /* Number of d
0d50: 6f 63 73 20 69 6e 20 64 61 74 61 62 61 73 65 20  ocs in database 
0d60: 2a 2f 0a 20 20 75 33 32 20 2a 61 4d 61 74 63 68  */.  u32 *aMatch
0d70: 69 6e 66 6f 3b 20 20 20 20 20 20 20 20 20 20 20  info;           
0d80: 20 20 20 20 20 2f 2a 20 50 72 65 2d 61 6c 6c 6f       /* Pre-allo
0d90: 63 61 74 65 64 20 62 75 66 66 65 72 20 2a 2f 0a  cated buffer */.
0da0: 7d 3b 0a 0a 0a 0a 2f 2a 0a 2a 2a 20 54 68 65 20  };..../*.** The 
0db0: 73 6e 69 70 70 65 74 28 29 20 61 6e 64 20 6f 66  snippet() and of
0dc0: 66 73 65 74 73 28 29 20 66 75 6e 63 74 69 6f 6e  fsets() function
0dd0: 73 20 62 6f 74 68 20 72 65 74 75 72 6e 20 74 65  s both return te
0de0: 78 74 20 76 61 6c 75 65 73 2e 20 41 6e 20 69 6e  xt values. An in
0df0: 73 74 61 6e 63 65 0a 2a 2a 20 6f 66 20 74 68 65  stance.** of the
0e00: 20 66 6f 6c 6c 6f 77 69 6e 67 20 73 74 72 75 63   following struc
0e10: 74 75 72 65 20 69 73 20 75 73 65 64 20 74 6f 20  ture is used to 
0e20: 61 63 63 75 6d 75 6c 61 74 65 20 74 68 6f 73 65  accumulate those
0e30: 20 76 61 6c 75 65 73 20 77 68 69 6c 65 20 74 68   values while th
0e40: 65 0a 2a 2a 20 66 75 6e 63 74 69 6f 6e 73 20 61  e.** functions a
0e50: 72 65 20 72 75 6e 6e 69 6e 67 2e 20 53 65 65 20  re running. See 
0e60: 66 74 73 33 53 74 72 69 6e 67 41 70 70 65 6e 64  fts3StringAppend
0e70: 28 29 20 66 6f 72 20 64 65 74 61 69 6c 73 2e 0a  () for details..
0e80: 2a 2f 0a 74 79 70 65 64 65 66 20 73 74 72 75 63  */.typedef struc
0e90: 74 20 53 74 72 42 75 66 66 65 72 20 53 74 72 42  t StrBuffer StrB
0ea0: 75 66 66 65 72 3b 0a 73 74 72 75 63 74 20 53 74  uffer;.struct St
0eb0: 72 42 75 66 66 65 72 20 7b 0a 20 20 63 68 61 72  rBuffer {.  char
0ec0: 20 2a 7a 3b 20 20 20 20 20 20 20 20 20 20 20 20   *z;            
0ed0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50              /* P
0ee0: 6f 69 6e 74 65 72 20 74 6f 20 62 75 66 66 65 72  ointer to buffer
0ef0: 20 63 6f 6e 74 61 69 6e 69 6e 67 20 73 74 72 69   containing stri
0f00: 6e 67 20 2a 2f 0a 20 20 69 6e 74 20 6e 3b 20 20  ng */.  int n;  
0f10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0f20: 20 20 20 20 20 20 20 20 2f 2a 20 4c 65 6e 67 74          /* Lengt
0f30: 68 20 6f 66 20 7a 20 69 6e 20 62 79 74 65 73 20  h of z in bytes 
0f40: 28 65 78 63 6c 2e 20 6e 75 6c 2d 74 65 72 6d 29  (excl. nul-term)
0f50: 20 2a 2f 0a 20 20 69 6e 74 20 6e 41 6c 6c 6f 63   */.  int nAlloc
0f60: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
0f70: 20 20 20 20 20 20 2f 2a 20 41 6c 6c 6f 63 61 74        /* Allocat
0f80: 65 64 20 73 69 7a 65 20 6f 66 20 62 75 66 66 65  ed size of buffe
0f90: 72 20 7a 20 69 6e 20 62 79 74 65 73 20 2a 2f 0a  r z in bytes */.
0fa0: 7d 3b 0a 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  };.../*.** This 
0fb0: 66 75 6e 63 74 69 6f 6e 20 69 73 20 75 73 65 64  function is used
0fc0: 20 74 6f 20 68 65 6c 70 20 69 74 65 72 61 74 65   to help iterate
0fd0: 20 74 68 72 6f 75 67 68 20 61 20 70 6f 73 69 74   through a posit
0fe0: 69 6f 6e 2d 6c 69 73 74 2e 20 41 20 70 6f 73 69  ion-list. A posi
0ff0: 74 69 6f 6e 0a 2a 2a 20 6c 69 73 74 20 69 73 20  tion.** list is 
1000: 61 20 6c 69 73 74 20 6f 66 20 75 6e 69 71 75 65  a list of unique
1010: 20 69 6e 74 65 67 65 72 73 2c 20 73 6f 72 74 65   integers, sorte
1020: 64 20 66 72 6f 6d 20 73 6d 61 6c 6c 65 73 74 20  d from smallest 
1030: 74 6f 20 6c 61 72 67 65 73 74 2e 20 45 61 63 68  to largest. Each
1040: 0a 2a 2a 20 65 6c 65 6d 65 6e 74 20 6f 66 20 74  .** element of t
1050: 68 65 20 6c 69 73 74 20 69 73 20 72 65 70 72 65  he list is repre
1060: 73 65 6e 74 65 64 20 62 79 20 61 6e 20 46 54 53  sented by an FTS
1070: 33 20 76 61 72 69 6e 74 20 74 68 61 74 20 74 61  3 varint that ta
1080: 6b 65 73 20 74 68 65 20 76 61 6c 75 65 0a 2a 2a  kes the value.**
1090: 20 6f 66 20 74 68 65 20 64 69 66 66 65 72 65 6e   of the differen
10a0: 63 65 20 62 65 74 77 65 65 6e 20 74 68 65 20 63  ce between the c
10b0: 75 72 72 65 6e 74 20 65 6c 65 6d 65 6e 74 20 61  urrent element a
10c0: 6e 64 20 74 68 65 20 70 72 65 76 69 6f 75 73 20  nd the previous 
10d0: 6f 6e 65 20 70 6c 75 73 0a 2a 2a 20 74 77 6f 2e  one plus.** two.
10e0: 20 46 6f 72 20 65 78 61 6d 70 6c 65 2c 20 74 6f   For example, to
10f0: 20 73 74 6f 72 65 20 74 68 65 20 70 6f 73 69 74   store the posit
1100: 69 6f 6e 2d 6c 69 73 74 3a 0a 2a 2a 0a 2a 2a 20  ion-list:.**.** 
1110: 20 20 20 20 34 20 39 20 31 31 33 0a 2a 2a 0a 2a      4 9 113.**.*
1120: 2a 20 74 68 65 20 74 68 72 65 65 20 76 61 72 69  * the three vari
1130: 6e 74 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 20 36  nts:.**.**     6
1140: 20 37 20 31 30 36 0a 2a 2a 0a 2a 2a 20 61 72 65   7 106.**.** are
1150: 20 65 6e 63 6f 64 65 64 2e 0a 2a 2a 0a 2a 2a 20   encoded..**.** 
1160: 57 68 65 6e 20 74 68 69 73 20 66 75 6e 63 74 69  When this functi
1170: 6f 6e 20 69 73 20 63 61 6c 6c 65 64 2c 20 2a 70  on is called, *p
1180: 70 20 70 6f 69 6e 74 73 20 74 6f 20 74 68 65 20  p points to the 
1190: 73 74 61 72 74 20 6f 66 20 61 6e 20 65 6c 65 6d  start of an elem
11a0: 65 6e 74 20 6f 66 0a 2a 2a 20 74 68 65 20 6c 69  ent of.** the li
11b0: 73 74 2e 20 2a 70 69 50 6f 73 20 63 6f 6e 74 61  st. *piPos conta
11c0: 69 6e 73 20 74 68 65 20 76 61 6c 75 65 20 6f 66  ins the value of
11d0: 20 74 68 65 20 70 72 65 76 69 6f 75 73 20 65 6e   the previous en
11e0: 74 72 79 20 69 6e 20 74 68 65 20 6c 69 73 74 2e  try in the list.
11f0: 0a 2a 2a 20 41 66 74 65 72 20 69 74 20 72 65 74  .** After it ret
1200: 75 72 6e 73 2c 20 2a 70 69 50 6f 73 20 63 6f 6e  urns, *piPos con
1210: 74 61 69 6e 73 20 74 68 65 20 76 61 6c 75 65 20  tains the value 
1220: 6f 66 20 74 68 65 20 6e 65 78 74 20 65 6c 65 6d  of the next elem
1230: 65 6e 74 20 6f 66 20 74 68 65 0a 2a 2a 20 6c 69  ent of the.** li
1240: 73 74 20 61 6e 64 20 2a 70 70 20 69 73 20 61 64  st and *pp is ad
1250: 76 61 6e 63 65 64 20 74 6f 20 74 68 65 20 66 6f  vanced to the fo
1260: 6c 6c 6f 77 69 6e 67 20 76 61 72 69 6e 74 2e 0a  llowing varint..
1270: 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 66  */.static void f
1280: 74 73 33 47 65 74 44 65 6c 74 61 50 6f 73 69 74  ts3GetDeltaPosit
1290: 69 6f 6e 28 63 68 61 72 20 2a 2a 70 70 2c 20 69  ion(char **pp, i
12a0: 6e 74 20 2a 70 69 50 6f 73 29 7b 0a 20 20 69 6e  nt *piPos){.  in
12b0: 74 20 69 56 61 6c 3b 0a 20 20 2a 70 70 20 2b 3d  t iVal;.  *pp +=
12c0: 20 73 71 6c 69 74 65 33 46 74 73 33 47 65 74 56   sqlite3Fts3GetV
12d0: 61 72 69 6e 74 33 32 28 2a 70 70 2c 20 26 69 56  arint32(*pp, &iV
12e0: 61 6c 29 3b 0a 20 20 2a 70 69 50 6f 73 20 2b 3d  al);.  *piPos +=
12f0: 20 28 69 56 61 6c 2d 32 29 3b 0a 7d 0a 0a 2f 2a   (iVal-2);.}../*
1300: 0a 2a 2a 20 48 65 6c 70 65 72 20 66 75 6e 63 74  .** Helper funct
1310: 69 6f 6e 20 66 6f 72 20 66 74 73 33 45 78 70 72  ion for fts3Expr
1320: 49 74 65 72 61 74 65 28 29 20 28 73 65 65 20 62  Iterate() (see b
1330: 65 6c 6f 77 29 2e 0a 2a 2f 0a 73 74 61 74 69 63  elow)..*/.static
1340: 20 69 6e 74 20 66 74 73 33 45 78 70 72 49 74 65   int fts3ExprIte
1350: 72 61 74 65 32 28 0a 20 20 46 74 73 33 45 78 70  rate2(.  Fts3Exp
1360: 72 20 2a 70 45 78 70 72 2c 20 20 20 20 20 20 20  r *pExpr,       
1370: 20 20 20 20 20 20 20 20 20 2f 2a 20 45 78 70 72           /* Expr
1380: 65 73 73 69 6f 6e 20 74 6f 20 69 74 65 72 61 74  ession to iterat
1390: 65 20 70 68 72 61 73 65 73 20 6f 66 20 2a 2f 0a  e phrases of */.
13a0: 20 20 69 6e 74 20 2a 70 69 50 68 72 61 73 65 2c    int *piPhrase,
13b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13c0: 20 20 2f 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20    /* Pointer to 
13d0: 70 68 72 61 73 65 20 63 6f 75 6e 74 65 72 20 2a  phrase counter *
13e0: 2f 0a 20 20 69 6e 74 20 28 2a 78 29 28 46 74 73  /.  int (*x)(Fts
13f0: 33 45 78 70 72 2a 2c 69 6e 74 2c 76 6f 69 64 2a  3Expr*,int,void*
1400: 29 2c 20 20 2f 2a 20 43 61 6c 6c 62 61 63 6b 20  ),  /* Callback 
1410: 66 75 6e 63 74 69 6f 6e 20 74 6f 20 69 6e 76 6f  function to invo
1420: 6b 65 20 66 6f 72 20 70 68 72 61 73 65 73 20 2a  ke for phrases *
1430: 2f 0a 20 20 76 6f 69 64 20 2a 70 43 74 78 20 20  /.  void *pCtx  
1440: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1450: 20 20 20 20 2f 2a 20 53 65 63 6f 6e 64 20 61 72      /* Second ar
1460: 67 75 6d 65 6e 74 20 74 6f 20 70 61 73 73 20 74  gument to pass t
1470: 6f 20 63 61 6c 6c 62 61 63 6b 20 2a 2f 0a 29 7b  o callback */.){
1480: 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20  .  int rc;      
1490: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
14a0: 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 63 6f 64     /* Return cod
14b0: 65 20 2a 2f 0a 20 20 69 6e 74 20 65 54 79 70 65  e */.  int eType
14c0: 20 3d 20 70 45 78 70 72 2d 3e 65 54 79 70 65 3b   = pExpr->eType;
14d0: 20 20 20 20 20 20 20 2f 2a 20 54 79 70 65 20 6f         /* Type o
14e0: 66 20 65 78 70 72 65 73 73 69 6f 6e 20 6e 6f 64  f expression nod
14f0: 65 20 70 45 78 70 72 20 2a 2f 0a 0a 20 20 69 66  e pExpr */..  if
1500: 28 20 65 54 79 70 65 21 3d 46 54 53 51 55 45 52  ( eType!=FTSQUER
1510: 59 5f 50 48 52 41 53 45 20 29 7b 0a 20 20 20 20  Y_PHRASE ){.    
1520: 61 73 73 65 72 74 28 20 70 45 78 70 72 2d 3e 70  assert( pExpr->p
1530: 4c 65 66 74 20 26 26 20 70 45 78 70 72 2d 3e 70  Left && pExpr->p
1540: 52 69 67 68 74 20 29 3b 0a 20 20 20 20 72 63 20  Right );.    rc 
1550: 3d 20 66 74 73 33 45 78 70 72 49 74 65 72 61 74  = fts3ExprIterat
1560: 65 32 28 70 45 78 70 72 2d 3e 70 4c 65 66 74 2c  e2(pExpr->pLeft,
1570: 20 70 69 50 68 72 61 73 65 2c 20 78 2c 20 70 43   piPhrase, x, pC
1580: 74 78 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d  tx);.    if( rc=
1590: 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 65 54  =SQLITE_OK && eT
15a0: 79 70 65 21 3d 46 54 53 51 55 45 52 59 5f 4e 4f  ype!=FTSQUERY_NO
15b0: 54 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  T ){.      rc = 
15c0: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 32  fts3ExprIterate2
15d0: 28 70 45 78 70 72 2d 3e 70 52 69 67 68 74 2c 20  (pExpr->pRight, 
15e0: 70 69 50 68 72 61 73 65 2c 20 78 2c 20 70 43 74  piPhrase, x, pCt
15f0: 78 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73  x);.    }.  }els
1600: 65 7b 0a 20 20 20 20 72 63 20 3d 20 78 28 70 45  e{.    rc = x(pE
1610: 78 70 72 2c 20 2a 70 69 50 68 72 61 73 65 2c 20  xpr, *piPhrase, 
1620: 70 43 74 78 29 3b 0a 20 20 20 20 28 2a 70 69 50  pCtx);.    (*piP
1630: 68 72 61 73 65 29 2b 2b 3b 0a 20 20 7d 0a 20 20  hrase)++;.  }.  
1640: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
1650: 0a 2a 2a 20 49 74 65 72 61 74 65 20 74 68 72 6f  .** Iterate thro
1660: 75 67 68 20 61 6c 6c 20 70 68 72 61 73 65 20 6e  ugh all phrase n
1670: 6f 64 65 73 20 69 6e 20 61 6e 20 46 54 53 33 20  odes in an FTS3 
1680: 71 75 65 72 79 2c 20 65 78 63 65 70 74 20 74 68  query, except th
1690: 6f 73 65 20 74 68 61 74 0a 2a 2a 20 61 72 65 20  ose that.** are 
16a0: 70 61 72 74 20 6f 66 20 61 20 73 75 62 2d 74 72  part of a sub-tr
16b0: 65 65 20 74 68 61 74 20 69 73 20 74 68 65 20 72  ee that is the r
16c0: 69 67 68 74 2d 68 61 6e 64 2d 73 69 64 65 20 6f  ight-hand-side o
16d0: 66 20 61 20 4e 4f 54 20 6f 70 65 72 61 74 6f 72  f a NOT operator
16e0: 2e 0a 2a 2a 20 46 6f 72 20 65 61 63 68 20 70 68  ..** For each ph
16f0: 72 61 73 65 20 6e 6f 64 65 20 66 6f 75 6e 64 2c  rase node found,
1700: 20 74 68 65 20 73 75 70 70 6c 69 65 64 20 63 61   the supplied ca
1710: 6c 6c 62 61 63 6b 20 66 75 6e 63 74 69 6f 6e 20  llback function 
1720: 69 73 20 69 6e 76 6f 6b 65 64 2e 0a 2a 2a 0a 2a  is invoked..**.*
1730: 2a 20 49 66 20 74 68 65 20 63 61 6c 6c 62 61 63  * If the callbac
1740: 6b 20 66 75 6e 63 74 69 6f 6e 20 72 65 74 75 72  k function retur
1750: 6e 73 20 61 6e 79 74 68 69 6e 67 20 6f 74 68 65  ns anything othe
1760: 72 20 74 68 61 6e 20 53 51 4c 49 54 45 5f 4f 4b  r than SQLITE_OK
1770: 2c 20 0a 2a 2a 20 74 68 65 20 69 74 65 72 61 74  , .** the iterat
1780: 69 6f 6e 20 69 73 20 61 62 61 6e 64 6f 6e 65 64  ion is abandoned
1790: 20 61 6e 64 20 74 68 65 20 65 72 72 6f 72 20 63   and the error c
17a0: 6f 64 65 20 72 65 74 75 72 6e 65 64 20 69 6d 6d  ode returned imm
17b0: 65 64 69 61 74 65 6c 79 2e 0a 2a 2a 20 4f 74 68  ediately..** Oth
17c0: 65 72 77 69 73 65 2c 20 53 51 4c 49 54 45 5f 4f  erwise, SQLITE_O
17d0: 4b 20 69 73 20 72 65 74 75 72 6e 65 64 20 61 66  K is returned af
17e0: 74 65 72 20 61 20 63 61 6c 6c 62 61 63 6b 20 68  ter a callback h
17f0: 61 73 20 62 65 65 6e 20 6d 61 64 65 20 66 6f 72  as been made for
1800: 0a 2a 2a 20 61 6c 6c 20 65 6c 69 67 69 62 6c 65  .** all eligible
1810: 20 70 68 72 61 73 65 20 6e 6f 64 65 73 2e 0a 2a   phrase nodes..*
1820: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74 73  /.static int fts
1830: 33 45 78 70 72 49 74 65 72 61 74 65 28 0a 20 20  3ExprIterate(.  
1840: 46 74 73 33 45 78 70 72 20 2a 70 45 78 70 72 2c  Fts3Expr *pExpr,
1850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1860: 2f 2a 20 45 78 70 72 65 73 73 69 6f 6e 20 74 6f  /* Expression to
1870: 20 69 74 65 72 61 74 65 20 70 68 72 61 73 65 73   iterate phrases
1880: 20 6f 66 20 2a 2f 0a 20 20 69 6e 74 20 28 2a 78   of */.  int (*x
1890: 29 28 46 74 73 33 45 78 70 72 2a 2c 69 6e 74 2c  )(Fts3Expr*,int,
18a0: 76 6f 69 64 2a 29 2c 20 20 2f 2a 20 43 61 6c 6c  void*),  /* Call
18b0: 62 61 63 6b 20 66 75 6e 63 74 69 6f 6e 20 74 6f  back function to
18c0: 20 69 6e 76 6f 6b 65 20 66 6f 72 20 70 68 72 61   invoke for phra
18d0: 73 65 73 20 2a 2f 0a 20 20 76 6f 69 64 20 2a 70  ses */.  void *p
18e0: 43 74 78 20 20 20 20 20 20 20 20 20 20 20 20 20  Ctx             
18f0: 20 20 20 20 20 20 20 20 20 2f 2a 20 53 65 63 6f           /* Seco
1900: 6e 64 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 70  nd argument to p
1910: 61 73 73 20 74 6f 20 63 61 6c 6c 62 61 63 6b 20  ass to callback 
1920: 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 69 50 68 72  */.){.  int iPhr
1930: 61 73 65 20 3d 20 30 3b 20 20 20 20 20 20 20 20  ase = 0;        
1940: 20 20 20 20 20 20 20 20 2f 2a 20 56 61 72 69 61          /* Varia
1950: 62 6c 65 20 75 73 65 64 20 61 73 20 74 68 65 20  ble used as the 
1960: 70 68 72 61 73 65 20 63 6f 75 6e 74 65 72 20 2a  phrase counter *
1970: 2f 0a 20 20 72 65 74 75 72 6e 20 66 74 73 33 45  /.  return fts3E
1980: 78 70 72 49 74 65 72 61 74 65 32 28 70 45 78 70  xprIterate2(pExp
1990: 72 2c 20 26 69 50 68 72 61 73 65 2c 20 78 2c 20  r, &iPhrase, x, 
19a0: 70 43 74 78 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  pCtx);.}../*.** 
19b0: 54 68 69 73 20 69 73 20 61 6e 20 66 74 73 33 45  This is an fts3E
19c0: 78 70 72 49 74 65 72 61 74 65 28 29 20 63 61 6c  xprIterate() cal
19d0: 6c 62 61 63 6b 20 75 73 65 64 20 77 68 69 6c 65  lback used while
19e0: 20 6c 6f 61 64 69 6e 67 20 74 68 65 20 64 6f 63   loading the doc
19f0: 6c 69 73 74 73 0a 2a 2a 20 66 6f 72 20 65 61 63  lists.** for eac
1a00: 68 20 70 68 72 61 73 65 20 69 6e 74 6f 20 46 74  h phrase into Ft
1a10: 73 33 45 78 70 72 2e 61 44 6f 63 6c 69 73 74 5b  s3Expr.aDoclist[
1a20: 5d 2f 6e 44 6f 63 6c 69 73 74 2e 20 53 65 65 20  ]/nDoclist. See 
1a30: 61 6c 73 6f 0a 2a 2a 20 66 74 73 33 45 78 70 72  also.** fts3Expr
1a40: 4c 6f 61 64 44 6f 63 6c 69 73 74 73 28 29 2e 0a  LoadDoclists()..
1a50: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74  */.static int ft
1a60: 73 33 45 78 70 72 4c 6f 61 64 44 6f 63 6c 69 73  s3ExprLoadDoclis
1a70: 74 73 43 62 28 46 74 73 33 45 78 70 72 20 2a 70  tsCb(Fts3Expr *p
1a80: 45 78 70 72 2c 20 69 6e 74 20 69 50 68 72 61 73  Expr, int iPhras
1a90: 65 2c 20 76 6f 69 64 20 2a 63 74 78 29 7b 0a 20  e, void *ctx){. 
1aa0: 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45   int rc = SQLITE
1ab0: 5f 4f 4b 3b 0a 20 20 46 74 73 33 50 68 72 61 73  _OK;.  Fts3Phras
1ac0: 65 20 2a 70 50 68 72 61 73 65 20 3d 20 70 45 78  e *pPhrase = pEx
1ad0: 70 72 2d 3e 70 50 68 72 61 73 65 3b 0a 20 20 4c  pr->pPhrase;.  L
1ae0: 6f 61 64 44 6f 63 6c 69 73 74 43 74 78 20 2a 70  oadDoclistCtx *p
1af0: 20 3d 20 28 4c 6f 61 64 44 6f 63 6c 69 73 74 43   = (LoadDoclistC
1b00: 74 78 20 2a 29 63 74 78 3b 0a 0a 20 20 55 4e 55  tx *)ctx;..  UNU
1b10: 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 69 50  SED_PARAMETER(iP
1b20: 68 72 61 73 65 29 3b 0a 0a 20 20 70 2d 3e 6e 50  hrase);..  p->nP
1b30: 68 72 61 73 65 2b 2b 3b 0a 20 20 70 2d 3e 6e 54  hrase++;.  p->nT
1b40: 6f 6b 65 6e 20 2b 3d 20 70 50 68 72 61 73 65 2d  oken += pPhrase-
1b50: 3e 6e 54 6f 6b 65 6e 3b 0a 0a 20 20 72 65 74 75  >nToken;..  retu
1b60: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  rn rc;.}../*.** 
1b70: 4c 6f 61 64 20 74 68 65 20 64 6f 63 6c 69 73 74  Load the doclist
1b80: 73 20 66 6f 72 20 65 61 63 68 20 70 68 72 61 73  s for each phras
1b90: 65 20 69 6e 20 74 68 65 20 71 75 65 72 79 20 61  e in the query a
1ba0: 73 73 6f 63 69 61 74 65 64 20 77 69 74 68 20 46  ssociated with F
1bb0: 54 53 33 20 63 75 72 73 6f 72 0a 2a 2a 20 70 43  TS3 cursor.** pC
1bc0: 73 72 2e 20 0a 2a 2a 0a 2a 2a 20 49 66 20 70 6e  sr. .**.** If pn
1bd0: 50 68 72 61 73 65 20 69 73 20 6e 6f 74 20 4e 55  Phrase is not NU
1be0: 4c 4c 2c 20 74 68 65 6e 20 2a 70 6e 50 68 72 61  LL, then *pnPhra
1bf0: 73 65 20 69 73 20 73 65 74 20 74 6f 20 74 68 65  se is set to the
1c00: 20 6e 75 6d 62 65 72 20 6f 66 20 6d 61 74 63 68   number of match
1c10: 61 62 6c 65 20 0a 2a 2a 20 70 68 72 61 73 65 73  able .** phrases
1c20: 20 69 6e 20 74 68 65 20 65 78 70 72 65 73 73 69   in the expressi
1c30: 6f 6e 20 28 61 6c 6c 20 70 68 72 61 73 65 73 20  on (all phrases 
1c40: 65 78 63 65 70 74 20 74 68 6f 73 65 20 64 69 72  except those dir
1c50: 65 63 74 6c 79 20 6f 72 20 0a 2a 2a 20 69 6e 64  ectly or .** ind
1c60: 69 72 65 63 74 6c 79 20 64 65 73 63 65 6e 64 65  irectly descende
1c70: 64 20 66 72 6f 6d 20 74 68 65 20 72 69 67 68 74  d from the right
1c80: 2d 68 61 6e 64 2d 73 69 64 65 20 6f 66 20 61 20  -hand-side of a 
1c90: 4e 4f 54 20 6f 70 65 72 61 74 6f 72 29 2e 20 49  NOT operator). I
1ca0: 66 20 0a 2a 2a 20 70 6e 54 6f 6b 65 6e 20 69 73  f .** pnToken is
1cb0: 20 6e 6f 74 20 4e 55 4c 4c 2c 20 74 68 65 6e 20   not NULL, then 
1cc0: 69 74 20 69 73 20 73 65 74 20 74 6f 20 74 68 65  it is set to the
1cd0: 20 6e 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e   number of token
1ce0: 73 20 69 6e 20 61 6c 6c 0a 2a 2a 20 6d 61 74 63  s in all.** matc
1cf0: 68 61 62 6c 65 20 70 68 72 61 73 65 73 20 6f 66  hable phrases of
1d00: 20 74 68 65 20 65 78 70 72 65 73 73 69 6f 6e 2e   the expression.
1d10: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66  .*/.static int f
1d20: 74 73 33 45 78 70 72 4c 6f 61 64 44 6f 63 6c 69  ts3ExprLoadDocli
1d30: 73 74 73 28 0a 20 20 46 74 73 33 43 75 72 73 6f  sts(.  Fts3Curso
1d40: 72 20 2a 70 43 73 72 2c 20 20 20 20 20 20 20 20  r *pCsr,        
1d50: 20 20 20 20 20 20 20 2f 2a 20 46 74 73 33 20 63         /* Fts3 c
1d60: 75 72 73 6f 72 20 66 6f 72 20 63 75 72 72 65 6e  ursor for curren
1d70: 74 20 71 75 65 72 79 20 2a 2f 0a 20 20 69 6e 74  t query */.  int
1d80: 20 2a 70 6e 50 68 72 61 73 65 2c 20 20 20 20 20   *pnPhrase,     
1d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
1da0: 4f 55 54 3a 20 4e 75 6d 62 65 72 20 6f 66 20 70  OUT: Number of p
1db0: 68 72 61 73 65 73 20 69 6e 20 71 75 65 72 79 20  hrases in query 
1dc0: 2a 2f 0a 20 20 69 6e 74 20 2a 70 6e 54 6f 6b 65  */.  int *pnToke
1dd0: 6e 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n               
1de0: 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 4e 75 6d       /* OUT: Num
1df0: 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20 69 6e  ber of tokens in
1e00: 20 71 75 65 72 79 20 2a 2f 0a 29 7b 0a 20 20 69   query */.){.  i
1e10: 6e 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20  nt rc;          
1e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
1e30: 2a 20 52 65 74 75 72 6e 20 43 6f 64 65 20 2a 2f  * Return Code */
1e40: 0a 20 20 4c 6f 61 64 44 6f 63 6c 69 73 74 43 74  .  LoadDoclistCt
1e50: 78 20 73 43 74 78 20 3d 20 7b 30 2c 30 2c 30 7d  x sCtx = {0,0,0}
1e60: 3b 20 20 2f 2a 20 43 6f 6e 74 65 78 74 20 66 6f  ;  /* Context fo
1e70: 72 20 66 74 73 33 45 78 70 72 49 74 65 72 61 74  r fts3ExprIterat
1e80: 65 28 29 20 2a 2f 0a 20 20 73 43 74 78 2e 70 43  e() */.  sCtx.pC
1e90: 73 72 20 3d 20 70 43 73 72 3b 0a 20 20 72 63 20  sr = pCsr;.  rc 
1ea0: 3d 20 66 74 73 33 45 78 70 72 49 74 65 72 61 74  = fts3ExprIterat
1eb0: 65 28 70 43 73 72 2d 3e 70 45 78 70 72 2c 20 66  e(pCsr->pExpr, f
1ec0: 74 73 33 45 78 70 72 4c 6f 61 64 44 6f 63 6c 69  ts3ExprLoadDocli
1ed0: 73 74 73 43 62 2c 20 28 76 6f 69 64 20 2a 29 26  stsCb, (void *)&
1ee0: 73 43 74 78 29 3b 0a 20 20 69 66 28 20 70 6e 50  sCtx);.  if( pnP
1ef0: 68 72 61 73 65 20 29 20 2a 70 6e 50 68 72 61 73  hrase ) *pnPhras
1f00: 65 20 3d 20 73 43 74 78 2e 6e 50 68 72 61 73 65  e = sCtx.nPhrase
1f10: 3b 0a 20 20 69 66 28 20 70 6e 54 6f 6b 65 6e 20  ;.  if( pnToken 
1f20: 29 20 2a 70 6e 54 6f 6b 65 6e 20 3d 20 73 43 74  ) *pnToken = sCt
1f30: 78 2e 6e 54 6f 6b 65 6e 3b 0a 20 20 72 65 74 75  x.nToken;.  retu
1f40: 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63  rn rc;.}..static
1f50: 20 69 6e 74 20 66 74 73 33 45 78 70 72 50 68 72   int fts3ExprPhr
1f60: 61 73 65 43 6f 75 6e 74 43 62 28 46 74 73 33 45  aseCountCb(Fts3E
1f70: 78 70 72 20 2a 70 45 78 70 72 2c 20 69 6e 74 20  xpr *pExpr, int 
1f80: 69 50 68 72 61 73 65 2c 20 76 6f 69 64 20 2a 63  iPhrase, void *c
1f90: 74 78 29 7b 0a 20 20 28 2a 28 69 6e 74 20 2a 29  tx){.  (*(int *)
1fa0: 63 74 78 29 2b 2b 3b 0a 20 20 55 4e 55 53 45 44  ctx)++;.  UNUSED
1fb0: 5f 50 41 52 41 4d 45 54 45 52 28 70 45 78 70 72  _PARAMETER(pExpr
1fc0: 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41  );.  UNUSED_PARA
1fd0: 4d 45 54 45 52 28 69 50 68 72 61 73 65 29 3b 0a  METER(iPhrase);.
1fe0: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
1ff0: 4f 4b 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74  OK;.}.static int
2000: 20 66 74 73 33 45 78 70 72 50 68 72 61 73 65 43   fts3ExprPhraseC
2010: 6f 75 6e 74 28 46 74 73 33 45 78 70 72 20 2a 70  ount(Fts3Expr *p
2020: 45 78 70 72 29 7b 0a 20 20 69 6e 74 20 6e 50 68  Expr){.  int nPh
2030: 72 61 73 65 20 3d 20 30 3b 0a 20 20 28 76 6f 69  rase = 0;.  (voi
2040: 64 29 66 74 73 33 45 78 70 72 49 74 65 72 61 74  d)fts3ExprIterat
2050: 65 28 70 45 78 70 72 2c 20 66 74 73 33 45 78 70  e(pExpr, fts3Exp
2060: 72 50 68 72 61 73 65 43 6f 75 6e 74 43 62 2c 20  rPhraseCountCb, 
2070: 28 76 6f 69 64 20 2a 29 26 6e 50 68 72 61 73 65  (void *)&nPhrase
2080: 29 3b 0a 20 20 72 65 74 75 72 6e 20 6e 50 68 72  );.  return nPhr
2090: 61 73 65 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 64  ase;.}../*.** Ad
20a0: 76 61 6e 63 65 20 74 68 65 20 70 6f 73 69 74 69  vance the positi
20b0: 6f 6e 20 6c 69 73 74 20 69 74 65 72 61 74 6f 72  on list iterator
20c0: 20 73 70 65 63 69 66 69 65 64 20 62 79 20 74 68   specified by th
20d0: 65 20 66 69 72 73 74 20 74 77 6f 20 0a 2a 2a 20  e first two .** 
20e0: 61 72 67 75 6d 65 6e 74 73 20 73 6f 20 74 68 61  arguments so tha
20f0: 74 20 69 74 20 70 6f 69 6e 74 73 20 74 6f 20 74  t it points to t
2100: 68 65 20 66 69 72 73 74 20 65 6c 65 6d 65 6e 74  he first element
2110: 20 77 69 74 68 20 61 20 76 61 6c 75 65 20 67 72   with a value gr
2120: 65 61 74 65 72 0a 2a 2a 20 74 68 61 6e 20 6f 72  eater.** than or
2130: 20 65 71 75 61 6c 20 74 6f 20 70 61 72 61 6d 65   equal to parame
2140: 74 65 72 20 69 4e 65 78 74 2e 0a 2a 2f 0a 73 74  ter iNext..*/.st
2150: 61 74 69 63 20 76 6f 69 64 20 66 74 73 33 53 6e  atic void fts3Sn
2160: 69 70 70 65 74 41 64 76 61 6e 63 65 28 63 68 61  ippetAdvance(cha
2170: 72 20 2a 2a 70 70 49 74 65 72 2c 20 69 6e 74 20  r **ppIter, int 
2180: 2a 70 69 49 74 65 72 2c 20 69 6e 74 20 69 4e 65  *piIter, int iNe
2190: 78 74 29 7b 0a 20 20 63 68 61 72 20 2a 70 49 74  xt){.  char *pIt
21a0: 65 72 20 3d 20 2a 70 70 49 74 65 72 3b 0a 20 20  er = *ppIter;.  
21b0: 69 66 28 20 70 49 74 65 72 20 29 7b 0a 20 20 20  if( pIter ){.   
21c0: 20 69 6e 74 20 69 49 74 65 72 20 3d 20 2a 70 69   int iIter = *pi
21d0: 49 74 65 72 3b 0a 0a 20 20 20 20 77 68 69 6c 65  Iter;..    while
21e0: 28 20 69 49 74 65 72 3c 69 4e 65 78 74 20 29 7b  ( iIter<iNext ){
21f0: 0a 20 20 20 20 20 20 69 66 28 20 30 3d 3d 28 2a  .      if( 0==(*
2200: 70 49 74 65 72 20 26 20 30 78 46 45 29 20 29 7b  pIter & 0xFE) ){
2210: 0a 20 20 20 20 20 20 20 20 69 49 74 65 72 20 3d  .        iIter =
2220: 20 2d 31 3b 0a 20 20 20 20 20 20 20 20 70 49 74   -1;.        pIt
2230: 65 72 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20  er = 0;.        
2240: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 20  break;.      }. 
2250: 20 20 20 20 20 66 74 73 33 47 65 74 44 65 6c 74       fts3GetDelt
2260: 61 50 6f 73 69 74 69 6f 6e 28 26 70 49 74 65 72  aPosition(&pIter
2270: 2c 20 26 69 49 74 65 72 29 3b 0a 20 20 20 20 7d  , &iIter);.    }
2280: 0a 0a 20 20 20 20 2a 70 69 49 74 65 72 20 3d 20  ..    *piIter = 
2290: 69 49 74 65 72 3b 0a 20 20 20 20 2a 70 70 49 74  iIter;.    *ppIt
22a0: 65 72 20 3d 20 70 49 74 65 72 3b 0a 20 20 7d 0a  er = pIter;.  }.
22b0: 7d 0a 0a 2f 2a 0a 2a 2a 20 41 64 76 61 6e 63 65  }../*.** Advance
22c0: 20 74 68 65 20 73 6e 69 70 70 65 74 20 69 74 65   the snippet ite
22d0: 72 61 74 6f 72 20 74 6f 20 74 68 65 20 6e 65 78  rator to the nex
22e0: 74 20 63 61 6e 64 69 64 61 74 65 20 73 6e 69 70  t candidate snip
22f0: 70 65 74 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  pet..*/.static i
2300: 6e 74 20 66 74 73 33 53 6e 69 70 70 65 74 4e 65  nt fts3SnippetNe
2310: 78 74 43 61 6e 64 69 64 61 74 65 28 53 6e 69 70  xtCandidate(Snip
2320: 70 65 74 49 74 65 72 20 2a 70 49 74 65 72 29 7b  petIter *pIter){
2330: 0a 20 20 69 6e 74 20 69 3b 20 20 20 20 20 20 20  .  int i;       
2340: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2350: 20 20 20 2f 2a 20 4c 6f 6f 70 20 63 6f 75 6e 74     /* Loop count
2360: 65 72 20 2a 2f 0a 0a 20 20 69 66 28 20 70 49 74  er */..  if( pIt
2370: 65 72 2d 3e 69 43 75 72 72 65 6e 74 3c 30 20 29  er->iCurrent<0 )
2380: 7b 0a 20 20 20 20 2f 2a 20 54 68 65 20 53 6e 69  {.    /* The Sni
2390: 70 70 65 74 49 74 65 72 20 6f 62 6a 65 63 74 20  ppetIter object 
23a0: 68 61 73 20 6a 75 73 74 20 62 65 65 6e 20 69 6e  has just been in
23b0: 69 74 69 61 6c 69 7a 65 64 2e 20 54 68 65 20 66  itialized. The f
23c0: 69 72 73 74 20 73 6e 69 70 70 65 74 0a 20 20 20  irst snippet.   
23d0: 20 2a 2a 20 63 61 6e 64 69 64 61 74 65 20 61 6c   ** candidate al
23e0: 77 61 79 73 20 73 74 61 72 74 73 20 61 74 20 6f  ways starts at o
23f0: 66 66 73 65 74 20 30 20 28 65 76 65 6e 20 69 66  ffset 0 (even if
2400: 20 74 68 69 73 20 63 61 6e 64 69 64 61 74 65 20   this candidate 
2410: 68 61 73 20 61 0a 20 20 20 20 2a 2a 20 73 63 6f  has a.    ** sco
2420: 72 65 20 6f 66 20 30 2e 30 29 2e 0a 20 20 20 20  re of 0.0)..    
2430: 2a 2f 0a 20 20 20 20 70 49 74 65 72 2d 3e 69 43  */.    pIter->iC
2440: 75 72 72 65 6e 74 20 3d 20 30 3b 0a 0a 20 20 20  urrent = 0;..   
2450: 20 2f 2a 20 41 64 76 61 6e 63 65 20 74 68 65 20   /* Advance the 
2460: 27 68 65 61 64 27 20 69 74 65 72 61 74 6f 72 20  'head' iterator 
2470: 6f 66 20 65 61 63 68 20 70 68 72 61 73 65 20 74  of each phrase t
2480: 6f 20 74 68 65 20 66 69 72 73 74 20 6f 66 66 73  o the first offs
2490: 65 74 20 74 68 61 74 0a 20 20 20 20 2a 2a 20 69  et that.    ** i
24a0: 73 20 67 72 65 61 74 65 72 20 74 68 61 6e 20 6f  s greater than o
24b0: 72 20 65 71 75 61 6c 20 74 6f 20 28 69 4e 65 78  r equal to (iNex
24c0: 74 2b 6e 53 6e 69 70 70 65 74 29 2e 0a 20 20 20  t+nSnippet)..   
24d0: 20 2a 2f 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b   */.    for(i=0;
24e0: 20 69 3c 70 49 74 65 72 2d 3e 6e 50 68 72 61 73   i<pIter->nPhras
24f0: 65 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 53  e; i++){.      S
2500: 6e 69 70 70 65 74 50 68 72 61 73 65 20 2a 70 50  nippetPhrase *pP
2510: 68 72 61 73 65 20 3d 20 26 70 49 74 65 72 2d 3e  hrase = &pIter->
2520: 61 50 68 72 61 73 65 5b 69 5d 3b 0a 20 20 20 20  aPhrase[i];.    
2530: 20 20 66 74 73 33 53 6e 69 70 70 65 74 41 64 76    fts3SnippetAdv
2540: 61 6e 63 65 28 26 70 50 68 72 61 73 65 2d 3e 70  ance(&pPhrase->p
2550: 48 65 61 64 2c 20 26 70 50 68 72 61 73 65 2d 3e  Head, &pPhrase->
2560: 69 48 65 61 64 2c 20 70 49 74 65 72 2d 3e 6e 53  iHead, pIter->nS
2570: 6e 69 70 70 65 74 29 3b 0a 20 20 20 20 7d 0a 20  nippet);.    }. 
2580: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 69 6e 74 20   }else{.    int 
2590: 69 53 74 61 72 74 3b 0a 20 20 20 20 69 6e 74 20  iStart;.    int 
25a0: 69 45 6e 64 20 3d 20 30 78 37 46 46 46 46 46 46  iEnd = 0x7FFFFFF
25b0: 46 3b 0a 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b  F;..    for(i=0;
25c0: 20 69 3c 70 49 74 65 72 2d 3e 6e 50 68 72 61 73   i<pIter->nPhras
25d0: 65 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 53  e; i++){.      S
25e0: 6e 69 70 70 65 74 50 68 72 61 73 65 20 2a 70 50  nippetPhrase *pP
25f0: 68 72 61 73 65 20 3d 20 26 70 49 74 65 72 2d 3e  hrase = &pIter->
2600: 61 50 68 72 61 73 65 5b 69 5d 3b 0a 20 20 20 20  aPhrase[i];.    
2610: 20 20 69 66 28 20 70 50 68 72 61 73 65 2d 3e 70    if( pPhrase->p
2620: 48 65 61 64 20 26 26 20 70 50 68 72 61 73 65 2d  Head && pPhrase-
2630: 3e 69 48 65 61 64 3c 69 45 6e 64 20 29 7b 0a 20  >iHead<iEnd ){. 
2640: 20 20 20 20 20 20 20 69 45 6e 64 20 3d 20 70 50         iEnd = pP
2650: 68 72 61 73 65 2d 3e 69 48 65 61 64 3b 0a 20 20  hrase->iHead;.  
2660: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20      }.    }.    
2670: 69 66 28 20 69 45 6e 64 3d 3d 30 78 37 46 46 46  if( iEnd==0x7FFF
2680: 46 46 46 46 20 29 7b 0a 20 20 20 20 20 20 72 65  FFFF ){.      re
2690: 74 75 72 6e 20 31 3b 0a 20 20 20 20 7d 0a 0a 20  turn 1;.    }.. 
26a0: 20 20 20 70 49 74 65 72 2d 3e 69 43 75 72 72 65     pIter->iCurre
26b0: 6e 74 20 3d 20 69 53 74 61 72 74 20 3d 20 69 45  nt = iStart = iE
26c0: 6e 64 20 2d 20 70 49 74 65 72 2d 3e 6e 53 6e 69  nd - pIter->nSni
26d0: 70 70 65 74 20 2b 20 31 3b 0a 20 20 20 20 66 6f  ppet + 1;.    fo
26e0: 72 28 69 3d 30 3b 20 69 3c 70 49 74 65 72 2d 3e  r(i=0; i<pIter->
26f0: 6e 50 68 72 61 73 65 3b 20 69 2b 2b 29 7b 0a 20  nPhrase; i++){. 
2700: 20 20 20 20 20 53 6e 69 70 70 65 74 50 68 72 61       SnippetPhra
2710: 73 65 20 2a 70 50 68 72 61 73 65 20 3d 20 26 70  se *pPhrase = &p
2720: 49 74 65 72 2d 3e 61 50 68 72 61 73 65 5b 69 5d  Iter->aPhrase[i]
2730: 3b 0a 20 20 20 20 20 20 66 74 73 33 53 6e 69 70  ;.      fts3Snip
2740: 70 65 74 41 64 76 61 6e 63 65 28 26 70 50 68 72  petAdvance(&pPhr
2750: 61 73 65 2d 3e 70 48 65 61 64 2c 20 26 70 50 68  ase->pHead, &pPh
2760: 72 61 73 65 2d 3e 69 48 65 61 64 2c 20 69 45 6e  rase->iHead, iEn
2770: 64 2b 31 29 3b 0a 20 20 20 20 20 20 66 74 73 33  d+1);.      fts3
2780: 53 6e 69 70 70 65 74 41 64 76 61 6e 63 65 28 26  SnippetAdvance(&
2790: 70 50 68 72 61 73 65 2d 3e 70 54 61 69 6c 2c 20  pPhrase->pTail, 
27a0: 26 70 50 68 72 61 73 65 2d 3e 69 54 61 69 6c 2c  &pPhrase->iTail,
27b0: 20 69 53 74 61 72 74 29 3b 0a 20 20 20 20 7d 0a   iStart);.    }.
27c0: 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 30 3b    }..  return 0;
27d0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 72 69 65  .}../*.** Retrie
27e0: 76 65 20 69 6e 66 6f 72 6d 61 74 69 6f 6e 20 61  ve information a
27f0: 62 6f 75 74 20 74 68 65 20 63 75 72 72 65 6e 74  bout the current
2800: 20 63 61 6e 64 69 64 61 74 65 20 73 6e 69 70 70   candidate snipp
2810: 65 74 20 6f 66 20 73 6e 69 70 70 65 74 20 0a 2a  et of snippet .*
2820: 2a 20 69 74 65 72 61 74 6f 72 20 70 49 74 65 72  * iterator pIter
2830: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
2840: 20 66 74 73 33 53 6e 69 70 70 65 74 44 65 74 61   fts3SnippetDeta
2850: 69 6c 73 28 0a 20 20 53 6e 69 70 70 65 74 49 74  ils(.  SnippetIt
2860: 65 72 20 2a 70 49 74 65 72 2c 20 20 20 20 20 20  er *pIter,      
2870: 20 20 20 20 20 20 20 2f 2a 20 53 6e 69 70 70 65         /* Snippe
2880: 74 20 69 74 65 72 61 74 6f 72 20 2a 2f 0a 20 20  t iterator */.  
2890: 75 36 34 20 6d 43 6f 76 65 72 65 64 2c 20 20 20  u64 mCovered,   
28a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
28b0: 2f 2a 20 42 69 74 6d 61 73 6b 20 6f 66 20 70 68  /* Bitmask of ph
28c0: 72 61 73 65 73 20 61 6c 72 65 61 64 79 20 63 6f  rases already co
28d0: 76 65 72 65 64 20 2a 2f 0a 20 20 69 6e 74 20 2a  vered */.  int *
28e0: 70 69 54 6f 6b 65 6e 2c 20 20 20 20 20 20 20 20  piToken,        
28f0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 55             /* OU
2900: 54 3a 20 46 69 72 73 74 20 74 6f 6b 65 6e 20 6f  T: First token o
2910: 66 20 70 72 6f 70 6f 73 65 64 20 73 6e 69 70 70  f proposed snipp
2920: 65 74 20 2a 2f 0a 20 20 69 6e 74 20 2a 70 69 53  et */.  int *piS
2930: 63 6f 72 65 2c 20 20 20 20 20 20 20 20 20 20 20  core,           
2940: 20 20 20 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20          /* OUT: 
2950: 22 53 63 6f 72 65 22 20 66 6f 72 20 74 68 69 73  "Score" for this
2960: 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20 75 36   snippet */.  u6
2970: 34 20 2a 70 6d 43 6f 76 65 72 2c 20 20 20 20 20  4 *pmCover,     
2980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
2990: 20 4f 55 54 3a 20 42 69 74 6d 61 73 6b 20 6f 66   OUT: Bitmask of
29a0: 20 70 68 72 61 73 65 73 20 63 6f 76 65 72 65 64   phrases covered
29b0: 20 2a 2f 0a 20 20 75 36 34 20 2a 70 6d 48 69 67   */.  u64 *pmHig
29c0: 68 6c 69 67 68 74 20 20 20 20 20 20 20 20 20 20  hlight          
29d0: 20 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 42 69        /* OUT: Bi
29e0: 74 6d 61 73 6b 20 6f 66 20 74 65 72 6d 73 20 74  tmask of terms t
29f0: 6f 20 68 69 67 68 6c 69 67 68 74 20 2a 2f 0a 29  o highlight */.)
2a00: 7b 0a 20 20 69 6e 74 20 69 53 74 61 72 74 20 3d  {.  int iStart =
2a10: 20 70 49 74 65 72 2d 3e 69 43 75 72 72 65 6e 74   pIter->iCurrent
2a20: 3b 20 20 20 2f 2a 20 46 69 72 73 74 20 74 6f 6b  ;   /* First tok
2a30: 65 6e 20 6f 66 20 73 6e 69 70 70 65 74 20 2a 2f  en of snippet */
2a40: 0a 20 20 69 6e 74 20 69 53 63 6f 72 65 20 3d 20  .  int iScore = 
2a50: 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0;              
2a60: 20 20 20 2f 2a 20 53 63 6f 72 65 20 6f 66 20 74     /* Score of t
2a70: 68 69 73 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20  his snippet */. 
2a80: 20 69 6e 74 20 69 3b 20 20 20 20 20 20 20 20 20   int i;         
2a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2aa0: 20 2f 2a 20 4c 6f 6f 70 20 63 6f 75 6e 74 65 72   /* Loop counter
2ab0: 20 2a 2f 0a 20 20 75 36 34 20 6d 43 6f 76 65 72   */.  u64 mCover
2ac0: 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20   = 0;           
2ad0: 20 20 20 20 20 20 2f 2a 20 4d 61 73 6b 20 6f 66        /* Mask of
2ae0: 20 70 68 72 61 73 65 73 20 63 6f 76 65 72 65 64   phrases covered
2af0: 20 62 79 20 74 68 69 73 20 73 6e 69 70 70 65 74   by this snippet
2b00: 20 2a 2f 0a 20 20 75 36 34 20 6d 48 69 67 68 6c   */.  u64 mHighl
2b10: 69 67 68 74 20 3d 20 30 3b 20 20 20 20 20 20 20  ight = 0;       
2b20: 20 20 20 20 20 20 2f 2a 20 4d 61 73 6b 20 6f 66        /* Mask of
2b30: 20 74 6f 6b 65 6e 73 20 74 6f 20 68 69 67 68 6c   tokens to highl
2b40: 69 67 68 74 20 69 6e 20 73 6e 69 70 70 65 74 20  ight in snippet 
2b50: 2a 2f 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69  */..  for(i=0; i
2b60: 3c 70 49 74 65 72 2d 3e 6e 50 68 72 61 73 65 3b  <pIter->nPhrase;
2b70: 20 69 2b 2b 29 7b 0a 20 20 20 20 53 6e 69 70 70   i++){.    Snipp
2b80: 65 74 50 68 72 61 73 65 20 2a 70 50 68 72 61 73  etPhrase *pPhras
2b90: 65 20 3d 20 26 70 49 74 65 72 2d 3e 61 50 68 72  e = &pIter->aPhr
2ba0: 61 73 65 5b 69 5d 3b 0a 20 20 20 20 69 66 28 20  ase[i];.    if( 
2bb0: 70 50 68 72 61 73 65 2d 3e 70 54 61 69 6c 20 29  pPhrase->pTail )
2bc0: 7b 0a 20 20 20 20 20 20 63 68 61 72 20 2a 70 43  {.      char *pC
2bd0: 73 72 20 3d 20 70 50 68 72 61 73 65 2d 3e 70 54  sr = pPhrase->pT
2be0: 61 69 6c 3b 0a 20 20 20 20 20 20 69 6e 74 20 69  ail;.      int i
2bf0: 43 73 72 20 3d 20 70 50 68 72 61 73 65 2d 3e 69  Csr = pPhrase->i
2c00: 54 61 69 6c 3b 0a 0a 20 20 20 20 20 20 77 68 69  Tail;..      whi
2c10: 6c 65 28 20 69 43 73 72 3c 28 69 53 74 61 72 74  le( iCsr<(iStart
2c20: 2b 70 49 74 65 72 2d 3e 6e 53 6e 69 70 70 65 74  +pIter->nSnippet
2c30: 29 20 29 7b 0a 20 20 20 20 20 20 20 20 69 6e 74  ) ){.        int
2c40: 20 6a 3b 0a 20 20 20 20 20 20 20 20 75 36 34 20   j;.        u64 
2c50: 6d 50 68 72 61 73 65 20 3d 20 28 75 36 34 29 31  mPhrase = (u64)1
2c60: 20 3c 3c 20 69 3b 0a 20 20 20 20 20 20 20 20 75   << i;.        u
2c70: 36 34 20 6d 50 6f 73 20 3d 20 28 75 36 34 29 31  64 mPos = (u64)1
2c80: 20 3c 3c 20 28 69 43 73 72 20 2d 20 69 53 74 61   << (iCsr - iSta
2c90: 72 74 29 3b 0a 20 20 20 20 20 20 20 20 61 73 73  rt);.        ass
2ca0: 65 72 74 28 20 69 43 73 72 3e 3d 69 53 74 61 72  ert( iCsr>=iStar
2cb0: 74 20 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28  t );.        if(
2cc0: 20 28 6d 43 6f 76 65 72 7c 6d 43 6f 76 65 72 65   (mCover|mCovere
2cd0: 64 29 26 6d 50 68 72 61 73 65 20 29 7b 0a 20 20  d)&mPhrase ){.  
2ce0: 20 20 20 20 20 20 20 20 69 53 63 6f 72 65 2b 2b          iScore++
2cf0: 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b  ;.        }else{
2d00: 0a 20 20 20 20 20 20 20 20 20 20 69 53 63 6f 72  .          iScor
2d10: 65 20 2b 3d 20 31 30 30 30 3b 0a 20 20 20 20 20  e += 1000;.     
2d20: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 6d 43 6f     }.        mCo
2d30: 76 65 72 20 7c 3d 20 6d 50 68 72 61 73 65 3b 0a  ver |= mPhrase;.
2d40: 0a 20 20 20 20 20 20 20 20 66 6f 72 28 6a 3d 30  .        for(j=0
2d50: 3b 20 6a 3c 70 50 68 72 61 73 65 2d 3e 6e 54 6f  ; j<pPhrase->nTo
2d60: 6b 65 6e 3b 20 6a 2b 2b 29 7b 0a 20 20 20 20 20  ken; j++){.     
2d70: 20 20 20 20 20 6d 48 69 67 68 6c 69 67 68 74 20       mHighlight 
2d80: 7c 3d 20 28 6d 50 6f 73 3e 3e 6a 29 3b 0a 20 20  |= (mPos>>j);.  
2d90: 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 20        }..       
2da0: 20 69 66 28 20 30 3d 3d 28 2a 70 43 73 72 20 26   if( 0==(*pCsr &
2db0: 20 30 78 30 46 45 29 20 29 20 62 72 65 61 6b 3b   0x0FE) ) break;
2dc0: 0a 20 20 20 20 20 20 20 20 66 74 73 33 47 65 74  .        fts3Get
2dd0: 44 65 6c 74 61 50 6f 73 69 74 69 6f 6e 28 26 70  DeltaPosition(&p
2de0: 43 73 72 2c 20 26 69 43 73 72 29 3b 0a 20 20 20  Csr, &iCsr);.   
2df0: 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a     }.    }.  }..
2e00: 20 20 2f 2a 20 53 65 74 20 74 68 65 20 6f 75 74    /* Set the out
2e10: 70 75 74 20 76 61 72 69 61 62 6c 65 73 20 62 65  put variables be
2e20: 66 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e 20  fore returning. 
2e30: 2a 2f 0a 20 20 2a 70 69 54 6f 6b 65 6e 20 3d 20  */.  *piToken = 
2e40: 69 53 74 61 72 74 3b 0a 20 20 2a 70 69 53 63 6f  iStart;.  *piSco
2e50: 72 65 20 3d 20 69 53 63 6f 72 65 3b 0a 20 20 2a  re = iScore;.  *
2e60: 70 6d 43 6f 76 65 72 20 3d 20 6d 43 6f 76 65 72  pmCover = mCover
2e70: 3b 0a 20 20 2a 70 6d 48 69 67 68 6c 69 67 68 74  ;.  *pmHighlight
2e80: 20 3d 20 6d 48 69 67 68 6c 69 67 68 74 3b 0a 7d   = mHighlight;.}
2e90: 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e  ../*.** This fun
2ea0: 63 74 69 6f 6e 20 69 73 20 61 6e 20 66 74 73 33  ction is an fts3
2eb0: 45 78 70 72 49 74 65 72 61 74 65 28 29 20 63 61  ExprIterate() ca
2ec0: 6c 6c 62 61 63 6b 20 75 73 65 64 20 62 79 20 66  llback used by f
2ed0: 74 73 33 42 65 73 74 53 6e 69 70 70 65 74 28 29  ts3BestSnippet()
2ee0: 2e 0a 2a 2a 20 45 61 63 68 20 69 6e 76 6f 63 61  ..** Each invoca
2ef0: 74 69 6f 6e 20 70 6f 70 75 6c 61 74 65 73 20 61  tion populates a
2f00: 6e 20 65 6c 65 6d 65 6e 74 20 6f 66 20 74 68 65  n element of the
2f10: 20 53 6e 69 70 70 65 74 49 74 65 72 2e 61 50 68   SnippetIter.aPh
2f20: 72 61 73 65 5b 5d 20 61 72 72 61 79 2e 0a 2a 2f  rase[] array..*/
2f30: 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33  .static int fts3
2f40: 53 6e 69 70 70 65 74 46 69 6e 64 50 6f 73 69 74  SnippetFindPosit
2f50: 69 6f 6e 73 28 46 74 73 33 45 78 70 72 20 2a 70  ions(Fts3Expr *p
2f60: 45 78 70 72 2c 20 69 6e 74 20 69 50 68 72 61 73  Expr, int iPhras
2f70: 65 2c 20 76 6f 69 64 20 2a 63 74 78 29 7b 0a 20  e, void *ctx){. 
2f80: 20 53 6e 69 70 70 65 74 49 74 65 72 20 2a 70 20   SnippetIter *p 
2f90: 3d 20 28 53 6e 69 70 70 65 74 49 74 65 72 20 2a  = (SnippetIter *
2fa0: 29 63 74 78 3b 0a 20 20 53 6e 69 70 70 65 74 50  )ctx;.  SnippetP
2fb0: 68 72 61 73 65 20 2a 70 50 68 72 61 73 65 20 3d  hrase *pPhrase =
2fc0: 20 26 70 2d 3e 61 50 68 72 61 73 65 5b 69 50 68   &p->aPhrase[iPh
2fd0: 72 61 73 65 5d 3b 0a 20 20 63 68 61 72 20 2a 70  rase];.  char *p
2fe0: 43 73 72 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 0a  Csr;.  int rc;..
2ff0: 20 20 70 50 68 72 61 73 65 2d 3e 6e 54 6f 6b 65    pPhrase->nToke
3000: 6e 20 3d 20 70 45 78 70 72 2d 3e 70 50 68 72 61  n = pExpr->pPhra
3010: 73 65 2d 3e 6e 54 6f 6b 65 6e 3b 0a 20 20 72 63  se->nToken;.  rc
3020: 20 3d 20 73 71 6c 69 74 65 33 46 74 73 33 45 76   = sqlite3Fts3Ev
3030: 61 6c 50 68 72 61 73 65 50 6f 73 6c 69 73 74 28  alPhrasePoslist(
3040: 70 2d 3e 70 43 73 72 2c 20 70 45 78 70 72 2c 20  p->pCsr, pExpr, 
3050: 70 2d 3e 69 43 6f 6c 2c 20 26 70 43 73 72 29 3b  p->iCol, &pCsr);
3060: 0a 20 20 61 73 73 65 72 74 28 20 72 63 3d 3d 53  .  assert( rc==S
3070: 51 4c 49 54 45 5f 4f 4b 20 7c 7c 20 70 43 73 72  QLITE_OK || pCsr
3080: 3d 3d 30 20 29 3b 0a 20 20 69 66 28 20 70 43 73  ==0 );.  if( pCs
3090: 72 20 29 7b 0a 20 20 20 20 69 6e 74 20 69 46 69  r ){.    int iFi
30a0: 72 73 74 20 3d 20 30 3b 0a 20 20 20 20 70 50 68  rst = 0;.    pPh
30b0: 72 61 73 65 2d 3e 70 4c 69 73 74 20 3d 20 70 43  rase->pList = pC
30c0: 73 72 3b 0a 20 20 20 20 66 74 73 33 47 65 74 44  sr;.    fts3GetD
30d0: 65 6c 74 61 50 6f 73 69 74 69 6f 6e 28 26 70 43  eltaPosition(&pC
30e0: 73 72 2c 20 26 69 46 69 72 73 74 29 3b 0a 20 20  sr, &iFirst);.  
30f0: 20 20 61 73 73 65 72 74 28 20 69 46 69 72 73 74    assert( iFirst
3100: 3e 3d 30 20 29 3b 0a 20 20 20 20 70 50 68 72 61  >=0 );.    pPhra
3110: 73 65 2d 3e 70 48 65 61 64 20 3d 20 70 43 73 72  se->pHead = pCsr
3120: 3b 0a 20 20 20 20 70 50 68 72 61 73 65 2d 3e 70  ;.    pPhrase->p
3130: 54 61 69 6c 20 3d 20 70 43 73 72 3b 0a 20 20 20  Tail = pCsr;.   
3140: 20 70 50 68 72 61 73 65 2d 3e 69 48 65 61 64 20   pPhrase->iHead 
3150: 3d 20 69 46 69 72 73 74 3b 0a 20 20 20 20 70 50  = iFirst;.    pP
3160: 68 72 61 73 65 2d 3e 69 54 61 69 6c 20 3d 20 69  hrase->iTail = i
3170: 46 69 72 73 74 3b 0a 20 20 7d 65 6c 73 65 7b 0a  First;.  }else{.
3180: 20 20 20 20 61 73 73 65 72 74 28 20 72 63 21 3d      assert( rc!=
3190: 53 51 4c 49 54 45 5f 4f 4b 20 7c 7c 20 28 0a 20  SQLITE_OK || (. 
31a0: 20 20 20 20 20 20 70 50 68 72 61 73 65 2d 3e 70        pPhrase->p
31b0: 4c 69 73 74 3d 3d 30 20 26 26 20 70 50 68 72 61  List==0 && pPhra
31c0: 73 65 2d 3e 70 48 65 61 64 3d 3d 30 20 26 26 20  se->pHead==0 && 
31d0: 70 50 68 72 61 73 65 2d 3e 70 54 61 69 6c 3d 3d  pPhrase->pTail==
31e0: 30 20 0a 20 20 20 20 29 29 3b 0a 20 20 7d 0a 0a  0 .    ));.  }..
31f0: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
3200: 2f 2a 0a 2a 2a 20 53 65 6c 65 63 74 20 74 68 65  /*.** Select the
3210: 20 66 72 61 67 6d 65 6e 74 20 6f 66 20 74 65 78   fragment of tex
3220: 74 20 63 6f 6e 73 69 73 74 69 6e 67 20 6f 66 20  t consisting of 
3230: 6e 46 72 61 67 6d 65 6e 74 20 63 6f 6e 74 69 67  nFragment contig
3240: 75 6f 75 73 20 74 6f 6b 65 6e 73 20 0a 2a 2a 20  uous tokens .** 
3250: 66 72 6f 6d 20 63 6f 6c 75 6d 6e 20 69 43 6f 6c  from column iCol
3260: 20 74 68 61 74 20 72 65 70 72 65 73 65 6e 74 20   that represent 
3270: 74 68 65 20 22 62 65 73 74 22 20 73 6e 69 70 70  the "best" snipp
3280: 65 74 2e 20 54 68 65 20 62 65 73 74 20 73 6e 69  et. The best sni
3290: 70 70 65 74 0a 2a 2a 20 69 73 20 74 68 65 20 73  ppet.** is the s
32a0: 6e 69 70 70 65 74 20 77 69 74 68 20 74 68 65 20  nippet with the 
32b0: 68 69 67 68 65 73 74 20 73 63 6f 72 65 2c 20 77  highest score, w
32c0: 68 65 72 65 20 73 63 6f 72 65 73 20 61 72 65 20  here scores are 
32d0: 63 61 6c 63 75 6c 61 74 65 64 0a 2a 2a 20 62 79  calculated.** by
32e0: 20 61 64 64 69 6e 67 3a 0a 2a 2a 0a 2a 2a 20 20   adding:.**.**  
32f0: 20 28 61 29 20 2b 31 20 70 6f 69 6e 74 20 66 6f   (a) +1 point fo
3300: 72 20 65 61 63 68 20 6f 63 63 75 72 65 6e 63 65  r each occurence
3310: 20 6f 66 20 61 20 6d 61 74 63 68 61 62 6c 65 20   of a matchable 
3320: 70 68 72 61 73 65 20 69 6e 20 74 68 65 20 73 6e  phrase in the sn
3330: 69 70 70 65 74 2e 0a 2a 2a 0a 2a 2a 20 20 20 28  ippet..**.**   (
3340: 62 29 20 2b 31 30 30 30 20 70 6f 69 6e 74 73 20  b) +1000 points 
3350: 66 6f 72 20 74 68 65 20 66 69 72 73 74 20 6f 63  for the first oc
3360: 63 75 72 65 6e 63 65 20 6f 66 20 65 61 63 68 20  curence of each 
3370: 6d 61 74 63 68 61 62 6c 65 20 70 68 72 61 73 65  matchable phrase
3380: 20 69 6e 20 0a 2a 2a 20 20 20 20 20 20 20 74 68   in .**       th
3390: 65 20 73 6e 69 70 70 65 74 20 66 6f 72 20 77 68  e snippet for wh
33a0: 69 63 68 20 74 68 65 20 63 6f 72 72 65 73 70 6f  ich the correspo
33b0: 6e 64 69 6e 67 20 6d 43 6f 76 65 72 65 64 20 62  nding mCovered b
33c0: 69 74 20 69 73 20 6e 6f 74 20 73 65 74 2e 0a 2a  it is not set..*
33d0: 2a 0a 2a 2a 20 54 68 65 20 73 65 6c 65 63 74 65  *.** The selecte
33e0: 64 20 73 6e 69 70 70 65 74 20 70 61 72 61 6d 65  d snippet parame
33f0: 74 65 72 73 20 61 72 65 20 73 74 6f 72 65 64 20  ters are stored 
3400: 69 6e 20 73 74 72 75 63 74 75 72 65 20 2a 70 46  in structure *pF
3410: 72 61 67 6d 65 6e 74 20 62 65 66 6f 72 65 0a 2a  ragment before.*
3420: 2a 20 72 65 74 75 72 6e 69 6e 67 2e 20 54 68 65  * returning. The
3430: 20 73 63 6f 72 65 20 6f 66 20 74 68 65 20 73 65   score of the se
3440: 6c 65 63 74 65 64 20 73 6e 69 70 70 65 74 20 69  lected snippet i
3450: 73 20 73 74 6f 72 65 64 20 69 6e 20 2a 70 69 53  s stored in *piS
3460: 63 6f 72 65 0a 2a 2a 20 62 65 66 6f 72 65 20 72  core.** before r
3470: 65 74 75 72 6e 69 6e 67 2e 0a 2a 2f 0a 73 74 61  eturning..*/.sta
3480: 74 69 63 20 69 6e 74 20 66 74 73 33 42 65 73 74  tic int fts3Best
3490: 53 6e 69 70 70 65 74 28 0a 20 20 69 6e 74 20 6e  Snippet(.  int n
34a0: 53 6e 69 70 70 65 74 2c 20 20 20 20 20 20 20 20  Snippet,        
34b0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44 65             /* De
34c0: 73 69 72 65 64 20 73 6e 69 70 70 65 74 20 6c 65  sired snippet le
34d0: 6e 67 74 68 20 2a 2f 0a 20 20 46 74 73 33 43 75  ngth */.  Fts3Cu
34e0: 72 73 6f 72 20 2a 70 43 73 72 2c 20 20 20 20 20  rsor *pCsr,     
34f0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 75 72            /* Cur
3500: 73 6f 72 20 74 6f 20 63 72 65 61 74 65 20 73 6e  sor to create sn
3510: 69 70 70 65 74 20 66 6f 72 20 2a 2f 0a 20 20 69  ippet for */.  i
3520: 6e 74 20 69 43 6f 6c 2c 20 20 20 20 20 20 20 20  nt iCol,        
3530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
3540: 2a 20 49 6e 64 65 78 20 6f 66 20 63 6f 6c 75 6d  * Index of colum
3550: 6e 20 74 6f 20 63 72 65 61 74 65 20 73 6e 69 70  n to create snip
3560: 70 65 74 20 66 72 6f 6d 20 2a 2f 0a 20 20 75 36  pet from */.  u6
3570: 34 20 6d 43 6f 76 65 72 65 64 2c 20 20 20 20 20  4 mCovered,     
3580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
3590: 20 4d 61 73 6b 20 6f 66 20 70 68 72 61 73 65 73   Mask of phrases
35a0: 20 61 6c 72 65 61 64 79 20 63 6f 76 65 72 65 64   already covered
35b0: 20 2a 2f 0a 20 20 75 36 34 20 2a 70 6d 53 65 65   */.  u64 *pmSee
35c0: 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n,              
35d0: 20 20 20 20 20 20 2f 2a 20 49 4e 2f 4f 55 54 3a        /* IN/OUT:
35e0: 20 4d 61 73 6b 20 6f 66 20 70 68 72 61 73 65 73   Mask of phrases
35f0: 20 73 65 65 6e 20 2a 2f 0a 20 20 53 6e 69 70 70   seen */.  Snipp
3600: 65 74 46 72 61 67 6d 65 6e 74 20 2a 70 46 72 61  etFragment *pFra
3610: 67 6d 65 6e 74 2c 20 20 20 20 20 2f 2a 20 4f 55  gment,     /* OU
3620: 54 3a 20 42 65 73 74 20 73 6e 69 70 70 65 74 20  T: Best snippet 
3630: 66 6f 75 6e 64 20 2a 2f 0a 20 20 69 6e 74 20 2a  found */.  int *
3640: 70 69 53 63 6f 72 65 20 20 20 20 20 20 20 20 20  piScore         
3650: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 55             /* OU
3660: 54 3a 20 53 63 6f 72 65 20 6f 66 20 73 6e 69 70  T: Score of snip
3670: 70 65 74 20 70 46 72 61 67 6d 65 6e 74 20 2a 2f  pet pFragment */
3680: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20  .){.  int rc;   
3690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
36a0: 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20        /* Return 
36b0: 43 6f 64 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 4c  Code */.  int nL
36c0: 69 73 74 3b 20 20 20 20 20 20 20 20 20 20 20 20  ist;            
36d0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d            /* Num
36e0: 62 65 72 20 6f 66 20 70 68 72 61 73 65 73 20 69  ber of phrases i
36f0: 6e 20 65 78 70 72 65 73 73 69 6f 6e 20 2a 2f 0a  n expression */.
3700: 20 20 53 6e 69 70 70 65 74 49 74 65 72 20 73 49    SnippetIter sI
3710: 74 65 72 3b 20 20 20 20 20 20 20 20 20 20 20 20  ter;            
3720: 20 20 2f 2a 20 49 74 65 72 61 74 65 73 20 74 68    /* Iterates th
3730: 72 6f 75 67 68 20 73 6e 69 70 70 65 74 20 63 61  rough snippet ca
3740: 6e 64 69 64 61 74 65 73 20 2a 2f 0a 20 20 69 6e  ndidates */.  in
3750: 74 20 6e 42 79 74 65 3b 20 20 20 20 20 20 20 20  t nByte;        
3760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
3770: 20 4e 75 6d 62 65 72 20 6f 66 20 62 79 74 65 73   Number of bytes
3780: 20 6f 66 20 73 70 61 63 65 20 74 6f 20 61 6c 6c   of space to all
3790: 6f 63 61 74 65 20 2a 2f 0a 20 20 69 6e 74 20 69  ocate */.  int i
37a0: 42 65 73 74 53 63 6f 72 65 20 3d 20 2d 31 3b 20  BestScore = -1; 
37b0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 42 65             /* Be
37c0: 73 74 20 73 6e 69 70 70 65 74 20 73 63 6f 72 65  st snippet score
37d0: 20 66 6f 75 6e 64 20 73 6f 20 66 61 72 20 2a 2f   found so far */
37e0: 0a 20 20 69 6e 74 20 69 3b 20 20 20 20 20 20 20  .  int i;       
37f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3800: 20 20 20 2f 2a 20 4c 6f 6f 70 20 63 6f 75 6e 74     /* Loop count
3810: 65 72 20 2a 2f 0a 0a 20 20 6d 65 6d 73 65 74 28  er */..  memset(
3820: 26 73 49 74 65 72 2c 20 30 2c 20 73 69 7a 65 6f  &sIter, 0, sizeo
3830: 66 28 73 49 74 65 72 29 29 3b 0a 0a 20 20 2f 2a  f(sIter));..  /*
3840: 20 49 74 65 72 61 74 65 20 74 68 72 6f 75 67 68   Iterate through
3850: 20 74 68 65 20 70 68 72 61 73 65 73 20 69 6e 20   the phrases in 
3860: 74 68 65 20 65 78 70 72 65 73 73 69 6f 6e 20 74  the expression t
3870: 6f 20 63 6f 75 6e 74 20 74 68 65 6d 2e 20 54 68  o count them. Th
3880: 65 20 73 61 6d 65 0a 20 20 2a 2a 20 63 61 6c 6c  e same.  ** call
3890: 62 61 63 6b 20 6d 61 6b 65 73 20 73 75 72 65 20  back makes sure 
38a0: 74 68 65 20 64 6f 63 6c 69 73 74 73 20 61 72 65  the doclists are
38b0: 20 6c 6f 61 64 65 64 20 66 6f 72 20 65 61 63 68   loaded for each
38c0: 20 70 68 72 61 73 65 2e 0a 20 20 2a 2f 0a 20 20   phrase..  */.  
38d0: 72 63 20 3d 20 66 74 73 33 45 78 70 72 4c 6f 61  rc = fts3ExprLoa
38e0: 64 44 6f 63 6c 69 73 74 73 28 70 43 73 72 2c 20  dDoclists(pCsr, 
38f0: 26 6e 4c 69 73 74 2c 20 30 29 3b 0a 20 20 69 66  &nList, 0);.  if
3900: 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc!=SQLITE_OK 
3910: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 72 63  ){.    return rc
3920: 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 4e 6f 77 20  ;.  }..  /* Now 
3930: 74 68 61 74 20 69 74 20 69 73 20 6b 6e 6f 77 6e  that it is known
3940: 20 68 6f 77 20 6d 61 6e 79 20 70 68 72 61 73 65   how many phrase
3950: 73 20 74 68 65 72 65 20 61 72 65 2c 20 61 6c 6c  s there are, all
3960: 6f 63 61 74 65 20 61 6e 64 20 7a 65 72 6f 0a 20  ocate and zero. 
3970: 20 2a 2a 20 74 68 65 20 72 65 71 75 69 72 65 64   ** the required
3980: 20 73 70 61 63 65 20 75 73 69 6e 67 20 6d 61 6c   space using mal
3990: 6c 6f 63 28 29 2e 0a 20 20 2a 2f 0a 20 20 6e 42  loc()..  */.  nB
39a0: 79 74 65 20 3d 20 73 69 7a 65 6f 66 28 53 6e 69  yte = sizeof(Sni
39b0: 70 70 65 74 50 68 72 61 73 65 29 20 2a 20 6e 4c  ppetPhrase) * nL
39c0: 69 73 74 3b 0a 20 20 73 49 74 65 72 2e 61 50 68  ist;.  sIter.aPh
39d0: 72 61 73 65 20 3d 20 28 53 6e 69 70 70 65 74 50  rase = (SnippetP
39e0: 68 72 61 73 65 20 2a 29 73 71 6c 69 74 65 33 5f  hrase *)sqlite3_
39f0: 6d 61 6c 6c 6f 63 28 6e 42 79 74 65 29 3b 0a 20  malloc(nByte);. 
3a00: 20 69 66 28 20 21 73 49 74 65 72 2e 61 50 68 72   if( !sIter.aPhr
3a10: 61 73 65 20 29 7b 0a 20 20 20 20 72 65 74 75 72  ase ){.    retur
3a20: 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a  n SQLITE_NOMEM;.
3a30: 20 20 7d 0a 20 20 6d 65 6d 73 65 74 28 73 49 74    }.  memset(sIt
3a40: 65 72 2e 61 50 68 72 61 73 65 2c 20 30 2c 20 6e  er.aPhrase, 0, n
3a50: 42 79 74 65 29 3b 0a 0a 20 20 2f 2a 20 49 6e 69  Byte);..  /* Ini
3a60: 74 69 61 6c 69 7a 65 20 74 68 65 20 63 6f 6e 74  tialize the cont
3a70: 65 6e 74 73 20 6f 66 20 74 68 65 20 53 6e 69 70  ents of the Snip
3a80: 70 65 74 49 74 65 72 20 6f 62 6a 65 63 74 2e 20  petIter object. 
3a90: 54 68 65 6e 20 69 74 65 72 61 74 65 20 74 68 72  Then iterate thr
3aa0: 6f 75 67 68 0a 20 20 2a 2a 20 74 68 65 20 73 65  ough.  ** the se
3ab0: 74 20 6f 66 20 70 68 72 61 73 65 73 20 69 6e 20  t of phrases in 
3ac0: 74 68 65 20 65 78 70 72 65 73 73 69 6f 6e 20 74  the expression t
3ad0: 6f 20 70 6f 70 75 6c 61 74 65 20 74 68 65 20 61  o populate the a
3ae0: 50 68 72 61 73 65 5b 5d 20 61 72 72 61 79 2e 0a  Phrase[] array..
3af0: 20 20 2a 2f 0a 20 20 73 49 74 65 72 2e 70 43 73    */.  sIter.pCs
3b00: 72 20 3d 20 70 43 73 72 3b 0a 20 20 73 49 74 65  r = pCsr;.  sIte
3b10: 72 2e 69 43 6f 6c 20 3d 20 69 43 6f 6c 3b 0a 20  r.iCol = iCol;. 
3b20: 20 73 49 74 65 72 2e 6e 53 6e 69 70 70 65 74 20   sIter.nSnippet 
3b30: 3d 20 6e 53 6e 69 70 70 65 74 3b 0a 20 20 73 49  = nSnippet;.  sI
3b40: 74 65 72 2e 6e 50 68 72 61 73 65 20 3d 20 6e 4c  ter.nPhrase = nL
3b50: 69 73 74 3b 0a 20 20 73 49 74 65 72 2e 69 43 75  ist;.  sIter.iCu
3b60: 72 72 65 6e 74 20 3d 20 2d 31 3b 0a 20 20 28 76  rrent = -1;.  (v
3b70: 6f 69 64 29 66 74 73 33 45 78 70 72 49 74 65 72  oid)fts3ExprIter
3b80: 61 74 65 28 70 43 73 72 2d 3e 70 45 78 70 72 2c  ate(pCsr->pExpr,
3b90: 20 66 74 73 33 53 6e 69 70 70 65 74 46 69 6e 64   fts3SnippetFind
3ba0: 50 6f 73 69 74 69 6f 6e 73 2c 20 28 76 6f 69 64  Positions, (void
3bb0: 20 2a 29 26 73 49 74 65 72 29 3b 0a 0a 20 20 2f   *)&sIter);..  /
3bc0: 2a 20 53 65 74 20 74 68 65 20 2a 70 6d 53 65 65  * Set the *pmSee
3bd0: 6e 20 6f 75 74 70 75 74 20 76 61 72 69 61 62 6c  n output variabl
3be0: 65 2e 20 2a 2f 0a 20 20 66 6f 72 28 69 3d 30 3b  e. */.  for(i=0;
3bf0: 20 69 3c 6e 4c 69 73 74 3b 20 69 2b 2b 29 7b 0a   i<nList; i++){.
3c00: 20 20 20 20 69 66 28 20 73 49 74 65 72 2e 61 50      if( sIter.aP
3c10: 68 72 61 73 65 5b 69 5d 2e 70 48 65 61 64 20 29  hrase[i].pHead )
3c20: 7b 0a 20 20 20 20 20 20 2a 70 6d 53 65 65 6e 20  {.      *pmSeen 
3c30: 7c 3d 20 28 75 36 34 29 31 20 3c 3c 20 69 3b 0a  |= (u64)1 << i;.
3c40: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f 2a 20      }.  }..  /* 
3c50: 4c 6f 6f 70 20 74 68 72 6f 75 67 68 20 61 6c 6c  Loop through all
3c60: 20 63 61 6e 64 69 64 61 74 65 20 73 6e 69 70 70   candidate snipp
3c70: 65 74 73 2e 20 53 74 6f 72 65 20 74 68 65 20 62  ets. Store the b
3c80: 65 73 74 20 73 6e 69 70 70 65 74 20 69 6e 20 0a  est snippet in .
3c90: 20 20 2a 2a 20 2a 70 46 72 61 67 6d 65 6e 74 2e    ** *pFragment.
3ca0: 20 53 74 6f 72 65 20 69 74 73 20 61 73 73 6f 63   Store its assoc
3cb0: 69 61 74 65 64 20 27 73 63 6f 72 65 27 20 69 6e  iated 'score' in
3cc0: 20 69 42 65 73 74 53 63 6f 72 65 2e 0a 20 20 2a   iBestScore..  *
3cd0: 2f 0a 20 20 70 46 72 61 67 6d 65 6e 74 2d 3e 69  /.  pFragment->i
3ce0: 43 6f 6c 20 3d 20 69 43 6f 6c 3b 0a 20 20 77 68  Col = iCol;.  wh
3cf0: 69 6c 65 28 20 21 66 74 73 33 53 6e 69 70 70 65  ile( !fts3Snippe
3d00: 74 4e 65 78 74 43 61 6e 64 69 64 61 74 65 28 26  tNextCandidate(&
3d10: 73 49 74 65 72 29 20 29 7b 0a 20 20 20 20 69 6e  sIter) ){.    in
3d20: 74 20 69 50 6f 73 3b 0a 20 20 20 20 69 6e 74 20  t iPos;.    int 
3d30: 69 53 63 6f 72 65 3b 0a 20 20 20 20 75 36 34 20  iScore;.    u64 
3d40: 6d 43 6f 76 65 72 3b 0a 20 20 20 20 75 36 34 20  mCover;.    u64 
3d50: 6d 48 69 67 68 6c 69 67 68 74 3b 0a 20 20 20 20  mHighlight;.    
3d60: 66 74 73 33 53 6e 69 70 70 65 74 44 65 74 61 69  fts3SnippetDetai
3d70: 6c 73 28 26 73 49 74 65 72 2c 20 6d 43 6f 76 65  ls(&sIter, mCove
3d80: 72 65 64 2c 20 26 69 50 6f 73 2c 20 26 69 53 63  red, &iPos, &iSc
3d90: 6f 72 65 2c 20 26 6d 43 6f 76 65 72 2c 20 26 6d  ore, &mCover, &m
3da0: 48 69 67 68 6c 69 67 68 74 29 3b 0a 20 20 20 20  Highlight);.    
3db0: 61 73 73 65 72 74 28 20 69 53 63 6f 72 65 3e 3d  assert( iScore>=
3dc0: 30 20 29 3b 0a 20 20 20 20 69 66 28 20 69 53 63  0 );.    if( iSc
3dd0: 6f 72 65 3e 69 42 65 73 74 53 63 6f 72 65 20 29  ore>iBestScore )
3de0: 7b 0a 20 20 20 20 20 20 70 46 72 61 67 6d 65 6e  {.      pFragmen
3df0: 74 2d 3e 69 50 6f 73 20 3d 20 69 50 6f 73 3b 0a  t->iPos = iPos;.
3e00: 20 20 20 20 20 20 70 46 72 61 67 6d 65 6e 74 2d        pFragment-
3e10: 3e 68 6c 6d 61 73 6b 20 3d 20 6d 48 69 67 68 6c  >hlmask = mHighl
3e20: 69 67 68 74 3b 0a 20 20 20 20 20 20 70 46 72 61  ight;.      pFra
3e30: 67 6d 65 6e 74 2d 3e 63 6f 76 65 72 65 64 20 3d  gment->covered =
3e40: 20 6d 43 6f 76 65 72 3b 0a 20 20 20 20 20 20 69   mCover;.      i
3e50: 42 65 73 74 53 63 6f 72 65 20 3d 20 69 53 63 6f  BestScore = iSco
3e60: 72 65 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20  re;.    }.  }.. 
3e70: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 73 49   sqlite3_free(sI
3e80: 74 65 72 2e 61 50 68 72 61 73 65 29 3b 0a 20 20  ter.aPhrase);.  
3e90: 2a 70 69 53 63 6f 72 65 20 3d 20 69 42 65 73 74  *piScore = iBest
3ea0: 53 63 6f 72 65 3b 0a 20 20 72 65 74 75 72 6e 20  Score;.  return 
3eb0: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 0a 2f  SQLITE_OK;.}.../
3ec0: 2a 0a 2a 2a 20 41 70 70 65 6e 64 20 61 20 73 74  *.** Append a st
3ed0: 72 69 6e 67 20 74 6f 20 74 68 65 20 73 74 72 69  ring to the stri
3ee0: 6e 67 2d 62 75 66 66 65 72 20 70 61 73 73 65 64  ng-buffer passed
3ef0: 20 61 73 20 74 68 65 20 66 69 72 73 74 20 61 72   as the first ar
3f00: 67 75 6d 65 6e 74 2e 0a 2a 2a 0a 2a 2a 20 49 66  gument..**.** If
3f10: 20 6e 41 70 70 65 6e 64 20 69 73 20 6e 65 67 61   nAppend is nega
3f20: 74 69 76 65 2c 20 74 68 65 6e 20 74 68 65 20 6c  tive, then the l
3f30: 65 6e 67 74 68 20 6f 66 20 74 68 65 20 73 74 72  ength of the str
3f40: 69 6e 67 20 7a 41 70 70 65 6e 64 20 69 73 0a 2a  ing zAppend is.*
3f50: 2a 20 64 65 74 65 72 6d 69 6e 65 64 20 75 73 69  * determined usi
3f60: 6e 67 20 73 74 72 6c 65 6e 28 29 2e 0a 2a 2f 0a  ng strlen()..*/.
3f70: 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 53  static int fts3S
3f80: 74 72 69 6e 67 41 70 70 65 6e 64 28 0a 20 20 53  tringAppend(.  S
3f90: 74 72 42 75 66 66 65 72 20 2a 70 53 74 72 2c 20  trBuffer *pStr, 
3fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
3fb0: 2a 20 42 75 66 66 65 72 20 74 6f 20 61 70 70 65  * Buffer to appe
3fc0: 6e 64 20 74 6f 20 2a 2f 0a 20 20 63 6f 6e 73 74  nd to */.  const
3fd0: 20 63 68 61 72 20 2a 7a 41 70 70 65 6e 64 2c 20   char *zAppend, 
3fe0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 6f             /* Po
3ff0: 69 6e 74 65 72 20 74 6f 20 64 61 74 61 20 74 6f  inter to data to
4000: 20 61 70 70 65 6e 64 20 74 6f 20 62 75 66 66 65   append to buffe
4010: 72 20 2a 2f 0a 20 20 69 6e 74 20 6e 41 70 70 65  r */.  int nAppe
4020: 6e 64 20 20 20 20 20 20 20 20 20 20 20 20 20 20  nd              
4030: 20 20 20 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f         /* Size o
4040: 66 20 7a 41 70 70 65 6e 64 20 69 6e 20 62 79 74  f zAppend in byt
4050: 65 73 20 28 6f 72 20 2d 31 29 20 2a 2f 0a 29 7b  es (or -1) */.){
4060: 0a 20 20 69 66 28 20 6e 41 70 70 65 6e 64 3c 30  .  if( nAppend<0
4070: 20 29 7b 0a 20 20 20 20 6e 41 70 70 65 6e 64 20   ){.    nAppend 
4080: 3d 20 28 69 6e 74 29 73 74 72 6c 65 6e 28 7a 41  = (int)strlen(zA
4090: 70 70 65 6e 64 29 3b 0a 20 20 7d 0a 0a 20 20 2f  ppend);.  }..  /
40a0: 2a 20 49 66 20 74 68 65 72 65 20 69 73 20 69 6e  * If there is in
40b0: 73 75 66 66 69 63 69 65 6e 74 20 73 70 61 63 65  sufficient space
40c0: 20 61 6c 6c 6f 63 61 74 65 64 20 61 74 20 53 74   allocated at St
40d0: 72 42 75 66 66 65 72 2e 7a 2c 20 75 73 65 20 72  rBuffer.z, use r
40e0: 65 61 6c 6c 6f 63 28 29 0a 20 20 2a 2a 20 74 6f  ealloc().  ** to
40f0: 20 67 72 6f 77 20 74 68 65 20 62 75 66 66 65 72   grow the buffer
4100: 20 75 6e 74 69 6c 20 73 6f 20 74 68 61 74 20 69   until so that i
4110: 74 20 69 73 20 62 69 67 20 65 6e 6f 75 67 68 20  t is big enough 
4120: 74 6f 20 61 63 63 6f 6d 61 64 61 74 65 20 74 68  to accomadate th
4130: 65 0a 20 20 2a 2a 20 61 70 70 65 6e 64 65 64 20  e.  ** appended 
4140: 64 61 74 61 2e 0a 20 20 2a 2f 0a 20 20 69 66 28  data..  */.  if(
4150: 20 70 53 74 72 2d 3e 6e 2b 6e 41 70 70 65 6e 64   pStr->n+nAppend
4160: 2b 31 3e 3d 70 53 74 72 2d 3e 6e 41 6c 6c 6f 63  +1>=pStr->nAlloc
4170: 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e 41 6c 6c   ){.    int nAll
4180: 6f 63 20 3d 20 70 53 74 72 2d 3e 6e 41 6c 6c 6f  oc = pStr->nAllo
4190: 63 2b 6e 41 70 70 65 6e 64 2b 31 30 30 3b 0a 20  c+nAppend+100;. 
41a0: 20 20 20 63 68 61 72 20 2a 7a 4e 65 77 20 3d 20     char *zNew = 
41b0: 73 71 6c 69 74 65 33 5f 72 65 61 6c 6c 6f 63 28  sqlite3_realloc(
41c0: 70 53 74 72 2d 3e 7a 2c 20 6e 41 6c 6c 6f 63 29  pStr->z, nAlloc)
41d0: 3b 0a 20 20 20 20 69 66 28 20 21 7a 4e 65 77 20  ;.    if( !zNew 
41e0: 29 7b 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20  ){.      return 
41f0: 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20  SQLITE_NOMEM;.  
4200: 20 20 7d 0a 20 20 20 20 70 53 74 72 2d 3e 7a 20    }.    pStr->z 
4210: 3d 20 7a 4e 65 77 3b 0a 20 20 20 20 70 53 74 72  = zNew;.    pStr
4220: 2d 3e 6e 41 6c 6c 6f 63 20 3d 20 6e 41 6c 6c 6f  ->nAlloc = nAllo
4230: 63 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 41 70 70  c;.  }..  /* App
4240: 65 6e 64 20 74 68 65 20 64 61 74 61 20 74 6f 20  end the data to 
4250: 74 68 65 20 73 74 72 69 6e 67 20 62 75 66 66 65  the string buffe
4260: 72 2e 20 2a 2f 0a 20 20 6d 65 6d 63 70 79 28 26  r. */.  memcpy(&
4270: 70 53 74 72 2d 3e 7a 5b 70 53 74 72 2d 3e 6e 5d  pStr->z[pStr->n]
4280: 2c 20 7a 41 70 70 65 6e 64 2c 20 6e 41 70 70 65  , zAppend, nAppe
4290: 6e 64 29 3b 0a 20 20 70 53 74 72 2d 3e 6e 20 2b  nd);.  pStr->n +
42a0: 3d 20 6e 41 70 70 65 6e 64 3b 0a 20 20 70 53 74  = nAppend;.  pSt
42b0: 72 2d 3e 7a 5b 70 53 74 72 2d 3e 6e 5d 20 3d 20  r->z[pStr->n] = 
42c0: 27 5c 30 27 3b 0a 0a 20 20 72 65 74 75 72 6e 20  '\0';..  return 
42d0: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  SQLITE_OK;.}../*
42e0: 0a 2a 2a 20 54 68 65 20 66 74 73 33 42 65 73 74  .** The fts3Best
42f0: 53 6e 69 70 70 65 74 28 29 20 66 75 6e 63 74 69  Snippet() functi
4300: 6f 6e 20 6f 66 74 65 6e 20 73 65 6c 65 63 74 73  on often selects
4310: 20 73 6e 69 70 70 65 74 73 20 74 68 61 74 20 65   snippets that e
4320: 6e 64 20 77 69 74 68 20 61 0a 2a 2a 20 71 75 65  nd with a.** que
4330: 72 79 20 74 65 72 6d 2e 20 54 68 61 74 20 69 73  ry term. That is
4340: 2c 20 74 68 65 20 66 69 6e 61 6c 20 74 65 72 6d  , the final term
4350: 20 6f 66 20 74 68 65 20 73 6e 69 70 70 65 74 20   of the snippet 
4360: 69 73 20 61 6c 77 61 79 73 20 61 20 74 65 72 6d  is always a term
4370: 0a 2a 2a 20 74 68 61 74 20 72 65 71 75 69 72 65  .** that require
4380: 73 20 68 69 67 68 6c 69 67 68 74 69 6e 67 2e 20  s highlighting. 
4390: 46 6f 72 20 65 78 61 6d 70 6c 65 2c 20 69 66 20  For example, if 
43a0: 27 58 27 20 69 73 20 61 20 68 69 67 68 6c 69 67  'X' is a highlig
43b0: 68 74 65 64 20 74 65 72 6d 0a 2a 2a 20 61 6e 64  hted term.** and
43c0: 20 27 2e 27 20 69 73 20 61 20 6e 6f 6e 2d 68 69   '.' is a non-hi
43d0: 67 68 6c 69 67 68 74 65 64 20 74 65 72 6d 2c 20  ghlighted term, 
43e0: 42 65 73 74 53 6e 69 70 70 65 74 28 29 20 6d 61  BestSnippet() ma
43f0: 79 20 73 65 6c 65 63 74 3a 0a 2a 2a 0a 2a 2a 20  y select:.**.** 
4400: 20 20 20 20 2e 2e 2e 2e 2e 2e 2e 2e 58 2e 2e 2e      ........X...
4410: 2e 2e 58 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 66  ..X.**.** This f
4420: 75 6e 63 74 69 6f 6e 20 22 73 68 69 66 74 73 22  unction "shifts"
4430: 20 74 68 65 20 62 65 67 69 6e 6e 69 6e 67 20 6f   the beginning o
4440: 66 20 74 68 65 20 73 6e 69 70 70 65 74 20 66 6f  f the snippet fo
4450: 72 77 61 72 64 20 69 6e 20 74 68 65 20 0a 2a 2a  rward in the .**
4460: 20 64 6f 63 75 6d 65 6e 74 20 73 6f 20 74 68 61   document so tha
4470: 74 20 74 68 65 72 65 20 61 72 65 20 61 70 70 72  t there are appr
4480: 6f 78 69 6d 61 74 65 6c 79 20 74 68 65 20 73 61  oximately the sa
4490: 6d 65 20 6e 75 6d 62 65 72 20 6f 66 20 0a 2a 2a  me number of .**
44a0: 20 6e 6f 6e 2d 68 69 67 68 6c 69 67 68 74 65 64   non-highlighted
44b0: 20 74 65 72 6d 73 20 74 6f 20 74 68 65 20 72 69   terms to the ri
44c0: 67 68 74 20 6f 66 20 74 68 65 20 66 69 6e 61 6c  ght of the final
44d0: 20 68 69 67 68 6c 69 67 68 74 65 64 20 74 65 72   highlighted ter
44e0: 6d 20 61 73 20 74 68 65 72 65 0a 2a 2a 20 61 72  m as there.** ar
44f0: 65 20 74 6f 20 74 68 65 20 6c 65 66 74 20 6f 66  e to the left of
4500: 20 74 68 65 20 66 69 72 73 74 20 68 69 67 68 6c   the first highl
4510: 69 67 68 74 65 64 20 74 65 72 6d 2e 20 46 6f 72  ighted term. For
4520: 20 65 78 61 6d 70 6c 65 2c 20 74 6f 20 74 68 69   example, to thi
4530: 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 20 2e 2e 2e  s:.**.**     ...
4540: 2e 58 2e 2e 2e 2e 2e 58 2e 2e 2e 2e 0a 2a 2a 0a  .X.....X.....**.
4550: 2a 2a 20 54 68 69 73 20 69 73 20 64 6f 6e 65 20  ** This is done 
4560: 61 73 20 70 61 72 74 20 6f 66 20 65 78 74 72 61  as part of extra
4570: 63 74 69 6e 67 20 74 68 65 20 73 6e 69 70 70 65  cting the snippe
4580: 74 20 74 65 78 74 2c 20 6e 6f 74 20 77 68 65 6e  t text, not when
4590: 20 73 65 6c 65 63 74 69 6e 67 0a 2a 2a 20 74 68   selecting.** th
45a0: 65 20 73 6e 69 70 70 65 74 2e 20 53 6e 69 70 70  e snippet. Snipp
45b0: 65 74 20 73 65 6c 65 63 74 69 6f 6e 20 69 73 20  et selection is 
45c0: 64 6f 6e 65 20 62 61 73 65 64 20 6f 6e 20 64 6f  done based on do
45d0: 63 6c 69 73 74 73 20 6f 6e 6c 79 2c 20 73 6f 20  clists only, so 
45e0: 74 68 65 72 65 0a 2a 2a 20 69 73 20 6e 6f 20 77  there.** is no w
45f0: 61 79 20 66 6f 72 20 66 74 73 33 42 65 73 74 53  ay for fts3BestS
4600: 6e 69 70 70 65 74 28 29 20 74 6f 20 6b 6e 6f 77  nippet() to know
4610: 20 77 68 65 74 68 65 72 20 6f 72 20 6e 6f 74 20   whether or not 
4620: 74 68 65 20 64 6f 63 75 6d 65 6e 74 20 0a 2a 2a  the document .**
4630: 20 61 63 74 75 61 6c 6c 79 20 63 6f 6e 74 61 69   actually contai
4640: 6e 73 20 74 65 72 6d 73 20 74 68 61 74 20 66 6f  ns terms that fo
4650: 6c 6c 6f 77 20 74 68 65 20 66 69 6e 61 6c 20 68  llow the final h
4660: 69 67 68 6c 69 67 68 74 65 64 20 74 65 72 6d 2e  ighlighted term.
4670: 20 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20   .*/.static int 
4680: 66 74 73 33 53 6e 69 70 70 65 74 53 68 69 66 74  fts3SnippetShift
4690: 28 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a 70  (.  Fts3Table *p
46a0: 54 61 62 2c 20 20 20 20 20 20 20 20 20 20 20 20  Tab,            
46b0: 20 20 20 20 2f 2a 20 46 54 53 33 20 74 61 62 6c      /* FTS3 tabl
46c0: 65 20 73 6e 69 70 70 65 74 20 63 6f 6d 65 73 20  e snippet comes 
46d0: 66 72 6f 6d 20 2a 2f 0a 20 20 69 6e 74 20 69 4c  from */.  int iL
46e0: 61 6e 67 69 64 2c 20 20 20 20 20 20 20 20 20 20  angid,          
46f0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 61 6e            /* Lan
4700: 67 75 61 67 65 20 69 64 20 74 6f 20 75 73 65 20  guage id to use 
4710: 69 6e 20 74 6f 6b 65 6e 69 7a 69 6e 67 20 2a 2f  in tokenizing */
4720: 0a 20 20 69 6e 74 20 6e 53 6e 69 70 70 65 74 2c  .  int nSnippet,
4730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4740: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
4750: 74 6f 6b 65 6e 73 20 64 65 73 69 72 65 64 20 66  tokens desired f
4760: 6f 72 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20  or snippet */.  
4770: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 44 6f 63  const char *zDoc
4780: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
4790: 2f 2a 20 44 6f 63 75 6d 65 6e 74 20 74 65 78 74  /* Document text
47a0: 20 74 6f 20 65 78 74 72 61 63 74 20 73 6e 69 70   to extract snip
47b0: 70 65 74 20 66 72 6f 6d 20 2a 2f 0a 20 20 69 6e  pet from */.  in
47c0: 74 20 6e 44 6f 63 2c 20 20 20 20 20 20 20 20 20  t nDoc,         
47d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
47e0: 20 53 69 7a 65 20 6f 66 20 62 75 66 66 65 72 20   Size of buffer 
47f0: 7a 44 6f 63 20 69 6e 20 62 79 74 65 73 20 2a 2f  zDoc in bytes */
4800: 0a 20 20 69 6e 74 20 2a 70 69 50 6f 73 2c 20 20  .  int *piPos,  
4810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4820: 20 20 20 2f 2a 20 49 4e 2f 4f 55 54 3a 20 46 69     /* IN/OUT: Fi
4830: 72 73 74 20 74 6f 6b 65 6e 20 6f 66 20 73 6e 69  rst token of sni
4840: 70 70 65 74 20 2a 2f 0a 20 20 75 36 34 20 2a 70  ppet */.  u64 *p
4850: 48 6c 6d 61 73 6b 20 20 20 20 20 20 20 20 20 20  Hlmask          
4860: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49 4e 2f            /* IN/
4870: 4f 55 54 3a 20 4d 61 73 6b 20 6f 66 20 74 6f 6b  OUT: Mask of tok
4880: 65 6e 73 20 74 6f 20 68 69 67 68 6c 69 67 68 74  ens to highlight
4890: 20 2a 2f 0a 29 7b 0a 20 20 75 36 34 20 68 6c 6d   */.){.  u64 hlm
48a0: 61 73 6b 20 3d 20 2a 70 48 6c 6d 61 73 6b 3b 20  ask = *pHlmask; 
48b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 6f 63 61           /* Loca
48c0: 6c 20 63 6f 70 79 20 6f 66 20 69 6e 69 74 69 61  l copy of initia
48d0: 6c 20 68 69 67 68 6c 69 67 68 74 2d 6d 61 73 6b  l highlight-mask
48e0: 20 2a 2f 0a 0a 20 20 69 66 28 20 68 6c 6d 61 73   */..  if( hlmas
48f0: 6b 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e 4c 65  k ){.    int nLe
4900: 66 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  ft;             
4910: 20 20 20 20 20 20 20 2f 2a 20 54 6f 6b 65 6e 73         /* Tokens
4920: 20 74 6f 20 74 68 65 20 6c 65 66 74 20 6f 66 20   to the left of 
4930: 66 69 72 73 74 20 68 69 67 68 6c 69 67 68 74 20  first highlight 
4940: 2a 2f 0a 20 20 20 20 69 6e 74 20 6e 52 69 67 68  */.    int nRigh
4950: 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  t;              
4960: 20 20 20 20 20 2f 2a 20 54 6f 6b 65 6e 73 20 74       /* Tokens t
4970: 6f 20 74 68 65 20 72 69 67 68 74 20 6f 66 20 6c  o the right of l
4980: 61 73 74 20 68 69 67 68 6c 69 67 68 74 20 2a 2f  ast highlight */
4990: 0a 20 20 20 20 69 6e 74 20 6e 44 65 73 69 72 65  .    int nDesire
49a0: 64 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  d;              
49b0: 20 20 20 2f 2a 20 49 64 65 61 6c 20 6e 75 6d 62     /* Ideal numb
49c0: 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20 74 6f 20  er of tokens to 
49d0: 73 68 69 66 74 20 66 6f 72 77 61 72 64 20 2a 2f  shift forward */
49e0: 0a 0a 20 20 20 20 66 6f 72 28 6e 4c 65 66 74 3d  ..    for(nLeft=
49f0: 30 3b 20 21 28 68 6c 6d 61 73 6b 20 26 20 28 28  0; !(hlmask & ((
4a00: 75 36 34 29 31 20 3c 3c 20 6e 4c 65 66 74 29 29  u64)1 << nLeft))
4a10: 3b 20 6e 4c 65 66 74 2b 2b 29 3b 0a 20 20 20 20  ; nLeft++);.    
4a20: 66 6f 72 28 6e 52 69 67 68 74 3d 30 3b 20 21 28  for(nRight=0; !(
4a30: 68 6c 6d 61 73 6b 20 26 20 28 28 75 36 34 29 31  hlmask & ((u64)1
4a40: 20 3c 3c 20 28 6e 53 6e 69 70 70 65 74 2d 31 2d   << (nSnippet-1-
4a50: 6e 52 69 67 68 74 29 29 29 3b 20 6e 52 69 67 68  nRight))); nRigh
4a60: 74 2b 2b 29 3b 0a 20 20 20 20 6e 44 65 73 69 72  t++);.    nDesir
4a70: 65 64 20 3d 20 28 6e 4c 65 66 74 2d 6e 52 69 67  ed = (nLeft-nRig
4a80: 68 74 29 2f 32 3b 0a 0a 20 20 20 20 2f 2a 20 49  ht)/2;..    /* I
4a90: 64 65 61 6c 6c 79 2c 20 74 68 65 20 73 74 61 72  deally, the star
4aa0: 74 20 6f 66 20 74 68 65 20 73 6e 69 70 70 65 74  t of the snippet
4ab0: 20 73 68 6f 75 6c 64 20 62 65 20 70 75 73 68 65   should be pushe
4ac0: 64 20 66 6f 72 77 61 72 64 20 69 6e 20 74 68 65  d forward in the
4ad0: 0a 20 20 20 20 2a 2a 20 64 6f 63 75 6d 65 6e 74  .    ** document
4ae0: 20 6e 44 65 73 69 72 65 64 20 74 6f 6b 65 6e 73   nDesired tokens
4af0: 2e 20 54 68 69 73 20 62 6c 6f 63 6b 20 63 68 65  . This block che
4b00: 63 6b 73 20 69 66 20 74 68 65 72 65 20 61 72 65  cks if there are
4b10: 20 61 63 74 75 61 6c 6c 79 0a 20 20 20 20 2a 2a   actually.    **
4b20: 20 6e 44 65 73 69 72 65 64 20 74 6f 6b 65 6e 73   nDesired tokens
4b30: 20 74 6f 20 74 68 65 20 72 69 67 68 74 20 6f 66   to the right of
4b40: 20 74 68 65 20 73 6e 69 70 70 65 74 2e 20 49 66   the snippet. If
4b50: 20 73 6f 2c 20 2a 70 69 50 6f 73 20 61 6e 64 0a   so, *piPos and.
4b60: 20 20 20 20 2a 2a 20 2a 70 48 6c 4d 61 73 6b 20      ** *pHlMask 
4b70: 61 72 65 20 75 70 64 61 74 65 64 20 74 6f 20 73  are updated to s
4b80: 68 69 66 74 20 74 68 65 20 73 6e 69 70 70 65 74  hift the snippet
4b90: 20 6e 44 65 73 69 72 65 64 20 74 6f 6b 65 6e 73   nDesired tokens
4ba0: 20 74 6f 20 74 68 65 0a 20 20 20 20 2a 2a 20 72   to the.    ** r
4bb0: 69 67 68 74 2e 20 4f 74 68 65 72 77 69 73 65 2c  ight. Otherwise,
4bc0: 20 74 68 65 20 73 6e 69 70 70 65 74 20 69 73 20   the snippet is 
4bd0: 73 68 69 66 74 65 64 20 62 79 20 74 68 65 20 6e  shifted by the n
4be0: 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 0a  umber of tokens.
4bf0: 20 20 20 20 2a 2a 20 61 76 61 69 6c 61 62 6c 65      ** available
4c00: 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20 69 66 28  ..    */.    if(
4c10: 20 6e 44 65 73 69 72 65 64 3e 30 20 29 7b 0a 20   nDesired>0 ){. 
4c20: 20 20 20 20 20 69 6e 74 20 6e 53 68 69 66 74 3b       int nShift;
4c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4c40: 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 74 6f   /* Number of to
4c50: 6b 65 6e 73 20 74 6f 20 73 68 69 66 74 20 73 6e  kens to shift sn
4c60: 69 70 70 65 74 20 62 79 20 2a 2f 0a 20 20 20 20  ippet by */.    
4c70: 20 20 69 6e 74 20 69 43 75 72 72 65 6e 74 20 3d    int iCurrent =
4c80: 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 2f 2a   0;           /*
4c90: 20 54 6f 6b 65 6e 20 63 6f 75 6e 74 65 72 20 2a   Token counter *
4ca0: 2f 0a 20 20 20 20 20 20 69 6e 74 20 72 63 3b 20  /.      int rc; 
4cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4cc0: 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 43 6f      /* Return Co
4cd0: 64 65 20 2a 2f 0a 20 20 20 20 20 20 73 71 6c 69  de */.      sqli
4ce0: 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 6d 6f  te3_tokenizer_mo
4cf0: 64 75 6c 65 20 2a 70 4d 6f 64 3b 0a 20 20 20 20  dule *pMod;.    
4d00: 20 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69    sqlite3_tokeni
4d10: 7a 65 72 5f 63 75 72 73 6f 72 20 2a 70 43 3b 0a  zer_cursor *pC;.
4d20: 20 20 20 20 20 20 70 4d 6f 64 20 3d 20 28 73 71        pMod = (sq
4d30: 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f  lite3_tokenizer_
4d40: 6d 6f 64 75 6c 65 20 2a 29 70 54 61 62 2d 3e 70  module *)pTab->p
4d50: 54 6f 6b 65 6e 69 7a 65 72 2d 3e 70 4d 6f 64 75  Tokenizer->pModu
4d60: 6c 65 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 4f 70  le;..      /* Op
4d70: 65 6e 20 61 20 63 75 72 73 6f 72 20 6f 6e 20 7a  en a cursor on z
4d80: 44 6f 63 2f 6e 44 6f 63 2e 20 43 68 65 63 6b 20  Doc/nDoc. Check 
4d90: 69 66 20 74 68 65 72 65 20 61 72 65 20 28 6e 53  if there are (nS
4da0: 6e 69 70 70 65 74 2b 6e 44 65 73 69 72 65 64 29  nippet+nDesired)
4db0: 0a 20 20 20 20 20 20 2a 2a 20 6f 72 20 6d 6f 72  .      ** or mor
4dc0: 65 20 74 6f 6b 65 6e 73 20 69 6e 20 7a 44 6f 63  e tokens in zDoc
4dd0: 2f 6e 44 6f 63 2e 0a 20 20 20 20 20 20 2a 2f 0a  /nDoc..      */.
4de0: 20 20 20 20 20 20 72 63 20 3d 20 73 71 6c 69 74        rc = sqlit
4df0: 65 33 46 74 73 33 4f 70 65 6e 54 6f 6b 65 6e 69  e3Fts3OpenTokeni
4e00: 7a 65 72 28 70 54 61 62 2d 3e 70 54 6f 6b 65 6e  zer(pTab->pToken
4e10: 69 7a 65 72 2c 20 69 4c 61 6e 67 69 64 2c 20 7a  izer, iLangid, z
4e20: 44 6f 63 2c 20 6e 44 6f 63 2c 20 26 70 43 29 3b  Doc, nDoc, &pC);
4e30: 0a 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53  .      if( rc!=S
4e40: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
4e50: 20 20 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 20      return rc;. 
4e60: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 77 68 69       }.      whi
4e70: 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f  le( rc==SQLITE_O
4e80: 4b 20 26 26 20 69 43 75 72 72 65 6e 74 3c 28 6e  K && iCurrent<(n
4e90: 53 6e 69 70 70 65 74 2b 6e 44 65 73 69 72 65 64  Snippet+nDesired
4ea0: 29 20 29 7b 0a 20 20 20 20 20 20 20 20 63 6f 6e  ) ){.        con
4eb0: 73 74 20 63 68 61 72 20 2a 5a 44 55 4d 4d 59 3b  st char *ZDUMMY;
4ec0: 20 69 6e 74 20 44 55 4d 4d 59 31 20 3d 20 30 2c   int DUMMY1 = 0,
4ed0: 20 44 55 4d 4d 59 32 20 3d 20 30 2c 20 44 55 4d   DUMMY2 = 0, DUM
4ee0: 4d 59 33 20 3d 20 30 3b 0a 20 20 20 20 20 20 20  MY3 = 0;.       
4ef0: 20 72 63 20 3d 20 70 4d 6f 64 2d 3e 78 4e 65 78   rc = pMod->xNex
4f00: 74 28 70 43 2c 20 26 5a 44 55 4d 4d 59 2c 20 26  t(pC, &ZDUMMY, &
4f10: 44 55 4d 4d 59 31 2c 20 26 44 55 4d 4d 59 32 2c  DUMMY1, &DUMMY2,
4f20: 20 26 44 55 4d 4d 59 33 2c 20 26 69 43 75 72 72   &DUMMY3, &iCurr
4f30: 65 6e 74 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20  ent);.      }.  
4f40: 20 20 20 20 70 4d 6f 64 2d 3e 78 43 6c 6f 73 65      pMod->xClose
4f50: 28 70 43 29 3b 0a 20 20 20 20 20 20 69 66 28 20  (pC);.      if( 
4f60: 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc!=SQLITE_OK &&
4f70: 20 72 63 21 3d 53 51 4c 49 54 45 5f 44 4f 4e 45   rc!=SQLITE_DONE
4f80: 20 29 7b 20 72 65 74 75 72 6e 20 72 63 3b 20 7d   ){ return rc; }
4f90: 0a 0a 20 20 20 20 20 20 6e 53 68 69 66 74 20 3d  ..      nShift =
4fa0: 20 28 72 63 3d 3d 53 51 4c 49 54 45 5f 44 4f 4e   (rc==SQLITE_DON
4fb0: 45 29 2b 69 43 75 72 72 65 6e 74 2d 6e 53 6e 69  E)+iCurrent-nSni
4fc0: 70 70 65 74 3b 0a 20 20 20 20 20 20 61 73 73 65  ppet;.      asse
4fd0: 72 74 28 20 6e 53 68 69 66 74 3c 3d 6e 44 65 73  rt( nShift<=nDes
4fe0: 69 72 65 64 20 29 3b 0a 20 20 20 20 20 20 69 66  ired );.      if
4ff0: 28 20 6e 53 68 69 66 74 3e 30 20 29 7b 0a 20 20  ( nShift>0 ){.  
5000: 20 20 20 20 20 20 2a 70 69 50 6f 73 20 2b 3d 20        *piPos += 
5010: 6e 53 68 69 66 74 3b 0a 20 20 20 20 20 20 20 20  nShift;.        
5020: 2a 70 48 6c 6d 61 73 6b 20 3d 20 68 6c 6d 61 73  *pHlmask = hlmas
5030: 6b 20 3e 3e 20 6e 53 68 69 66 74 3b 0a 20 20 20  k >> nShift;.   
5040: 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 20     }.    }.  }. 
5050: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f   return SQLITE_O
5060: 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 45 78 74 72  K;.}../*.** Extr
5070: 61 63 74 20 74 68 65 20 73 6e 69 70 70 65 74 20  act the snippet 
5080: 74 65 78 74 20 66 6f 72 20 66 72 61 67 6d 65 6e  text for fragmen
5090: 74 20 70 46 72 61 67 6d 65 6e 74 20 66 72 6f 6d  t pFragment from
50a0: 20 63 75 72 73 6f 72 20 70 43 73 72 20 61 6e 64   cursor pCsr and
50b0: 0a 2a 2a 20 61 70 70 65 6e 64 20 69 74 20 74 6f  .** append it to
50c0: 20 73 74 72 69 6e 67 20 62 75 66 66 65 72 20 70   string buffer p
50d0: 4f 75 74 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  Out..*/.static i
50e0: 6e 74 20 66 74 73 33 53 6e 69 70 70 65 74 54 65  nt fts3SnippetTe
50f0: 78 74 28 0a 20 20 46 74 73 33 43 75 72 73 6f 72  xt(.  Fts3Cursor
5100: 20 2a 70 43 73 72 2c 20 20 20 20 20 20 20 20 20   *pCsr,         
5110: 20 20 20 20 20 20 2f 2a 20 46 54 53 33 20 43 75        /* FTS3 Cu
5120: 72 73 6f 72 20 2a 2f 0a 20 20 53 6e 69 70 70 65  rsor */.  Snippe
5130: 74 46 72 61 67 6d 65 6e 74 20 2a 70 46 72 61 67  tFragment *pFrag
5140: 6d 65 6e 74 2c 20 20 20 20 20 2f 2a 20 53 6e 69  ment,     /* Sni
5150: 70 70 65 74 20 74 6f 20 65 78 74 72 61 63 74 20  ppet to extract 
5160: 2a 2f 0a 20 20 69 6e 74 20 69 46 72 61 67 6d 65  */.  int iFragme
5170: 6e 74 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  nt,             
5180: 20 20 20 20 20 2f 2a 20 46 72 61 67 6d 65 6e 74       /* Fragment
5190: 20 6e 75 6d 62 65 72 20 2a 2f 0a 20 20 69 6e 74   number */.  int
51a0: 20 69 73 4c 61 73 74 2c 20 20 20 20 20 20 20 20   isLast,        
51b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
51c0: 54 72 75 65 20 66 6f 72 20 66 69 6e 61 6c 20 66  True for final f
51d0: 72 61 67 6d 65 6e 74 20 69 6e 20 73 6e 69 70 70  ragment in snipp
51e0: 65 74 20 2a 2f 0a 20 20 69 6e 74 20 6e 53 6e 69  et */.  int nSni
51f0: 70 70 65 74 2c 20 20 20 20 20 20 20 20 20 20 20  ppet,           
5200: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
5210: 72 20 6f 66 20 74 6f 6b 65 6e 73 20 69 6e 20 65  r of tokens in e
5220: 78 74 72 61 63 74 65 64 20 73 6e 69 70 70 65 74  xtracted snippet
5230: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
5240: 20 2a 7a 4f 70 65 6e 2c 20 20 20 20 20 20 20 20   *zOpen,        
5250: 20 20 20 20 20 20 2f 2a 20 53 74 72 69 6e 67 20        /* String 
5260: 69 6e 73 65 72 74 65 64 20 62 65 66 6f 72 65 20  inserted before 
5270: 68 69 67 68 6c 69 67 68 74 65 64 20 74 65 72 6d  highlighted term
5280: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
5290: 20 2a 7a 43 6c 6f 73 65 2c 20 20 20 20 20 20 20   *zClose,       
52a0: 20 20 20 20 20 20 2f 2a 20 53 74 72 69 6e 67 20        /* String 
52b0: 69 6e 73 65 72 74 65 64 20 61 66 74 65 72 20 68  inserted after h
52c0: 69 67 68 6c 69 67 68 74 65 64 20 74 65 72 6d 20  ighlighted term 
52d0: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
52e0: 2a 7a 45 6c 6c 69 70 73 69 73 2c 20 20 20 20 20  *zEllipsis,     
52f0: 20 20 20 20 20 2f 2a 20 53 74 72 69 6e 67 20 69       /* String i
5300: 6e 73 65 72 74 65 64 20 62 65 74 77 65 65 6e 20  nserted between 
5310: 73 6e 69 70 70 65 74 73 20 2a 2f 0a 20 20 53 74  snippets */.  St
5320: 72 42 75 66 66 65 72 20 2a 70 4f 75 74 20 20 20  rBuffer *pOut   
5330: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
5340: 20 57 72 69 74 65 20 6f 75 74 70 75 74 20 68 65   Write output he
5350: 72 65 20 2a 2f 0a 29 7b 0a 20 20 46 74 73 33 54  re */.){.  Fts3T
5360: 61 62 6c 65 20 2a 70 54 61 62 20 3d 20 28 46 74  able *pTab = (Ft
5370: 73 33 54 61 62 6c 65 20 2a 29 70 43 73 72 2d 3e  s3Table *)pCsr->
5380: 62 61 73 65 2e 70 56 74 61 62 3b 0a 20 20 69 6e  base.pVtab;.  in
5390: 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20  t rc;           
53a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
53b0: 20 52 65 74 75 72 6e 20 63 6f 64 65 20 2a 2f 0a   Return code */.
53c0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 44    const char *zD
53d0: 6f 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  oc;             
53e0: 20 20 2f 2a 20 44 6f 63 75 6d 65 6e 74 20 74 65    /* Document te
53f0: 78 74 20 74 6f 20 65 78 74 72 61 63 74 20 73 6e  xt to extract sn
5400: 69 70 70 65 74 20 66 72 6f 6d 20 2a 2f 0a 20 20  ippet from */.  
5410: 69 6e 74 20 6e 44 6f 63 3b 20 20 20 20 20 20 20  int nDoc;       
5420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5430: 2f 2a 20 53 69 7a 65 20 6f 66 20 7a 44 6f 63 20  /* Size of zDoc 
5440: 69 6e 20 62 79 74 65 73 20 2a 2f 0a 20 20 69 6e  in bytes */.  in
5450: 74 20 69 43 75 72 72 65 6e 74 20 3d 20 30 3b 20  t iCurrent = 0; 
5460: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
5470: 20 43 75 72 72 65 6e 74 20 74 6f 6b 65 6e 20 6e   Current token n
5480: 75 6d 62 65 72 20 6f 66 20 64 6f 63 75 6d 65 6e  umber of documen
5490: 74 20 2a 2f 0a 20 20 69 6e 74 20 69 45 6e 64 20  t */.  int iEnd 
54a0: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
54b0: 20 20 20 20 20 20 20 2f 2a 20 42 79 74 65 20 6f         /* Byte o
54c0: 66 66 73 65 74 20 6f 66 20 65 6e 64 20 6f 66 20  ffset of end of 
54d0: 63 75 72 72 65 6e 74 20 74 6f 6b 65 6e 20 2a 2f  current token */
54e0: 0a 20 20 69 6e 74 20 69 73 53 68 69 66 74 44 6f  .  int isShiftDo
54f0: 6e 65 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  ne = 0;         
5500: 20 20 20 2f 2a 20 54 72 75 65 20 61 66 74 65 72     /* True after
5510: 20 73 6e 69 70 70 65 74 20 69 73 20 73 68 69 66   snippet is shif
5520: 74 65 64 20 2a 2f 0a 20 20 69 6e 74 20 69 50 6f  ted */.  int iPo
5530: 73 20 3d 20 70 46 72 61 67 6d 65 6e 74 2d 3e 69  s = pFragment->i
5540: 50 6f 73 3b 20 20 20 20 20 2f 2a 20 46 69 72 73  Pos;     /* Firs
5550: 74 20 74 6f 6b 65 6e 20 6f 66 20 73 6e 69 70 70  t token of snipp
5560: 65 74 20 2a 2f 0a 20 20 75 36 34 20 68 6c 6d 61  et */.  u64 hlma
5570: 73 6b 20 3d 20 70 46 72 61 67 6d 65 6e 74 2d 3e  sk = pFragment->
5580: 68 6c 6d 61 73 6b 3b 20 2f 2a 20 48 69 67 68 6c  hlmask; /* Highl
5590: 69 67 68 74 2d 6d 61 73 6b 20 66 6f 72 20 73 6e  ight-mask for sn
55a0: 69 70 70 65 74 20 2a 2f 0a 20 20 69 6e 74 20 69  ippet */.  int i
55b0: 43 6f 6c 20 3d 20 70 46 72 61 67 6d 65 6e 74 2d  Col = pFragment-
55c0: 3e 69 43 6f 6c 2b 31 3b 20 20 20 2f 2a 20 51 75  >iCol+1;   /* Qu
55d0: 65 72 79 20 63 6f 6c 75 6d 6e 20 74 6f 20 65 78  ery column to ex
55e0: 74 72 61 63 74 20 74 65 78 74 20 66 72 6f 6d 20  tract text from 
55f0: 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 74 6f 6b  */.  sqlite3_tok
5600: 65 6e 69 7a 65 72 5f 6d 6f 64 75 6c 65 20 2a 70  enizer_module *p
5610: 4d 6f 64 3b 20 2f 2a 20 54 6f 6b 65 6e 69 7a 65  Mod; /* Tokenize
5620: 72 20 6d 6f 64 75 6c 65 20 6d 65 74 68 6f 64 73  r module methods
5630: 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 73 71 6c   object */.  sql
5640: 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63  ite3_tokenizer_c
5650: 75 72 73 6f 72 20 2a 70 43 3b 20 20 20 2f 2a 20  ursor *pC;   /* 
5660: 54 6f 6b 65 6e 69 7a 65 72 20 63 75 72 73 6f 72  Tokenizer cursor
5670: 20 6f 70 65 6e 20 6f 6e 20 7a 44 6f 63 2f 6e 44   open on zDoc/nD
5680: 6f 63 20 2a 2f 0a 20 20 0a 20 20 7a 44 6f 63 20  oc */.  .  zDoc 
5690: 3d 20 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 29  = (const char *)
56a0: 73 71 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f 74  sqlite3_column_t
56b0: 65 78 74 28 70 43 73 72 2d 3e 70 53 74 6d 74 2c  ext(pCsr->pStmt,
56c0: 20 69 43 6f 6c 29 3b 0a 20 20 69 66 28 20 7a 44   iCol);.  if( zD
56d0: 6f 63 3d 3d 30 20 29 7b 0a 20 20 20 20 69 66 28  oc==0 ){.    if(
56e0: 20 73 71 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f   sqlite3_column_
56f0: 74 79 70 65 28 70 43 73 72 2d 3e 70 53 74 6d 74  type(pCsr->pStmt
5700: 2c 20 69 43 6f 6c 29 21 3d 53 51 4c 49 54 45 5f  , iCol)!=SQLITE_
5710: 4e 55 4c 4c 20 29 7b 0a 20 20 20 20 20 20 72 65  NULL ){.      re
5720: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45  turn SQLITE_NOME
5730: 4d 3b 0a 20 20 20 20 7d 0a 20 20 20 20 72 65 74  M;.    }.    ret
5740: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  urn SQLITE_OK;. 
5750: 20 7d 0a 20 20 6e 44 6f 63 20 3d 20 73 71 6c 69   }.  nDoc = sqli
5760: 74 65 33 5f 63 6f 6c 75 6d 6e 5f 62 79 74 65 73  te3_column_bytes
5770: 28 70 43 73 72 2d 3e 70 53 74 6d 74 2c 20 69 43  (pCsr->pStmt, iC
5780: 6f 6c 29 3b 0a 0a 20 20 2f 2a 20 4f 70 65 6e 20  ol);..  /* Open 
5790: 61 20 74 6f 6b 65 6e 20 63 75 72 73 6f 72 20 6f  a token cursor o
57a0: 6e 20 74 68 65 20 64 6f 63 75 6d 65 6e 74 2e 20  n the document. 
57b0: 2a 2f 0a 20 20 70 4d 6f 64 20 3d 20 28 73 71 6c  */.  pMod = (sql
57c0: 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 6d  ite3_tokenizer_m
57d0: 6f 64 75 6c 65 20 2a 29 70 54 61 62 2d 3e 70 54  odule *)pTab->pT
57e0: 6f 6b 65 6e 69 7a 65 72 2d 3e 70 4d 6f 64 75 6c  okenizer->pModul
57f0: 65 3b 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65  e;.  rc = sqlite
5800: 33 46 74 73 33 4f 70 65 6e 54 6f 6b 65 6e 69 7a  3Fts3OpenTokeniz
5810: 65 72 28 70 54 61 62 2d 3e 70 54 6f 6b 65 6e 69  er(pTab->pTokeni
5820: 7a 65 72 2c 20 70 43 73 72 2d 3e 69 4c 61 6e 67  zer, pCsr->iLang
5830: 69 64 2c 20 7a 44 6f 63 2c 6e 44 6f 63 2c 26 70  id, zDoc,nDoc,&p
5840: 43 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 53 51  C);.  if( rc!=SQ
5850: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 72  LITE_OK ){.    r
5860: 65 74 75 72 6e 20 72 63 3b 0a 20 20 7d 0a 0a 20  eturn rc;.  }.. 
5870: 20 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49   while( rc==SQLI
5880: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 63 6f 6e  TE_OK ){.    con
5890: 73 74 20 63 68 61 72 20 2a 5a 44 55 4d 4d 59 3b  st char *ZDUMMY;
58a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44 75             /* Du
58b0: 6d 6d 79 20 61 72 67 75 6d 65 6e 74 20 75 73 65  mmy argument use
58c0: 64 20 77 69 74 68 20 74 6f 6b 65 6e 69 7a 65 72  d with tokenizer
58d0: 20 2a 2f 0a 20 20 20 20 69 6e 74 20 44 55 4d 4d   */.    int DUMM
58e0: 59 31 20 3d 20 2d 31 3b 20 20 20 20 20 20 20 20  Y1 = -1;        
58f0: 20 20 20 20 20 20 2f 2a 20 44 75 6d 6d 79 20 61        /* Dummy a
5900: 72 67 75 6d 65 6e 74 20 75 73 65 64 20 77 69 74  rgument used wit
5910: 68 20 74 6f 6b 65 6e 69 7a 65 72 20 2a 2f 0a 20  h tokenizer */. 
5920: 20 20 20 69 6e 74 20 69 42 65 67 69 6e 20 3d 20     int iBegin = 
5930: 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0;              
5940: 20 2f 2a 20 4f 66 66 73 65 74 20 69 6e 20 7a 44   /* Offset in zD
5950: 6f 63 20 6f 66 20 73 74 61 72 74 20 6f 66 20 74  oc of start of t
5960: 6f 6b 65 6e 20 2a 2f 0a 20 20 20 20 69 6e 74 20  oken */.    int 
5970: 69 46 69 6e 20 3d 20 30 3b 20 20 20 20 20 20 20  iFin = 0;       
5980: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 66 66            /* Off
5990: 73 65 74 20 69 6e 20 7a 44 6f 63 20 6f 66 20 65  set in zDoc of e
59a0: 6e 64 20 6f 66 20 74 6f 6b 65 6e 20 2a 2f 0a 20  nd of token */. 
59b0: 20 20 20 69 6e 74 20 69 73 48 69 67 68 6c 69 67     int isHighlig
59c0: 68 74 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  ht = 0;         
59d0: 20 2f 2a 20 54 72 75 65 20 66 6f 72 20 68 69 67   /* True for hig
59e0: 68 6c 69 67 68 74 65 64 20 74 65 72 6d 73 20 2a  hlighted terms *
59f0: 2f 0a 0a 20 20 20 20 2f 2a 20 56 61 72 69 61 62  /..    /* Variab
5a00: 6c 65 20 44 55 4d 4d 59 31 20 69 73 20 69 6e 69  le DUMMY1 is ini
5a10: 74 69 61 6c 69 7a 65 64 20 74 6f 20 61 20 6e 65  tialized to a ne
5a20: 67 61 74 69 76 65 20 76 61 6c 75 65 20 61 62 6f  gative value abo
5a30: 76 65 2e 20 45 6c 73 65 77 68 65 72 65 0a 20 20  ve. Elsewhere.  
5a40: 20 20 2a 2a 20 69 6e 20 74 68 65 20 46 54 53 20    ** in the FTS 
5a50: 63 6f 64 65 20 74 68 65 20 76 61 72 69 61 62 6c  code the variabl
5a60: 65 20 74 68 61 74 20 74 68 65 20 74 68 69 72 64  e that the third
5a70: 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 78 4e 65   argument to xNe
5a80: 78 74 20 70 6f 69 6e 74 73 20 74 6f 0a 20 20 20  xt points to.   
5a90: 20 2a 2a 20 69 73 20 69 6e 69 74 69 61 6c 69 7a   ** is initializ
5aa0: 65 64 20 74 6f 20 7a 65 72 6f 20 62 65 66 6f 72  ed to zero befor
5ab0: 65 20 74 68 65 20 66 69 72 73 74 20 28 2a 62 75  e the first (*bu
5ac0: 74 20 6e 6f 74 20 6e 65 63 65 73 73 61 72 69 6c  t not necessaril
5ad0: 79 0a 20 20 20 20 2a 2a 20 73 75 62 73 65 71 75  y.    ** subsequ
5ae0: 65 6e 74 2a 29 20 63 61 6c 6c 20 74 6f 20 78 4e  ent*) call to xN
5af0: 65 78 74 28 29 2e 20 54 68 69 73 20 69 73 20 64  ext(). This is d
5b00: 6f 6e 65 20 66 6f 72 20 61 20 70 61 72 74 69 63  one for a partic
5b10: 75 6c 61 72 20 61 70 70 6c 69 63 61 74 69 6f 6e  ular application
5b20: 0a 20 20 20 20 2a 2a 20 74 68 61 74 20 6e 65 65  .    ** that nee
5b30: 64 73 20 74 6f 20 6b 6e 6f 77 20 77 68 65 74 68  ds to know wheth
5b40: 65 72 20 6f 72 20 6e 6f 74 20 74 68 65 20 74 6f  er or not the to
5b50: 6b 65 6e 69 7a 65 72 20 69 73 20 62 65 69 6e 67  kenizer is being
5b60: 20 75 73 65 64 20 66 6f 72 0a 20 20 20 20 2a 2a   used for.    **
5b70: 20 73 6e 69 70 70 65 74 20 67 65 6e 65 72 61 74   snippet generat
5b80: 69 6f 6e 20 6f 72 20 66 6f 72 20 73 6f 6d 65 20  ion or for some 
5b90: 6f 74 68 65 72 20 70 75 72 70 6f 73 65 2e 0a 20  other purpose.. 
5ba0: 20 20 20 2a 2a 0a 20 20 20 20 2a 2a 20 45 78 74     **.    ** Ext
5bb0: 72 65 6d 65 20 63 61 72 65 20 69 73 20 72 65 71  reme care is req
5bc0: 75 69 72 65 64 20 77 68 65 6e 20 77 72 69 74 69  uired when writi
5bd0: 6e 67 20 63 6f 64 65 20 74 6f 20 64 65 70 65 6e  ng code to depen
5be0: 64 20 6f 6e 20 74 68 69 73 0a 20 20 20 20 2a 2a  d on this.    **
5bf0: 20 69 6e 69 74 69 61 6c 69 7a 61 74 69 6f 6e 2e   initialization.
5c00: 20 49 74 20 69 73 20 6e 6f 74 20 61 20 64 6f 63   It is not a doc
5c10: 75 6d 65 6e 74 65 64 20 70 61 72 74 20 6f 66 20  umented part of 
5c20: 74 68 65 20 74 6f 6b 65 6e 69 7a 65 72 20 69 6e  the tokenizer in
5c30: 74 65 72 66 61 63 65 2e 0a 20 20 20 20 2a 2a 20  terface..    ** 
5c40: 49 66 20 61 20 74 6f 6b 65 6e 69 7a 65 72 20 69  If a tokenizer i
5c50: 73 20 75 73 65 64 20 64 69 72 65 63 74 6c 79 20  s used directly 
5c60: 62 79 20 61 6e 79 20 63 6f 64 65 20 6f 75 74 73  by any code outs
5c70: 69 64 65 20 6f 66 20 46 54 53 2c 20 74 68 69 73  ide of FTS, this
5c80: 0a 20 20 20 20 2a 2a 20 63 6f 6e 76 65 6e 74 69  .    ** conventi
5c90: 6f 6e 20 6d 69 67 68 74 20 6e 6f 74 20 62 65 20  on might not be 
5ca0: 72 65 73 70 65 63 74 65 64 2e 20 20 2a 2f 0a 20  respected.  */. 
5cb0: 20 20 20 72 63 20 3d 20 70 4d 6f 64 2d 3e 78 4e     rc = pMod->xN
5cc0: 65 78 74 28 70 43 2c 20 26 5a 44 55 4d 4d 59 2c  ext(pC, &ZDUMMY,
5cd0: 20 26 44 55 4d 4d 59 31 2c 20 26 69 42 65 67 69   &DUMMY1, &iBegi
5ce0: 6e 2c 20 26 69 46 69 6e 2c 20 26 69 43 75 72 72  n, &iFin, &iCurr
5cf0: 65 6e 74 29 3b 0a 20 20 20 20 69 66 28 20 72 63  ent);.    if( rc
5d00: 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20  !=SQLITE_OK ){. 
5d10: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c       if( rc==SQL
5d20: 49 54 45 5f 44 4f 4e 45 20 29 7b 0a 20 20 20 20  ITE_DONE ){.    
5d30: 20 20 20 20 2f 2a 20 53 70 65 63 69 61 6c 20 63      /* Special c
5d40: 61 73 65 20 2d 20 74 68 65 20 6c 61 73 74 20 74  ase - the last t
5d50: 6f 6b 65 6e 20 6f 66 20 74 68 65 20 73 6e 69 70  oken of the snip
5d60: 70 65 74 20 69 73 20 61 6c 73 6f 20 74 68 65 20  pet is also the 
5d70: 6c 61 73 74 20 74 6f 6b 65 6e 0a 20 20 20 20 20  last token.     
5d80: 20 20 20 2a 2a 20 6f 66 20 74 68 65 20 63 6f 6c     ** of the col
5d90: 75 6d 6e 2e 20 41 70 70 65 6e 64 20 61 6e 79 20  umn. Append any 
5da0: 70 75 6e 63 74 75 61 74 69 6f 6e 20 74 68 61 74  punctuation that
5db0: 20 6f 63 63 75 72 72 65 64 20 62 65 74 77 65 65   occurred betwee
5dc0: 6e 20 74 68 65 20 65 6e 64 0a 20 20 20 20 20 20  n the end.      
5dd0: 20 20 2a 2a 20 6f 66 20 74 68 65 20 70 72 65 76    ** of the prev
5de0: 69 6f 75 73 20 74 6f 6b 65 6e 20 61 6e 64 20 74  ious token and t
5df0: 68 65 20 65 6e 64 20 6f 66 20 74 68 65 20 64 6f  he end of the do
5e00: 63 75 6d 65 6e 74 20 74 6f 20 74 68 65 20 6f 75  cument to the ou
5e10: 74 70 75 74 2e 20 0a 20 20 20 20 20 20 20 20 2a  tput. .        *
5e20: 2a 20 54 68 65 6e 20 62 72 65 61 6b 20 6f 75 74  * Then break out
5e30: 20 6f 66 20 74 68 65 20 6c 6f 6f 70 2e 20 2a 2f   of the loop. */
5e40: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 66 74  .        rc = ft
5e50: 73 33 53 74 72 69 6e 67 41 70 70 65 6e 64 28 70  s3StringAppend(p
5e60: 4f 75 74 2c 20 26 7a 44 6f 63 5b 69 45 6e 64 5d  Out, &zDoc[iEnd]
5e70: 2c 20 2d 31 29 3b 0a 20 20 20 20 20 20 7d 0a 20  , -1);.      }. 
5e80: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
5e90: 7d 0a 20 20 20 20 69 66 28 20 69 43 75 72 72 65  }.    if( iCurre
5ea0: 6e 74 3c 69 50 6f 73 20 29 7b 20 63 6f 6e 74 69  nt<iPos ){ conti
5eb0: 6e 75 65 3b 20 7d 0a 0a 20 20 20 20 69 66 28 20  nue; }..    if( 
5ec0: 21 69 73 53 68 69 66 74 44 6f 6e 65 20 29 7b 0a  !isShiftDone ){.
5ed0: 20 20 20 20 20 20 69 6e 74 20 6e 20 3d 20 6e 44        int n = nD
5ee0: 6f 63 20 2d 20 69 42 65 67 69 6e 3b 0a 20 20 20  oc - iBegin;.   
5ef0: 20 20 20 72 63 20 3d 20 66 74 73 33 53 6e 69 70     rc = fts3Snip
5f00: 70 65 74 53 68 69 66 74 28 0a 20 20 20 20 20 20  petShift(.      
5f10: 20 20 20 20 70 54 61 62 2c 20 70 43 73 72 2d 3e      pTab, pCsr->
5f20: 69 4c 61 6e 67 69 64 2c 20 6e 53 6e 69 70 70 65  iLangid, nSnippe
5f30: 74 2c 20 26 7a 44 6f 63 5b 69 42 65 67 69 6e 5d  t, &zDoc[iBegin]
5f40: 2c 20 6e 2c 20 26 69 50 6f 73 2c 20 26 68 6c 6d  , n, &iPos, &hlm
5f50: 61 73 6b 0a 20 20 20 20 20 20 29 3b 0a 20 20 20  ask.      );.   
5f60: 20 20 20 69 73 53 68 69 66 74 44 6f 6e 65 20 3d     isShiftDone =
5f70: 20 31 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 4e 6f   1;..      /* No
5f80: 77 20 74 68 61 74 20 74 68 65 20 73 68 69 66 74  w that the shift
5f90: 20 68 61 73 20 62 65 65 6e 20 64 6f 6e 65 2c 20   has been done, 
5fa0: 63 68 65 63 6b 20 69 66 20 74 68 65 20 69 6e 69  check if the ini
5fb0: 74 69 61 6c 20 22 2e 2e 2e 22 20 61 72 65 0a 20  tial "..." are. 
5fc0: 20 20 20 20 20 2a 2a 20 72 65 71 75 69 72 65 64       ** required
5fd0: 2e 20 54 68 65 79 20 61 72 65 20 72 65 71 75 69  . They are requi
5fe0: 72 65 64 20 69 66 20 28 61 29 20 74 68 69 73 20  red if (a) this 
5ff0: 69 73 20 6e 6f 74 20 74 68 65 20 66 69 72 73 74  is not the first
6000: 20 66 72 61 67 6d 65 6e 74 2c 0a 20 20 20 20 20   fragment,.     
6010: 20 2a 2a 20 6f 72 20 28 62 29 20 74 68 69 73 20   ** or (b) this 
6020: 66 72 61 67 6d 65 6e 74 20 64 6f 65 73 20 6e 6f  fragment does no
6030: 74 20 62 65 67 69 6e 20 61 74 20 70 6f 73 69 74  t begin at posit
6040: 69 6f 6e 20 30 20 6f 66 20 69 74 73 20 63 6f 6c  ion 0 of its col
6050: 75 6d 6e 2e 20 0a 20 20 20 20 20 20 2a 2f 0a 20  umn. .      */. 
6060: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c       if( rc==SQL
6070: 49 54 45 5f 4f 4b 20 26 26 20 28 69 50 6f 73 3e  ITE_OK && (iPos>
6080: 30 20 7c 7c 20 69 46 72 61 67 6d 65 6e 74 3e 30  0 || iFragment>0
6090: 29 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20  ) ){.        rc 
60a0: 3d 20 66 74 73 33 53 74 72 69 6e 67 41 70 70 65  = fts3StringAppe
60b0: 6e 64 28 70 4f 75 74 2c 20 7a 45 6c 6c 69 70 73  nd(pOut, zEllips
60c0: 69 73 2c 20 2d 31 29 3b 0a 20 20 20 20 20 20 7d  is, -1);.      }
60d0: 0a 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53  .      if( rc!=S
60e0: 51 4c 49 54 45 5f 4f 4b 20 7c 7c 20 69 43 75 72  QLITE_OK || iCur
60f0: 72 65 6e 74 3c 69 50 6f 73 20 29 20 63 6f 6e 74  rent<iPos ) cont
6100: 69 6e 75 65 3b 0a 20 20 20 20 7d 0a 0a 20 20 20  inue;.    }..   
6110: 20 69 66 28 20 69 43 75 72 72 65 6e 74 3e 3d 28   if( iCurrent>=(
6120: 69 50 6f 73 2b 6e 53 6e 69 70 70 65 74 29 20 29  iPos+nSnippet) )
6130: 7b 0a 20 20 20 20 20 20 69 66 28 20 69 73 4c 61  {.      if( isLa
6140: 73 74 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63  st ){.        rc
6150: 20 3d 20 66 74 73 33 53 74 72 69 6e 67 41 70 70   = fts3StringApp
6160: 65 6e 64 28 70 4f 75 74 2c 20 7a 45 6c 6c 69 70  end(pOut, zEllip
6170: 73 69 73 2c 20 2d 31 29 3b 0a 20 20 20 20 20 20  sis, -1);.      
6180: 7d 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  }.      break;. 
6190: 20 20 20 7d 0a 0a 20 20 20 20 2f 2a 20 53 65 74     }..    /* Set
61a0: 20 69 73 48 69 67 68 6c 69 67 68 74 20 74 6f 20   isHighlight to 
61b0: 74 72 75 65 20 69 66 20 74 68 69 73 20 74 65 72  true if this ter
61c0: 6d 20 73 68 6f 75 6c 64 20 62 65 20 68 69 67 68  m should be high
61d0: 6c 69 67 68 74 65 64 2e 20 2a 2f 0a 20 20 20 20  lighted. */.    
61e0: 69 73 48 69 67 68 6c 69 67 68 74 20 3d 20 28 68  isHighlight = (h
61f0: 6c 6d 61 73 6b 20 26 20 28 28 75 36 34 29 31 20  lmask & ((u64)1 
6200: 3c 3c 20 28 69 43 75 72 72 65 6e 74 2d 69 50 6f  << (iCurrent-iPo
6210: 73 29 29 29 21 3d 30 3b 0a 0a 20 20 20 20 69 66  s)))!=0;..    if
6220: 28 20 69 43 75 72 72 65 6e 74 3e 69 50 6f 73 20  ( iCurrent>iPos 
6230: 29 20 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e  ) rc = fts3Strin
6240: 67 41 70 70 65 6e 64 28 70 4f 75 74 2c 20 26 7a  gAppend(pOut, &z
6250: 44 6f 63 5b 69 45 6e 64 5d 2c 20 69 42 65 67 69  Doc[iEnd], iBegi
6260: 6e 2d 69 45 6e 64 29 3b 0a 20 20 20 20 69 66 28  n-iEnd);.    if(
6270: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
6280: 26 20 69 73 48 69 67 68 6c 69 67 68 74 20 29 20  & isHighlight ) 
6290: 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67 41  rc = fts3StringA
62a0: 70 70 65 6e 64 28 70 4f 75 74 2c 20 7a 4f 70 65  ppend(pOut, zOpe
62b0: 6e 2c 20 2d 31 29 3b 0a 20 20 20 20 69 66 28 20  n, -1);.    if( 
62c0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20  rc==SQLITE_OK ) 
62d0: 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67 41  rc = fts3StringA
62e0: 70 70 65 6e 64 28 70 4f 75 74 2c 20 26 7a 44 6f  ppend(pOut, &zDo
62f0: 63 5b 69 42 65 67 69 6e 5d 2c 20 69 46 69 6e 2d  c[iBegin], iFin-
6300: 69 42 65 67 69 6e 29 3b 0a 20 20 20 20 69 66 28  iBegin);.    if(
6310: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
6320: 26 20 69 73 48 69 67 68 6c 69 67 68 74 20 29 20  & isHighlight ) 
6330: 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67 41  rc = fts3StringA
6340: 70 70 65 6e 64 28 70 4f 75 74 2c 20 7a 43 6c 6f  ppend(pOut, zClo
6350: 73 65 2c 20 2d 31 29 3b 0a 0a 20 20 20 20 69 45  se, -1);..    iE
6360: 6e 64 20 3d 20 69 46 69 6e 3b 0a 20 20 7d 0a 0a  nd = iFin;.  }..
6370: 20 20 70 4d 6f 64 2d 3e 78 43 6c 6f 73 65 28 70    pMod->xClose(p
6380: 43 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  C);.  return rc;
6390: 0a 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  .}.../*.** This 
63a0: 66 75 6e 63 74 69 6f 6e 20 69 73 20 75 73 65 64  function is used
63b0: 20 74 6f 20 63 6f 75 6e 74 20 74 68 65 20 65 6e   to count the en
63c0: 74 72 69 65 73 20 69 6e 20 61 20 63 6f 6c 75 6d  tries in a colum
63d0: 6e 2d 6c 69 73 74 20 28 61 20 0a 2a 2a 20 64 65  n-list (a .** de
63e0: 6c 74 61 2d 65 6e 63 6f 64 65 64 20 6c 69 73 74  lta-encoded list
63f0: 20 6f 66 20 74 65 72 6d 20 6f 66 66 73 65 74 73   of term offsets
6400: 20 77 69 74 68 69 6e 20 61 20 73 69 6e 67 6c 65   within a single
6410: 20 63 6f 6c 75 6d 6e 20 6f 66 20 61 20 73 69 6e   column of a sin
6420: 67 6c 65 20 0a 2a 2a 20 72 6f 77 29 2e 20 57 68  gle .** row). Wh
6430: 65 6e 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e  en this function
6440: 20 69 73 20 63 61 6c 6c 65 64 2c 20 2a 70 70 43   is called, *ppC
6450: 6f 6c 6c 69 73 74 20 73 68 6f 75 6c 64 20 70 6f  ollist should po
6460: 69 6e 74 20 74 6f 20 74 68 65 0a 2a 2a 20 62 65  int to the.** be
6470: 67 69 6e 6e 69 6e 67 20 6f 66 20 74 68 65 20 66  ginning of the f
6480: 69 72 73 74 20 76 61 72 69 6e 74 20 69 6e 20 74  irst varint in t
6490: 68 65 20 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 28  he column-list (
64a0: 74 68 65 20 76 61 72 69 6e 74 20 74 68 61 74 0a  the varint that.
64b0: 2a 2a 20 63 6f 6e 74 61 69 6e 73 20 74 68 65 20  ** contains the 
64c0: 70 6f 73 69 74 69 6f 6e 20 6f 66 20 74 68 65 20  position of the 
64d0: 66 69 72 73 74 20 6d 61 74 63 68 69 6e 67 20 74  first matching t
64e0: 65 72 6d 20 69 6e 20 74 68 65 20 63 6f 6c 75 6d  erm in the colum
64f0: 6e 20 64 61 74 61 29 2e 0a 2a 2a 20 42 65 66 6f  n data)..** Befo
6500: 72 65 20 72 65 74 75 72 6e 69 6e 67 2c 20 2a 70  re returning, *p
6510: 70 43 6f 6c 6c 69 73 74 20 69 73 20 73 65 74 20  pCollist is set 
6520: 74 6f 20 70 6f 69 6e 74 20 74 6f 20 74 68 65 20  to point to the 
6530: 66 69 72 73 74 20 62 79 74 65 20 61 66 74 65 72  first byte after
6540: 0a 2a 2a 20 74 68 65 20 6c 61 73 74 20 76 61 72  .** the last var
6550: 69 6e 74 20 69 6e 20 74 68 65 20 63 6f 6c 75 6d  int in the colum
6560: 6e 2d 6c 69 73 74 20 28 65 69 74 68 65 72 20 74  n-list (either t
6570: 68 65 20 30 78 30 30 20 73 69 67 6e 69 66 79 69  he 0x00 signifyi
6580: 6e 67 20 74 68 65 20 65 6e 64 0a 2a 2a 20 6f 66  ng the end.** of
6590: 20 74 68 65 20 70 6f 73 69 74 69 6f 6e 2d 6c 69   the position-li
65a0: 73 74 2c 20 6f 72 20 74 68 65 20 30 78 30 31 20  st, or the 0x01 
65b0: 74 68 61 74 20 70 72 65 63 65 64 65 73 20 74 68  that precedes th
65c0: 65 20 63 6f 6c 75 6d 6e 20 6e 75 6d 62 65 72 20  e column number 
65d0: 6f 66 0a 2a 2a 20 74 68 65 20 6e 65 78 74 20 63  of.** the next c
65e0: 6f 6c 75 6d 6e 20 69 6e 20 74 68 65 20 70 6f 73  olumn in the pos
65f0: 69 74 69 6f 6e 2d 6c 69 73 74 29 2e 0a 2a 2a 0a  ition-list)..**.
6600: 2a 2a 20 54 68 65 20 6e 75 6d 62 65 72 20 6f 66  ** The number of
6610: 20 65 6c 65 6d 65 6e 74 73 20 69 6e 20 74 68 65   elements in the
6620: 20 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 69 73 20   column-list is 
6630: 72 65 74 75 72 6e 65 64 2e 0a 2a 2f 0a 73 74 61  returned..*/.sta
6640: 74 69 63 20 69 6e 74 20 66 74 73 33 43 6f 6c 75  tic int fts3Colu
6650: 6d 6e 6c 69 73 74 43 6f 75 6e 74 28 63 68 61 72  mnlistCount(char
6660: 20 2a 2a 70 70 43 6f 6c 6c 69 73 74 29 7b 0a 20   **ppCollist){. 
6670: 20 63 68 61 72 20 2a 70 45 6e 64 20 3d 20 2a 70   char *pEnd = *p
6680: 70 43 6f 6c 6c 69 73 74 3b 0a 20 20 63 68 61 72  pCollist;.  char
6690: 20 63 20 3d 20 30 3b 0a 20 20 69 6e 74 20 6e 45   c = 0;.  int nE
66a0: 6e 74 72 79 20 3d 20 30 3b 0a 0a 20 20 2f 2a 20  ntry = 0;..  /* 
66b0: 41 20 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 69 73  A column-list is
66c0: 20 74 65 72 6d 69 6e 61 74 65 64 20 62 79 20 65   terminated by e
66d0: 69 74 68 65 72 20 61 20 30 78 30 31 20 6f 72 20  ither a 0x01 or 
66e0: 30 78 30 30 2e 20 2a 2f 0a 20 20 77 68 69 6c 65  0x00. */.  while
66f0: 28 20 30 78 46 45 20 26 20 28 2a 70 45 6e 64 20  ( 0xFE & (*pEnd 
6700: 7c 20 63 29 20 29 7b 0a 20 20 20 20 63 20 3d 20  | c) ){.    c = 
6710: 2a 70 45 6e 64 2b 2b 20 26 20 30 78 38 30 3b 0a  *pEnd++ & 0x80;.
6720: 20 20 20 20 69 66 28 20 21 63 20 29 20 6e 45 6e      if( !c ) nEn
6730: 74 72 79 2b 2b 3b 0a 20 20 7d 0a 0a 20 20 2a 70  try++;.  }..  *p
6740: 70 43 6f 6c 6c 69 73 74 20 3d 20 70 45 6e 64 3b  pCollist = pEnd;
6750: 0a 20 20 72 65 74 75 72 6e 20 6e 45 6e 74 72 79  .  return nEntry
6760: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 66 74 73 33 45  ;.}../*.** fts3E
6770: 78 70 72 49 74 65 72 61 74 65 28 29 20 63 61 6c  xprIterate() cal
6780: 6c 62 61 63 6b 20 75 73 65 64 20 74 6f 20 63 6f  lback used to co
6790: 6c 6c 65 63 74 20 74 68 65 20 22 67 6c 6f 62 61  llect the "globa
67a0: 6c 22 20 6d 61 74 63 68 69 6e 66 6f 20 73 74 61  l" matchinfo sta
67b0: 74 73 0a 2a 2a 20 66 6f 72 20 61 20 73 69 6e 67  ts.** for a sing
67c0: 6c 65 20 71 75 65 72 79 2e 20 0a 2a 2a 0a 2a 2a  le query. .**.**
67d0: 20 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65   fts3ExprIterate
67e0: 28 29 20 63 61 6c 6c 62 61 63 6b 20 74 6f 20 6c  () callback to l
67f0: 6f 61 64 20 74 68 65 20 27 67 6c 6f 62 61 6c 27  oad the 'global'
6800: 20 65 6c 65 6d 65 6e 74 73 20 6f 66 20 61 0a 2a   elements of a.*
6810: 2a 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f  * FTS3_MATCHINFO
6820: 5f 48 49 54 53 20 6d 61 74 63 68 69 6e 66 6f 20  _HITS matchinfo 
6830: 61 72 72 61 79 2e 20 54 68 65 20 67 6c 6f 62 61  array. The globa
6840: 6c 20 73 74 61 74 73 20 61 72 65 20 74 68 6f 73  l stats are thos
6850: 65 20 65 6c 65 6d 65 6e 74 73 20 0a 2a 2a 20 6f  e elements .** o
6860: 66 20 74 68 65 20 6d 61 74 63 68 69 6e 66 6f 20  f the matchinfo 
6870: 61 72 72 61 79 20 74 68 61 74 20 61 72 65 20 63  array that are c
6880: 6f 6e 73 74 61 6e 74 20 66 6f 72 20 61 6c 6c 20  onstant for all 
6890: 72 6f 77 73 20 72 65 74 75 72 6e 65 64 20 62 79  rows returned by
68a0: 20 74 68 65 20 0a 2a 2a 20 63 75 72 72 65 6e 74   the .** current
68b0: 20 71 75 65 72 79 2e 0a 2a 2a 0a 2a 2a 20 41 72   query..**.** Ar
68c0: 67 75 6d 65 6e 74 20 70 43 74 78 20 69 73 20 61  gument pCtx is a
68d0: 63 74 75 61 6c 6c 79 20 61 20 70 6f 69 6e 74 65  ctually a pointe
68e0: 72 20 74 6f 20 61 20 73 74 72 75 63 74 20 6f 66  r to a struct of
68f0: 20 74 79 70 65 20 4d 61 74 63 68 49 6e 66 6f 2e   type MatchInfo.
6900: 20 54 68 69 73 0a 2a 2a 20 66 75 6e 63 74 69 6f   This.** functio
6910: 6e 20 70 6f 70 75 6c 61 74 65 73 20 4d 61 74 63  n populates Matc
6920: 68 69 6e 66 6f 2e 61 4d 61 74 63 68 69 6e 66 6f  hinfo.aMatchinfo
6930: 5b 5d 20 61 73 20 66 6f 6c 6c 6f 77 73 3a 0a 2a  [] as follows:.*
6940: 2a 0a 2a 2a 20 20 20 66 6f 72 28 69 43 6f 6c 3d  *.**   for(iCol=
6950: 30 3b 20 69 43 6f 6c 3c 6e 43 6f 6c 3b 20 69 43  0; iCol<nCol; iC
6960: 6f 6c 2b 2b 29 7b 0a 2a 2a 20 20 20 20 20 61 4d  ol++){.**     aM
6970: 61 74 63 68 69 6e 66 6f 5b 33 2a 69 50 68 72 61  atchinfo[3*iPhra
6980: 73 65 2a 6e 43 6f 6c 20 2b 20 33 2a 69 43 6f 6c  se*nCol + 3*iCol
6990: 20 2b 20 31 5d 20 3d 20 58 3b 0a 2a 2a 20 20 20   + 1] = X;.**   
69a0: 20 20 61 4d 61 74 63 68 69 6e 66 6f 5b 33 2a 69    aMatchinfo[3*i
69b0: 50 68 72 61 73 65 2a 6e 43 6f 6c 20 2b 20 33 2a  Phrase*nCol + 3*
69c0: 69 43 6f 6c 20 2b 20 32 5d 20 3d 20 59 3b 0a 2a  iCol + 2] = Y;.*
69d0: 2a 20 20 20 7d 0a 2a 2a 0a 2a 2a 20 77 68 65 72  *   }.**.** wher
69e0: 65 20 58 20 69 73 20 74 68 65 20 6e 75 6d 62 65  e X is the numbe
69f0: 72 20 6f 66 20 6d 61 74 63 68 65 73 20 66 6f 72  r of matches for
6a00: 20 70 68 72 61 73 65 20 69 50 68 72 61 73 65 20   phrase iPhrase 
6a10: 69 73 20 63 6f 6c 75 6d 6e 20 69 43 6f 6c 20 6f  is column iCol o
6a20: 66 20 61 6c 6c 0a 2a 2a 20 72 6f 77 73 20 6f 66  f all.** rows of
6a30: 20 74 68 65 20 74 61 62 6c 65 2e 20 59 20 69 73   the table. Y is
6a40: 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 72   the number of r
6a50: 6f 77 73 20 66 6f 72 20 77 68 69 63 68 20 63 6f  ows for which co
6a60: 6c 75 6d 6e 20 69 43 6f 6c 20 63 6f 6e 74 61 69  lumn iCol contai
6a70: 6e 73 0a 2a 2a 20 61 74 20 6c 65 61 73 74 20 6f  ns.** at least o
6a80: 6e 65 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 70  ne instance of p
6a90: 68 72 61 73 65 20 69 50 68 72 61 73 65 2e 0a 2a  hrase iPhrase..*
6aa0: 2a 0a 2a 2a 20 49 66 20 74 68 65 20 70 68 72 61  *.** If the phra
6ab0: 73 65 20 70 45 78 70 72 20 63 6f 6e 73 69 73 74  se pExpr consist
6ac0: 73 20 65 6e 74 69 72 65 6c 79 20 6f 66 20 64 65  s entirely of de
6ad0: 66 65 72 72 65 64 20 74 6f 6b 65 6e 73 2c 20 74  ferred tokens, t
6ae0: 68 65 6e 20 61 6c 6c 20 58 20 61 6e 64 0a 2a 2a  hen all X and.**
6af0: 20 59 20 76 61 6c 75 65 73 20 61 72 65 20 73 65   Y values are se
6b00: 74 20 74 6f 20 6e 44 6f 63 2c 20 77 68 65 72 65  t to nDoc, where
6b10: 20 6e 44 6f 63 20 69 73 20 74 68 65 20 6e 75 6d   nDoc is the num
6b20: 62 65 72 20 6f 66 20 64 6f 63 75 6d 65 6e 74 73  ber of documents
6b30: 20 69 6e 20 74 68 65 20 0a 2a 2a 20 66 69 6c 65   in the .** file
6b40: 20 73 79 73 74 65 6d 2e 20 54 68 69 73 20 69 73   system. This is
6b50: 20 64 6f 6e 65 20 62 65 63 61 75 73 65 20 74 68   done because th
6b60: 65 20 66 75 6c 6c 2d 74 65 78 74 20 69 6e 64 65  e full-text inde
6b70: 78 20 64 6f 63 6c 69 73 74 20 69 73 20 72 65 71  x doclist is req
6b80: 75 69 72 65 64 0a 2a 2a 20 74 6f 20 63 61 6c 63  uired.** to calc
6b90: 75 6c 61 74 65 20 74 68 65 73 65 20 76 61 6c 75  ulate these valu
6ba0: 65 73 20 70 72 6f 70 65 72 6c 79 2c 20 61 6e 64  es properly, and
6bb0: 20 74 68 65 20 66 75 6c 6c 2d 74 65 78 74 20 69   the full-text i
6bc0: 6e 64 65 78 20 64 6f 63 6c 69 73 74 20 69 73 0a  ndex doclist is.
6bd0: 2a 2a 20 6e 6f 74 20 61 76 61 69 6c 61 62 6c 65  ** not available
6be0: 20 66 6f 72 20 64 65 66 65 72 72 65 64 20 74 6f   for deferred to
6bf0: 6b 65 6e 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  kens..*/.static 
6c00: 69 6e 74 20 66 74 73 33 45 78 70 72 47 6c 6f 62  int fts3ExprGlob
6c10: 61 6c 48 69 74 73 43 62 28 0a 20 20 46 74 73 33  alHitsCb(.  Fts3
6c20: 45 78 70 72 20 2a 70 45 78 70 72 2c 20 20 20 20  Expr *pExpr,    
6c30: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50              /* P
6c40: 68 72 61 73 65 20 65 78 70 72 65 73 73 69 6f 6e  hrase expression
6c50: 20 6e 6f 64 65 20 2a 2f 0a 20 20 69 6e 74 20 69   node */.  int i
6c60: 50 68 72 61 73 65 2c 20 20 20 20 20 20 20 20 20  Phrase,         
6c70: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 68             /* Ph
6c80: 72 61 73 65 20 6e 75 6d 62 65 72 20 28 6e 75 6d  rase number (num
6c90: 62 65 72 65 64 20 66 72 6f 6d 20 7a 65 72 6f 29  bered from zero)
6ca0: 20 2a 2f 0a 20 20 76 6f 69 64 20 2a 70 43 74 78   */.  void *pCtx
6cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6cc0: 20 20 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65 72        /* Pointer
6cd0: 20 74 6f 20 4d 61 74 63 68 49 6e 66 6f 20 73 74   to MatchInfo st
6ce0: 72 75 63 74 75 72 65 20 2a 2f 0a 29 7b 0a 20 20  ructure */.){.  
6cf0: 4d 61 74 63 68 49 6e 66 6f 20 2a 70 20 3d 20 28  MatchInfo *p = (
6d00: 4d 61 74 63 68 49 6e 66 6f 20 2a 29 70 43 74 78  MatchInfo *)pCtx
6d10: 3b 0a 20 20 72 65 74 75 72 6e 20 73 71 6c 69 74  ;.  return sqlit
6d20: 65 33 46 74 73 33 45 76 61 6c 50 68 72 61 73 65  e3Fts3EvalPhrase
6d30: 53 74 61 74 73 28 0a 20 20 20 20 20 20 70 2d 3e  Stats(.      p->
6d40: 70 43 75 72 73 6f 72 2c 20 70 45 78 70 72 2c 20  pCursor, pExpr, 
6d50: 26 70 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 33  &p->aMatchinfo[3
6d60: 2a 69 50 68 72 61 73 65 2a 70 2d 3e 6e 43 6f 6c  *iPhrase*p->nCol
6d70: 5d 0a 20 20 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  ].  );.}../*.** 
6d80: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 28  fts3ExprIterate(
6d90: 29 20 63 61 6c 6c 62 61 63 6b 20 75 73 65 64 20  ) callback used 
6da0: 74 6f 20 63 6f 6c 6c 65 63 74 20 74 68 65 20 22  to collect the "
6db0: 6c 6f 63 61 6c 22 20 70 61 72 74 20 6f 66 20 74  local" part of t
6dc0: 68 65 0a 2a 2a 20 46 54 53 33 5f 4d 41 54 43 48  he.** FTS3_MATCH
6dd0: 49 4e 46 4f 5f 48 49 54 53 20 61 72 72 61 79 2e  INFO_HITS array.
6de0: 20 54 68 65 20 6c 6f 63 61 6c 20 73 74 61 74 73   The local stats
6df0: 20 61 72 65 20 74 68 6f 73 65 20 65 6c 65 6d 65   are those eleme
6e00: 6e 74 73 20 6f 66 20 74 68 65 20 0a 2a 2a 20 61  nts of the .** a
6e10: 72 72 61 79 20 74 68 61 74 20 61 72 65 20 64 69  rray that are di
6e20: 66 66 65 72 65 6e 74 20 66 6f 72 20 65 61 63 68  fferent for each
6e30: 20 72 6f 77 20 72 65 74 75 72 6e 65 64 20 62 79   row returned by
6e40: 20 74 68 65 20 71 75 65 72 79 2e 0a 2a 2f 0a 73   the query..*/.s
6e50: 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 45 78  tatic int fts3Ex
6e60: 70 72 4c 6f 63 61 6c 48 69 74 73 43 62 28 0a 20  prLocalHitsCb(. 
6e70: 20 46 74 73 33 45 78 70 72 20 2a 70 45 78 70 72   Fts3Expr *pExpr
6e80: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
6e90: 20 2f 2a 20 50 68 72 61 73 65 20 65 78 70 72 65   /* Phrase expre
6ea0: 73 73 69 6f 6e 20 6e 6f 64 65 20 2a 2f 0a 20 20  ssion node */.  
6eb0: 69 6e 74 20 69 50 68 72 61 73 65 2c 20 20 20 20  int iPhrase,    
6ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ed0: 2f 2a 20 50 68 72 61 73 65 20 6e 75 6d 62 65 72  /* Phrase number
6ee0: 20 2a 2f 0a 20 20 76 6f 69 64 20 2a 70 43 74 78   */.  void *pCtx
6ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6f00: 20 20 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65 72        /* Pointer
6f10: 20 74 6f 20 4d 61 74 63 68 49 6e 66 6f 20 73 74   to MatchInfo st
6f20: 72 75 63 74 75 72 65 20 2a 2f 0a 29 7b 0a 20 20  ructure */.){.  
6f30: 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f  int rc = SQLITE_
6f40: 4f 4b 3b 0a 20 20 4d 61 74 63 68 49 6e 66 6f 20  OK;.  MatchInfo 
6f50: 2a 70 20 3d 20 28 4d 61 74 63 68 49 6e 66 6f 20  *p = (MatchInfo 
6f60: 2a 29 70 43 74 78 3b 0a 20 20 69 6e 74 20 69 53  *)pCtx;.  int iS
6f70: 74 61 72 74 20 3d 20 69 50 68 72 61 73 65 20 2a  tart = iPhrase *
6f80: 20 70 2d 3e 6e 43 6f 6c 20 2a 20 33 3b 0a 20 20   p->nCol * 3;.  
6f90: 69 6e 74 20 69 3b 0a 0a 20 20 66 6f 72 28 69 3d  int i;..  for(i=
6fa0: 30 3b 20 69 3c 70 2d 3e 6e 43 6f 6c 20 26 26 20  0; i<p->nCol && 
6fb0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 3b 20 69  rc==SQLITE_OK; i
6fc0: 2b 2b 29 7b 0a 20 20 20 20 63 68 61 72 20 2a 70  ++){.    char *p
6fd0: 43 73 72 3b 0a 20 20 20 20 72 63 20 3d 20 73 71  Csr;.    rc = sq
6fe0: 6c 69 74 65 33 46 74 73 33 45 76 61 6c 50 68 72  lite3Fts3EvalPhr
6ff0: 61 73 65 50 6f 73 6c 69 73 74 28 70 2d 3e 70 43  asePoslist(p->pC
7000: 75 72 73 6f 72 2c 20 70 45 78 70 72 2c 20 69 2c  ursor, pExpr, i,
7010: 20 26 70 43 73 72 29 3b 0a 20 20 20 20 69 66 28   &pCsr);.    if(
7020: 20 70 43 73 72 20 29 7b 0a 20 20 20 20 20 20 70   pCsr ){.      p
7030: 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 69 53 74  ->aMatchinfo[iSt
7040: 61 72 74 2b 69 2a 33 5d 20 3d 20 66 74 73 33 43  art+i*3] = fts3C
7050: 6f 6c 75 6d 6e 6c 69 73 74 43 6f 75 6e 74 28 26  olumnlistCount(&
7060: 70 43 73 72 29 3b 0a 20 20 20 20 7d 65 6c 73 65  pCsr);.    }else
7070: 7b 0a 20 20 20 20 20 20 70 2d 3e 61 4d 61 74 63  {.      p->aMatc
7080: 68 69 6e 66 6f 5b 69 53 74 61 72 74 2b 69 2a 33  hinfo[iStart+i*3
7090: 5d 20 3d 20 30 3b 0a 20 20 20 20 7d 0a 20 20 7d  ] = 0;.    }.  }
70a0: 0a 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  ..  return rc;.}
70b0: 0a 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74 73  ..static int fts
70c0: 33 4d 61 74 63 68 69 6e 66 6f 43 68 65 63 6b 28  3MatchinfoCheck(
70d0: 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a 70 54  .  Fts3Table *pT
70e0: 61 62 2c 20 0a 20 20 63 68 61 72 20 63 41 72 67  ab, .  char cArg
70f0: 2c 0a 20 20 63 68 61 72 20 2a 2a 70 7a 45 72 72  ,.  char **pzErr
7100: 0a 29 7b 0a 20 20 69 66 28 20 28 63 41 72 67 3d  .){.  if( (cArg=
7110: 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f  =FTS3_MATCHINFO_
7120: 4e 50 48 52 41 53 45 29 0a 20 20 20 7c 7c 20 28  NPHRASE).   || (
7130: 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41 54 43 48  cArg==FTS3_MATCH
7140: 49 4e 46 4f 5f 4e 43 4f 4c 29 0a 20 20 20 7c 7c  INFO_NCOL).   ||
7150: 20 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41 54   (cArg==FTS3_MAT
7160: 43 48 49 4e 46 4f 5f 4e 44 4f 43 20 26 26 20 70  CHINFO_NDOC && p
7170: 54 61 62 2d 3e 62 46 74 73 34 29 0a 20 20 20 7c  Tab->bFts4).   |
7180: 7c 20 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41  | (cArg==FTS3_MA
7190: 54 43 48 49 4e 46 4f 5f 41 56 47 4c 45 4e 47 54  TCHINFO_AVGLENGT
71a0: 48 20 26 26 20 70 54 61 62 2d 3e 62 46 74 73 34  H && pTab->bFts4
71b0: 29 0a 20 20 20 7c 7c 20 28 63 41 72 67 3d 3d 46  ).   || (cArg==F
71c0: 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c 45  TS3_MATCHINFO_LE
71d0: 4e 47 54 48 20 26 26 20 70 54 61 62 2d 3e 62 48  NGTH && pTab->bH
71e0: 61 73 44 6f 63 73 69 7a 65 29 0a 20 20 20 7c 7c  asDocsize).   ||
71f0: 20 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41 54   (cArg==FTS3_MAT
7200: 43 48 49 4e 46 4f 5f 4c 43 53 29 0a 20 20 20 7c  CHINFO_LCS).   |
7210: 7c 20 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41  | (cArg==FTS3_MA
7220: 54 43 48 49 4e 46 4f 5f 48 49 54 53 29 0a 20 20  TCHINFO_HITS).  
7230: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 53 51  ){.    return SQ
7240: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 7d 0a 20 20 2a  LITE_OK;.  }.  *
7250: 70 7a 45 72 72 20 3d 20 73 71 6c 69 74 65 33 5f  pzErr = sqlite3_
7260: 6d 70 72 69 6e 74 66 28 22 75 6e 72 65 63 6f 67  mprintf("unrecog
7270: 6e 69 7a 65 64 20 6d 61 74 63 68 69 6e 66 6f 20  nized matchinfo 
7280: 72 65 71 75 65 73 74 3a 20 25 63 22 2c 20 63 41  request: %c", cA
7290: 72 67 29 3b 0a 20 20 72 65 74 75 72 6e 20 53 51  rg);.  return SQ
72a0: 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 7d 0a 0a 73  LITE_ERROR;.}..s
72b0: 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 4d 61  tatic int fts3Ma
72c0: 74 63 68 69 6e 66 6f 53 69 7a 65 28 4d 61 74 63  tchinfoSize(Matc
72d0: 68 49 6e 66 6f 20 2a 70 49 6e 66 6f 2c 20 63 68  hInfo *pInfo, ch
72e0: 61 72 20 63 41 72 67 29 7b 0a 20 20 69 6e 74 20  ar cArg){.  int 
72f0: 6e 56 61 6c 3b 20 20 20 20 20 20 20 20 20 20 20  nVal;           
7300: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
7310: 75 6d 62 65 72 20 6f 66 20 69 6e 74 65 67 65 72  umber of integer
7320: 73 20 6f 75 74 70 75 74 20 62 79 20 63 41 72 67  s output by cArg
7330: 20 2a 2f 0a 0a 20 20 73 77 69 74 63 68 28 20 63   */..  switch( c
7340: 41 72 67 20 29 7b 0a 20 20 20 20 63 61 73 65 20  Arg ){.    case 
7350: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e  FTS3_MATCHINFO_N
7360: 44 4f 43 3a 0a 20 20 20 20 63 61 73 65 20 46 54  DOC:.    case FT
7370: 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e 50 48  S3_MATCHINFO_NPH
7380: 52 41 53 45 3a 20 0a 20 20 20 20 63 61 73 65 20  RASE: .    case 
7390: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e  FTS3_MATCHINFO_N
73a0: 43 4f 4c 3a 20 0a 20 20 20 20 20 20 6e 56 61 6c  COL: .      nVal
73b0: 20 3d 20 31 3b 0a 20 20 20 20 20 20 62 72 65 61   = 1;.      brea
73c0: 6b 3b 0a 0a 20 20 20 20 63 61 73 65 20 46 54 53  k;..    case FTS
73d0: 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 41 56 47 4c  3_MATCHINFO_AVGL
73e0: 45 4e 47 54 48 3a 0a 20 20 20 20 63 61 73 65 20  ENGTH:.    case 
73f0: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c  FTS3_MATCHINFO_L
7400: 45 4e 47 54 48 3a 0a 20 20 20 20 63 61 73 65 20  ENGTH:.    case 
7410: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c  FTS3_MATCHINFO_L
7420: 43 53 3a 0a 20 20 20 20 20 20 6e 56 61 6c 20 3d  CS:.      nVal =
7430: 20 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 3b 0a 20 20   pInfo->nCol;.  
7440: 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20      break;..    
7450: 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 61  default:.      a
7460: 73 73 65 72 74 28 20 63 41 72 67 3d 3d 46 54 53  ssert( cArg==FTS
7470: 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 48 49 54 53  3_MATCHINFO_HITS
7480: 20 29 3b 0a 20 20 20 20 20 20 6e 56 61 6c 20 3d   );.      nVal =
7490: 20 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 20 2a 20 70   pInfo->nCol * p
74a0: 49 6e 66 6f 2d 3e 6e 50 68 72 61 73 65 20 2a 20  Info->nPhrase * 
74b0: 33 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  3;.      break;.
74c0: 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 6e 56    }..  return nV
74d0: 61 6c 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e  al;.}..static in
74e0: 74 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 53  t fts3MatchinfoS
74f0: 65 6c 65 63 74 44 6f 63 74 6f 74 61 6c 28 0a 20  electDoctotal(. 
7500: 20 46 74 73 33 54 61 62 6c 65 20 2a 70 54 61 62   Fts3Table *pTab
7510: 2c 0a 20 20 73 71 6c 69 74 65 33 5f 73 74 6d 74  ,.  sqlite3_stmt
7520: 20 2a 2a 70 70 53 74 6d 74 2c 0a 20 20 73 71 6c   **ppStmt,.  sql
7530: 69 74 65 33 5f 69 6e 74 36 34 20 2a 70 6e 44 6f  ite3_int64 *pnDo
7540: 63 2c 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  c,.  const char 
7550: 2a 2a 70 61 4c 65 6e 0a 29 7b 0a 20 20 73 71 6c  **paLen.){.  sql
7560: 69 74 65 33 5f 73 74 6d 74 20 2a 70 53 74 6d 74  ite3_stmt *pStmt
7570: 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  ;.  const char *
7580: 61 3b 0a 20 20 73 71 6c 69 74 65 33 5f 69 6e 74  a;.  sqlite3_int
7590: 36 34 20 6e 44 6f 63 3b 0a 0a 20 20 69 66 28 20  64 nDoc;..  if( 
75a0: 21 2a 70 70 53 74 6d 74 20 29 7b 0a 20 20 20 20  !*ppStmt ){.    
75b0: 69 6e 74 20 72 63 20 3d 20 73 71 6c 69 74 65 33  int rc = sqlite3
75c0: 46 74 73 33 53 65 6c 65 63 74 44 6f 63 74 6f 74  Fts3SelectDoctot
75d0: 61 6c 28 70 54 61 62 2c 20 70 70 53 74 6d 74 29  al(pTab, ppStmt)
75e0: 3b 0a 20 20 20 20 69 66 28 20 72 63 21 3d 53 51  ;.    if( rc!=SQ
75f0: 4c 49 54 45 5f 4f 4b 20 29 20 72 65 74 75 72 6e  LITE_OK ) return
7600: 20 72 63 3b 0a 20 20 7d 0a 20 20 70 53 74 6d 74   rc;.  }.  pStmt
7610: 20 3d 20 2a 70 70 53 74 6d 74 3b 0a 20 20 61 73   = *ppStmt;.  as
7620: 73 65 72 74 28 20 73 71 6c 69 74 65 33 5f 64 61  sert( sqlite3_da
7630: 74 61 5f 63 6f 75 6e 74 28 70 53 74 6d 74 29 3d  ta_count(pStmt)=
7640: 3d 31 20 29 3b 0a 0a 20 20 61 20 3d 20 73 71 6c  =1 );..  a = sql
7650: 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f 62 6c 6f 62  ite3_column_blob
7660: 28 70 53 74 6d 74 2c 20 30 29 3b 0a 20 20 61 20  (pStmt, 0);.  a 
7670: 2b 3d 20 73 71 6c 69 74 65 33 46 74 73 33 47 65  += sqlite3Fts3Ge
7680: 74 56 61 72 69 6e 74 28 61 2c 20 26 6e 44 6f 63  tVarint(a, &nDoc
7690: 29 3b 0a 20 20 69 66 28 20 6e 44 6f 63 3d 3d 30  );.  if( nDoc==0
76a0: 20 29 20 72 65 74 75 72 6e 20 46 54 53 5f 43 4f   ) return FTS_CO
76b0: 52 52 55 50 54 5f 56 54 41 42 3b 0a 20 20 2a 70  RRUPT_VTAB;.  *p
76c0: 6e 44 6f 63 20 3d 20 28 75 33 32 29 6e 44 6f 63  nDoc = (u32)nDoc
76d0: 3b 0a 0a 20 20 69 66 28 20 70 61 4c 65 6e 20 29  ;..  if( paLen )
76e0: 20 2a 70 61 4c 65 6e 20 3d 20 61 3b 0a 20 20 72   *paLen = a;.  r
76f0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b  eturn SQLITE_OK;
7700: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 6e 20 69 6e 73  .}../*.** An ins
7710: 74 61 6e 63 65 20 6f 66 20 74 68 65 20 66 6f 6c  tance of the fol
7720: 6c 6f 77 69 6e 67 20 73 74 72 75 63 74 75 72 65  lowing structure
7730: 20 69 73 20 75 73 65 64 20 74 6f 20 73 74 6f 72   is used to stor
7740: 65 20 73 74 61 74 65 20 77 68 69 6c 65 20 0a 2a  e state while .*
7750: 2a 20 69 74 65 72 61 74 69 6e 67 20 74 68 72 6f  * iterating thro
7760: 75 67 68 20 61 20 6d 75 6c 74 69 2d 63 6f 6c 75  ugh a multi-colu
7770: 6d 6e 20 70 6f 73 69 74 69 6f 6e 2d 6c 69 73 74  mn position-list
7780: 20 63 6f 72 72 65 73 70 6f 6e 64 69 6e 67 20 74   corresponding t
7790: 6f 20 74 68 65 0a 2a 2a 20 68 69 74 73 20 66 6f  o the.** hits fo
77a0: 72 20 61 20 73 69 6e 67 6c 65 20 70 68 72 61 73  r a single phras
77b0: 65 20 6f 6e 20 61 20 73 69 6e 67 6c 65 20 72 6f  e on a single ro
77c0: 77 20 69 6e 20 6f 72 64 65 72 20 74 6f 20 63 61  w in order to ca
77d0: 6c 63 75 6c 61 74 65 20 74 68 65 0a 2a 2a 20 76  lculate the.** v
77e0: 61 6c 75 65 73 20 66 6f 72 20 61 20 6d 61 74 63  alues for a matc
77f0: 68 69 6e 66 6f 28 29 20 46 54 53 33 5f 4d 41 54  hinfo() FTS3_MAT
7800: 43 48 49 4e 46 4f 5f 4c 43 53 20 72 65 71 75 65  CHINFO_LCS reque
7810: 73 74 2e 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73  st..*/.typedef s
7820: 74 72 75 63 74 20 4c 63 73 49 74 65 72 61 74 6f  truct LcsIterato
7830: 72 20 4c 63 73 49 74 65 72 61 74 6f 72 3b 0a 73  r LcsIterator;.s
7840: 74 72 75 63 74 20 4c 63 73 49 74 65 72 61 74 6f  truct LcsIterato
7850: 72 20 7b 0a 20 20 46 74 73 33 45 78 70 72 20 2a  r {.  Fts3Expr *
7860: 70 45 78 70 72 3b 20 20 20 20 20 20 20 20 20 20  pExpr;          
7870: 20 20 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65 72        /* Pointer
7880: 20 74 6f 20 70 68 72 61 73 65 20 65 78 70 72 65   to phrase expre
7890: 73 73 69 6f 6e 20 2a 2f 0a 20 20 69 6e 74 20 69  ssion */.  int i
78a0: 50 6f 73 4f 66 66 73 65 74 3b 20 20 20 20 20 20  PosOffset;      
78b0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 6f             /* To
78c0: 6b 65 6e 73 20 63 6f 75 6e 74 20 75 70 20 74 6f  kens count up to
78d0: 20 65 6e 64 20 6f 66 20 74 68 69 73 20 70 68 72   end of this phr
78e0: 61 73 65 20 2a 2f 0a 20 20 63 68 61 72 20 2a 70  ase */.  char *p
78f0: 52 65 61 64 3b 20 20 20 20 20 20 20 20 20 20 20  Read;           
7900: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 75 72 73           /* Curs
7910: 6f 72 20 75 73 65 64 20 74 6f 20 69 74 65 72 61  or used to itera
7920: 74 65 20 74 68 72 6f 75 67 68 20 61 44 6f 63 6c  te through aDocl
7930: 69 73 74 20 2a 2f 0a 20 20 69 6e 74 20 69 50 6f  ist */.  int iPo
7940: 73 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s;              
7950: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 75 72 72           /* Curr
7960: 65 6e 74 20 70 6f 73 69 74 69 6f 6e 20 2a 2f 0a  ent position */.
7970: 7d 3b 0a 0a 2f 2a 20 0a 2a 2a 20 49 66 20 4c 63  };../* .** If Lc
7980: 73 49 74 65 72 61 74 6f 72 2e 69 43 6f 6c 20 69  sIterator.iCol i
7990: 73 20 73 65 74 20 74 6f 20 74 68 65 20 66 6f 6c  s set to the fol
79a0: 6c 6f 77 69 6e 67 20 76 61 6c 75 65 2c 20 74 68  lowing value, th
79b0: 65 20 69 74 65 72 61 74 6f 72 20 68 61 73 0a 2a  e iterator has.*
79c0: 2a 20 66 69 6e 69 73 68 65 64 20 69 74 65 72 61  * finished itera
79d0: 74 69 6e 67 20 74 68 72 6f 75 67 68 20 61 6c 6c  ting through all
79e0: 20 6f 66 66 73 65 74 73 20 66 6f 72 20 61 6c 6c   offsets for all
79f0: 20 63 6f 6c 75 6d 6e 73 2e 0a 2a 2f 0a 23 64 65   columns..*/.#de
7a00: 66 69 6e 65 20 4c 43 53 5f 49 54 45 52 41 54 4f  fine LCS_ITERATO
7a10: 52 5f 46 49 4e 49 53 48 45 44 20 30 78 37 46 46  R_FINISHED 0x7FF
7a20: 46 46 46 46 46 3b 0a 0a 73 74 61 74 69 63 20 69  FFFFF;..static i
7a30: 6e 74 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f  nt fts3Matchinfo
7a40: 4c 63 73 43 62 28 0a 20 20 46 74 73 33 45 78 70  LcsCb(.  Fts3Exp
7a50: 72 20 2a 70 45 78 70 72 2c 20 20 20 20 20 20 20  r *pExpr,       
7a60: 20 20 20 20 20 20 20 20 20 2f 2a 20 50 68 72 61           /* Phra
7a70: 73 65 20 65 78 70 72 65 73 73 69 6f 6e 20 6e 6f  se expression no
7a80: 64 65 20 2a 2f 0a 20 20 69 6e 74 20 69 50 68 72  de */.  int iPhr
7a90: 61 73 65 2c 20 20 20 20 20 20 20 20 20 20 20 20  ase,            
7aa0: 20 20 20 20 20 20 20 20 2f 2a 20 50 68 72 61 73          /* Phras
7ab0: 65 20 6e 75 6d 62 65 72 20 28 6e 75 6d 62 65 72  e number (number
7ac0: 65 64 20 66 72 6f 6d 20 7a 65 72 6f 29 20 2a 2f  ed from zero) */
7ad0: 0a 20 20 76 6f 69 64 20 2a 70 43 74 78 20 20 20  .  void *pCtx   
7ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7af0: 20 20 20 2f 2a 20 50 6f 69 6e 74 65 72 20 74 6f     /* Pointer to
7b00: 20 4d 61 74 63 68 49 6e 66 6f 20 73 74 72 75 63   MatchInfo struc
7b10: 74 75 72 65 20 2a 2f 0a 29 7b 0a 20 20 4c 63 73  ture */.){.  Lcs
7b20: 49 74 65 72 61 74 6f 72 20 2a 61 49 74 65 72 20  Iterator *aIter 
7b30: 3d 20 28 4c 63 73 49 74 65 72 61 74 6f 72 20 2a  = (LcsIterator *
7b40: 29 70 43 74 78 3b 0a 20 20 61 49 74 65 72 5b 69  )pCtx;.  aIter[i
7b50: 50 68 72 61 73 65 5d 2e 70 45 78 70 72 20 3d 20  Phrase].pExpr = 
7b60: 70 45 78 70 72 3b 0a 20 20 72 65 74 75 72 6e 20  pExpr;.  return 
7b70: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  SQLITE_OK;.}../*
7b80: 0a 2a 2a 20 41 64 76 61 6e 63 65 20 74 68 65 20  .** Advance the 
7b90: 69 74 65 72 61 74 6f 72 20 70 61 73 73 65 64 20  iterator passed 
7ba0: 61 73 20 61 6e 20 61 72 67 75 6d 65 6e 74 20 74  as an argument t
7bb0: 6f 20 74 68 65 20 6e 65 78 74 20 70 6f 73 69 74  o the next posit
7bc0: 69 6f 6e 2e 20 52 65 74 75 72 6e 0a 2a 2a 20 31  ion. Return.** 1
7bd0: 20 69 66 20 74 68 65 20 69 74 65 72 61 74 6f 72   if the iterator
7be0: 20 69 73 20 61 74 20 45 4f 46 20 6f 72 20 69 66   is at EOF or if
7bf0: 20 69 74 20 6e 6f 77 20 70 6f 69 6e 74 73 20 74   it now points t
7c00: 6f 20 74 68 65 20 73 74 61 72 74 20 6f 66 20 74  o the start of t
7c10: 68 65 0a 2a 2a 20 70 6f 73 69 74 69 6f 6e 20 6c  he.** position l
7c20: 69 73 74 20 66 6f 72 20 74 68 65 20 6e 65 78 74  ist for the next
7c30: 20 63 6f 6c 75 6d 6e 2e 0a 2a 2f 0a 73 74 61 74   column..*/.stat
7c40: 69 63 20 69 6e 74 20 66 74 73 33 4c 63 73 49 74  ic int fts3LcsIt
7c50: 65 72 61 74 6f 72 41 64 76 61 6e 63 65 28 4c 63  eratorAdvance(Lc
7c60: 73 49 74 65 72 61 74 6f 72 20 2a 70 49 74 65 72  sIterator *pIter
7c70: 29 7b 0a 20 20 63 68 61 72 20 2a 70 52 65 61 64  ){.  char *pRead
7c80: 20 3d 20 70 49 74 65 72 2d 3e 70 52 65 61 64 3b   = pIter->pRead;
7c90: 0a 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34  .  sqlite3_int64
7ca0: 20 69 52 65 61 64 3b 0a 20 20 69 6e 74 20 72 63   iRead;.  int rc
7cb0: 20 3d 20 30 3b 0a 0a 20 20 70 52 65 61 64 20 2b   = 0;..  pRead +
7cc0: 3d 20 73 71 6c 69 74 65 33 46 74 73 33 47 65 74  = sqlite3Fts3Get
7cd0: 56 61 72 69 6e 74 28 70 52 65 61 64 2c 20 26 69  Varint(pRead, &i
7ce0: 52 65 61 64 29 3b 0a 20 20 69 66 28 20 69 52 65  Read);.  if( iRe
7cf0: 61 64 3d 3d 30 20 7c 7c 20 69 52 65 61 64 3d 3d  ad==0 || iRead==
7d00: 31 20 29 7b 0a 20 20 20 20 70 52 65 61 64 20 3d  1 ){.    pRead =
7d10: 20 30 3b 0a 20 20 20 20 72 63 20 3d 20 31 3b 0a   0;.    rc = 1;.
7d20: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 70 49 74    }else{.    pIt
7d30: 65 72 2d 3e 69 50 6f 73 20 2b 3d 20 28 69 6e 74  er->iPos += (int
7d40: 29 28 69 52 65 61 64 2d 32 29 3b 0a 20 20 7d 0a  )(iRead-2);.  }.
7d50: 0a 20 20 70 49 74 65 72 2d 3e 70 52 65 61 64 20  .  pIter->pRead 
7d60: 3d 20 70 52 65 61 64 3b 0a 20 20 72 65 74 75 72  = pRead;.  retur
7d70: 6e 20 72 63 3b 0a 7d 0a 20 20 0a 2f 2a 0a 2a 2a  n rc;.}.  ./*.**
7d80: 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 69   This function i
7d90: 6d 70 6c 65 6d 65 6e 74 73 20 74 68 65 20 46 54  mplements the FT
7da0: 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c 43 53  S3_MATCHINFO_LCS
7db0: 20 6d 61 74 63 68 69 6e 66 6f 28 29 20 66 6c 61   matchinfo() fla
7dc0: 67 2e 20 0a 2a 2a 0a 2a 2a 20 49 66 20 74 68 65  g. .**.** If the
7dd0: 20 63 61 6c 6c 20 69 73 20 73 75 63 63 65 73 73   call is success
7de0: 66 75 6c 2c 20 74 68 65 20 6c 6f 6e 67 65 73 74  ful, the longest
7df0: 2d 63 6f 6d 6d 6f 6e 2d 73 75 62 73 74 72 69 6e  -common-substrin
7e00: 67 20 6c 65 6e 67 74 68 73 20 66 6f 72 20 65 61  g lengths for ea
7e10: 63 68 0a 2a 2a 20 63 6f 6c 75 6d 6e 20 61 72 65  ch.** column are
7e20: 20 77 72 69 74 74 65 6e 20 69 6e 74 6f 20 74 68   written into th
7e30: 65 20 66 69 72 73 74 20 6e 43 6f 6c 20 65 6c 65  e first nCol ele
7e40: 6d 65 6e 74 73 20 6f 66 20 74 68 65 20 70 49 6e  ments of the pIn
7e50: 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 5d  fo->aMatchinfo[]
7e60: 20 0a 2a 2a 20 61 72 72 61 79 20 62 65 66 6f 72   .** array befor
7e70: 65 20 72 65 74 75 72 6e 69 6e 67 2e 20 53 51 4c  e returning. SQL
7e80: 49 54 45 5f 4f 4b 20 69 73 20 72 65 74 75 72 6e  ITE_OK is return
7e90: 65 64 20 69 6e 20 74 68 69 73 20 63 61 73 65 2e  ed in this case.
7ea0: 0a 2a 2a 0a 2a 2a 20 4f 74 68 65 72 77 69 73 65  .**.** Otherwise
7eb0: 2c 20 69 66 20 61 6e 20 65 72 72 6f 72 20 6f 63  , if an error oc
7ec0: 63 75 72 73 2c 20 61 6e 20 53 51 4c 69 74 65 20  curs, an SQLite 
7ed0: 65 72 72 6f 72 20 63 6f 64 65 20 69 73 20 72 65  error code is re
7ee0: 74 75 72 6e 65 64 20 61 6e 64 20 74 68 65 0a 2a  turned and the.*
7ef0: 2a 20 64 61 74 61 20 77 72 69 74 74 65 6e 20 74  * data written t
7f00: 6f 20 74 68 65 20 66 69 72 73 74 20 6e 43 6f 6c  o the first nCol
7f10: 20 65 6c 65 6d 65 6e 74 73 20 6f 66 20 70 49 6e   elements of pIn
7f20: 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 5d  fo->aMatchinfo[]
7f30: 20 69 73 20 0a 2a 2a 20 75 6e 64 65 66 69 6e 65   is .** undefine
7f40: 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  d..*/.static int
7f50: 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 4c 63   fts3MatchinfoLc
7f60: 73 28 46 74 73 33 43 75 72 73 6f 72 20 2a 70 43  s(Fts3Cursor *pC
7f70: 73 72 2c 20 4d 61 74 63 68 49 6e 66 6f 20 2a 70  sr, MatchInfo *p
7f80: 49 6e 66 6f 29 7b 0a 20 20 4c 63 73 49 74 65 72  Info){.  LcsIter
7f90: 61 74 6f 72 20 2a 61 49 74 65 72 3b 0a 20 20 69  ator *aIter;.  i
7fa0: 6e 74 20 69 3b 0a 20 20 69 6e 74 20 69 43 6f 6c  nt i;.  int iCol
7fb0: 3b 0a 20 20 69 6e 74 20 6e 54 6f 6b 65 6e 20 3d  ;.  int nToken =
7fc0: 20 30 3b 0a 0a 20 20 2f 2a 20 41 6c 6c 6f 63 61   0;..  /* Alloca
7fd0: 74 65 20 61 6e 64 20 70 6f 70 75 6c 61 74 65 20  te and populate 
7fe0: 74 68 65 20 61 72 72 61 79 20 6f 66 20 4c 63 73  the array of Lcs
7ff0: 49 74 65 72 61 74 6f 72 20 6f 62 6a 65 63 74 73  Iterator objects
8000: 2e 20 54 68 65 20 61 72 72 61 79 0a 20 20 2a 2a  . The array.  **
8010: 20 63 6f 6e 74 61 69 6e 73 20 6f 6e 65 20 65 6c   contains one el
8020: 65 6d 65 6e 74 20 66 6f 72 20 65 61 63 68 20 6d  ement for each m
8030: 61 74 63 68 61 62 6c 65 20 70 68 72 61 73 65 20  atchable phrase 
8040: 69 6e 20 74 68 65 20 71 75 65 72 79 2e 0a 20 20  in the query..  
8050: 2a 2a 2f 0a 20 20 61 49 74 65 72 20 3d 20 73 71  **/.  aIter = sq
8060: 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 73 69 7a  lite3_malloc(siz
8070: 65 6f 66 28 4c 63 73 49 74 65 72 61 74 6f 72 29  eof(LcsIterator)
8080: 20 2a 20 70 43 73 72 2d 3e 6e 50 68 72 61 73 65   * pCsr->nPhrase
8090: 29 3b 0a 20 20 69 66 28 20 21 61 49 74 65 72 20  );.  if( !aIter 
80a0: 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f  ) return SQLITE_
80b0: 4e 4f 4d 45 4d 3b 0a 20 20 6d 65 6d 73 65 74 28  NOMEM;.  memset(
80c0: 61 49 74 65 72 2c 20 30 2c 20 73 69 7a 65 6f 66  aIter, 0, sizeof
80d0: 28 4c 63 73 49 74 65 72 61 74 6f 72 29 20 2a 20  (LcsIterator) * 
80e0: 70 43 73 72 2d 3e 6e 50 68 72 61 73 65 29 3b 0a  pCsr->nPhrase);.
80f0: 20 20 28 76 6f 69 64 29 66 74 73 33 45 78 70 72    (void)fts3Expr
8100: 49 74 65 72 61 74 65 28 70 43 73 72 2d 3e 70 45  Iterate(pCsr->pE
8110: 78 70 72 2c 20 66 74 73 33 4d 61 74 63 68 69 6e  xpr, fts3Matchin
8120: 66 6f 4c 63 73 43 62 2c 20 28 76 6f 69 64 2a 29  foLcsCb, (void*)
8130: 61 49 74 65 72 29 3b 0a 0a 20 20 66 6f 72 28 69  aIter);..  for(i
8140: 3d 30 3b 20 69 3c 70 49 6e 66 6f 2d 3e 6e 50 68  =0; i<pInfo->nPh
8150: 72 61 73 65 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  rase; i++){.    
8160: 4c 63 73 49 74 65 72 61 74 6f 72 20 2a 70 49 74  LcsIterator *pIt
8170: 65 72 20 3d 20 26 61 49 74 65 72 5b 69 5d 3b 0a  er = &aIter[i];.
8180: 20 20 20 20 6e 54 6f 6b 65 6e 20 2d 3d 20 70 49      nToken -= pI
8190: 74 65 72 2d 3e 70 45 78 70 72 2d 3e 70 50 68 72  ter->pExpr->pPhr
81a0: 61 73 65 2d 3e 6e 54 6f 6b 65 6e 3b 0a 20 20 20  ase->nToken;.   
81b0: 20 70 49 74 65 72 2d 3e 69 50 6f 73 4f 66 66 73   pIter->iPosOffs
81c0: 65 74 20 3d 20 6e 54 6f 6b 65 6e 3b 0a 20 20 7d  et = nToken;.  }
81d0: 0a 0a 20 20 66 6f 72 28 69 43 6f 6c 3d 30 3b 20  ..  for(iCol=0; 
81e0: 69 43 6f 6c 3c 70 49 6e 66 6f 2d 3e 6e 43 6f 6c  iCol<pInfo->nCol
81f0: 3b 20 69 43 6f 6c 2b 2b 29 7b 0a 20 20 20 20 69  ; iCol++){.    i
8200: 6e 74 20 6e 4c 63 73 20 3d 20 30 3b 20 20 20 20  nt nLcs = 0;    
8210: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
8220: 4c 43 53 20 76 61 6c 75 65 20 66 6f 72 20 74 68  LCS value for th
8230: 69 73 20 63 6f 6c 75 6d 6e 20 2a 2f 0a 20 20 20  is column */.   
8240: 20 69 6e 74 20 6e 4c 69 76 65 20 3d 20 30 3b 20   int nLive = 0; 
8250: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
8260: 2a 20 4e 75 6d 62 65 72 20 6f 66 20 69 74 65 72  * Number of iter
8270: 61 74 6f 72 73 20 69 6e 20 61 49 74 65 72 20 6e  ators in aIter n
8280: 6f 74 20 61 74 20 45 4f 46 20 2a 2f 0a 0a 20 20  ot at EOF */..  
8290: 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70 49 6e    for(i=0; i<pIn
82a0: 66 6f 2d 3e 6e 50 68 72 61 73 65 3b 20 69 2b 2b  fo->nPhrase; i++
82b0: 29 7b 0a 20 20 20 20 20 20 69 6e 74 20 72 63 3b  ){.      int rc;
82c0: 0a 20 20 20 20 20 20 4c 63 73 49 74 65 72 61 74  .      LcsIterat
82d0: 6f 72 20 2a 70 49 74 20 3d 20 26 61 49 74 65 72  or *pIt = &aIter
82e0: 5b 69 5d 3b 0a 20 20 20 20 20 20 72 63 20 3d 20  [i];.      rc = 
82f0: 73 71 6c 69 74 65 33 46 74 73 33 45 76 61 6c 50  sqlite3Fts3EvalP
8300: 68 72 61 73 65 50 6f 73 6c 69 73 74 28 70 43 73  hrasePoslist(pCs
8310: 72 2c 20 70 49 74 2d 3e 70 45 78 70 72 2c 20 69  r, pIt->pExpr, i
8320: 43 6f 6c 2c 20 26 70 49 74 2d 3e 70 52 65 61 64  Col, &pIt->pRead
8330: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 21  );.      if( rc!
8340: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 65 74  =SQLITE_OK ) ret
8350: 75 72 6e 20 72 63 3b 0a 20 20 20 20 20 20 69 66  urn rc;.      if
8360: 28 20 70 49 74 2d 3e 70 52 65 61 64 20 29 7b 0a  ( pIt->pRead ){.
8370: 20 20 20 20 20 20 20 20 70 49 74 2d 3e 69 50 6f          pIt->iPo
8380: 73 20 3d 20 70 49 74 2d 3e 69 50 6f 73 4f 66 66  s = pIt->iPosOff
8390: 73 65 74 3b 0a 20 20 20 20 20 20 20 20 66 74 73  set;.        fts
83a0: 33 4c 63 73 49 74 65 72 61 74 6f 72 41 64 76 61  3LcsIteratorAdva
83b0: 6e 63 65 28 26 61 49 74 65 72 5b 69 5d 29 3b 0a  nce(&aIter[i]);.
83c0: 20 20 20 20 20 20 20 20 6e 4c 69 76 65 2b 2b 3b          nLive++;
83d0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a  .      }.    }..
83e0: 20 20 20 20 77 68 69 6c 65 28 20 6e 4c 69 76 65      while( nLive
83f0: 3e 30 20 29 7b 0a 20 20 20 20 20 20 4c 63 73 49  >0 ){.      LcsI
8400: 74 65 72 61 74 6f 72 20 2a 70 41 64 76 20 3d 20  terator *pAdv = 
8410: 30 3b 20 20 20 20 20 20 2f 2a 20 54 68 65 20 69  0;      /* The i
8420: 74 65 72 61 74 6f 72 20 74 6f 20 61 64 76 61 6e  terator to advan
8430: 63 65 20 62 79 20 6f 6e 65 20 70 6f 73 69 74 69  ce by one positi
8440: 6f 6e 20 2a 2f 0a 20 20 20 20 20 20 69 6e 74 20  on */.      int 
8450: 6e 54 68 69 73 4c 63 73 20 3d 20 30 3b 20 20 20  nThisLcs = 0;   
8460: 20 20 20 20 20 20 20 20 2f 2a 20 4c 43 53 20 66          /* LCS f
8470: 6f 72 20 74 68 65 20 63 75 72 72 65 6e 74 20 69  or the current i
8480: 74 65 72 61 74 6f 72 20 70 6f 73 69 74 69 6f 6e  terator position
8490: 73 20 2a 2f 0a 0a 20 20 20 20 20 20 66 6f 72 28  s */..      for(
84a0: 69 3d 30 3b 20 69 3c 70 49 6e 66 6f 2d 3e 6e 50  i=0; i<pInfo->nP
84b0: 68 72 61 73 65 3b 20 69 2b 2b 29 7b 0a 20 20 20  hrase; i++){.   
84c0: 20 20 20 20 20 4c 63 73 49 74 65 72 61 74 6f 72       LcsIterator
84d0: 20 2a 70 49 74 65 72 20 3d 20 26 61 49 74 65 72   *pIter = &aIter
84e0: 5b 69 5d 3b 0a 20 20 20 20 20 20 20 20 69 66 28  [i];.        if(
84f0: 20 70 49 74 65 72 2d 3e 70 52 65 61 64 3d 3d 30   pIter->pRead==0
8500: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 2f 2a   ){.          /*
8510: 20 54 68 69 73 20 69 74 65 72 61 74 6f 72 20 69   This iterator i
8520: 73 20 61 6c 72 65 61 64 79 20 61 74 20 45 4f 46  s already at EOF
8530: 20 66 6f 72 20 74 68 69 73 20 63 6f 6c 75 6d 6e   for this column
8540: 2e 20 2a 2f 0a 20 20 20 20 20 20 20 20 20 20 6e  . */.          n
8550: 54 68 69 73 4c 63 73 20 3d 20 30 3b 0a 20 20 20  ThisLcs = 0;.   
8560: 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20       }else{.    
8570: 20 20 20 20 20 20 69 66 28 20 70 41 64 76 3d 3d        if( pAdv==
8580: 30 20 7c 7c 20 70 49 74 65 72 2d 3e 69 50 6f 73  0 || pIter->iPos
8590: 3c 70 41 64 76 2d 3e 69 50 6f 73 20 29 7b 0a 20  <pAdv->iPos ){. 
85a0: 20 20 20 20 20 20 20 20 20 20 20 70 41 64 76 20             pAdv 
85b0: 3d 20 70 49 74 65 72 3b 0a 20 20 20 20 20 20 20  = pIter;.       
85c0: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20 20 69     }.          i
85d0: 66 28 20 6e 54 68 69 73 4c 63 73 3d 3d 30 20 7c  f( nThisLcs==0 |
85e0: 7c 20 70 49 74 65 72 2d 3e 69 50 6f 73 3d 3d 70  | pIter->iPos==p
85f0: 49 74 65 72 5b 2d 31 5d 2e 69 50 6f 73 20 29 7b  Iter[-1].iPos ){
8600: 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 68  .            nTh
8610: 69 73 4c 63 73 2b 2b 3b 0a 20 20 20 20 20 20 20  isLcs++;.       
8620: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
8630: 20 20 20 20 20 20 6e 54 68 69 73 4c 63 73 20 3d        nThisLcs =
8640: 20 31 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a   1;.          }.
8650: 20 20 20 20 20 20 20 20 20 20 69 66 28 20 6e 54            if( nT
8660: 68 69 73 4c 63 73 3e 6e 4c 63 73 20 29 20 6e 4c  hisLcs>nLcs ) nL
8670: 63 73 20 3d 20 6e 54 68 69 73 4c 63 73 3b 0a 20  cs = nThisLcs;. 
8680: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d         }.      }
8690: 0a 20 20 20 20 20 20 69 66 28 20 66 74 73 33 4c  .      if( fts3L
86a0: 63 73 49 74 65 72 61 74 6f 72 41 64 76 61 6e 63  csIteratorAdvanc
86b0: 65 28 70 41 64 76 29 20 29 20 6e 4c 69 76 65 2d  e(pAdv) ) nLive-
86c0: 2d 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20 70 49  -;.    }..    pI
86d0: 6e 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b  nfo->aMatchinfo[
86e0: 69 43 6f 6c 5d 20 3d 20 6e 4c 63 73 3b 0a 20 20  iCol] = nLcs;.  
86f0: 7d 0a 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65  }..  sqlite3_fre
8700: 65 28 61 49 74 65 72 29 3b 0a 20 20 72 65 74 75  e(aIter);.  retu
8710: 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a  rn SQLITE_OK;.}.
8720: 0a 2f 2a 0a 2a 2a 20 50 6f 70 75 6c 61 74 65 20  ./*.** Populate 
8730: 74 68 65 20 62 75 66 66 65 72 20 70 49 6e 66 6f  the buffer pInfo
8740: 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 5d 20 77  ->aMatchinfo[] w
8750: 69 74 68 20 61 6e 20 61 72 72 61 79 20 6f 66 20  ith an array of 
8760: 69 6e 74 65 67 65 72 73 20 74 6f 0a 2a 2a 20 62  integers to.** b
8770: 65 20 72 65 74 75 72 6e 65 64 20 62 79 20 74 68  e returned by th
8780: 65 20 6d 61 74 63 68 69 6e 66 6f 28 29 20 66 75  e matchinfo() fu
8790: 6e 63 74 69 6f 6e 2e 20 41 72 67 75 6d 65 6e 74  nction. Argument
87a0: 20 7a 41 72 67 20 63 6f 6e 74 61 69 6e 73 20 74   zArg contains t
87b0: 68 65 20 0a 2a 2a 20 66 6f 72 6d 61 74 20 73 74  he .** format st
87c0: 72 69 6e 67 20 70 61 73 73 65 64 20 61 73 20 74  ring passed as t
87d0: 68 65 20 73 65 63 6f 6e 64 20 61 72 67 75 6d 65  he second argume
87e0: 6e 74 20 74 6f 20 6d 61 74 63 68 69 6e 66 6f 20  nt to matchinfo 
87f0: 28 6f 72 20 74 68 65 0a 2a 2a 20 64 65 66 61 75  (or the.** defau
8800: 6c 74 20 76 61 6c 75 65 20 22 70 63 78 22 20 69  lt value "pcx" i
8810: 66 20 6e 6f 20 73 65 63 6f 6e 64 20 61 72 67 75  f no second argu
8820: 6d 65 6e 74 20 77 61 73 20 73 70 65 63 69 66 69  ment was specifi
8830: 65 64 29 2e 20 54 68 65 20 66 6f 72 6d 61 74 0a  ed). The format.
8840: 2a 2a 20 73 74 72 69 6e 67 20 68 61 73 20 61 6c  ** string has al
8850: 72 65 61 64 79 20 62 65 65 6e 20 76 61 6c 69 64  ready been valid
8860: 61 74 65 64 20 61 6e 64 20 74 68 65 20 70 49 6e  ated and the pIn
8870: 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 5d  fo->aMatchinfo[]
8880: 20 61 72 72 61 79 0a 2a 2a 20 69 73 20 67 75 61   array.** is gua
8890: 72 61 6e 74 65 65 64 20 74 6f 20 62 65 20 6c 61  ranteed to be la
88a0: 72 67 65 20 65 6e 6f 75 67 68 20 66 6f 72 20 74  rge enough for t
88b0: 68 65 20 6f 75 74 70 75 74 2e 0a 2a 2a 0a 2a 2a  he output..**.**
88c0: 20 49 66 20 62 47 6c 6f 62 61 6c 20 69 73 20 74   If bGlobal is t
88d0: 72 75 65 2c 20 74 68 65 6e 20 70 6f 70 75 6c 61  rue, then popula
88e0: 74 65 20 61 6c 6c 20 66 69 65 6c 64 73 20 6f 66  te all fields of
88f0: 20 74 68 65 20 6d 61 74 63 68 69 6e 66 6f 28 29   the matchinfo()
8900: 20 6f 75 74 70 75 74 2e 0a 2a 2a 20 49 66 20 69   output..** If i
8910: 74 20 69 73 20 66 61 6c 73 65 2c 20 74 68 65 6e  t is false, then
8920: 20 61 73 73 75 6d 65 20 74 68 61 74 20 74 68 6f   assume that tho
8930: 73 65 20 66 69 65 6c 64 73 20 74 68 61 74 20 64  se fields that d
8940: 6f 20 6e 6f 74 20 63 68 61 6e 67 65 20 62 65 74  o not change bet
8950: 77 65 65 6e 0a 2a 2a 20 72 6f 77 73 20 28 69 2e  ween.** rows (i.
8960: 65 2e 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  e. FTS3_MATCHINF
8970: 4f 5f 4e 50 48 52 41 53 45 2c 20 4e 43 4f 4c 2c  O_NPHRASE, NCOL,
8980: 20 4e 44 4f 43 2c 20 41 56 47 4c 45 4e 47 54 48   NDOC, AVGLENGTH
8990: 20 61 6e 64 20 70 61 72 74 20 6f 66 20 48 49 54   and part of HIT
89a0: 53 29 0a 2a 2a 20 68 61 76 65 20 61 6c 72 65 61  S).** have alrea
89b0: 64 79 20 62 65 65 6e 20 70 6f 70 75 6c 61 74 65  dy been populate
89c0: 64 2e 0a 2a 2a 0a 2a 2a 20 52 65 74 75 72 6e 20  d..**.** Return 
89d0: 53 51 4c 49 54 45 5f 4f 4b 20 69 66 20 73 75 63  SQLITE_OK if suc
89e0: 63 65 73 73 66 75 6c 2c 20 6f 72 20 61 6e 20 53  cessful, or an S
89f0: 51 4c 69 74 65 20 65 72 72 6f 72 20 63 6f 64 65  QLite error code
8a00: 20 69 66 20 61 6e 20 65 72 72 6f 72 20 0a 2a 2a   if an error .**
8a10: 20 6f 63 63 75 72 73 2e 20 49 66 20 61 20 76 61   occurs. If a va
8a20: 6c 75 65 20 6f 74 68 65 72 20 74 68 61 6e 20 53  lue other than S
8a30: 51 4c 49 54 45 5f 4f 4b 20 69 73 20 72 65 74 75  QLITE_OK is retu
8a40: 72 6e 65 64 2c 20 74 68 65 20 73 74 61 74 65 20  rned, the state 
8a50: 74 68 65 0a 2a 2a 20 70 49 6e 66 6f 2d 3e 61 4d  the.** pInfo->aM
8a60: 61 74 63 68 69 6e 66 6f 5b 5d 20 62 75 66 66 65  atchinfo[] buffe
8a70: 72 20 69 73 20 6c 65 66 74 20 69 6e 20 69 73 20  r is left in is 
8a80: 75 6e 64 65 66 69 6e 65 64 2e 0a 2a 2f 0a 73 74  undefined..*/.st
8a90: 61 74 69 63 20 69 6e 74 20 66 74 73 33 4d 61 74  atic int fts3Mat
8aa0: 63 68 69 6e 66 6f 56 61 6c 75 65 73 28 0a 20 20  chinfoValues(.  
8ab0: 46 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72  Fts3Cursor *pCsr
8ac0: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
8ad0: 2f 2a 20 46 54 53 33 20 63 75 72 73 6f 72 20 6f  /* FTS3 cursor o
8ae0: 62 6a 65 63 74 20 2a 2f 0a 20 20 69 6e 74 20 62  bject */.  int b
8af0: 47 6c 6f 62 61 6c 2c 20 20 20 20 20 20 20 20 20  Global,         
8b00: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72             /* Tr
8b10: 75 65 20 74 6f 20 67 72 61 62 20 74 68 65 20 67  ue to grab the g
8b20: 6c 6f 62 61 6c 20 73 74 61 74 73 20 2a 2f 0a 20  lobal stats */. 
8b30: 20 4d 61 74 63 68 49 6e 66 6f 20 2a 70 49 6e 66   MatchInfo *pInf
8b40: 6f 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  o,              
8b50: 20 2f 2a 20 4d 61 74 63 68 69 6e 66 6f 20 63 6f   /* Matchinfo co
8b60: 6e 74 65 78 74 20 6f 62 6a 65 63 74 20 2a 2f 0a  ntext object */.
8b70: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 41    const char *zA
8b80: 72 67 20 20 20 20 20 20 20 20 20 20 20 20 20 20  rg              
8b90: 20 20 2f 2a 20 4d 61 74 63 68 69 6e 66 6f 20 66    /* Matchinfo f
8ba0: 6f 72 6d 61 74 20 73 74 72 69 6e 67 20 2a 2f 0a  ormat string */.
8bb0: 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51  ){.  int rc = SQ
8bc0: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20 69  LITE_OK;.  int i
8bd0: 3b 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a 70  ;.  Fts3Table *p
8be0: 54 61 62 20 3d 20 28 46 74 73 33 54 61 62 6c 65  Tab = (Fts3Table
8bf0: 20 2a 29 70 43 73 72 2d 3e 62 61 73 65 2e 70 56   *)pCsr->base.pV
8c00: 74 61 62 3b 0a 20 20 73 71 6c 69 74 65 33 5f 73  tab;.  sqlite3_s
8c10: 74 6d 74 20 2a 70 53 65 6c 65 63 74 20 3d 20 30  tmt *pSelect = 0
8c20: 3b 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 72 63  ;..  for(i=0; rc
8c30: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 7a  ==SQLITE_OK && z
8c40: 41 72 67 5b 69 5d 3b 20 69 2b 2b 29 7b 0a 0a 20  Arg[i]; i++){.. 
8c50: 20 20 20 73 77 69 74 63 68 28 20 7a 41 72 67 5b     switch( zArg[
8c60: 69 5d 20 29 7b 0a 20 20 20 20 20 20 63 61 73 65  i] ){.      case
8c70: 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f   FTS3_MATCHINFO_
8c80: 4e 50 48 52 41 53 45 3a 0a 20 20 20 20 20 20 20  NPHRASE:.       
8c90: 20 69 66 28 20 62 47 6c 6f 62 61 6c 20 29 20 70   if( bGlobal ) p
8ca0: 49 6e 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f  Info->aMatchinfo
8cb0: 5b 30 5d 20 3d 20 70 49 6e 66 6f 2d 3e 6e 50 68  [0] = pInfo->nPh
8cc0: 72 61 73 65 3b 0a 20 20 20 20 20 20 20 20 62 72  rase;.        br
8cd0: 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65  eak;..      case
8ce0: 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f   FTS3_MATCHINFO_
8cf0: 4e 43 4f 4c 3a 0a 20 20 20 20 20 20 20 20 69 66  NCOL:.        if
8d00: 28 20 62 47 6c 6f 62 61 6c 20 29 20 70 49 6e 66  ( bGlobal ) pInf
8d10: 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 30 5d  o->aMatchinfo[0]
8d20: 20 3d 20 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 3b 0a   = pInfo->nCol;.
8d30: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
8d40: 20 20 20 20 20 20 20 0a 20 20 20 20 20 20 63 61         .      ca
8d50: 73 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  se FTS3_MATCHINF
8d60: 4f 5f 4e 44 4f 43 3a 0a 20 20 20 20 20 20 20 20  O_NDOC:.        
8d70: 69 66 28 20 62 47 6c 6f 62 61 6c 20 29 7b 0a 20  if( bGlobal ){. 
8d80: 20 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33           sqlite3
8d90: 5f 69 6e 74 36 34 20 6e 44 6f 63 20 3d 20 30 3b  _int64 nDoc = 0;
8da0: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
8db0: 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 53 65 6c  fts3MatchinfoSel
8dc0: 65 63 74 44 6f 63 74 6f 74 61 6c 28 70 54 61 62  ectDoctotal(pTab
8dd0: 2c 20 26 70 53 65 6c 65 63 74 2c 20 26 6e 44 6f  , &pSelect, &nDo
8de0: 63 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20 20  c, 0);.         
8df0: 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63 68 69 6e   pInfo->aMatchin
8e00: 66 6f 5b 30 5d 20 3d 20 28 75 33 32 29 6e 44 6f  fo[0] = (u32)nDo
8e10: 63 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20  c;.        }.   
8e20: 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20       break;..   
8e30: 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54     case FTS3_MAT
8e40: 43 48 49 4e 46 4f 5f 41 56 47 4c 45 4e 47 54 48  CHINFO_AVGLENGTH
8e50: 3a 20 0a 20 20 20 20 20 20 20 20 69 66 28 20 62  : .        if( b
8e60: 47 6c 6f 62 61 6c 20 29 7b 0a 20 20 20 20 20 20  Global ){.      
8e70: 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36      sqlite3_int6
8e80: 34 20 6e 44 6f 63 3b 20 20 20 20 20 2f 2a 20 4e  4 nDoc;     /* N
8e90: 75 6d 62 65 72 20 6f 66 20 72 6f 77 73 20 69 6e  umber of rows in
8ea0: 20 74 61 62 6c 65 20 2a 2f 0a 20 20 20 20 20 20   table */.      
8eb0: 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a      const char *
8ec0: 61 3b 20 20 20 20 20 20 20 20 20 20 2f 2a 20 41  a;          /* A
8ed0: 67 67 72 65 67 61 74 65 20 63 6f 6c 75 6d 6e 20  ggregate column 
8ee0: 6c 65 6e 67 74 68 20 61 72 72 61 79 20 2a 2f 0a  length array */.
8ef0: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
8f00: 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 53 65 6c  fts3MatchinfoSel
8f10: 65 63 74 44 6f 63 74 6f 74 61 6c 28 70 54 61 62  ectDoctotal(pTab
8f20: 2c 20 26 70 53 65 6c 65 63 74 2c 20 26 6e 44 6f  , &pSelect, &nDo
8f30: 63 2c 20 26 61 29 3b 0a 20 20 20 20 20 20 20 20  c, &a);.        
8f40: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
8f50: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20  _OK ){.         
8f60: 20 20 20 69 6e 74 20 69 43 6f 6c 3b 0a 20 20 20     int iCol;.   
8f70: 20 20 20 20 20 20 20 20 20 66 6f 72 28 69 43 6f           for(iCo
8f80: 6c 3d 30 3b 20 69 43 6f 6c 3c 70 49 6e 66 6f 2d  l=0; iCol<pInfo-
8f90: 3e 6e 43 6f 6c 3b 20 69 43 6f 6c 2b 2b 29 7b 0a  >nCol; iCol++){.
8fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 75 33                u3
8fb0: 32 20 69 56 61 6c 3b 0a 20 20 20 20 20 20 20 20  2 iVal;.        
8fc0: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e        sqlite3_in
8fd0: 74 36 34 20 6e 54 6f 6b 65 6e 3b 0a 20 20 20 20  t64 nToken;.    
8fe0: 20 20 20 20 20 20 20 20 20 20 61 20 2b 3d 20 73            a += s
8ff0: 71 6c 69 74 65 33 46 74 73 33 47 65 74 56 61 72  qlite3Fts3GetVar
9000: 69 6e 74 28 61 2c 20 26 6e 54 6f 6b 65 6e 29 3b  int(a, &nToken);
9010: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69  .              i
9020: 56 61 6c 20 3d 20 28 75 33 32 29 28 28 28 75 33  Val = (u32)(((u3
9030: 32 29 28 6e 54 6f 6b 65 6e 26 30 78 66 66 66 66  2)(nToken&0xffff
9040: 66 66 66 66 29 2b 6e 44 6f 63 2f 32 29 2f 6e 44  ffff)+nDoc/2)/nD
9050: 6f 63 29 3b 0a 20 20 20 20 20 20 20 20 20 20 20  oc);.           
9060: 20 20 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63 68     pInfo->aMatch
9070: 69 6e 66 6f 5b 69 43 6f 6c 5d 20 3d 20 69 56 61  info[iCol] = iVa
9080: 6c 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20 7d  l;.            }
9090: 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20  .          }.   
90a0: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 62       }.        b
90b0: 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73  reak;..      cas
90c0: 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f  e FTS3_MATCHINFO
90d0: 5f 4c 45 4e 47 54 48 3a 20 7b 0a 20 20 20 20 20  _LENGTH: {.     
90e0: 20 20 20 73 71 6c 69 74 65 33 5f 73 74 6d 74 20     sqlite3_stmt 
90f0: 2a 70 53 65 6c 65 63 74 44 6f 63 73 69 7a 65 20  *pSelectDocsize 
9100: 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 72 63 20  = 0;.        rc 
9110: 3d 20 73 71 6c 69 74 65 33 46 74 73 33 53 65 6c  = sqlite3Fts3Sel
9120: 65 63 74 44 6f 63 73 69 7a 65 28 70 54 61 62 2c  ectDocsize(pTab,
9130: 20 70 43 73 72 2d 3e 69 50 72 65 76 49 64 2c 20   pCsr->iPrevId, 
9140: 26 70 53 65 6c 65 63 74 44 6f 63 73 69 7a 65 29  &pSelectDocsize)
9150: 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63  ;.        if( rc
9160: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20  ==SQLITE_OK ){. 
9170: 20 20 20 20 20 20 20 20 20 69 6e 74 20 69 43 6f           int iCo
9180: 6c 3b 0a 20 20 20 20 20 20 20 20 20 20 63 6f 6e  l;.          con
9190: 73 74 20 63 68 61 72 20 2a 61 20 3d 20 73 71 6c  st char *a = sql
91a0: 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f 62 6c 6f 62  ite3_column_blob
91b0: 28 70 53 65 6c 65 63 74 44 6f 63 73 69 7a 65 2c  (pSelectDocsize,
91c0: 20 30 29 3b 0a 20 20 20 20 20 20 20 20 20 20 66   0);.          f
91d0: 6f 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f 6c 3c  or(iCol=0; iCol<
91e0: 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 3b 20 69 43 6f  pInfo->nCol; iCo
91f0: 6c 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 20 20  l++){.          
9200: 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20    sqlite3_int64 
9210: 6e 54 6f 6b 65 6e 3b 0a 20 20 20 20 20 20 20 20  nToken;.        
9220: 20 20 20 20 61 20 2b 3d 20 73 71 6c 69 74 65 33      a += sqlite3
9230: 46 74 73 33 47 65 74 56 61 72 69 6e 74 28 61 2c  Fts3GetVarint(a,
9240: 20 26 6e 54 6f 6b 65 6e 29 3b 0a 20 20 20 20 20   &nToken);.     
9250: 20 20 20 20 20 20 20 70 49 6e 66 6f 2d 3e 61 4d         pInfo->aM
9260: 61 74 63 68 69 6e 66 6f 5b 69 43 6f 6c 5d 20 3d  atchinfo[iCol] =
9270: 20 28 75 33 32 29 6e 54 6f 6b 65 6e 3b 0a 20 20   (u32)nToken;.  
9280: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
9290: 20 20 7d 0a 20 20 20 20 20 20 20 20 73 71 6c 69    }.        sqli
92a0: 74 65 33 5f 72 65 73 65 74 28 70 53 65 6c 65 63  te3_reset(pSelec
92b0: 74 44 6f 63 73 69 7a 65 29 3b 0a 20 20 20 20 20  tDocsize);.     
92c0: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
92d0: 7d 0a 0a 20 20 20 20 20 20 63 61 73 65 20 46 54  }..      case FT
92e0: 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c 43 53  S3_MATCHINFO_LCS
92f0: 3a 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 66  :.        rc = f
9300: 74 73 33 45 78 70 72 4c 6f 61 64 44 6f 63 6c 69  ts3ExprLoadDocli
9310: 73 74 73 28 70 43 73 72 2c 20 30 2c 20 30 29 3b  sts(pCsr, 0, 0);
9320: 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63 3d  .        if( rc=
9330: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
9340: 20 20 20 20 20 20 20 20 72 63 20 3d 20 66 74 73          rc = fts
9350: 33 4d 61 74 63 68 69 6e 66 6f 4c 63 73 28 70 43  3MatchinfoLcs(pC
9360: 73 72 2c 20 70 49 6e 66 6f 29 3b 0a 20 20 20 20  sr, pInfo);.    
9370: 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 62 72      }.        br
9380: 65 61 6b 3b 0a 0a 20 20 20 20 20 20 64 65 66 61  eak;..      defa
9390: 75 6c 74 3a 20 7b 0a 20 20 20 20 20 20 20 20 46  ult: {.        F
93a0: 74 73 33 45 78 70 72 20 2a 70 45 78 70 72 3b 0a  ts3Expr *pExpr;.
93b0: 20 20 20 20 20 20 20 20 61 73 73 65 72 74 28 20          assert( 
93c0: 7a 41 72 67 5b 69 5d 3d 3d 46 54 53 33 5f 4d 41  zArg[i]==FTS3_MA
93d0: 54 43 48 49 4e 46 4f 5f 48 49 54 53 20 29 3b 0a  TCHINFO_HITS );.
93e0: 20 20 20 20 20 20 20 20 70 45 78 70 72 20 3d 20          pExpr = 
93f0: 70 43 73 72 2d 3e 70 45 78 70 72 3b 0a 20 20 20  pCsr->pExpr;.   
9400: 20 20 20 20 20 72 63 20 3d 20 66 74 73 33 45 78       rc = fts3Ex
9410: 70 72 4c 6f 61 64 44 6f 63 6c 69 73 74 73 28 70  prLoadDoclists(p
9420: 43 73 72 2c 20 30 2c 20 30 29 3b 0a 20 20 20 20  Csr, 0, 0);.    
9430: 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49      if( rc!=SQLI
9440: 54 45 5f 4f 4b 20 29 20 62 72 65 61 6b 3b 0a 20  TE_OK ) break;. 
9450: 20 20 20 20 20 20 20 69 66 28 20 62 47 6c 6f 62         if( bGlob
9460: 61 6c 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  al ){.          
9470: 69 66 28 20 70 43 73 72 2d 3e 70 44 65 66 65 72  if( pCsr->pDefer
9480: 72 65 64 20 29 7b 0a 20 20 20 20 20 20 20 20 20  red ){.         
9490: 20 20 20 72 63 20 3d 20 66 74 73 33 4d 61 74 63     rc = fts3Matc
94a0: 68 69 6e 66 6f 53 65 6c 65 63 74 44 6f 63 74 6f  hinfoSelectDocto
94b0: 74 61 6c 28 70 54 61 62 2c 20 26 70 53 65 6c 65  tal(pTab, &pSele
94c0: 63 74 2c 20 26 70 49 6e 66 6f 2d 3e 6e 44 6f 63  ct, &pInfo->nDoc
94d0: 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20 20 20  , 0);.          
94e0: 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45    if( rc!=SQLITE
94f0: 5f 4f 4b 20 29 20 62 72 65 61 6b 3b 0a 20 20 20  _OK ) break;.   
9500: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
9510: 20 20 20 72 63 20 3d 20 66 74 73 33 45 78 70 72     rc = fts3Expr
9520: 49 74 65 72 61 74 65 28 70 45 78 70 72 2c 20 66  Iterate(pExpr, f
9530: 74 73 33 45 78 70 72 47 6c 6f 62 61 6c 48 69 74  ts3ExprGlobalHit
9540: 73 43 62 2c 28 76 6f 69 64 2a 29 70 49 6e 66 6f  sCb,(void*)pInfo
9550: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 69 66 28  );.          if(
9560: 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29   rc!=SQLITE_OK )
9570: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20   break;.        
9580: 7d 0a 20 20 20 20 20 20 20 20 28 76 6f 69 64 29  }.        (void)
9590: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 28  fts3ExprIterate(
95a0: 70 45 78 70 72 2c 20 66 74 73 33 45 78 70 72 4c  pExpr, fts3ExprL
95b0: 6f 63 61 6c 48 69 74 73 43 62 2c 28 76 6f 69 64  ocalHitsCb,(void
95c0: 2a 29 70 49 6e 66 6f 29 3b 0a 20 20 20 20 20 20  *)pInfo);.      
95d0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d    break;.      }
95e0: 0a 20 20 20 20 7d 0a 0a 20 20 20 20 70 49 6e 66  .    }..    pInf
95f0: 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 20 2b 3d  o->aMatchinfo +=
9600: 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 53 69   fts3MatchinfoSi
9610: 7a 65 28 70 49 6e 66 6f 2c 20 7a 41 72 67 5b 69  ze(pInfo, zArg[i
9620: 5d 29 3b 0a 20 20 7d 0a 0a 20 20 73 71 6c 69 74  ]);.  }..  sqlit
9630: 65 33 5f 72 65 73 65 74 28 70 53 65 6c 65 63 74  e3_reset(pSelect
9640: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
9650: 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 50 6f 70 75 6c 61  }.../*.** Popula
9660: 74 65 20 70 43 73 72 2d 3e 61 4d 61 74 63 68 69  te pCsr->aMatchi
9670: 6e 66 6f 5b 5d 20 77 69 74 68 20 64 61 74 61 20  nfo[] with data 
9680: 66 6f 72 20 74 68 65 20 63 75 72 72 65 6e 74 20  for the current 
9690: 72 6f 77 2e 20 54 68 65 20 0a 2a 2a 20 27 6d 61  row. The .** 'ma
96a0: 74 63 68 69 6e 66 6f 27 20 64 61 74 61 20 69 73  tchinfo' data is
96b0: 20 61 6e 20 61 72 72 61 79 20 6f 66 20 33 32 2d   an array of 32-
96c0: 62 69 74 20 75 6e 73 69 67 6e 65 64 20 69 6e 74  bit unsigned int
96d0: 65 67 65 72 73 20 28 43 20 74 79 70 65 20 75 33  egers (C type u3
96e0: 32 29 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  2)..*/.static in
96f0: 74 20 66 74 73 33 47 65 74 4d 61 74 63 68 69 6e  t fts3GetMatchin
9700: 66 6f 28 0a 20 20 46 74 73 33 43 75 72 73 6f 72  fo(.  Fts3Cursor
9710: 20 2a 70 43 73 72 2c 20 20 20 20 20 20 20 20 20   *pCsr,         
9720: 20 20 20 20 20 20 2f 2a 20 46 54 53 33 20 43 75        /* FTS3 Cu
9730: 72 73 6f 72 20 6f 62 6a 65 63 74 20 2a 2f 0a 20  rsor object */. 
9740: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 41 72   const char *zAr
9750: 67 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  g               
9760: 20 2f 2a 20 53 65 63 6f 6e 64 20 61 72 67 75 6d   /* Second argum
9770: 65 6e 74 20 74 6f 20 6d 61 74 63 68 69 6e 66 6f  ent to matchinfo
9780: 28 29 20 66 75 6e 63 74 69 6f 6e 20 2a 2f 0a 29  () function */.)
9790: 7b 0a 20 20 4d 61 74 63 68 49 6e 66 6f 20 73 49  {.  MatchInfo sI
97a0: 6e 66 6f 3b 0a 20 20 46 74 73 33 54 61 62 6c 65  nfo;.  Fts3Table
97b0: 20 2a 70 54 61 62 20 3d 20 28 46 74 73 33 54 61   *pTab = (Fts3Ta
97c0: 62 6c 65 20 2a 29 70 43 73 72 2d 3e 62 61 73 65  ble *)pCsr->base
97d0: 2e 70 56 74 61 62 3b 0a 20 20 69 6e 74 20 72 63  .pVtab;.  int rc
97e0: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20   = SQLITE_OK;.  
97f0: 69 6e 74 20 62 47 6c 6f 62 61 6c 20 3d 20 30 3b  int bGlobal = 0;
9800: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9810: 2f 2a 20 43 6f 6c 6c 65 63 74 20 27 67 6c 6f 62  /* Collect 'glob
9820: 61 6c 27 20 73 74 61 74 73 20 61 73 20 77 65 6c  al' stats as wel
9830: 6c 20 61 73 20 6c 6f 63 61 6c 20 2a 2f 0a 0a 20  l as local */.. 
9840: 20 6d 65 6d 73 65 74 28 26 73 49 6e 66 6f 2c 20   memset(&sInfo, 
9850: 30 2c 20 73 69 7a 65 6f 66 28 4d 61 74 63 68 49  0, sizeof(MatchI
9860: 6e 66 6f 29 29 3b 0a 20 20 73 49 6e 66 6f 2e 70  nfo));.  sInfo.p
9870: 43 75 72 73 6f 72 20 3d 20 70 43 73 72 3b 0a 20  Cursor = pCsr;. 
9880: 20 73 49 6e 66 6f 2e 6e 43 6f 6c 20 3d 20 70 54   sInfo.nCol = pT
9890: 61 62 2d 3e 6e 43 6f 6c 75 6d 6e 3b 0a 0a 20 20  ab->nColumn;..  
98a0: 2f 2a 20 49 66 20 74 68 65 72 65 20 69 73 20 63  /* If there is c
98b0: 61 63 68 65 64 20 6d 61 74 63 68 69 6e 66 6f 28  ached matchinfo(
98c0: 29 20 64 61 74 61 2c 20 62 75 74 20 74 68 65 20  ) data, but the 
98d0: 66 6f 72 6d 61 74 20 73 74 72 69 6e 67 20 66 6f  format string fo
98e0: 72 20 74 68 65 20 0a 20 20 2a 2a 20 63 61 63 68  r the .  ** cach
98f0: 65 20 64 6f 65 73 20 6e 6f 74 20 6d 61 74 63 68  e does not match
9900: 20 74 68 65 20 66 6f 72 6d 61 74 20 73 74 72 69   the format stri
9910: 6e 67 20 66 6f 72 20 74 68 69 73 20 72 65 71 75  ng for this requ
9920: 65 73 74 2c 20 64 69 73 63 61 72 64 20 0a 20 20  est, discard .  
9930: 2a 2a 20 74 68 65 20 63 61 63 68 65 64 20 64 61  ** the cached da
9940: 74 61 2e 20 2a 2f 0a 20 20 69 66 28 20 70 43 73  ta. */.  if( pCs
9950: 72 2d 3e 7a 4d 61 74 63 68 69 6e 66 6f 20 26 26  r->zMatchinfo &&
9960: 20 73 74 72 63 6d 70 28 70 43 73 72 2d 3e 7a 4d   strcmp(pCsr->zM
9970: 61 74 63 68 69 6e 66 6f 2c 20 7a 41 72 67 29 20  atchinfo, zArg) 
9980: 29 7b 0a 20 20 20 20 61 73 73 65 72 74 28 20 70  ){.    assert( p
9990: 43 73 72 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 20  Csr->aMatchinfo 
99a0: 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66  );.    sqlite3_f
99b0: 72 65 65 28 70 43 73 72 2d 3e 61 4d 61 74 63 68  ree(pCsr->aMatch
99c0: 69 6e 66 6f 29 3b 0a 20 20 20 20 70 43 73 72 2d  info);.    pCsr-
99d0: 3e 7a 4d 61 74 63 68 69 6e 66 6f 20 3d 20 30 3b  >zMatchinfo = 0;
99e0: 0a 20 20 20 20 70 43 73 72 2d 3e 61 4d 61 74 63  .    pCsr->aMatc
99f0: 68 69 6e 66 6f 20 3d 20 30 3b 0a 20 20 7d 0a 0a  hinfo = 0;.  }..
9a00: 20 20 2f 2a 20 49 66 20 46 74 73 33 43 75 72 73    /* If Fts3Curs
9a10: 6f 72 2e 61 4d 61 74 63 68 69 6e 66 6f 5b 5d 20  or.aMatchinfo[] 
9a20: 69 73 20 4e 55 4c 4c 2c 20 74 68 65 6e 20 74 68  is NULL, then th
9a30: 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20  is is the first 
9a40: 74 69 6d 65 20 74 68 65 0a 20 20 2a 2a 20 6d 61  time the.  ** ma
9a50: 74 63 68 69 6e 66 6f 20 66 75 6e 63 74 69 6f 6e  tchinfo function
9a60: 20 68 61 73 20 62 65 65 6e 20 63 61 6c 6c 65 64   has been called
9a70: 20 66 6f 72 20 74 68 69 73 20 71 75 65 72 79 2e   for this query.
9a80: 20 49 6e 20 74 68 69 73 20 63 61 73 65 20 0a 20   In this case . 
9a90: 20 2a 2a 20 61 6c 6c 6f 63 61 74 65 20 74 68 65   ** allocate the
9aa0: 20 61 72 72 61 79 20 75 73 65 64 20 74 6f 20 61   array used to a
9ab0: 63 63 75 6d 75 6c 61 74 65 20 74 68 65 20 6d 61  ccumulate the ma
9ac0: 74 63 68 69 6e 66 6f 20 64 61 74 61 20 61 6e 64  tchinfo data and
9ad0: 0a 20 20 2a 2a 20 69 6e 69 74 69 61 6c 69 7a 65  .  ** initialize
9ae0: 20 74 68 6f 73 65 20 65 6c 65 6d 65 6e 74 73 20   those elements 
9af0: 74 68 61 74 20 61 72 65 20 63 6f 6e 73 74 61 6e  that are constan
9b00: 74 20 66 6f 72 20 65 76 65 72 79 20 72 6f 77 2e  t for every row.
9b10: 0a 20 20 2a 2f 0a 20 20 69 66 28 20 70 43 73 72  .  */.  if( pCsr
9b20: 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 3d 3d 30 20  ->aMatchinfo==0 
9b30: 29 7b 0a 20 20 20 20 69 6e 74 20 6e 4d 61 74 63  ){.    int nMatc
9b40: 68 69 6e 66 6f 20 3d 20 30 3b 20 20 20 20 20 20  hinfo = 0;      
9b50: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
9b60: 66 20 75 33 32 20 65 6c 65 6d 65 6e 74 73 20 69  f u32 elements i
9b70: 6e 20 6d 61 74 63 68 2d 69 6e 66 6f 20 2a 2f 0a  n match-info */.
9b80: 20 20 20 20 69 6e 74 20 6e 41 72 67 3b 20 20 20      int nArg;   
9b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9ba0: 20 20 2f 2a 20 42 79 74 65 73 20 69 6e 20 7a 41    /* Bytes in zA
9bb0: 72 67 20 2a 2f 0a 20 20 20 20 69 6e 74 20 69 3b  rg */.    int i;
9bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9bd0: 20 20 20 20 20 20 20 20 2f 2a 20 55 73 65 64 20          /* Used 
9be0: 74 6f 20 69 74 65 72 61 74 65 20 74 68 72 6f 75  to iterate throu
9bf0: 67 68 20 7a 41 72 67 20 2a 2f 0a 0a 20 20 20 20  gh zArg */..    
9c00: 2f 2a 20 44 65 74 65 72 6d 69 6e 65 20 74 68 65  /* Determine the
9c10: 20 6e 75 6d 62 65 72 20 6f 66 20 70 68 72 61 73   number of phras
9c20: 65 73 20 69 6e 20 74 68 65 20 71 75 65 72 79 20  es in the query 
9c30: 2a 2f 0a 20 20 20 20 70 43 73 72 2d 3e 6e 50 68  */.    pCsr->nPh
9c40: 72 61 73 65 20 3d 20 66 74 73 33 45 78 70 72 50  rase = fts3ExprP
9c50: 68 72 61 73 65 43 6f 75 6e 74 28 70 43 73 72 2d  hraseCount(pCsr-
9c60: 3e 70 45 78 70 72 29 3b 0a 20 20 20 20 73 49 6e  >pExpr);.    sIn
9c70: 66 6f 2e 6e 50 68 72 61 73 65 20 3d 20 70 43 73  fo.nPhrase = pCs
9c80: 72 2d 3e 6e 50 68 72 61 73 65 3b 0a 0a 20 20 20  r->nPhrase;..   
9c90: 20 2f 2a 20 44 65 74 65 72 6d 69 6e 65 20 74 68   /* Determine th
9ca0: 65 20 6e 75 6d 62 65 72 20 6f 66 20 69 6e 74 65  e number of inte
9cb0: 67 65 72 73 20 69 6e 20 74 68 65 20 62 75 66 66  gers in the buff
9cc0: 65 72 20 72 65 74 75 72 6e 65 64 20 62 79 20 74  er returned by t
9cd0: 68 69 73 20 63 61 6c 6c 2e 20 2a 2f 0a 20 20 20  his call. */.   
9ce0: 20 66 6f 72 28 69 3d 30 3b 20 7a 41 72 67 5b 69   for(i=0; zArg[i
9cf0: 5d 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 6e  ]; i++){.      n
9d00: 4d 61 74 63 68 69 6e 66 6f 20 2b 3d 20 66 74 73  Matchinfo += fts
9d10: 33 4d 61 74 63 68 69 6e 66 6f 53 69 7a 65 28 26  3MatchinfoSize(&
9d20: 73 49 6e 66 6f 2c 20 7a 41 72 67 5b 69 5d 29 3b  sInfo, zArg[i]);
9d30: 0a 20 20 20 20 7d 0a 0a 20 20 20 20 2f 2a 20 41  .    }..    /* A
9d40: 6c 6c 6f 63 61 74 65 20 73 70 61 63 65 20 66 6f  llocate space fo
9d50: 72 20 46 74 73 33 43 75 72 73 6f 72 2e 61 4d 61  r Fts3Cursor.aMa
9d60: 74 63 68 69 6e 66 6f 5b 5d 20 61 6e 64 20 46 74  tchinfo[] and Ft
9d70: 73 33 43 75 72 73 6f 72 2e 7a 4d 61 74 63 68 69  s3Cursor.zMatchi
9d80: 6e 66 6f 2e 20 2a 2f 0a 20 20 20 20 6e 41 72 67  nfo. */.    nArg
9d90: 20 3d 20 28 69 6e 74 29 73 74 72 6c 65 6e 28 7a   = (int)strlen(z
9da0: 41 72 67 29 3b 0a 20 20 20 20 70 43 73 72 2d 3e  Arg);.    pCsr->
9db0: 61 4d 61 74 63 68 69 6e 66 6f 20 3d 20 28 75 33  aMatchinfo = (u3
9dc0: 32 20 2a 29 73 71 6c 69 74 65 33 5f 6d 61 6c 6c  2 *)sqlite3_mall
9dd0: 6f 63 28 73 69 7a 65 6f 66 28 75 33 32 29 2a 6e  oc(sizeof(u32)*n
9de0: 4d 61 74 63 68 69 6e 66 6f 20 2b 20 6e 41 72 67  Matchinfo + nArg
9df0: 20 2b 20 31 29 3b 0a 20 20 20 20 69 66 28 20 21   + 1);.    if( !
9e00: 70 43 73 72 2d 3e 61 4d 61 74 63 68 69 6e 66 6f  pCsr->aMatchinfo
9e10: 20 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45   ) return SQLITE
9e20: 5f 4e 4f 4d 45 4d 3b 0a 0a 20 20 20 20 70 43 73  _NOMEM;..    pCs
9e30: 72 2d 3e 7a 4d 61 74 63 68 69 6e 66 6f 20 3d 20  r->zMatchinfo = 
9e40: 28 63 68 61 72 20 2a 29 26 70 43 73 72 2d 3e 61  (char *)&pCsr->a
9e50: 4d 61 74 63 68 69 6e 66 6f 5b 6e 4d 61 74 63 68  Matchinfo[nMatch
9e60: 69 6e 66 6f 5d 3b 0a 20 20 20 20 70 43 73 72 2d  info];.    pCsr-
9e70: 3e 6e 4d 61 74 63 68 69 6e 66 6f 20 3d 20 6e 4d  >nMatchinfo = nM
9e80: 61 74 63 68 69 6e 66 6f 3b 0a 20 20 20 20 6d 65  atchinfo;.    me
9e90: 6d 63 70 79 28 70 43 73 72 2d 3e 7a 4d 61 74 63  mcpy(pCsr->zMatc
9ea0: 68 69 6e 66 6f 2c 20 7a 41 72 67 2c 20 6e 41 72  hinfo, zArg, nAr
9eb0: 67 2b 31 29 3b 0a 20 20 20 20 6d 65 6d 73 65 74  g+1);.    memset
9ec0: 28 70 43 73 72 2d 3e 61 4d 61 74 63 68 69 6e 66  (pCsr->aMatchinf
9ed0: 6f 2c 20 30 2c 20 73 69 7a 65 6f 66 28 75 33 32  o, 0, sizeof(u32
9ee0: 29 2a 6e 4d 61 74 63 68 69 6e 66 6f 29 3b 0a 20  )*nMatchinfo);. 
9ef0: 20 20 20 70 43 73 72 2d 3e 69 73 4d 61 74 63 68     pCsr->isMatch
9f00: 69 6e 66 6f 4e 65 65 64 65 64 20 3d 20 31 3b 0a  infoNeeded = 1;.
9f10: 20 20 20 20 62 47 6c 6f 62 61 6c 20 3d 20 31 3b      bGlobal = 1;
9f20: 0a 20 20 7d 0a 0a 20 20 73 49 6e 66 6f 2e 61 4d  .  }..  sInfo.aM
9f30: 61 74 63 68 69 6e 66 6f 20 3d 20 70 43 73 72 2d  atchinfo = pCsr-
9f40: 3e 61 4d 61 74 63 68 69 6e 66 6f 3b 0a 20 20 73  >aMatchinfo;.  s
9f50: 49 6e 66 6f 2e 6e 50 68 72 61 73 65 20 3d 20 70  Info.nPhrase = p
9f60: 43 73 72 2d 3e 6e 50 68 72 61 73 65 3b 0a 20 20  Csr->nPhrase;.  
9f70: 69 66 28 20 70 43 73 72 2d 3e 69 73 4d 61 74 63  if( pCsr->isMatc
9f80: 68 69 6e 66 6f 4e 65 65 64 65 64 20 29 7b 0a 20  hinfoNeeded ){. 
9f90: 20 20 20 72 63 20 3d 20 66 74 73 33 4d 61 74 63     rc = fts3Matc
9fa0: 68 69 6e 66 6f 56 61 6c 75 65 73 28 70 43 73 72  hinfoValues(pCsr
9fb0: 2c 20 62 47 6c 6f 62 61 6c 2c 20 26 73 49 6e 66  , bGlobal, &sInf
9fc0: 6f 2c 20 7a 41 72 67 29 3b 0a 20 20 20 20 70 43  o, zArg);.    pC
9fd0: 73 72 2d 3e 69 73 4d 61 74 63 68 69 6e 66 6f 4e  sr->isMatchinfoN
9fe0: 65 65 64 65 64 20 3d 20 30 3b 0a 20 20 7d 0a 0a  eeded = 0;.  }..
9ff0: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
a000: 2f 2a 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e 74 61  /*.** Implementa
a010: 74 69 6f 6e 20 6f 66 20 73 6e 69 70 70 65 74 28  tion of snippet(
a020: 29 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a 76  ) function..*/.v
a030: 6f 69 64 20 73 71 6c 69 74 65 33 46 74 73 33 53  oid sqlite3Fts3S
a040: 6e 69 70 70 65 74 28 0a 20 20 73 71 6c 69 74 65  nippet(.  sqlite
a050: 33 5f 63 6f 6e 74 65 78 74 20 2a 70 43 74 78 2c  3_context *pCtx,
a060: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 51 4c            /* SQL
a070: 69 74 65 20 66 75 6e 63 74 69 6f 6e 20 63 61 6c  ite function cal
a080: 6c 20 63 6f 6e 74 65 78 74 20 2a 2f 0a 20 20 46  l context */.  F
a090: 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72 2c  ts3Cursor *pCsr,
a0a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
a0b0: 2a 20 43 75 72 73 6f 72 20 6f 62 6a 65 63 74 20  * Cursor object 
a0c0: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
a0d0: 2a 7a 53 74 61 72 74 2c 20 20 20 20 20 20 20 20  *zStart,        
a0e0: 20 20 20 20 20 2f 2a 20 53 6e 69 70 70 65 74 20       /* Snippet 
a0f0: 73 74 61 72 74 20 74 65 78 74 20 2d 20 22 3c 62  start text - "<b
a100: 3e 22 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68  >" */.  const ch
a110: 61 72 20 2a 7a 45 6e 64 2c 20 20 20 20 20 20 20  ar *zEnd,       
a120: 20 20 20 20 20 20 20 20 2f 2a 20 53 6e 69 70 70          /* Snipp
a130: 65 74 20 65 6e 64 20 74 65 78 74 20 2d 20 22 3c  et end text - "<
a140: 2f 62 3e 22 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  /b>" */.  const 
a150: 63 68 61 72 20 2a 7a 45 6c 6c 69 70 73 69 73 2c  char *zEllipsis,
a160: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 6e 69            /* Sni
a170: 70 70 65 74 20 65 6c 6c 69 70 73 69 73 20 74 65  ppet ellipsis te
a180: 78 74 20 2d 20 22 3c 62 3e 2e 2e 2e 3c 2f 62 3e  xt - "<b>...</b>
a190: 22 20 2a 2f 0a 20 20 69 6e 74 20 69 43 6f 6c 2c  " */.  int iCol,
a1a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a1b0: 20 20 20 20 20 20 20 2f 2a 20 45 78 74 72 61 63         /* Extrac
a1c0: 74 20 73 6e 69 70 70 65 74 20 66 72 6f 6d 20 74  t snippet from t
a1d0: 68 69 73 20 63 6f 6c 75 6d 6e 20 2a 2f 0a 20 20  his column */.  
a1e0: 69 6e 74 20 6e 54 6f 6b 65 6e 20 20 20 20 20 20  int nToken      
a1f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a200: 2f 2a 20 41 70 70 72 6f 78 69 6d 61 74 65 20 6e  /* Approximate n
a210: 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20  umber of tokens 
a220: 69 6e 20 73 6e 69 70 70 65 74 20 2a 2f 0a 29 7b  in snippet */.){
a230: 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a 70 54  .  Fts3Table *pT
a240: 61 62 20 3d 20 28 46 74 73 33 54 61 62 6c 65 20  ab = (Fts3Table 
a250: 2a 29 70 43 73 72 2d 3e 62 61 73 65 2e 70 56 74  *)pCsr->base.pVt
a260: 61 62 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  ab;.  int rc = S
a270: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20  QLITE_OK;.  int 
a280: 69 3b 0a 20 20 53 74 72 42 75 66 66 65 72 20 72  i;.  StrBuffer r
a290: 65 73 20 3d 20 7b 30 2c 20 30 2c 20 30 7d 3b 0a  es = {0, 0, 0};.
a2a0: 0a 20 20 2f 2a 20 54 68 65 20 72 65 74 75 72 6e  .  /* The return
a2b0: 65 64 20 74 65 78 74 20 69 6e 63 6c 75 64 65 73  ed text includes
a2c0: 20 75 70 20 74 6f 20 66 6f 75 72 20 66 72 61 67   up to four frag
a2d0: 6d 65 6e 74 73 20 6f 66 20 74 65 78 74 20 65 78  ments of text ex
a2e0: 74 72 61 63 74 65 64 20 66 72 6f 6d 0a 20 20 2a  tracted from.  *
a2f0: 2a 20 74 68 65 20 64 61 74 61 20 69 6e 20 74 68  * the data in th
a300: 65 20 63 75 72 72 65 6e 74 20 72 6f 77 2e 20 54  e current row. T
a310: 68 65 20 66 69 72 73 74 20 69 74 65 72 61 74 69  he first iterati
a320: 6f 6e 20 6f 66 20 74 68 65 20 66 6f 72 28 2e 2e  on of the for(..
a330: 2e 29 20 6c 6f 6f 70 0a 20 20 2a 2a 20 62 65 6c  .) loop.  ** bel
a340: 6f 77 20 61 74 74 65 6d 70 74 73 20 74 6f 20 6c  ow attempts to l
a350: 6f 63 61 74 65 20 61 20 73 69 6e 67 6c 65 20 66  ocate a single f
a360: 72 61 67 6d 65 6e 74 20 6f 66 20 74 65 78 74 20  ragment of text 
a370: 6e 54 6f 6b 65 6e 20 74 6f 6b 65 6e 73 20 69 6e  nToken tokens in
a380: 20 0a 20 20 2a 2a 20 73 69 7a 65 20 74 68 61 74   .  ** size that
a390: 20 63 6f 6e 74 61 69 6e 73 20 61 74 20 6c 65 61   contains at lea
a3a0: 73 74 20 6f 6e 65 20 69 6e 73 74 61 6e 63 65 20  st one instance 
a3b0: 6f 66 20 61 6c 6c 20 70 68 72 61 73 65 73 20 69  of all phrases i
a3c0: 6e 20 74 68 65 20 71 75 65 72 79 0a 20 20 2a 2a  n the query.  **
a3d0: 20 65 78 70 72 65 73 73 69 6f 6e 20 74 68 61 74   expression that
a3e0: 20 61 70 70 65 61 72 20 69 6e 20 74 68 65 20 63   appear in the c
a3f0: 75 72 72 65 6e 74 20 72 6f 77 2e 20 49 66 20 73  urrent row. If s
a400: 75 63 68 20 61 20 66 72 61 67 6d 65 6e 74 20 6f  uch a fragment o
a410: 66 20 74 65 78 74 0a 20 20 2a 2a 20 63 61 6e 6e  f text.  ** cann
a420: 6f 74 20 62 65 20 66 6f 75 6e 64 2c 20 74 68 65  ot be found, the
a430: 20 73 65 63 6f 6e 64 20 69 74 65 72 61 74 69 6f   second iteratio
a440: 6e 20 6f 66 20 74 68 65 20 6c 6f 6f 70 20 61 74  n of the loop at
a450: 74 65 6d 70 74 73 20 74 6f 20 6c 6f 63 61 74 65  tempts to locate
a460: 0a 20 20 2a 2a 20 61 20 70 61 69 72 20 6f 66 20  .  ** a pair of 
a470: 66 72 61 67 6d 65 6e 74 73 2c 20 61 6e 64 20 73  fragments, and s
a480: 6f 20 6f 6e 2e 0a 20 20 2a 2f 0a 20 20 69 6e 74  o on..  */.  int
a490: 20 6e 53 6e 69 70 70 65 74 20 3d 20 30 3b 20 20   nSnippet = 0;  
a4a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
a4b0: 4e 75 6d 62 65 72 20 6f 66 20 66 72 61 67 6d 65  Number of fragme
a4c0: 6e 74 73 20 69 6e 20 74 68 69 73 20 73 6e 69 70  nts in this snip
a4d0: 70 65 74 20 2a 2f 0a 20 20 53 6e 69 70 70 65 74  pet */.  Snippet
a4e0: 46 72 61 67 6d 65 6e 74 20 61 53 6e 69 70 70 65  Fragment aSnippe
a4f0: 74 5b 34 5d 3b 20 20 20 20 2f 2a 20 4d 61 78 69  t[4];    /* Maxi
a500: 6d 75 6d 20 6f 66 20 34 20 66 72 61 67 6d 65 6e  mum of 4 fragmen
a510: 74 73 20 70 65 72 20 73 6e 69 70 70 65 74 20 2a  ts per snippet *
a520: 2f 0a 20 20 69 6e 74 20 6e 46 54 6f 6b 65 6e 20  /.  int nFToken 
a530: 3d 20 2d 31 3b 20 20 20 20 20 20 20 20 20 20 20  = -1;           
a540: 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66      /* Number of
a550: 20 74 6f 6b 65 6e 73 20 69 6e 20 65 61 63 68 20   tokens in each 
a560: 66 72 61 67 6d 65 6e 74 20 2a 2f 0a 0a 20 20 69  fragment */..  i
a570: 66 28 20 21 70 43 73 72 2d 3e 70 45 78 70 72 20  f( !pCsr->pExpr 
a580: 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 72  ){.    sqlite3_r
a590: 65 73 75 6c 74 5f 74 65 78 74 28 70 43 74 78 2c  esult_text(pCtx,
a5a0: 20 22 22 2c 20 30 2c 20 53 51 4c 49 54 45 5f 53   "", 0, SQLITE_S
a5b0: 54 41 54 49 43 29 3b 0a 20 20 20 20 72 65 74 75  TATIC);.    retu
a5c0: 72 6e 3b 0a 20 20 7d 0a 0a 20 20 66 6f 72 28 6e  rn;.  }..  for(n
a5d0: 53 6e 69 70 70 65 74 3d 31 3b 20 31 3b 20 6e 53  Snippet=1; 1; nS
a5e0: 6e 69 70 70 65 74 2b 2b 29 7b 0a 0a 20 20 20 20  nippet++){..    
a5f0: 69 6e 74 20 69 53 6e 69 70 3b 20 20 20 20 20 20  int iSnip;      
a600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
a610: 20 4c 6f 6f 70 20 63 6f 75 6e 74 65 72 20 30 2e   Loop counter 0.
a620: 2e 6e 53 6e 69 70 70 65 74 2d 31 20 2a 2f 0a 20  .nSnippet-1 */. 
a630: 20 20 20 75 36 34 20 6d 43 6f 76 65 72 65 64 20     u64 mCovered 
a640: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
a650: 20 2f 2a 20 42 69 74 6d 61 73 6b 20 6f 66 20 70   /* Bitmask of p
a660: 68 72 61 73 65 73 20 63 6f 76 65 72 65 64 20 62  hrases covered b
a670: 79 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20 20  y snippet */.   
a680: 20 75 36 34 20 6d 53 65 65 6e 20 3d 20 30 3b 20   u64 mSeen = 0; 
a690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
a6a0: 2a 20 42 69 74 6d 61 73 6b 20 6f 66 20 70 68 72  * Bitmask of phr
a6b0: 61 73 65 73 20 73 65 65 6e 20 62 79 20 42 65 73  ases seen by Bes
a6c0: 74 53 6e 69 70 70 65 74 28 29 20 2a 2f 0a 0a 20  tSnippet() */.. 
a6d0: 20 20 20 69 66 28 20 6e 54 6f 6b 65 6e 3e 3d 30     if( nToken>=0
a6e0: 20 29 7b 0a 20 20 20 20 20 20 6e 46 54 6f 6b 65   ){.      nFToke
a6f0: 6e 20 3d 20 28 6e 54 6f 6b 65 6e 2b 6e 53 6e 69  n = (nToken+nSni
a700: 70 70 65 74 2d 31 29 20 2f 20 6e 53 6e 69 70 70  ppet-1) / nSnipp
a710: 65 74 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20  et;.    }else{. 
a720: 20 20 20 20 20 6e 46 54 6f 6b 65 6e 20 3d 20 2d       nFToken = -
a730: 31 20 2a 20 6e 54 6f 6b 65 6e 3b 0a 20 20 20 20  1 * nToken;.    
a740: 7d 0a 0a 20 20 20 20 66 6f 72 28 69 53 6e 69 70  }..    for(iSnip
a750: 3d 30 3b 20 69 53 6e 69 70 3c 6e 53 6e 69 70 70  =0; iSnip<nSnipp
a760: 65 74 3b 20 69 53 6e 69 70 2b 2b 29 7b 0a 20 20  et; iSnip++){.  
a770: 20 20 20 20 69 6e 74 20 69 42 65 73 74 53 63 6f      int iBestSco
a780: 72 65 20 3d 20 2d 31 3b 20 20 20 20 20 20 20 20  re = -1;        
a790: 2f 2a 20 42 65 73 74 20 73 63 6f 72 65 20 6f 66  /* Best score of
a7a0: 20 63 6f 6c 75 6d 6e 73 20 63 68 65 63 6b 65 64   columns checked
a7b0: 20 73 6f 20 66 61 72 20 2a 2f 0a 20 20 20 20 20   so far */.     
a7c0: 20 69 6e 74 20 69 52 65 61 64 3b 20 20 20 20 20   int iRead;     
a7d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
a7e0: 55 73 65 64 20 74 6f 20 69 74 65 72 61 74 65 20  Used to iterate 
a7f0: 74 68 72 6f 75 67 68 20 63 6f 6c 75 6d 6e 73 20  through columns 
a800: 2a 2f 0a 20 20 20 20 20 20 53 6e 69 70 70 65 74  */.      Snippet
a810: 46 72 61 67 6d 65 6e 74 20 2a 70 46 72 61 67 6d  Fragment *pFragm
a820: 65 6e 74 20 3d 20 26 61 53 6e 69 70 70 65 74 5b  ent = &aSnippet[
a830: 69 53 6e 69 70 5d 3b 0a 0a 20 20 20 20 20 20 6d  iSnip];..      m
a840: 65 6d 73 65 74 28 70 46 72 61 67 6d 65 6e 74 2c  emset(pFragment,
a850: 20 30 2c 20 73 69 7a 65 6f 66 28 2a 70 46 72 61   0, sizeof(*pFra
a860: 67 6d 65 6e 74 29 29 3b 0a 0a 20 20 20 20 20 20  gment));..      
a870: 2f 2a 20 4c 6f 6f 70 20 74 68 72 6f 75 67 68 20  /* Loop through 
a880: 61 6c 6c 20 63 6f 6c 75 6d 6e 73 20 6f 66 20 74  all columns of t
a890: 68 65 20 74 61 62 6c 65 20 62 65 69 6e 67 20 63  he table being c
a8a0: 6f 6e 73 69 64 65 72 65 64 20 66 6f 72 20 73 6e  onsidered for sn
a8b0: 69 70 70 65 74 73 2e 0a 20 20 20 20 20 20 2a 2a  ippets..      **
a8c0: 20 49 66 20 74 68 65 20 69 43 6f 6c 20 61 72 67   If the iCol arg
a8d0: 75 6d 65 6e 74 20 74 6f 20 74 68 69 73 20 66 75  ument to this fu
a8e0: 6e 63 74 69 6f 6e 20 77 61 73 20 6e 65 67 61 74  nction was negat
a8f0: 69 76 65 2c 20 74 68 69 73 20 6d 65 61 6e 73 20  ive, this means 
a900: 61 6c 6c 0a 20 20 20 20 20 20 2a 2a 20 63 6f 6c  all.      ** col
a910: 75 6d 6e 73 20 6f 66 20 74 68 65 20 46 54 53 33  umns of the FTS3
a920: 20 74 61 62 6c 65 2e 20 4f 74 68 65 72 77 69 73   table. Otherwis
a930: 65 2c 20 6f 6e 6c 79 20 63 6f 6c 75 6d 6e 20 69  e, only column i
a940: 43 6f 6c 20 69 73 20 63 6f 6e 73 69 64 65 72 65  Col is considere
a950: 64 2e 0a 20 20 20 20 20 20 2a 2f 0a 20 20 20 20  d..      */.    
a960: 20 20 66 6f 72 28 69 52 65 61 64 3d 30 3b 20 69    for(iRead=0; i
a970: 52 65 61 64 3c 70 54 61 62 2d 3e 6e 43 6f 6c 75  Read<pTab->nColu
a980: 6d 6e 3b 20 69 52 65 61 64 2b 2b 29 7b 0a 20 20  mn; iRead++){.  
a990: 20 20 20 20 20 20 53 6e 69 70 70 65 74 46 72 61        SnippetFra
a9a0: 67 6d 65 6e 74 20 73 46 20 3d 20 7b 30 2c 20 30  gment sF = {0, 0
a9b0: 2c 20 30 2c 20 30 7d 3b 0a 20 20 20 20 20 20 20  , 0, 0};.       
a9c0: 20 69 6e 74 20 69 53 3b 0a 20 20 20 20 20 20 20   int iS;.       
a9d0: 20 69 66 28 20 69 43 6f 6c 3e 3d 30 20 26 26 20   if( iCol>=0 && 
a9e0: 69 52 65 61 64 21 3d 69 43 6f 6c 20 29 20 63 6f  iRead!=iCol ) co
a9f0: 6e 74 69 6e 75 65 3b 0a 0a 20 20 20 20 20 20 20  ntinue;..       
aa00: 20 2f 2a 20 46 69 6e 64 20 74 68 65 20 62 65 73   /* Find the bes
aa10: 74 20 73 6e 69 70 70 65 74 20 6f 66 20 6e 46 54  t snippet of nFT
aa20: 6f 6b 65 6e 20 74 6f 6b 65 6e 73 20 69 6e 20 63  oken tokens in c
aa30: 6f 6c 75 6d 6e 20 69 52 65 61 64 2e 20 2a 2f 0a  olumn iRead. */.
aa40: 20 20 20 20 20 20 20 20 72 63 20 3d 20 66 74 73          rc = fts
aa50: 33 42 65 73 74 53 6e 69 70 70 65 74 28 6e 46 54  3BestSnippet(nFT
aa60: 6f 6b 65 6e 2c 20 70 43 73 72 2c 20 69 52 65 61  oken, pCsr, iRea
aa70: 64 2c 20 6d 43 6f 76 65 72 65 64 2c 20 26 6d 53  d, mCovered, &mS
aa80: 65 65 6e 2c 20 26 73 46 2c 20 26 69 53 29 3b 0a  een, &sF, &iS);.
aa90: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 21 3d          if( rc!=
aaa0: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
aab0: 20 20 20 20 20 20 20 67 6f 74 6f 20 73 6e 69 70         goto snip
aac0: 70 65 74 5f 6f 75 74 3b 0a 20 20 20 20 20 20 20  pet_out;.       
aad0: 20 7d 0a 20 20 20 20 20 20 20 20 69 66 28 20 69   }.        if( i
aae0: 53 3e 69 42 65 73 74 53 63 6f 72 65 20 29 7b 0a  S>iBestScore ){.
aaf0: 20 20 20 20 20 20 20 20 20 20 2a 70 46 72 61 67            *pFrag
ab00: 6d 65 6e 74 20 3d 20 73 46 3b 0a 20 20 20 20 20  ment = sF;.     
ab10: 20 20 20 20 20 69 42 65 73 74 53 63 6f 72 65 20       iBestScore 
ab20: 3d 20 69 53 3b 0a 20 20 20 20 20 20 20 20 7d 0a  = iS;.        }.
ab30: 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 6d        }..      m
ab40: 43 6f 76 65 72 65 64 20 7c 3d 20 70 46 72 61 67  Covered |= pFrag
ab50: 6d 65 6e 74 2d 3e 63 6f 76 65 72 65 64 3b 0a 20  ment->covered;. 
ab60: 20 20 20 7d 0a 0a 20 20 20 20 2f 2a 20 49 66 20     }..    /* If 
ab70: 61 6c 6c 20 71 75 65 72 79 20 70 68 72 61 73 65  all query phrase
ab80: 73 20 73 65 65 6e 20 62 79 20 66 74 73 33 42 65  s seen by fts3Be
ab90: 73 74 53 6e 69 70 70 65 74 28 29 20 61 72 65 20  stSnippet() are 
aba0: 70 72 65 73 65 6e 74 20 69 6e 20 61 74 20 6c 65  present in at le
abb0: 61 73 74 0a 20 20 20 20 2a 2a 20 6f 6e 65 20 6f  ast.    ** one o
abc0: 66 20 74 68 65 20 6e 53 6e 69 70 70 65 74 20 73  f the nSnippet s
abd0: 6e 69 70 70 65 74 20 66 72 61 67 6d 65 6e 74 73  nippet fragments
abe0: 2c 20 62 72 65 61 6b 20 6f 75 74 20 6f 66 20 74  , break out of t
abf0: 68 65 20 6c 6f 6f 70 2e 0a 20 20 20 20 2a 2f 0a  he loop..    */.
ac00: 20 20 20 20 61 73 73 65 72 74 28 20 28 6d 43 6f      assert( (mCo
ac10: 76 65 72 65 64 26 6d 53 65 65 6e 29 3d 3d 6d 43  vered&mSeen)==mC
ac20: 6f 76 65 72 65 64 20 29 3b 0a 20 20 20 20 69 66  overed );.    if
ac30: 28 20 6d 53 65 65 6e 3d 3d 6d 43 6f 76 65 72 65  ( mSeen==mCovere
ac40: 64 20 7c 7c 20 6e 53 6e 69 70 70 65 74 3d 3d 53  d || nSnippet==S
ac50: 69 7a 65 6f 66 41 72 72 61 79 28 61 53 6e 69 70  izeofArray(aSnip
ac60: 70 65 74 29 20 29 20 62 72 65 61 6b 3b 0a 20 20  pet) ) break;.  
ac70: 7d 0a 0a 20 20 61 73 73 65 72 74 28 20 6e 46 54  }..  assert( nFT
ac80: 6f 6b 65 6e 3e 30 20 29 3b 0a 0a 20 20 66 6f 72  oken>0 );..  for
ac90: 28 69 3d 30 3b 20 69 3c 6e 53 6e 69 70 70 65 74  (i=0; i<nSnippet
aca0: 20 26 26 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f   && rc==SQLITE_O
acb0: 4b 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 72 63 20  K; i++){.    rc 
acc0: 3d 20 66 74 73 33 53 6e 69 70 70 65 74 54 65 78  = fts3SnippetTex
acd0: 74 28 70 43 73 72 2c 20 26 61 53 6e 69 70 70 65  t(pCsr, &aSnippe
ace0: 74 5b 69 5d 2c 20 0a 20 20 20 20 20 20 20 20 69  t[i], .        i
acf0: 2c 20 28 69 3d 3d 6e 53 6e 69 70 70 65 74 2d 31  , (i==nSnippet-1
ad00: 29 2c 20 6e 46 54 6f 6b 65 6e 2c 20 7a 53 74 61  ), nFToken, zSta
ad10: 72 74 2c 20 7a 45 6e 64 2c 20 7a 45 6c 6c 69 70  rt, zEnd, zEllip
ad20: 73 69 73 2c 20 26 72 65 73 0a 20 20 20 20 29 3b  sis, &res.    );
ad30: 0a 20 20 7d 0a 0a 20 73 6e 69 70 70 65 74 5f 6f  .  }.. snippet_o
ad40: 75 74 3a 0a 20 20 73 71 6c 69 74 65 33 46 74 73  ut:.  sqlite3Fts
ad50: 33 53 65 67 6d 65 6e 74 73 43 6c 6f 73 65 28 70  3SegmentsClose(p
ad60: 54 61 62 29 3b 0a 20 20 69 66 28 20 72 63 21 3d  Tab);.  if( rc!=
ad70: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
ad80: 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f   sqlite3_result_
ad90: 65 72 72 6f 72 5f 63 6f 64 65 28 70 43 74 78 2c  error_code(pCtx,
ada0: 20 72 63 29 3b 0a 20 20 20 20 73 71 6c 69 74 65   rc);.    sqlite
adb0: 33 5f 66 72 65 65 28 72 65 73 2e 7a 29 3b 0a 20  3_free(res.z);. 
adc0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 73 71 6c 69   }else{.    sqli
add0: 74 65 33 5f 72 65 73 75 6c 74 5f 74 65 78 74 28  te3_result_text(
ade0: 70 43 74 78 2c 20 72 65 73 2e 7a 2c 20 2d 31 2c  pCtx, res.z, -1,
adf0: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 29 3b 0a   sqlite3_free);.
ae00: 20 20 7d 0a 7d 0a 0a 0a 74 79 70 65 64 65 66 20    }.}...typedef 
ae10: 73 74 72 75 63 74 20 54 65 72 6d 4f 66 66 73 65  struct TermOffse
ae20: 74 20 54 65 72 6d 4f 66 66 73 65 74 3b 0a 74 79  t TermOffset;.ty
ae30: 70 65 64 65 66 20 73 74 72 75 63 74 20 54 65 72  pedef struct Ter
ae40: 6d 4f 66 66 73 65 74 43 74 78 20 54 65 72 6d 4f  mOffsetCtx TermO
ae50: 66 66 73 65 74 43 74 78 3b 0a 0a 73 74 72 75 63  ffsetCtx;..struc
ae60: 74 20 54 65 72 6d 4f 66 66 73 65 74 20 7b 0a 20  t TermOffset {. 
ae70: 20 63 68 61 72 20 2a 70 4c 69 73 74 3b 20 20 20   char *pList;   
ae80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ae90: 20 2f 2a 20 50 6f 73 69 74 69 6f 6e 2d 6c 69 73   /* Position-lis
aea0: 74 20 2a 2f 0a 20 20 69 6e 74 20 69 50 6f 73 3b  t */.  int iPos;
aeb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aec0: 20 20 20 20 20 20 20 2f 2a 20 50 6f 73 69 74 69         /* Positi
aed0: 6f 6e 20 6a 75 73 74 20 72 65 61 64 20 66 72 6f  on just read fro
aee0: 6d 20 70 4c 69 73 74 20 2a 2f 0a 20 20 69 6e 74  m pList */.  int
aef0: 20 69 4f 66 66 3b 20 20 20 20 20 20 20 20 20 20   iOff;          
af00: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
af10: 4f 66 66 73 65 74 20 6f 66 20 74 68 69 73 20 74  Offset of this t
af20: 65 72 6d 20 66 72 6f 6d 20 72 65 61 64 20 70 6f  erm from read po
af30: 73 69 74 69 6f 6e 73 20 2a 2f 0a 7d 3b 0a 0a 73  sitions */.};..s
af40: 74 72 75 63 74 20 54 65 72 6d 4f 66 66 73 65 74  truct TermOffset
af50: 43 74 78 20 7b 0a 20 20 46 74 73 33 43 75 72 73  Ctx {.  Fts3Curs
af60: 6f 72 20 2a 70 43 73 72 3b 0a 20 20 69 6e 74 20  or *pCsr;.  int 
af70: 69 43 6f 6c 3b 20 20 20 20 20 20 20 20 20 20 20  iCol;           
af80: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43              /* C
af90: 6f 6c 75 6d 6e 20 6f 66 20 74 61 62 6c 65 20 74  olumn of table t
afa0: 6f 20 70 6f 70 75 6c 61 74 65 20 61 54 65 72 6d  o populate aTerm
afb0: 20 66 6f 72 20 2a 2f 0a 20 20 69 6e 74 20 69 54   for */.  int iT
afc0: 65 72 6d 3b 0a 20 20 73 71 6c 69 74 65 33 5f 69  erm;.  sqlite3_i
afd0: 6e 74 36 34 20 69 44 6f 63 69 64 3b 0a 20 20 54  nt64 iDocid;.  T
afe0: 65 72 6d 4f 66 66 73 65 74 20 2a 61 54 65 72 6d  ermOffset *aTerm
aff0: 3b 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73  ;.};../*.** This
b000: 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 61 6e 20   function is an 
b010: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 28  fts3ExprIterate(
b020: 29 20 63 61 6c 6c 62 61 63 6b 20 75 73 65 64 20  ) callback used 
b030: 62 79 20 73 71 6c 69 74 65 33 46 74 73 33 4f 66  by sqlite3Fts3Of
b040: 66 73 65 74 73 28 29 2e 0a 2a 2f 0a 73 74 61 74  fsets()..*/.stat
b050: 69 63 20 69 6e 74 20 66 74 73 33 45 78 70 72 54  ic int fts3ExprT
b060: 65 72 6d 4f 66 66 73 65 74 49 6e 69 74 28 46 74  ermOffsetInit(Ft
b070: 73 33 45 78 70 72 20 2a 70 45 78 70 72 2c 20 69  s3Expr *pExpr, i
b080: 6e 74 20 69 50 68 72 61 73 65 2c 20 76 6f 69 64  nt iPhrase, void
b090: 20 2a 63 74 78 29 7b 0a 20 20 54 65 72 6d 4f 66   *ctx){.  TermOf
b0a0: 66 73 65 74 43 74 78 20 2a 70 20 3d 20 28 54 65  fsetCtx *p = (Te
b0b0: 72 6d 4f 66 66 73 65 74 43 74 78 20 2a 29 63 74  rmOffsetCtx *)ct
b0c0: 78 3b 0a 20 20 69 6e 74 20 6e 54 65 72 6d 3b 20  x;.  int nTerm; 
b0d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b0e0: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
b0f0: 66 20 74 6f 6b 65 6e 73 20 69 6e 20 70 68 72 61  f tokens in phra
b100: 73 65 20 2a 2f 0a 20 20 69 6e 74 20 69 54 65 72  se */.  int iTer
b110: 6d 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  m;              
b120: 20 20 20 20 20 20 20 20 2f 2a 20 46 6f 72 20 6c          /* For l
b130: 6f 6f 70 69 6e 67 20 74 68 72 6f 75 67 68 20 6e  ooping through n
b140: 54 65 72 6d 20 70 68 72 61 73 65 20 74 65 72 6d  Term phrase term
b150: 73 20 2a 2f 0a 20 20 63 68 61 72 20 2a 70 4c 69  s */.  char *pLi
b160: 73 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  st;             
b170: 20 20 20 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65         /* Pointe
b180: 72 20 74 6f 20 70 6f 73 69 74 69 6f 6e 20 6c 69  r to position li
b190: 73 74 20 66 6f 72 20 70 68 72 61 73 65 20 2a 2f  st for phrase */
b1a0: 0a 20 20 69 6e 74 20 69 50 6f 73 20 3d 20 30 3b  .  int iPos = 0;
b1b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b1c0: 20 20 20 2f 2a 20 46 69 72 73 74 20 70 6f 73 69     /* First posi
b1d0: 74 69 6f 6e 20 69 6e 20 70 6f 73 69 74 69 6f 6e  tion in position
b1e0: 2d 6c 69 73 74 20 2a 2f 0a 20 20 69 6e 74 20 72  -list */.  int r
b1f0: 63 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  c;..  UNUSED_PAR
b200: 41 4d 45 54 45 52 28 69 50 68 72 61 73 65 29 3b  AMETER(iPhrase);
b210: 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 46  .  rc = sqlite3F
b220: 74 73 33 45 76 61 6c 50 68 72 61 73 65 50 6f 73  ts3EvalPhrasePos
b230: 6c 69 73 74 28 70 2d 3e 70 43 73 72 2c 20 70 45  list(p->pCsr, pE
b240: 78 70 72 2c 20 70 2d 3e 69 43 6f 6c 2c 20 26 70  xpr, p->iCol, &p
b250: 4c 69 73 74 29 3b 0a 20 20 6e 54 65 72 6d 20 3d  List);.  nTerm =
b260: 20 70 45 78 70 72 2d 3e 70 50 68 72 61 73 65 2d   pExpr->pPhrase-
b270: 3e 6e 54 6f 6b 65 6e 3b 0a 20 20 69 66 28 20 70  >nToken;.  if( p
b280: 4c 69 73 74 20 29 7b 0a 20 20 20 20 66 74 73 33  List ){.    fts3
b290: 47 65 74 44 65 6c 74 61 50 6f 73 69 74 69 6f 6e  GetDeltaPosition
b2a0: 28 26 70 4c 69 73 74 2c 20 26 69 50 6f 73 29 3b  (&pList, &iPos);
b2b0: 0a 20 20 20 20 61 73 73 65 72 74 28 20 69 50 6f  .    assert( iPo
b2c0: 73 3e 3d 30 20 29 3b 0a 20 20 7d 0a 0a 20 20 66  s>=0 );.  }..  f
b2d0: 6f 72 28 69 54 65 72 6d 3d 30 3b 20 69 54 65 72  or(iTerm=0; iTer
b2e0: 6d 3c 6e 54 65 72 6d 3b 20 69 54 65 72 6d 2b 2b  m<nTerm; iTerm++
b2f0: 29 7b 0a 20 20 20 20 54 65 72 6d 4f 66 66 73 65  ){.    TermOffse
b300: 74 20 2a 70 54 20 3d 20 26 70 2d 3e 61 54 65 72  t *pT = &p->aTer
b310: 6d 5b 70 2d 3e 69 54 65 72 6d 2b 2b 5d 3b 0a 20  m[p->iTerm++];. 
b320: 20 20 20 70 54 2d 3e 69 4f 66 66 20 3d 20 6e 54     pT->iOff = nT
b330: 65 72 6d 2d 69 54 65 72 6d 2d 31 3b 0a 20 20 20  erm-iTerm-1;.   
b340: 20 70 54 2d 3e 70 4c 69 73 74 20 3d 20 70 4c 69   pT->pList = pLi
b350: 73 74 3b 0a 20 20 20 20 70 54 2d 3e 69 50 6f 73  st;.    pT->iPos
b360: 20 3d 20 69 50 6f 73 3b 0a 20 20 7d 0a 0a 20 20   = iPos;.  }..  
b370: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
b380: 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e 74 61 74 69  .** Implementati
b390: 6f 6e 20 6f 66 20 6f 66 66 73 65 74 73 28 29 20  on of offsets() 
b3a0: 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a 76 6f 69  function..*/.voi
b3b0: 64 20 73 71 6c 69 74 65 33 46 74 73 33 4f 66 66  d sqlite3Fts3Off
b3c0: 73 65 74 73 28 0a 20 20 73 71 6c 69 74 65 33 5f  sets(.  sqlite3_
b3d0: 63 6f 6e 74 65 78 74 20 2a 70 43 74 78 2c 20 20  context *pCtx,  
b3e0: 20 20 20 20 20 20 20 20 2f 2a 20 53 51 4c 69 74          /* SQLit
b3f0: 65 20 66 75 6e 63 74 69 6f 6e 20 63 61 6c 6c 20  e function call 
b400: 63 6f 6e 74 65 78 74 20 2a 2f 0a 20 20 46 74 73  context */.  Fts
b410: 33 43 75 72 73 6f 72 20 2a 70 43 73 72 20 20 20  3Cursor *pCsr   
b420: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
b430: 43 75 72 73 6f 72 20 6f 62 6a 65 63 74 20 2a 2f  Cursor object */
b440: 0a 29 7b 0a 20 20 46 74 73 33 54 61 62 6c 65 20  .){.  Fts3Table 
b450: 2a 70 54 61 62 20 3d 20 28 46 74 73 33 54 61 62  *pTab = (Fts3Tab
b460: 6c 65 20 2a 29 70 43 73 72 2d 3e 62 61 73 65 2e  le *)pCsr->base.
b470: 70 56 74 61 62 3b 0a 20 20 73 71 6c 69 74 65 33  pVtab;.  sqlite3
b480: 5f 74 6f 6b 65 6e 69 7a 65 72 5f 6d 6f 64 75 6c  _tokenizer_modul
b490: 65 20 63 6f 6e 73 74 20 2a 70 4d 6f 64 20 3d 20  e const *pMod = 
b4a0: 70 54 61 62 2d 3e 70 54 6f 6b 65 6e 69 7a 65 72  pTab->pTokenizer
b4b0: 2d 3e 70 4d 6f 64 75 6c 65 3b 0a 20 20 69 6e 74  ->pModule;.  int
b4c0: 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20   rc;            
b4d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
b4e0: 52 65 74 75 72 6e 20 43 6f 64 65 20 2a 2f 0a 20  Return Code */. 
b4f0: 20 69 6e 74 20 6e 54 6f 6b 65 6e 3b 20 20 20 20   int nToken;    
b500: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b510: 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 74 6f   /* Number of to
b520: 6b 65 6e 73 20 69 6e 20 71 75 65 72 79 20 2a 2f  kens in query */
b530: 0a 20 20 69 6e 74 20 69 43 6f 6c 3b 20 20 20 20  .  int iCol;    
b540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b550: 20 20 20 2f 2a 20 43 6f 6c 75 6d 6e 20 63 75 72     /* Column cur
b560: 72 65 6e 74 6c 79 20 62 65 69 6e 67 20 70 72 6f  rently being pro
b570: 63 65 73 73 65 64 20 2a 2f 0a 20 20 53 74 72 42  cessed */.  StrB
b580: 75 66 66 65 72 20 72 65 73 20 3d 20 7b 30 2c 20  uffer res = {0, 
b590: 30 2c 20 30 7d 3b 20 20 20 20 20 20 2f 2a 20 52  0, 0};      /* R
b5a0: 65 73 75 6c 74 20 73 74 72 69 6e 67 20 2a 2f 0a  esult string */.
b5b0: 20 20 54 65 72 6d 4f 66 66 73 65 74 43 74 78 20    TermOffsetCtx 
b5c0: 73 43 74 78 3b 20 20 20 20 20 20 20 20 20 20 20  sCtx;           
b5d0: 20 20 2f 2a 20 43 6f 6e 74 65 78 74 20 66 6f 72    /* Context for
b5e0: 20 66 74 73 33 45 78 70 72 54 65 72 6d 4f 66 66   fts3ExprTermOff
b5f0: 73 65 74 49 6e 69 74 28 29 20 2a 2f 0a 0a 20 20  setInit() */..  
b600: 69 66 28 20 21 70 43 73 72 2d 3e 70 45 78 70 72  if( !pCsr->pExpr
b610: 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f   ){.    sqlite3_
b620: 72 65 73 75 6c 74 5f 74 65 78 74 28 70 43 74 78  result_text(pCtx
b630: 2c 20 22 22 2c 20 30 2c 20 53 51 4c 49 54 45 5f  , "", 0, SQLITE_
b640: 53 54 41 54 49 43 29 3b 0a 20 20 20 20 72 65 74  STATIC);.    ret
b650: 75 72 6e 3b 0a 20 20 7d 0a 0a 20 20 6d 65 6d 73  urn;.  }..  mems
b660: 65 74 28 26 73 43 74 78 2c 20 30 2c 20 73 69 7a  et(&sCtx, 0, siz
b670: 65 6f 66 28 73 43 74 78 29 29 3b 0a 20 20 61 73  eof(sCtx));.  as
b680: 73 65 72 74 28 20 70 43 73 72 2d 3e 69 73 52 65  sert( pCsr->isRe
b690: 71 75 69 72 65 53 65 65 6b 3d 3d 30 20 29 3b 0a  quireSeek==0 );.
b6a0: 0a 20 20 2f 2a 20 43 6f 75 6e 74 20 74 68 65 20  .  /* Count the 
b6b0: 6e 75 6d 62 65 72 20 6f 66 20 74 65 72 6d 73 20  number of terms 
b6c0: 69 6e 20 74 68 65 20 71 75 65 72 79 20 2a 2f 0a  in the query */.
b6d0: 20 20 72 63 20 3d 20 66 74 73 33 45 78 70 72 4c    rc = fts3ExprL
b6e0: 6f 61 64 44 6f 63 6c 69 73 74 73 28 70 43 73 72  oadDoclists(pCsr
b6f0: 2c 20 30 2c 20 26 6e 54 6f 6b 65 6e 29 3b 0a 20  , 0, &nToken);. 
b700: 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f   if( rc!=SQLITE_
b710: 4f 4b 20 29 20 67 6f 74 6f 20 6f 66 66 73 65 74  OK ) goto offset
b720: 73 5f 6f 75 74 3b 0a 0a 20 20 2f 2a 20 41 6c 6c  s_out;..  /* All
b730: 6f 63 61 74 65 20 74 68 65 20 61 72 72 61 79 20  ocate the array 
b740: 6f 66 20 54 65 72 6d 4f 66 66 73 65 74 20 69 74  of TermOffset it
b750: 65 72 61 74 6f 72 73 2e 20 2a 2f 0a 20 20 73 43  erators. */.  sC
b760: 74 78 2e 61 54 65 72 6d 20 3d 20 28 54 65 72 6d  tx.aTerm = (Term
b770: 4f 66 66 73 65 74 20 2a 29 73 71 6c 69 74 65 33  Offset *)sqlite3
b780: 5f 6d 61 6c 6c 6f 63 28 73 69 7a 65 6f 66 28 54  _malloc(sizeof(T
b790: 65 72 6d 4f 66 66 73 65 74 29 2a 6e 54 6f 6b 65  ermOffset)*nToke
b7a0: 6e 29 3b 0a 20 20 69 66 28 20 30 3d 3d 73 43 74  n);.  if( 0==sCt
b7b0: 78 2e 61 54 65 72 6d 20 29 7b 0a 20 20 20 20 72  x.aTerm ){.    r
b7c0: 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d  c = SQLITE_NOMEM
b7d0: 3b 0a 20 20 20 20 67 6f 74 6f 20 6f 66 66 73 65  ;.    goto offse
b7e0: 74 73 5f 6f 75 74 3b 0a 20 20 7d 0a 20 20 73 43  ts_out;.  }.  sC
b7f0: 74 78 2e 69 44 6f 63 69 64 20 3d 20 70 43 73 72  tx.iDocid = pCsr
b800: 2d 3e 69 50 72 65 76 49 64 3b 0a 20 20 73 43 74  ->iPrevId;.  sCt
b810: 78 2e 70 43 73 72 20 3d 20 70 43 73 72 3b 0a 0a  x.pCsr = pCsr;..
b820: 20 20 2f 2a 20 4c 6f 6f 70 20 74 68 72 6f 75 67    /* Loop throug
b830: 68 20 74 68 65 20 74 61 62 6c 65 20 63 6f 6c 75  h the table colu
b840: 6d 6e 73 2c 20 61 70 70 65 6e 64 69 6e 67 20 6f  mns, appending o
b850: 66 66 73 65 74 20 69 6e 66 6f 72 6d 61 74 69 6f  ffset informatio
b860: 6e 20 74 6f 20 0a 20 20 2a 2a 20 73 74 72 69 6e  n to .  ** strin
b870: 67 2d 62 75 66 66 65 72 20 72 65 73 20 66 6f 72  g-buffer res for
b880: 20 65 61 63 68 20 63 6f 6c 75 6d 6e 2e 0a 20 20   each column..  
b890: 2a 2f 0a 20 20 66 6f 72 28 69 43 6f 6c 3d 30 3b  */.  for(iCol=0;
b8a0: 20 69 43 6f 6c 3c 70 54 61 62 2d 3e 6e 43 6f 6c   iCol<pTab->nCol
b8b0: 75 6d 6e 3b 20 69 43 6f 6c 2b 2b 29 7b 0a 20 20  umn; iCol++){.  
b8c0: 20 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69    sqlite3_tokeni
b8d0: 7a 65 72 5f 63 75 72 73 6f 72 20 2a 70 43 3b 20  zer_cursor *pC; 
b8e0: 2f 2a 20 54 6f 6b 65 6e 69 7a 65 72 20 63 75 72  /* Tokenizer cur
b8f0: 73 6f 72 20 2a 2f 0a 20 20 20 20 63 6f 6e 73 74  sor */.    const
b900: 20 63 68 61 72 20 2a 5a 44 55 4d 4d 59 3b 20 20   char *ZDUMMY;  
b910: 20 20 20 20 20 20 20 20 20 2f 2a 20 44 75 6d 6d           /* Dumm
b920: 79 20 61 72 67 75 6d 65 6e 74 20 75 73 65 64 20  y argument used 
b930: 77 69 74 68 20 78 4e 65 78 74 28 29 20 2a 2f 0a  with xNext() */.
b940: 20 20 20 20 69 6e 74 20 4e 44 55 4d 4d 59 20 3d      int NDUMMY =
b950: 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   0;             
b960: 20 20 2f 2a 20 44 75 6d 6d 79 20 61 72 67 75 6d    /* Dummy argum
b970: 65 6e 74 20 75 73 65 64 20 77 69 74 68 20 78 4e  ent used with xN
b980: 65 78 74 28 29 20 2a 2f 0a 20 20 20 20 69 6e 74  ext() */.    int
b990: 20 69 53 74 61 72 74 20 3d 20 30 3b 0a 20 20 20   iStart = 0;.   
b9a0: 20 69 6e 74 20 69 45 6e 64 20 3d 20 30 3b 0a 20   int iEnd = 0;. 
b9b0: 20 20 20 69 6e 74 20 69 43 75 72 72 65 6e 74 20     int iCurrent 
b9c0: 3d 20 30 3b 0a 20 20 20 20 63 6f 6e 73 74 20 63  = 0;.    const c
b9d0: 68 61 72 20 2a 7a 44 6f 63 3b 0a 20 20 20 20 69  har *zDoc;.    i
b9e0: 6e 74 20 6e 44 6f 63 3b 0a 0a 20 20 20 20 2f 2a  nt nDoc;..    /*
b9f0: 20 49 6e 69 74 69 61 6c 69 7a 65 20 74 68 65 20   Initialize the 
ba00: 63 6f 6e 74 65 6e 74 73 20 6f 66 20 73 43 74 78  contents of sCtx
ba10: 2e 61 54 65 72 6d 5b 5d 20 66 6f 72 20 63 6f 6c  .aTerm[] for col
ba20: 75 6d 6e 20 69 43 6f 6c 2e 20 54 68 65 72 65 20  umn iCol. There 
ba30: 69 73 20 0a 20 20 20 20 2a 2a 20 6e 6f 20 77 61  is .    ** no wa
ba40: 79 20 74 68 61 74 20 74 68 69 73 20 6f 70 65 72  y that this oper
ba50: 61 74 69 6f 6e 20 63 61 6e 20 66 61 69 6c 2c 20  ation can fail, 
ba60: 73 6f 20 74 68 65 20 72 65 74 75 72 6e 20 63 6f  so the return co
ba70: 64 65 20 66 72 6f 6d 0a 20 20 20 20 2a 2a 20 66  de from.    ** f
ba80: 74 73 33 45 78 70 72 49 74 65 72 61 74 65 28 29  ts3ExprIterate()
ba90: 20 63 61 6e 20 62 65 20 64 69 73 63 61 72 64 65   can be discarde
baa0: 64 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20 73 43  d..    */.    sC
bab0: 74 78 2e 69 43 6f 6c 20 3d 20 69 43 6f 6c 3b 0a  tx.iCol = iCol;.
bac0: 20 20 20 20 73 43 74 78 2e 69 54 65 72 6d 20 3d      sCtx.iTerm =
bad0: 20 30 3b 0a 20 20 20 20 28 76 6f 69 64 29 66 74   0;.    (void)ft
bae0: 73 33 45 78 70 72 49 74 65 72 61 74 65 28 70 43  s3ExprIterate(pC
baf0: 73 72 2d 3e 70 45 78 70 72 2c 20 66 74 73 33 45  sr->pExpr, fts3E
bb00: 78 70 72 54 65 72 6d 4f 66 66 73 65 74 49 6e 69  xprTermOffsetIni
bb10: 74 2c 20 28 76 6f 69 64 20 2a 29 26 73 43 74 78  t, (void *)&sCtx
bb20: 29 3b 0a 0a 20 20 20 20 2f 2a 20 52 65 74 72 65  );..    /* Retre
bb30: 69 76 65 20 74 68 65 20 74 65 78 74 20 73 74 6f  ive the text sto
bb40: 72 65 64 20 69 6e 20 63 6f 6c 75 6d 6e 20 69 43  red in column iC
bb50: 6f 6c 2e 20 49 66 20 61 6e 20 53 51 4c 20 4e 55  ol. If an SQL NU
bb60: 4c 4c 20 69 73 20 73 74 6f 72 65 64 20 0a 20 20  LL is stored .  
bb70: 20 20 2a 2a 20 69 6e 20 63 6f 6c 75 6d 6e 20 69    ** in column i
bb80: 43 6f 6c 2c 20 6a 75 6d 70 20 69 6d 6d 65 64 69  Col, jump immedi
bb90: 61 74 65 6c 79 20 74 6f 20 74 68 65 20 6e 65 78  ately to the nex
bba0: 74 20 69 74 65 72 61 74 69 6f 6e 20 6f 66 20 74  t iteration of t
bbb0: 68 65 20 6c 6f 6f 70 2e 0a 20 20 20 20 2a 2a 20  he loop..    ** 
bbc0: 49 66 20 61 6e 20 4f 4f 4d 20 6f 63 63 75 72 73  If an OOM occurs
bbd0: 20 77 68 69 6c 65 20 72 65 74 72 69 65 76 69 6e   while retrievin
bbe0: 67 20 74 68 65 20 64 61 74 61 20 28 74 68 69 73  g the data (this
bbf0: 20 63 61 6e 20 68 61 70 70 65 6e 20 69 66 20 53   can happen if S
bc00: 51 4c 69 74 65 0a 20 20 20 20 2a 2a 20 6e 65 65  QLite.    ** nee
bc10: 64 73 20 74 6f 20 74 72 61 6e 73 66 6f 72 6d 20  ds to transform 
bc20: 74 68 65 20 64 61 74 61 20 66 72 6f 6d 20 75 74  the data from ut
bc30: 66 2d 31 36 20 74 6f 20 75 74 66 2d 38 29 2c 20  f-16 to utf-8), 
bc40: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f  return SQLITE_NO
bc50: 4d 45 4d 20 0a 20 20 20 20 2a 2a 20 74 6f 20 74  MEM .    ** to t
bc60: 68 65 20 63 61 6c 6c 65 72 2e 20 0a 20 20 20 20  he caller. .    
bc70: 2a 2f 0a 20 20 20 20 7a 44 6f 63 20 3d 20 28 63  */.    zDoc = (c
bc80: 6f 6e 73 74 20 63 68 61 72 20 2a 29 73 71 6c 69  onst char *)sqli
bc90: 74 65 33 5f 63 6f 6c 75 6d 6e 5f 74 65 78 74 28  te3_column_text(
bca0: 70 43 73 72 2d 3e 70 53 74 6d 74 2c 20 69 43 6f  pCsr->pStmt, iCo
bcb0: 6c 2b 31 29 3b 0a 20 20 20 20 6e 44 6f 63 20 3d  l+1);.    nDoc =
bcc0: 20 73 71 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f   sqlite3_column_
bcd0: 62 79 74 65 73 28 70 43 73 72 2d 3e 70 53 74 6d  bytes(pCsr->pStm
bce0: 74 2c 20 69 43 6f 6c 2b 31 29 3b 0a 20 20 20 20  t, iCol+1);.    
bcf0: 69 66 28 20 7a 44 6f 63 3d 3d 30 20 29 7b 0a 20  if( zDoc==0 ){. 
bd00: 20 20 20 20 20 69 66 28 20 73 71 6c 69 74 65 33       if( sqlite3
bd10: 5f 63 6f 6c 75 6d 6e 5f 74 79 70 65 28 70 43 73  _column_type(pCs
bd20: 72 2d 3e 70 53 74 6d 74 2c 20 69 43 6f 6c 2b 31  r->pStmt, iCol+1
bd30: 29 3d 3d 53 51 4c 49 54 45 5f 4e 55 4c 4c 20 29  )==SQLITE_NULL )
bd40: 7b 0a 20 20 20 20 20 20 20 20 63 6f 6e 74 69 6e  {.        contin
bd50: 75 65 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  ue;.      }.    
bd60: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f    rc = SQLITE_NO
bd70: 4d 45 4d 3b 0a 20 20 20 20 20 20 67 6f 74 6f 20  MEM;.      goto 
bd80: 6f 66 66 73 65 74 73 5f 6f 75 74 3b 0a 20 20 20  offsets_out;.   
bd90: 20 7d 0a 0a 20 20 20 20 2f 2a 20 49 6e 69 74 69   }..    /* Initi
bda0: 61 6c 69 7a 65 20 61 20 74 6f 6b 65 6e 69 7a 65  alize a tokenize
bdb0: 72 20 69 74 65 72 61 74 6f 72 20 74 6f 20 69 74  r iterator to it
bdc0: 65 72 61 74 65 20 74 68 72 6f 75 67 68 20 63 6f  erate through co
bdd0: 6c 75 6d 6e 20 69 43 6f 6c 2e 20 2a 2f 0a 20 20  lumn iCol. */.  
bde0: 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 46 74    rc = sqlite3Ft
bdf0: 73 33 4f 70 65 6e 54 6f 6b 65 6e 69 7a 65 72 28  s3OpenTokenizer(
be00: 70 54 61 62 2d 3e 70 54 6f 6b 65 6e 69 7a 65 72  pTab->pTokenizer
be10: 2c 20 70 43 73 72 2d 3e 69 4c 61 6e 67 69 64 2c  , pCsr->iLangid,
be20: 0a 20 20 20 20 20 20 20 20 7a 44 6f 63 2c 20 6e  .        zDoc, n
be30: 44 6f 63 2c 20 26 70 43 0a 20 20 20 20 29 3b 0a  Doc, &pC.    );.
be40: 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49      if( rc!=SQLI
be50: 54 45 5f 4f 4b 20 29 20 67 6f 74 6f 20 6f 66 66  TE_OK ) goto off
be60: 73 65 74 73 5f 6f 75 74 3b 0a 0a 20 20 20 20 72  sets_out;..    r
be70: 63 20 3d 20 70 4d 6f 64 2d 3e 78 4e 65 78 74 28  c = pMod->xNext(
be80: 70 43 2c 20 26 5a 44 55 4d 4d 59 2c 20 26 4e 44  pC, &ZDUMMY, &ND
be90: 55 4d 4d 59 2c 20 26 69 53 74 61 72 74 2c 20 26  UMMY, &iStart, &
bea0: 69 45 6e 64 2c 20 26 69 43 75 72 72 65 6e 74 29  iEnd, &iCurrent)
beb0: 3b 0a 20 20 20 20 77 68 69 6c 65 28 20 72 63 3d  ;.    while( rc=
bec0: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
bed0: 20 20 20 20 69 6e 74 20 69 3b 20 20 20 20 20 20      int i;      
bee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
bef0: 2f 2a 20 55 73 65 64 20 74 6f 20 6c 6f 6f 70 20  /* Used to loop 
bf00: 74 68 72 6f 75 67 68 20 74 65 72 6d 73 20 2a 2f  through terms */
bf10: 0a 20 20 20 20 20 20 69 6e 74 20 69 4d 69 6e 50  .      int iMinP
bf20: 6f 73 20 3d 20 30 78 37 46 46 46 46 46 46 46 3b  os = 0x7FFFFFFF;
bf30: 20 20 20 2f 2a 20 50 6f 73 69 74 69 6f 6e 20 6f     /* Position o
bf40: 66 20 6e 65 78 74 20 74 6f 6b 65 6e 20 2a 2f 0a  f next token */.
bf50: 20 20 20 20 20 20 54 65 72 6d 4f 66 66 73 65 74        TermOffset
bf60: 20 2a 70 54 65 72 6d 20 3d 20 30 3b 20 20 20 20   *pTerm = 0;    
bf70: 20 20 2f 2a 20 54 65 72 6d 4f 66 66 73 65 74 20    /* TermOffset 
bf80: 61 73 73 6f 63 69 61 74 65 64 20 77 69 74 68 20  associated with 
bf90: 6e 65 78 74 20 74 6f 6b 65 6e 20 2a 2f 0a 0a 20  next token */.. 
bfa0: 20 20 20 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c       for(i=0; i<
bfb0: 6e 54 6f 6b 65 6e 3b 20 69 2b 2b 29 7b 0a 20 20  nToken; i++){.  
bfc0: 20 20 20 20 20 20 54 65 72 6d 4f 66 66 73 65 74        TermOffset
bfd0: 20 2a 70 54 20 3d 20 26 73 43 74 78 2e 61 54 65   *pT = &sCtx.aTe
bfe0: 72 6d 5b 69 5d 3b 0a 20 20 20 20 20 20 20 20 69  rm[i];.        i
bff0: 66 28 20 70 54 2d 3e 70 4c 69 73 74 20 26 26 20  f( pT->pList && 
c000: 28 70 54 2d 3e 69 50 6f 73 2d 70 54 2d 3e 69 4f  (pT->iPos-pT->iO
c010: 66 66 29 3c 69 4d 69 6e 50 6f 73 20 29 7b 0a 20  ff)<iMinPos ){. 
c020: 20 20 20 20 20 20 20 20 20 69 4d 69 6e 50 6f 73           iMinPos
c030: 20 3d 20 70 54 2d 3e 69 50 6f 73 2d 70 54 2d 3e   = pT->iPos-pT->
c040: 69 4f 66 66 3b 0a 20 20 20 20 20 20 20 20 20 20  iOff;.          
c050: 70 54 65 72 6d 20 3d 20 70 54 3b 0a 20 20 20 20  pTerm = pT;.    
c060: 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 0a 20      }.      }.. 
c070: 20 20 20 20 20 69 66 28 20 21 70 54 65 72 6d 20       if( !pTerm 
c080: 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20 41 6c  ){.        /* Al
c090: 6c 20 6f 66 66 73 65 74 73 20 66 6f 72 20 74 68  l offsets for th
c0a0: 69 73 20 63 6f 6c 75 6d 6e 20 68 61 76 65 20 62  is column have b
c0b0: 65 65 6e 20 67 61 74 68 65 72 65 64 2e 20 2a 2f  een gathered. */
c0c0: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51  .        rc = SQ
c0d0: 4c 49 54 45 5f 44 4f 4e 45 3b 0a 20 20 20 20 20  LITE_DONE;.     
c0e0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
c0f0: 61 73 73 65 72 74 28 20 69 43 75 72 72 65 6e 74  assert( iCurrent
c100: 3c 3d 69 4d 69 6e 50 6f 73 20 29 3b 0a 20 20 20  <=iMinPos );.   
c110: 20 20 20 20 20 69 66 28 20 30 3d 3d 28 30 78 46       if( 0==(0xF
c120: 45 26 2a 70 54 65 72 6d 2d 3e 70 4c 69 73 74 29  E&*pTerm->pList)
c130: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 70 54   ){.          pT
c140: 65 72 6d 2d 3e 70 4c 69 73 74 20 3d 20 30 3b 0a  erm->pList = 0;.
c150: 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20          }else{. 
c160: 20 20 20 20 20 20 20 20 20 66 74 73 33 47 65 74           fts3Get
c170: 44 65 6c 74 61 50 6f 73 69 74 69 6f 6e 28 26 70  DeltaPosition(&p
c180: 54 65 72 6d 2d 3e 70 4c 69 73 74 2c 20 26 70 54  Term->pList, &pT
c190: 65 72 6d 2d 3e 69 50 6f 73 29 3b 0a 20 20 20 20  erm->iPos);.    
c1a0: 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 77 68      }.        wh
c1b0: 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f  ile( rc==SQLITE_
c1c0: 4f 4b 20 26 26 20 69 43 75 72 72 65 6e 74 3c 69  OK && iCurrent<i
c1d0: 4d 69 6e 50 6f 73 20 29 7b 0a 20 20 20 20 20 20  MinPos ){.      
c1e0: 20 20 20 20 72 63 20 3d 20 70 4d 6f 64 2d 3e 78      rc = pMod->x
c1f0: 4e 65 78 74 28 70 43 2c 20 26 5a 44 55 4d 4d 59  Next(pC, &ZDUMMY
c200: 2c 20 26 4e 44 55 4d 4d 59 2c 20 26 69 53 74 61  , &NDUMMY, &iSta
c210: 72 74 2c 20 26 69 45 6e 64 2c 20 26 69 43 75 72  rt, &iEnd, &iCur
c220: 72 65 6e 74 29 3b 0a 20 20 20 20 20 20 20 20 7d  rent);.        }
c230: 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63 3d  .        if( rc=
c240: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
c250: 20 20 20 20 20 20 20 20 63 68 61 72 20 61 42 75          char aBu
c260: 66 66 65 72 5b 36 34 5d 3b 0a 20 20 20 20 20 20  ffer[64];.      
c270: 20 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72      sqlite3_snpr
c280: 69 6e 74 66 28 73 69 7a 65 6f 66 28 61 42 75 66  intf(sizeof(aBuf
c290: 66 65 72 29 2c 20 61 42 75 66 66 65 72 2c 20 0a  fer), aBuffer, .
c2a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 25                "%
c2b0: 64 20 25 64 20 25 64 20 25 64 20 22 2c 20 69 43  d %d %d %d ", iC
c2c0: 6f 6c 2c 20 70 54 65 72 6d 2d 73 43 74 78 2e 61  ol, pTerm-sCtx.a
c2d0: 54 65 72 6d 2c 20 69 53 74 61 72 74 2c 20 69 45  Term, iStart, iE
c2e0: 6e 64 2d 69 53 74 61 72 74 0a 20 20 20 20 20 20  nd-iStart.      
c2f0: 20 20 20 20 29 3b 0a 20 20 20 20 20 20 20 20 20      );.         
c300: 20 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67   rc = fts3String
c310: 41 70 70 65 6e 64 28 26 72 65 73 2c 20 61 42 75  Append(&res, aBu
c320: 66 66 65 72 2c 20 2d 31 29 3b 0a 20 20 20 20 20  ffer, -1);.     
c330: 20 20 20 7d 65 6c 73 65 20 69 66 28 20 72 63 3d     }else if( rc=
c340: 3d 53 51 4c 49 54 45 5f 44 4f 4e 45 20 26 26 20  =SQLITE_DONE && 
c350: 70 54 61 62 2d 3e 7a 43 6f 6e 74 65 6e 74 54 62  pTab->zContentTb
c360: 6c 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20  l==0 ){.        
c370: 20 20 72 63 20 3d 20 46 54 53 5f 43 4f 52 52 55    rc = FTS_CORRU
c380: 50 54 5f 56 54 41 42 3b 0a 20 20 20 20 20 20 20  PT_VTAB;.       
c390: 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d   }.      }.    }
c3a0: 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  .    if( rc==SQL
c3b0: 49 54 45 5f 44 4f 4e 45 20 29 7b 0a 20 20 20 20  ITE_DONE ){.    
c3c0: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b    rc = SQLITE_OK
c3d0: 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20 70 4d 6f  ;.    }..    pMo
c3e0: 64 2d 3e 78 43 6c 6f 73 65 28 70 43 29 3b 0a 20  d->xClose(pC);. 
c3f0: 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54     if( rc!=SQLIT
c400: 45 5f 4f 4b 20 29 20 67 6f 74 6f 20 6f 66 66 73  E_OK ) goto offs
c410: 65 74 73 5f 6f 75 74 3b 0a 20 20 7d 0a 0a 20 6f  ets_out;.  }.. o
c420: 66 66 73 65 74 73 5f 6f 75 74 3a 0a 20 20 73 71  ffsets_out:.  sq
c430: 6c 69 74 65 33 5f 66 72 65 65 28 73 43 74 78 2e  lite3_free(sCtx.
c440: 61 54 65 72 6d 29 3b 0a 20 20 61 73 73 65 72 74  aTerm);.  assert
c450: 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 44 4f 4e  ( rc!=SQLITE_DON
c460: 45 20 29 3b 0a 20 20 73 71 6c 69 74 65 33 46 74  E );.  sqlite3Ft
c470: 73 33 53 65 67 6d 65 6e 74 73 43 6c 6f 73 65 28  s3SegmentsClose(
c480: 70 54 61 62 29 3b 0a 20 20 69 66 28 20 72 63 21  pTab);.  if( rc!
c490: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
c4a0: 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74    sqlite3_result
c4b0: 5f 65 72 72 6f 72 5f 63 6f 64 65 28 70 43 74 78  _error_code(pCtx
c4c0: 2c 20 20 72 63 29 3b 0a 20 20 20 20 73 71 6c 69  ,  rc);.    sqli
c4d0: 74 65 33 5f 66 72 65 65 28 72 65 73 2e 7a 29 3b  te3_free(res.z);
c4e0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 73 71  .  }else{.    sq
c4f0: 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 74 65 78  lite3_result_tex
c500: 74 28 70 43 74 78 2c 20 72 65 73 2e 7a 2c 20 72  t(pCtx, res.z, r
c510: 65 73 2e 6e 2d 31 2c 20 73 71 6c 69 74 65 33 5f  es.n-1, sqlite3_
c520: 66 72 65 65 29 3b 0a 20 20 7d 0a 20 20 72 65 74  free);.  }.  ret
c530: 75 72 6e 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6d  urn;.}../*.** Im
c540: 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20  plementation of 
c550: 6d 61 74 63 68 69 6e 66 6f 28 29 20 66 75 6e 63  matchinfo() func
c560: 74 69 6f 6e 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71  tion..*/.void sq
c570: 6c 69 74 65 33 46 74 73 33 4d 61 74 63 68 69 6e  lite3Fts3Matchin
c580: 66 6f 28 0a 20 20 73 71 6c 69 74 65 33 5f 63 6f  fo(.  sqlite3_co
c590: 6e 74 65 78 74 20 2a 70 43 6f 6e 74 65 78 74 2c  ntext *pContext,
c5a0: 20 20 20 20 20 20 2f 2a 20 46 75 6e 63 74 69 6f        /* Functio
c5b0: 6e 20 63 61 6c 6c 20 63 6f 6e 74 65 78 74 20 2a  n call context *
c5c0: 2f 0a 20 20 46 74 73 33 43 75 72 73 6f 72 20 2a  /.  Fts3Cursor *
c5d0: 70 43 73 72 2c 20 20 20 20 20 20 20 20 20 20 20  pCsr,           
c5e0: 20 20 20 20 2f 2a 20 46 54 53 33 20 74 61 62 6c      /* FTS3 tabl
c5f0: 65 20 63 75 72 73 6f 72 20 2a 2f 0a 20 20 63 6f  e cursor */.  co
c600: 6e 73 74 20 63 68 61 72 20 2a 7a 41 72 67 20 20  nst char *zArg  
c610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
c620: 20 53 65 63 6f 6e 64 20 61 72 67 20 74 6f 20 6d   Second arg to m
c630: 61 74 63 68 69 6e 66 6f 28 29 20 66 75 6e 63 74  atchinfo() funct
c640: 69 6f 6e 20 2a 2f 0a 29 7b 0a 20 20 46 74 73 33  ion */.){.  Fts3
c650: 54 61 62 6c 65 20 2a 70 54 61 62 20 3d 20 28 46  Table *pTab = (F
c660: 74 73 33 54 61 62 6c 65 20 2a 29 70 43 73 72 2d  ts3Table *)pCsr-
c670: 3e 62 61 73 65 2e 70 56 74 61 62 3b 0a 20 20 69  >base.pVtab;.  i
c680: 6e 74 20 72 63 3b 0a 20 20 69 6e 74 20 69 3b 0a  nt rc;.  int i;.
c690: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 46    const char *zF
c6a0: 6f 72 6d 61 74 3b 0a 0a 20 20 69 66 28 20 7a 41  ormat;..  if( zA
c6b0: 72 67 20 29 7b 0a 20 20 20 20 66 6f 72 28 69 3d  rg ){.    for(i=
c6c0: 30 3b 20 7a 41 72 67 5b 69 5d 3b 20 69 2b 2b 29  0; zArg[i]; i++)
c6d0: 7b 0a 20 20 20 20 20 20 63 68 61 72 20 2a 7a 45  {.      char *zE
c6e0: 72 72 20 3d 20 30 3b 0a 20 20 20 20 20 20 69 66  rr = 0;.      if
c6f0: 28 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 43  ( fts3MatchinfoC
c700: 68 65 63 6b 28 70 54 61 62 2c 20 7a 41 72 67 5b  heck(pTab, zArg[
c710: 69 5d 2c 20 26 7a 45 72 72 29 20 29 7b 0a 20 20  i], &zErr) ){.  
c720: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 72 65        sqlite3_re
c730: 73 75 6c 74 5f 65 72 72 6f 72 28 70 43 6f 6e 74  sult_error(pCont
c740: 65 78 74 2c 20 7a 45 72 72 2c 20 2d 31 29 3b 0a  ext, zErr, -1);.
c750: 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f          sqlite3_
c760: 66 72 65 65 28 7a 45 72 72 29 3b 0a 20 20 20 20  free(zErr);.    
c770: 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 20 20      return;.    
c780: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 7a 46    }.    }.    zF
c790: 6f 72 6d 61 74 20 3d 20 7a 41 72 67 3b 0a 20 20  ormat = zArg;.  
c7a0: 7d 65 6c 73 65 7b 0a 20 20 20 20 7a 46 6f 72 6d  }else{.    zForm
c7b0: 61 74 20 3d 20 46 54 53 33 5f 4d 41 54 43 48 49  at = FTS3_MATCHI
c7c0: 4e 46 4f 5f 44 45 46 41 55 4c 54 3b 0a 20 20 7d  NFO_DEFAULT;.  }
c7d0: 0a 0a 20 20 69 66 28 20 21 70 43 73 72 2d 3e 70  ..  if( !pCsr->p
c7e0: 45 78 70 72 20 29 7b 0a 20 20 20 20 73 71 6c 69  Expr ){.    sqli
c7f0: 74 65 33 5f 72 65 73 75 6c 74 5f 62 6c 6f 62 28  te3_result_blob(
c800: 70 43 6f 6e 74 65 78 74 2c 20 22 22 2c 20 30 2c  pContext, "", 0,
c810: 20 53 51 4c 49 54 45 5f 53 54 41 54 49 43 29 3b   SQLITE_STATIC);
c820: 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d  .    return;.  }
c830: 0a 0a 20 20 2f 2a 20 52 65 74 72 69 65 76 65 20  ..  /* Retrieve 
c840: 6d 61 74 63 68 69 6e 66 6f 28 29 20 64 61 74 61  matchinfo() data
c850: 2e 20 2a 2f 0a 20 20 72 63 20 3d 20 66 74 73 33  . */.  rc = fts3
c860: 47 65 74 4d 61 74 63 68 69 6e 66 6f 28 70 43 73  GetMatchinfo(pCs
c870: 72 2c 20 7a 46 6f 72 6d 61 74 29 3b 0a 20 20 73  r, zFormat);.  s
c880: 71 6c 69 74 65 33 46 74 73 33 53 65 67 6d 65 6e  qlite3Fts3Segmen
c890: 74 73 43 6c 6f 73 65 28 70 54 61 62 29 3b 0a 0a  tsClose(pTab);..
c8a0: 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45    if( rc!=SQLITE
c8b0: 5f 4f 4b 20 29 7b 0a 20 20 20 20 73 71 6c 69 74  _OK ){.    sqlit
c8c0: 65 33 5f 72 65 73 75 6c 74 5f 65 72 72 6f 72 5f  e3_result_error_
c8d0: 63 6f 64 65 28 70 43 6f 6e 74 65 78 74 2c 20 72  code(pContext, r
c8e0: 63 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  c);.  }else{.   
c8f0: 20 69 6e 74 20 6e 20 3d 20 70 43 73 72 2d 3e 6e   int n = pCsr->n
c900: 4d 61 74 63 68 69 6e 66 6f 20 2a 20 73 69 7a 65  Matchinfo * size
c910: 6f 66 28 75 33 32 29 3b 0a 20 20 20 20 73 71 6c  of(u32);.    sql
c920: 69 74 65 33 5f 72 65 73 75 6c 74 5f 62 6c 6f 62  ite3_result_blob
c930: 28 70 43 6f 6e 74 65 78 74 2c 20 70 43 73 72 2d  (pContext, pCsr-
c940: 3e 61 4d 61 74 63 68 69 6e 66 6f 2c 20 6e 2c 20  >aMatchinfo, n, 
c950: 53 51 4c 49 54 45 5f 54 52 41 4e 53 49 45 4e 54  SQLITE_TRANSIENT
c960: 29 3b 0a 20 20 7d 0a 7d 0a 0a 23 65 6e 64 69 66  );.  }.}..#endif
c970: 0a                                               .