/ Hex Artifact Content
Login

Artifact bf67520ae9d2352a65368ed101729ff701c08808:


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 2c 20 44 55 4d   int DUMMY1, DUM
4ed0: 4d 59 32 2c 20 44 55 4d 4d 59 33 3b 0a 20 20 20  MY2, DUMMY3;.   
4ee0: 20 20 20 20 20 72 63 20 3d 20 70 4d 6f 64 2d 3e       rc = pMod->
4ef0: 78 4e 65 78 74 28 70 43 2c 20 26 5a 44 55 4d 4d  xNext(pC, &ZDUMM
4f00: 59 2c 20 26 44 55 4d 4d 59 31 2c 20 26 44 55 4d  Y, &DUMMY1, &DUM
4f10: 4d 59 32 2c 20 26 44 55 4d 4d 59 33 2c 20 26 69  MY2, &DUMMY3, &i
4f20: 43 75 72 72 65 6e 74 29 3b 0a 20 20 20 20 20 20  Current);.      
4f30: 7d 0a 20 20 20 20 20 20 70 4d 6f 64 2d 3e 78 43  }.      pMod->xC
4f40: 6c 6f 73 65 28 70 43 29 3b 0a 20 20 20 20 20 20  lose(pC);.      
4f50: 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f  if( rc!=SQLITE_O
4f60: 4b 20 26 26 20 72 63 21 3d 53 51 4c 49 54 45 5f  K && rc!=SQLITE_
4f70: 44 4f 4e 45 20 29 7b 20 72 65 74 75 72 6e 20 72  DONE ){ return r
4f80: 63 3b 20 7d 0a 0a 20 20 20 20 20 20 6e 53 68 69  c; }..      nShi
4f90: 66 74 20 3d 20 28 72 63 3d 3d 53 51 4c 49 54 45  ft = (rc==SQLITE
4fa0: 5f 44 4f 4e 45 29 2b 69 43 75 72 72 65 6e 74 2d  _DONE)+iCurrent-
4fb0: 6e 53 6e 69 70 70 65 74 3b 0a 20 20 20 20 20 20  nSnippet;.      
4fc0: 61 73 73 65 72 74 28 20 6e 53 68 69 66 74 3c 3d  assert( nShift<=
4fd0: 6e 44 65 73 69 72 65 64 20 29 3b 0a 20 20 20 20  nDesired );.    
4fe0: 20 20 69 66 28 20 6e 53 68 69 66 74 3e 30 20 29    if( nShift>0 )
4ff0: 7b 0a 20 20 20 20 20 20 20 20 2a 70 69 50 6f 73  {.        *piPos
5000: 20 2b 3d 20 6e 53 68 69 66 74 3b 0a 20 20 20 20   += nShift;.    
5010: 20 20 20 20 2a 70 48 6c 6d 61 73 6b 20 3d 20 68      *pHlmask = h
5020: 6c 6d 61 73 6b 20 3e 3e 20 6e 53 68 69 66 74 3b  lmask >> nShift;
5030: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
5040: 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49   }.  return SQLI
5050: 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  TE_OK;.}../*.** 
5060: 45 78 74 72 61 63 74 20 74 68 65 20 73 6e 69 70  Extract the snip
5070: 70 65 74 20 74 65 78 74 20 66 6f 72 20 66 72 61  pet text for fra
5080: 67 6d 65 6e 74 20 70 46 72 61 67 6d 65 6e 74 20  gment pFragment 
5090: 66 72 6f 6d 20 63 75 72 73 6f 72 20 70 43 73 72  from cursor pCsr
50a0: 20 61 6e 64 0a 2a 2a 20 61 70 70 65 6e 64 20 69   and.** append i
50b0: 74 20 74 6f 20 73 74 72 69 6e 67 20 62 75 66 66  t to string buff
50c0: 65 72 20 70 4f 75 74 2e 0a 2a 2f 0a 73 74 61 74  er pOut..*/.stat
50d0: 69 63 20 69 6e 74 20 66 74 73 33 53 6e 69 70 70  ic int fts3Snipp
50e0: 65 74 54 65 78 74 28 0a 20 20 46 74 73 33 43 75  etText(.  Fts3Cu
50f0: 72 73 6f 72 20 2a 70 43 73 72 2c 20 20 20 20 20  rsor *pCsr,     
5100: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 54 53            /* FTS
5110: 33 20 43 75 72 73 6f 72 20 2a 2f 0a 20 20 53 6e  3 Cursor */.  Sn
5120: 69 70 70 65 74 46 72 61 67 6d 65 6e 74 20 2a 70  ippetFragment *p
5130: 46 72 61 67 6d 65 6e 74 2c 20 20 20 20 20 2f 2a  Fragment,     /*
5140: 20 53 6e 69 70 70 65 74 20 74 6f 20 65 78 74 72   Snippet to extr
5150: 61 63 74 20 2a 2f 0a 20 20 69 6e 74 20 69 46 72  act */.  int iFr
5160: 61 67 6d 65 6e 74 2c 20 20 20 20 20 20 20 20 20  agment,         
5170: 20 20 20 20 20 20 20 20 20 2f 2a 20 46 72 61 67           /* Frag
5180: 6d 65 6e 74 20 6e 75 6d 62 65 72 20 2a 2f 0a 20  ment number */. 
5190: 20 69 6e 74 20 69 73 4c 61 73 74 2c 20 20 20 20   int isLast,    
51a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
51b0: 20 2f 2a 20 54 72 75 65 20 66 6f 72 20 66 69 6e   /* True for fin
51c0: 61 6c 20 66 72 61 67 6d 65 6e 74 20 69 6e 20 73  al fragment in s
51d0: 6e 69 70 70 65 74 20 2a 2f 0a 20 20 69 6e 74 20  nippet */.  int 
51e0: 6e 53 6e 69 70 70 65 74 2c 20 20 20 20 20 20 20  nSnippet,       
51f0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
5200: 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20  umber of tokens 
5210: 69 6e 20 65 78 74 72 61 63 74 65 64 20 73 6e 69  in extracted sni
5220: 70 70 65 74 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  ppet */.  const 
5230: 63 68 61 72 20 2a 7a 4f 70 65 6e 2c 20 20 20 20  char *zOpen,    
5240: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 74 72            /* Str
5250: 69 6e 67 20 69 6e 73 65 72 74 65 64 20 62 65 66  ing inserted bef
5260: 6f 72 65 20 68 69 67 68 6c 69 67 68 74 65 64 20  ore highlighted 
5270: 74 65 72 6d 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  term */.  const 
5280: 63 68 61 72 20 2a 7a 43 6c 6f 73 65 2c 20 20 20  char *zClose,   
5290: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 74 72            /* Str
52a0: 69 6e 67 20 69 6e 73 65 72 74 65 64 20 61 66 74  ing inserted aft
52b0: 65 72 20 68 69 67 68 6c 69 67 68 74 65 64 20 74  er highlighted t
52c0: 65 72 6d 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  erm */.  const c
52d0: 68 61 72 20 2a 7a 45 6c 6c 69 70 73 69 73 2c 20  har *zEllipsis, 
52e0: 20 20 20 20 20 20 20 20 20 2f 2a 20 53 74 72 69           /* Stri
52f0: 6e 67 20 69 6e 73 65 72 74 65 64 20 62 65 74 77  ng inserted betw
5300: 65 65 6e 20 73 6e 69 70 70 65 74 73 20 2a 2f 0a  een snippets */.
5310: 20 20 53 74 72 42 75 66 66 65 72 20 2a 70 4f 75    StrBuffer *pOu
5320: 74 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  t               
5330: 20 20 2f 2a 20 57 72 69 74 65 20 6f 75 74 70 75    /* Write outpu
5340: 74 20 68 65 72 65 20 2a 2f 0a 29 7b 0a 20 20 46  t here */.){.  F
5350: 74 73 33 54 61 62 6c 65 20 2a 70 54 61 62 20 3d  ts3Table *pTab =
5360: 20 28 46 74 73 33 54 61 62 6c 65 20 2a 29 70 43   (Fts3Table *)pC
5370: 73 72 2d 3e 62 61 73 65 2e 70 56 74 61 62 3b 0a  sr->base.pVtab;.
5380: 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20    int rc;       
5390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
53a0: 20 20 2f 2a 20 52 65 74 75 72 6e 20 63 6f 64 65    /* Return code
53b0: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
53c0: 20 2a 7a 44 6f 63 3b 20 20 20 20 20 20 20 20 20   *zDoc;         
53d0: 20 20 20 20 20 20 2f 2a 20 44 6f 63 75 6d 65 6e        /* Documen
53e0: 74 20 74 65 78 74 20 74 6f 20 65 78 74 72 61 63  t text to extrac
53f0: 74 20 73 6e 69 70 70 65 74 20 66 72 6f 6d 20 2a  t snippet from *
5400: 2f 0a 20 20 69 6e 74 20 6e 44 6f 63 3b 20 20 20  /.  int nDoc;   
5410: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5420: 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20 7a      /* Size of z
5430: 44 6f 63 20 69 6e 20 62 79 74 65 73 20 2a 2f 0a  Doc in bytes */.
5440: 20 20 69 6e 74 20 69 43 75 72 72 65 6e 74 20 3d    int iCurrent =
5450: 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   0;             
5460: 20 20 2f 2a 20 43 75 72 72 65 6e 74 20 74 6f 6b    /* Current tok
5470: 65 6e 20 6e 75 6d 62 65 72 20 6f 66 20 64 6f 63  en number of doc
5480: 75 6d 65 6e 74 20 2a 2f 0a 20 20 69 6e 74 20 69  ument */.  int i
5490: 45 6e 64 20 3d 20 30 3b 20 20 20 20 20 20 20 20  End = 0;        
54a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 42 79             /* By
54b0: 74 65 20 6f 66 66 73 65 74 20 6f 66 20 65 6e 64  te offset of end
54c0: 20 6f 66 20 63 75 72 72 65 6e 74 20 74 6f 6b 65   of current toke
54d0: 6e 20 2a 2f 0a 20 20 69 6e 74 20 69 73 53 68 69  n */.  int isShi
54e0: 66 74 44 6f 6e 65 20 3d 20 30 3b 20 20 20 20 20  ftDone = 0;     
54f0: 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 61         /* True a
5500: 66 74 65 72 20 73 6e 69 70 70 65 74 20 69 73 20  fter snippet is 
5510: 73 68 69 66 74 65 64 20 2a 2f 0a 20 20 69 6e 74  shifted */.  int
5520: 20 69 50 6f 73 20 3d 20 70 46 72 61 67 6d 65 6e   iPos = pFragmen
5530: 74 2d 3e 69 50 6f 73 3b 20 20 20 20 20 2f 2a 20  t->iPos;     /* 
5540: 46 69 72 73 74 20 74 6f 6b 65 6e 20 6f 66 20 73  First token of s
5550: 6e 69 70 70 65 74 20 2a 2f 0a 20 20 75 36 34 20  nippet */.  u64 
5560: 68 6c 6d 61 73 6b 20 3d 20 70 46 72 61 67 6d 65  hlmask = pFragme
5570: 6e 74 2d 3e 68 6c 6d 61 73 6b 3b 20 2f 2a 20 48  nt->hlmask; /* H
5580: 69 67 68 6c 69 67 68 74 2d 6d 61 73 6b 20 66 6f  ighlight-mask fo
5590: 72 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20 69  r snippet */.  i
55a0: 6e 74 20 69 43 6f 6c 20 3d 20 70 46 72 61 67 6d  nt iCol = pFragm
55b0: 65 6e 74 2d 3e 69 43 6f 6c 2b 31 3b 20 20 20 2f  ent->iCol+1;   /
55c0: 2a 20 51 75 65 72 79 20 63 6f 6c 75 6d 6e 20 74  * Query column t
55d0: 6f 20 65 78 74 72 61 63 74 20 74 65 78 74 20 66  o extract text f
55e0: 72 6f 6d 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33  rom */.  sqlite3
55f0: 5f 74 6f 6b 65 6e 69 7a 65 72 5f 6d 6f 64 75 6c  _tokenizer_modul
5600: 65 20 2a 70 4d 6f 64 3b 20 2f 2a 20 54 6f 6b 65  e *pMod; /* Toke
5610: 6e 69 7a 65 72 20 6d 6f 64 75 6c 65 20 6d 65 74  nizer module met
5620: 68 6f 64 73 20 6f 62 6a 65 63 74 20 2a 2f 0a 20  hods object */. 
5630: 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a   sqlite3_tokeniz
5640: 65 72 5f 63 75 72 73 6f 72 20 2a 70 43 3b 20 20  er_cursor *pC;  
5650: 20 2f 2a 20 54 6f 6b 65 6e 69 7a 65 72 20 63 75   /* Tokenizer cu
5660: 72 73 6f 72 20 6f 70 65 6e 20 6f 6e 20 7a 44 6f  rsor open on zDo
5670: 63 2f 6e 44 6f 63 20 2a 2f 0a 20 20 63 6f 6e 73  c/nDoc */.  cons
5680: 74 20 63 68 61 72 20 2a 5a 44 55 4d 4d 59 3b 20  t char *ZDUMMY; 
5690: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44              /* D
56a0: 75 6d 6d 79 20 61 72 67 75 6d 65 6e 74 20 75 73  ummy argument us
56b0: 65 64 20 77 69 74 68 20 74 6f 6b 65 6e 69 7a 65  ed with tokenize
56c0: 72 20 2a 2f 0a 20 20 69 6e 74 20 44 55 4d 4d 59  r */.  int DUMMY
56d0: 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1;              
56e0: 20 20 20 20 20 20 20 2f 2a 20 44 75 6d 6d 79 20         /* Dummy 
56f0: 61 72 67 75 6d 65 6e 74 20 75 73 65 64 20 77 69  argument used wi
5700: 74 68 20 74 6f 6b 65 6e 69 7a 65 72 20 2a 2f 0a  th tokenizer */.
5710: 20 20 0a 20 20 7a 44 6f 63 20 3d 20 28 63 6f 6e    .  zDoc = (con
5720: 73 74 20 63 68 61 72 20 2a 29 73 71 6c 69 74 65  st char *)sqlite
5730: 33 5f 63 6f 6c 75 6d 6e 5f 74 65 78 74 28 70 43  3_column_text(pC
5740: 73 72 2d 3e 70 53 74 6d 74 2c 20 69 43 6f 6c 29  sr->pStmt, iCol)
5750: 3b 0a 20 20 69 66 28 20 7a 44 6f 63 3d 3d 30 20  ;.  if( zDoc==0 
5760: 29 7b 0a 20 20 20 20 69 66 28 20 73 71 6c 69 74  ){.    if( sqlit
5770: 65 33 5f 63 6f 6c 75 6d 6e 5f 74 79 70 65 28 70  e3_column_type(p
5780: 43 73 72 2d 3e 70 53 74 6d 74 2c 20 69 43 6f 6c  Csr->pStmt, iCol
5790: 29 21 3d 53 51 4c 49 54 45 5f 4e 55 4c 4c 20 29  )!=SQLITE_NULL )
57a0: 7b 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20 53  {.      return S
57b0: 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20  QLITE_NOMEM;.   
57c0: 20 7d 0a 20 20 20 20 72 65 74 75 72 6e 20 53 51   }.    return SQ
57d0: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 7d 0a 20 20 6e  LITE_OK;.  }.  n
57e0: 44 6f 63 20 3d 20 73 71 6c 69 74 65 33 5f 63 6f  Doc = sqlite3_co
57f0: 6c 75 6d 6e 5f 62 79 74 65 73 28 70 43 73 72 2d  lumn_bytes(pCsr-
5800: 3e 70 53 74 6d 74 2c 20 69 43 6f 6c 29 3b 0a 0a  >pStmt, iCol);..
5810: 20 20 2f 2a 20 4f 70 65 6e 20 61 20 74 6f 6b 65    /* Open a toke
5820: 6e 20 63 75 72 73 6f 72 20 6f 6e 20 74 68 65 20  n cursor on the 
5830: 64 6f 63 75 6d 65 6e 74 2e 20 2a 2f 0a 20 20 70  document. */.  p
5840: 4d 6f 64 20 3d 20 28 73 71 6c 69 74 65 33 5f 74  Mod = (sqlite3_t
5850: 6f 6b 65 6e 69 7a 65 72 5f 6d 6f 64 75 6c 65 20  okenizer_module 
5860: 2a 29 70 54 61 62 2d 3e 70 54 6f 6b 65 6e 69 7a  *)pTab->pTokeniz
5870: 65 72 2d 3e 70 4d 6f 64 75 6c 65 3b 0a 20 20 72  er->pModule;.  r
5880: 63 20 3d 20 73 71 6c 69 74 65 33 46 74 73 33 4f  c = sqlite3Fts3O
5890: 70 65 6e 54 6f 6b 65 6e 69 7a 65 72 28 70 54 61  penTokenizer(pTa
58a0: 62 2d 3e 70 54 6f 6b 65 6e 69 7a 65 72 2c 20 70  b->pTokenizer, p
58b0: 43 73 72 2d 3e 69 4c 61 6e 67 69 64 2c 20 7a 44  Csr->iLangid, zD
58c0: 6f 63 2c 6e 44 6f 63 2c 26 70 43 29 3b 0a 20 20  oc,nDoc,&pC);.  
58d0: 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f  if( rc!=SQLITE_O
58e0: 4b 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  K ){.    return 
58f0: 72 63 3b 0a 20 20 7d 0a 0a 20 20 77 68 69 6c 65  rc;.  }..  while
5900: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
5910: 29 7b 0a 20 20 20 20 69 6e 74 20 69 42 65 67 69  ){.    int iBegi
5920: 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n;              
5930: 20 20 20 20 20 2f 2a 20 4f 66 66 73 65 74 20 69       /* Offset i
5940: 6e 20 7a 44 6f 63 20 6f 66 20 73 74 61 72 74 20  n zDoc of start 
5950: 6f 66 20 74 6f 6b 65 6e 20 2a 2f 0a 20 20 20 20  of token */.    
5960: 69 6e 74 20 69 46 69 6e 3b 20 20 20 20 20 20 20  int iFin;       
5970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
5980: 20 4f 66 66 73 65 74 20 69 6e 20 7a 44 6f 63 20   Offset in zDoc 
5990: 6f 66 20 65 6e 64 20 6f 66 20 74 6f 6b 65 6e 20  of end of token 
59a0: 2a 2f 0a 20 20 20 20 69 6e 74 20 69 73 48 69 67  */.    int isHig
59b0: 68 6c 69 67 68 74 3b 20 20 20 20 20 20 20 20 20  hlight;         
59c0: 20 20 20 20 20 2f 2a 20 54 72 75 65 20 66 6f 72       /* True for
59d0: 20 68 69 67 68 6c 69 67 68 74 65 64 20 74 65 72   highlighted ter
59e0: 6d 73 20 2a 2f 0a 0a 20 20 20 20 72 63 20 3d 20  ms */..    rc = 
59f0: 70 4d 6f 64 2d 3e 78 4e 65 78 74 28 70 43 2c 20  pMod->xNext(pC, 
5a00: 26 5a 44 55 4d 4d 59 2c 20 26 44 55 4d 4d 59 31  &ZDUMMY, &DUMMY1
5a10: 2c 20 26 69 42 65 67 69 6e 2c 20 26 69 46 69 6e  , &iBegin, &iFin
5a20: 2c 20 26 69 43 75 72 72 65 6e 74 29 3b 0a 20 20  , &iCurrent);.  
5a30: 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45    if( rc!=SQLITE
5a40: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 69 66 28  _OK ){.      if(
5a50: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 44 4f 4e 45   rc==SQLITE_DONE
5a60: 20 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20 53   ){.        /* S
5a70: 70 65 63 69 61 6c 20 63 61 73 65 20 2d 20 74 68  pecial case - th
5a80: 65 20 6c 61 73 74 20 74 6f 6b 65 6e 20 6f 66 20  e last token of 
5a90: 74 68 65 20 73 6e 69 70 70 65 74 20 69 73 20 61  the snippet is a
5aa0: 6c 73 6f 20 74 68 65 20 6c 61 73 74 20 74 6f 6b  lso the last tok
5ab0: 65 6e 0a 20 20 20 20 20 20 20 20 2a 2a 20 6f 66  en.        ** of
5ac0: 20 74 68 65 20 63 6f 6c 75 6d 6e 2e 20 41 70 70   the column. App
5ad0: 65 6e 64 20 61 6e 79 20 70 75 6e 63 74 75 61 74  end any punctuat
5ae0: 69 6f 6e 20 74 68 61 74 20 6f 63 63 75 72 72 65  ion that occurre
5af0: 64 20 62 65 74 77 65 65 6e 20 74 68 65 20 65 6e  d between the en
5b00: 64 0a 20 20 20 20 20 20 20 20 2a 2a 20 6f 66 20  d.        ** of 
5b10: 74 68 65 20 70 72 65 76 69 6f 75 73 20 74 6f 6b  the previous tok
5b20: 65 6e 20 61 6e 64 20 74 68 65 20 65 6e 64 20 6f  en and the end o
5b30: 66 20 74 68 65 20 64 6f 63 75 6d 65 6e 74 20 74  f the document t
5b40: 6f 20 74 68 65 20 6f 75 74 70 75 74 2e 20 0a 20  o the output. . 
5b50: 20 20 20 20 20 20 20 2a 2a 20 54 68 65 6e 20 62         ** Then b
5b60: 72 65 61 6b 20 6f 75 74 20 6f 66 20 74 68 65 20  reak out of the 
5b70: 6c 6f 6f 70 2e 20 2a 2f 0a 20 20 20 20 20 20 20  loop. */.       
5b80: 20 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67   rc = fts3String
5b90: 41 70 70 65 6e 64 28 70 4f 75 74 2c 20 26 7a 44  Append(pOut, &zD
5ba0: 6f 63 5b 69 45 6e 64 5d 2c 20 2d 31 29 3b 0a 20  oc[iEnd], -1);. 
5bb0: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62 72 65       }.      bre
5bc0: 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66  ak;.    }.    if
5bd0: 28 20 69 43 75 72 72 65 6e 74 3c 69 50 6f 73 20  ( iCurrent<iPos 
5be0: 29 7b 20 63 6f 6e 74 69 6e 75 65 3b 20 7d 0a 0a  ){ continue; }..
5bf0: 20 20 20 20 69 66 28 20 21 69 73 53 68 69 66 74      if( !isShift
5c00: 44 6f 6e 65 20 29 7b 0a 20 20 20 20 20 20 69 6e  Done ){.      in
5c10: 74 20 6e 20 3d 20 6e 44 6f 63 20 2d 20 69 42 65  t n = nDoc - iBe
5c20: 67 69 6e 3b 0a 20 20 20 20 20 20 72 63 20 3d 20  gin;.      rc = 
5c30: 66 74 73 33 53 6e 69 70 70 65 74 53 68 69 66 74  fts3SnippetShift
5c40: 28 0a 20 20 20 20 20 20 20 20 20 20 70 54 61 62  (.          pTab
5c50: 2c 20 70 43 73 72 2d 3e 69 4c 61 6e 67 69 64 2c  , pCsr->iLangid,
5c60: 20 6e 53 6e 69 70 70 65 74 2c 20 26 7a 44 6f 63   nSnippet, &zDoc
5c70: 5b 69 42 65 67 69 6e 5d 2c 20 6e 2c 20 26 69 50  [iBegin], n, &iP
5c80: 6f 73 2c 20 26 68 6c 6d 61 73 6b 0a 20 20 20 20  os, &hlmask.    
5c90: 20 20 29 3b 0a 20 20 20 20 20 20 69 73 53 68 69    );.      isShi
5ca0: 66 74 44 6f 6e 65 20 3d 20 31 3b 0a 0a 20 20 20  ftDone = 1;..   
5cb0: 20 20 20 2f 2a 20 4e 6f 77 20 74 68 61 74 20 74     /* Now that t
5cc0: 68 65 20 73 68 69 66 74 20 68 61 73 20 62 65 65  he shift has bee
5cd0: 6e 20 64 6f 6e 65 2c 20 63 68 65 63 6b 20 69 66  n done, check if
5ce0: 20 74 68 65 20 69 6e 69 74 69 61 6c 20 22 2e 2e   the initial "..
5cf0: 2e 22 20 61 72 65 0a 20 20 20 20 20 20 2a 2a 20  ." are.      ** 
5d00: 72 65 71 75 69 72 65 64 2e 20 54 68 65 79 20 61  required. They a
5d10: 72 65 20 72 65 71 75 69 72 65 64 20 69 66 20 28  re required if (
5d20: 61 29 20 74 68 69 73 20 69 73 20 6e 6f 74 20 74  a) this is not t
5d30: 68 65 20 66 69 72 73 74 20 66 72 61 67 6d 65 6e  he first fragmen
5d40: 74 2c 0a 20 20 20 20 20 20 2a 2a 20 6f 72 20 28  t,.      ** or (
5d50: 62 29 20 74 68 69 73 20 66 72 61 67 6d 65 6e 74  b) this fragment
5d60: 20 64 6f 65 73 20 6e 6f 74 20 62 65 67 69 6e 20   does not begin 
5d70: 61 74 20 70 6f 73 69 74 69 6f 6e 20 30 20 6f 66  at position 0 of
5d80: 20 69 74 73 20 63 6f 6c 75 6d 6e 2e 20 0a 20 20   its column. .  
5d90: 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 69 66 28      */.      if(
5da0: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
5db0: 26 20 28 69 50 6f 73 3e 30 20 7c 7c 20 69 46 72  & (iPos>0 || iFr
5dc0: 61 67 6d 65 6e 74 3e 30 29 20 29 7b 0a 20 20 20  agment>0) ){.   
5dd0: 20 20 20 20 20 72 63 20 3d 20 66 74 73 33 53 74       rc = fts3St
5de0: 72 69 6e 67 41 70 70 65 6e 64 28 70 4f 75 74 2c  ringAppend(pOut,
5df0: 20 7a 45 6c 6c 69 70 73 69 73 2c 20 2d 31 29 3b   zEllipsis, -1);
5e00: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 69  .      }.      i
5e10: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
5e20: 20 7c 7c 20 69 43 75 72 72 65 6e 74 3c 69 50 6f   || iCurrent<iPo
5e30: 73 20 29 20 63 6f 6e 74 69 6e 75 65 3b 0a 20 20  s ) continue;.  
5e40: 20 20 7d 0a 0a 20 20 20 20 69 66 28 20 69 43 75    }..    if( iCu
5e50: 72 72 65 6e 74 3e 3d 28 69 50 6f 73 2b 6e 53 6e  rrent>=(iPos+nSn
5e60: 69 70 70 65 74 29 20 29 7b 0a 20 20 20 20 20 20  ippet) ){.      
5e70: 69 66 28 20 69 73 4c 61 73 74 20 29 7b 0a 20 20  if( isLast ){.  
5e80: 20 20 20 20 20 20 72 63 20 3d 20 66 74 73 33 53        rc = fts3S
5e90: 74 72 69 6e 67 41 70 70 65 6e 64 28 70 4f 75 74  tringAppend(pOut
5ea0: 2c 20 7a 45 6c 6c 69 70 73 69 73 2c 20 2d 31 29  , zEllipsis, -1)
5eb0: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
5ec0: 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 0a 20 20  break;.    }..  
5ed0: 20 20 2f 2a 20 53 65 74 20 69 73 48 69 67 68 6c    /* Set isHighl
5ee0: 69 67 68 74 20 74 6f 20 74 72 75 65 20 69 66 20  ight to true if 
5ef0: 74 68 69 73 20 74 65 72 6d 20 73 68 6f 75 6c 64  this term should
5f00: 20 62 65 20 68 69 67 68 6c 69 67 68 74 65 64 2e   be highlighted.
5f10: 20 2a 2f 0a 20 20 20 20 69 73 48 69 67 68 6c 69   */.    isHighli
5f20: 67 68 74 20 3d 20 28 68 6c 6d 61 73 6b 20 26 20  ght = (hlmask & 
5f30: 28 28 75 36 34 29 31 20 3c 3c 20 28 69 43 75 72  ((u64)1 << (iCur
5f40: 72 65 6e 74 2d 69 50 6f 73 29 29 29 21 3d 30 3b  rent-iPos)))!=0;
5f50: 0a 0a 20 20 20 20 69 66 28 20 69 43 75 72 72 65  ..    if( iCurre
5f60: 6e 74 3e 69 50 6f 73 20 29 20 72 63 20 3d 20 66  nt>iPos ) rc = f
5f70: 74 73 33 53 74 72 69 6e 67 41 70 70 65 6e 64 28  ts3StringAppend(
5f80: 70 4f 75 74 2c 20 26 7a 44 6f 63 5b 69 45 6e 64  pOut, &zDoc[iEnd
5f90: 5d 2c 20 69 42 65 67 69 6e 2d 69 45 6e 64 29 3b  ], iBegin-iEnd);
5fa0: 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  .    if( rc==SQL
5fb0: 49 54 45 5f 4f 4b 20 26 26 20 69 73 48 69 67 68  ITE_OK && isHigh
5fc0: 6c 69 67 68 74 20 29 20 72 63 20 3d 20 66 74 73  light ) rc = fts
5fd0: 33 53 74 72 69 6e 67 41 70 70 65 6e 64 28 70 4f  3StringAppend(pO
5fe0: 75 74 2c 20 7a 4f 70 65 6e 2c 20 2d 31 29 3b 0a  ut, zOpen, -1);.
5ff0: 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49      if( rc==SQLI
6000: 54 45 5f 4f 4b 20 29 20 72 63 20 3d 20 66 74 73  TE_OK ) rc = fts
6010: 33 53 74 72 69 6e 67 41 70 70 65 6e 64 28 70 4f  3StringAppend(pO
6020: 75 74 2c 20 26 7a 44 6f 63 5b 69 42 65 67 69 6e  ut, &zDoc[iBegin
6030: 5d 2c 20 69 46 69 6e 2d 69 42 65 67 69 6e 29 3b  ], iFin-iBegin);
6040: 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  .    if( rc==SQL
6050: 49 54 45 5f 4f 4b 20 26 26 20 69 73 48 69 67 68  ITE_OK && isHigh
6060: 6c 69 67 68 74 20 29 20 72 63 20 3d 20 66 74 73  light ) rc = fts
6070: 33 53 74 72 69 6e 67 41 70 70 65 6e 64 28 70 4f  3StringAppend(pO
6080: 75 74 2c 20 7a 43 6c 6f 73 65 2c 20 2d 31 29 3b  ut, zClose, -1);
6090: 0a 0a 20 20 20 20 69 45 6e 64 20 3d 20 69 46 69  ..    iEnd = iFi
60a0: 6e 3b 0a 20 20 7d 0a 0a 20 20 70 4d 6f 64 2d 3e  n;.  }..  pMod->
60b0: 78 43 6c 6f 73 65 28 70 43 29 3b 0a 20 20 72 65  xClose(pC);.  re
60c0: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a 2f 2a 0a  turn rc;.}.../*.
60d0: 2a 2a 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e  ** This function
60e0: 20 69 73 20 75 73 65 64 20 74 6f 20 63 6f 75 6e   is used to coun
60f0: 74 20 74 68 65 20 65 6e 74 72 69 65 73 20 69 6e  t the entries in
6100: 20 61 20 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 28   a column-list (
6110: 61 20 0a 2a 2a 20 64 65 6c 74 61 2d 65 6e 63 6f  a .** delta-enco
6120: 64 65 64 20 6c 69 73 74 20 6f 66 20 74 65 72 6d  ded list of term
6130: 20 6f 66 66 73 65 74 73 20 77 69 74 68 69 6e 20   offsets within 
6140: 61 20 73 69 6e 67 6c 65 20 63 6f 6c 75 6d 6e 20  a single column 
6150: 6f 66 20 61 20 73 69 6e 67 6c 65 20 0a 2a 2a 20  of a single .** 
6160: 72 6f 77 29 2e 20 57 68 65 6e 20 74 68 69 73 20  row). When this 
6170: 66 75 6e 63 74 69 6f 6e 20 69 73 20 63 61 6c 6c  function is call
6180: 65 64 2c 20 2a 70 70 43 6f 6c 6c 69 73 74 20 73  ed, *ppCollist s
6190: 68 6f 75 6c 64 20 70 6f 69 6e 74 20 74 6f 20 74  hould point to t
61a0: 68 65 0a 2a 2a 20 62 65 67 69 6e 6e 69 6e 67 20  he.** beginning 
61b0: 6f 66 20 74 68 65 20 66 69 72 73 74 20 76 61 72  of the first var
61c0: 69 6e 74 20 69 6e 20 74 68 65 20 63 6f 6c 75 6d  int in the colum
61d0: 6e 2d 6c 69 73 74 20 28 74 68 65 20 76 61 72 69  n-list (the vari
61e0: 6e 74 20 74 68 61 74 0a 2a 2a 20 63 6f 6e 74 61  nt that.** conta
61f0: 69 6e 73 20 74 68 65 20 70 6f 73 69 74 69 6f 6e  ins the position
6200: 20 6f 66 20 74 68 65 20 66 69 72 73 74 20 6d 61   of the first ma
6210: 74 63 68 69 6e 67 20 74 65 72 6d 20 69 6e 20 74  tching term in t
6220: 68 65 20 63 6f 6c 75 6d 6e 20 64 61 74 61 29 2e  he column data).
6230: 0a 2a 2a 20 42 65 66 6f 72 65 20 72 65 74 75 72  .** Before retur
6240: 6e 69 6e 67 2c 20 2a 70 70 43 6f 6c 6c 69 73 74  ning, *ppCollist
6250: 20 69 73 20 73 65 74 20 74 6f 20 70 6f 69 6e 74   is set to point
6260: 20 74 6f 20 74 68 65 20 66 69 72 73 74 20 62 79   to the first by
6270: 74 65 20 61 66 74 65 72 0a 2a 2a 20 74 68 65 20  te after.** the 
6280: 6c 61 73 74 20 76 61 72 69 6e 74 20 69 6e 20 74  last varint in t
6290: 68 65 20 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 28  he column-list (
62a0: 65 69 74 68 65 72 20 74 68 65 20 30 78 30 30 20  either the 0x00 
62b0: 73 69 67 6e 69 66 79 69 6e 67 20 74 68 65 20 65  signifying the e
62c0: 6e 64 0a 2a 2a 20 6f 66 20 74 68 65 20 70 6f 73  nd.** of the pos
62d0: 69 74 69 6f 6e 2d 6c 69 73 74 2c 20 6f 72 20 74  ition-list, or t
62e0: 68 65 20 30 78 30 31 20 74 68 61 74 20 70 72 65  he 0x01 that pre
62f0: 63 65 64 65 73 20 74 68 65 20 63 6f 6c 75 6d 6e  cedes the column
6300: 20 6e 75 6d 62 65 72 20 6f 66 0a 2a 2a 20 74 68   number of.** th
6310: 65 20 6e 65 78 74 20 63 6f 6c 75 6d 6e 20 69 6e  e next column in
6320: 20 74 68 65 20 70 6f 73 69 74 69 6f 6e 2d 6c 69   the position-li
6330: 73 74 29 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6e  st)..**.** The n
6340: 75 6d 62 65 72 20 6f 66 20 65 6c 65 6d 65 6e 74  umber of element
6350: 73 20 69 6e 20 74 68 65 20 63 6f 6c 75 6d 6e 2d  s in the column-
6360: 6c 69 73 74 20 69 73 20 72 65 74 75 72 6e 65 64  list is returned
6370: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
6380: 66 74 73 33 43 6f 6c 75 6d 6e 6c 69 73 74 43 6f  fts3ColumnlistCo
6390: 75 6e 74 28 63 68 61 72 20 2a 2a 70 70 43 6f 6c  unt(char **ppCol
63a0: 6c 69 73 74 29 7b 0a 20 20 63 68 61 72 20 2a 70  list){.  char *p
63b0: 45 6e 64 20 3d 20 2a 70 70 43 6f 6c 6c 69 73 74  End = *ppCollist
63c0: 3b 0a 20 20 63 68 61 72 20 63 20 3d 20 30 3b 0a  ;.  char c = 0;.
63d0: 20 20 69 6e 74 20 6e 45 6e 74 72 79 20 3d 20 30    int nEntry = 0
63e0: 3b 0a 0a 20 20 2f 2a 20 41 20 63 6f 6c 75 6d 6e  ;..  /* A column
63f0: 2d 6c 69 73 74 20 69 73 20 74 65 72 6d 69 6e 61  -list is termina
6400: 74 65 64 20 62 79 20 65 69 74 68 65 72 20 61 20  ted by either a 
6410: 30 78 30 31 20 6f 72 20 30 78 30 30 2e 20 2a 2f  0x01 or 0x00. */
6420: 0a 20 20 77 68 69 6c 65 28 20 30 78 46 45 20 26  .  while( 0xFE &
6430: 20 28 2a 70 45 6e 64 20 7c 20 63 29 20 29 7b 0a   (*pEnd | c) ){.
6440: 20 20 20 20 63 20 3d 20 2a 70 45 6e 64 2b 2b 20      c = *pEnd++ 
6450: 26 20 30 78 38 30 3b 0a 20 20 20 20 69 66 28 20  & 0x80;.    if( 
6460: 21 63 20 29 20 6e 45 6e 74 72 79 2b 2b 3b 0a 20  !c ) nEntry++;. 
6470: 20 7d 0a 0a 20 20 2a 70 70 43 6f 6c 6c 69 73 74   }..  *ppCollist
6480: 20 3d 20 70 45 6e 64 3b 0a 20 20 72 65 74 75 72   = pEnd;.  retur
6490: 6e 20 6e 45 6e 74 72 79 3b 0a 7d 0a 0a 2f 2a 0a  n nEntry;.}../*.
64a0: 2a 2a 20 66 74 73 33 45 78 70 72 49 74 65 72 61  ** fts3ExprItera
64b0: 74 65 28 29 20 63 61 6c 6c 62 61 63 6b 20 75 73  te() callback us
64c0: 65 64 20 74 6f 20 63 6f 6c 6c 65 63 74 20 74 68  ed to collect th
64d0: 65 20 22 67 6c 6f 62 61 6c 22 20 6d 61 74 63 68  e "global" match
64e0: 69 6e 66 6f 20 73 74 61 74 73 0a 2a 2a 20 66 6f  info stats.** fo
64f0: 72 20 61 20 73 69 6e 67 6c 65 20 71 75 65 72 79  r a single query
6500: 2e 20 0a 2a 2a 0a 2a 2a 20 66 74 73 33 45 78 70  . .**.** fts3Exp
6510: 72 49 74 65 72 61 74 65 28 29 20 63 61 6c 6c 62  rIterate() callb
6520: 61 63 6b 20 74 6f 20 6c 6f 61 64 20 74 68 65 20  ack to load the 
6530: 27 67 6c 6f 62 61 6c 27 20 65 6c 65 6d 65 6e 74  'global' element
6540: 73 20 6f 66 20 61 0a 2a 2a 20 46 54 53 33 5f 4d  s of a.** FTS3_M
6550: 41 54 43 48 49 4e 46 4f 5f 48 49 54 53 20 6d 61  ATCHINFO_HITS ma
6560: 74 63 68 69 6e 66 6f 20 61 72 72 61 79 2e 20 54  tchinfo array. T
6570: 68 65 20 67 6c 6f 62 61 6c 20 73 74 61 74 73 20  he global stats 
6580: 61 72 65 20 74 68 6f 73 65 20 65 6c 65 6d 65 6e  are those elemen
6590: 74 73 20 0a 2a 2a 20 6f 66 20 74 68 65 20 6d 61  ts .** of the ma
65a0: 74 63 68 69 6e 66 6f 20 61 72 72 61 79 20 74 68  tchinfo array th
65b0: 61 74 20 61 72 65 20 63 6f 6e 73 74 61 6e 74 20  at are constant 
65c0: 66 6f 72 20 61 6c 6c 20 72 6f 77 73 20 72 65 74  for all rows ret
65d0: 75 72 6e 65 64 20 62 79 20 74 68 65 20 0a 2a 2a  urned by the .**
65e0: 20 63 75 72 72 65 6e 74 20 71 75 65 72 79 2e 0a   current query..
65f0: 2a 2a 0a 2a 2a 20 41 72 67 75 6d 65 6e 74 20 70  **.** Argument p
6600: 43 74 78 20 69 73 20 61 63 74 75 61 6c 6c 79 20  Ctx is actually 
6610: 61 20 70 6f 69 6e 74 65 72 20 74 6f 20 61 20 73  a pointer to a s
6620: 74 72 75 63 74 20 6f 66 20 74 79 70 65 20 4d 61  truct of type Ma
6630: 74 63 68 49 6e 66 6f 2e 20 54 68 69 73 0a 2a 2a  tchInfo. This.**
6640: 20 66 75 6e 63 74 69 6f 6e 20 70 6f 70 75 6c 61   function popula
6650: 74 65 73 20 4d 61 74 63 68 69 6e 66 6f 2e 61 4d  tes Matchinfo.aM
6660: 61 74 63 68 69 6e 66 6f 5b 5d 20 61 73 20 66 6f  atchinfo[] as fo
6670: 6c 6c 6f 77 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 66  llows:.**.**   f
6680: 6f 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f 6c 3c  or(iCol=0; iCol<
6690: 6e 43 6f 6c 3b 20 69 43 6f 6c 2b 2b 29 7b 0a 2a  nCol; iCol++){.*
66a0: 2a 20 20 20 20 20 61 4d 61 74 63 68 69 6e 66 6f  *     aMatchinfo
66b0: 5b 33 2a 69 50 68 72 61 73 65 2a 6e 43 6f 6c 20  [3*iPhrase*nCol 
66c0: 2b 20 33 2a 69 43 6f 6c 20 2b 20 31 5d 20 3d 20  + 3*iCol + 1] = 
66d0: 58 3b 0a 2a 2a 20 20 20 20 20 61 4d 61 74 63 68  X;.**     aMatch
66e0: 69 6e 66 6f 5b 33 2a 69 50 68 72 61 73 65 2a 6e  info[3*iPhrase*n
66f0: 43 6f 6c 20 2b 20 33 2a 69 43 6f 6c 20 2b 20 32  Col + 3*iCol + 2
6700: 5d 20 3d 20 59 3b 0a 2a 2a 20 20 20 7d 0a 2a 2a  ] = Y;.**   }.**
6710: 0a 2a 2a 20 77 68 65 72 65 20 58 20 69 73 20 74  .** where X is t
6720: 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 6d 61 74  he number of mat
6730: 63 68 65 73 20 66 6f 72 20 70 68 72 61 73 65 20  ches for phrase 
6740: 69 50 68 72 61 73 65 20 69 73 20 63 6f 6c 75 6d  iPhrase is colum
6750: 6e 20 69 43 6f 6c 20 6f 66 20 61 6c 6c 0a 2a 2a  n iCol of all.**
6760: 20 72 6f 77 73 20 6f 66 20 74 68 65 20 74 61 62   rows of the tab
6770: 6c 65 2e 20 59 20 69 73 20 74 68 65 20 6e 75 6d  le. Y is the num
6780: 62 65 72 20 6f 66 20 72 6f 77 73 20 66 6f 72 20  ber of rows for 
6790: 77 68 69 63 68 20 63 6f 6c 75 6d 6e 20 69 43 6f  which column iCo
67a0: 6c 20 63 6f 6e 74 61 69 6e 73 0a 2a 2a 20 61 74  l contains.** at
67b0: 20 6c 65 61 73 74 20 6f 6e 65 20 69 6e 73 74 61   least one insta
67c0: 6e 63 65 20 6f 66 20 70 68 72 61 73 65 20 69 50  nce of phrase iP
67d0: 68 72 61 73 65 2e 0a 2a 2a 0a 2a 2a 20 49 66 20  hrase..**.** If 
67e0: 74 68 65 20 70 68 72 61 73 65 20 70 45 78 70 72  the phrase pExpr
67f0: 20 63 6f 6e 73 69 73 74 73 20 65 6e 74 69 72 65   consists entire
6800: 6c 79 20 6f 66 20 64 65 66 65 72 72 65 64 20 74  ly of deferred t
6810: 6f 6b 65 6e 73 2c 20 74 68 65 6e 20 61 6c 6c 20  okens, then all 
6820: 58 20 61 6e 64 0a 2a 2a 20 59 20 76 61 6c 75 65  X and.** Y value
6830: 73 20 61 72 65 20 73 65 74 20 74 6f 20 6e 44 6f  s are set to nDo
6840: 63 2c 20 77 68 65 72 65 20 6e 44 6f 63 20 69 73  c, where nDoc is
6850: 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 64   the number of d
6860: 6f 63 75 6d 65 6e 74 73 20 69 6e 20 74 68 65 20  ocuments in the 
6870: 0a 2a 2a 20 66 69 6c 65 20 73 79 73 74 65 6d 2e  .** file system.
6880: 20 54 68 69 73 20 69 73 20 64 6f 6e 65 20 62 65   This is done be
6890: 63 61 75 73 65 20 74 68 65 20 66 75 6c 6c 2d 74  cause the full-t
68a0: 65 78 74 20 69 6e 64 65 78 20 64 6f 63 6c 69 73  ext index doclis
68b0: 74 20 69 73 20 72 65 71 75 69 72 65 64 0a 2a 2a  t is required.**
68c0: 20 74 6f 20 63 61 6c 63 75 6c 61 74 65 20 74 68   to calculate th
68d0: 65 73 65 20 76 61 6c 75 65 73 20 70 72 6f 70 65  ese values prope
68e0: 72 6c 79 2c 20 61 6e 64 20 74 68 65 20 66 75 6c  rly, and the ful
68f0: 6c 2d 74 65 78 74 20 69 6e 64 65 78 20 64 6f 63  l-text index doc
6900: 6c 69 73 74 20 69 73 0a 2a 2a 20 6e 6f 74 20 61  list is.** not a
6910: 76 61 69 6c 61 62 6c 65 20 66 6f 72 20 64 65 66  vailable for def
6920: 65 72 72 65 64 20 74 6f 6b 65 6e 73 2e 0a 2a 2f  erred tokens..*/
6930: 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33  .static int fts3
6940: 45 78 70 72 47 6c 6f 62 61 6c 48 69 74 73 43 62  ExprGlobalHitsCb
6950: 28 0a 20 20 46 74 73 33 45 78 70 72 20 2a 70 45  (.  Fts3Expr *pE
6960: 78 70 72 2c 20 20 20 20 20 20 20 20 20 20 20 20  xpr,            
6970: 20 20 20 20 2f 2a 20 50 68 72 61 73 65 20 65 78      /* Phrase ex
6980: 70 72 65 73 73 69 6f 6e 20 6e 6f 64 65 20 2a 2f  pression node */
6990: 0a 20 20 69 6e 74 20 69 50 68 72 61 73 65 2c 20  .  int iPhrase, 
69a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
69b0: 20 20 20 2f 2a 20 50 68 72 61 73 65 20 6e 75 6d     /* Phrase num
69c0: 62 65 72 20 28 6e 75 6d 62 65 72 65 64 20 66 72  ber (numbered fr
69d0: 6f 6d 20 7a 65 72 6f 29 20 2a 2f 0a 20 20 76 6f  om zero) */.  vo
69e0: 69 64 20 2a 70 43 74 78 20 20 20 20 20 20 20 20  id *pCtx        
69f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
6a00: 20 50 6f 69 6e 74 65 72 20 74 6f 20 4d 61 74 63   Pointer to Matc
6a10: 68 49 6e 66 6f 20 73 74 72 75 63 74 75 72 65 20  hInfo structure 
6a20: 2a 2f 0a 29 7b 0a 20 20 4d 61 74 63 68 49 6e 66  */.){.  MatchInf
6a30: 6f 20 2a 70 20 3d 20 28 4d 61 74 63 68 49 6e 66  o *p = (MatchInf
6a40: 6f 20 2a 29 70 43 74 78 3b 0a 20 20 72 65 74 75  o *)pCtx;.  retu
6a50: 72 6e 20 73 71 6c 69 74 65 33 46 74 73 33 45 76  rn sqlite3Fts3Ev
6a60: 61 6c 50 68 72 61 73 65 53 74 61 74 73 28 0a 20  alPhraseStats(. 
6a70: 20 20 20 20 20 70 2d 3e 70 43 75 72 73 6f 72 2c       p->pCursor,
6a80: 20 70 45 78 70 72 2c 20 26 70 2d 3e 61 4d 61 74   pExpr, &p->aMat
6a90: 63 68 69 6e 66 6f 5b 33 2a 69 50 68 72 61 73 65  chinfo[3*iPhrase
6aa0: 2a 70 2d 3e 6e 43 6f 6c 5d 0a 20 20 29 3b 0a 7d  *p->nCol].  );.}
6ab0: 0a 0a 2f 2a 0a 2a 2a 20 66 74 73 33 45 78 70 72  ../*.** fts3Expr
6ac0: 49 74 65 72 61 74 65 28 29 20 63 61 6c 6c 62 61  Iterate() callba
6ad0: 63 6b 20 75 73 65 64 20 74 6f 20 63 6f 6c 6c 65  ck used to colle
6ae0: 63 74 20 74 68 65 20 22 6c 6f 63 61 6c 22 20 70  ct the "local" p
6af0: 61 72 74 20 6f 66 20 74 68 65 0a 2a 2a 20 46 54  art of the.** FT
6b00: 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 48 49 54  S3_MATCHINFO_HIT
6b10: 53 20 61 72 72 61 79 2e 20 54 68 65 20 6c 6f 63  S array. The loc
6b20: 61 6c 20 73 74 61 74 73 20 61 72 65 20 74 68 6f  al stats are tho
6b30: 73 65 20 65 6c 65 6d 65 6e 74 73 20 6f 66 20 74  se elements of t
6b40: 68 65 20 0a 2a 2a 20 61 72 72 61 79 20 74 68 61  he .** array tha
6b50: 74 20 61 72 65 20 64 69 66 66 65 72 65 6e 74 20  t are different 
6b60: 66 6f 72 20 65 61 63 68 20 72 6f 77 20 72 65 74  for each row ret
6b70: 75 72 6e 65 64 20 62 79 20 74 68 65 20 71 75 65  urned by the que
6b80: 72 79 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ry..*/.static in
6b90: 74 20 66 74 73 33 45 78 70 72 4c 6f 63 61 6c 48  t fts3ExprLocalH
6ba0: 69 74 73 43 62 28 0a 20 20 46 74 73 33 45 78 70  itsCb(.  Fts3Exp
6bb0: 72 20 2a 70 45 78 70 72 2c 20 20 20 20 20 20 20  r *pExpr,       
6bc0: 20 20 20 20 20 20 20 20 20 2f 2a 20 50 68 72 61           /* Phra
6bd0: 73 65 20 65 78 70 72 65 73 73 69 6f 6e 20 6e 6f  se expression no
6be0: 64 65 20 2a 2f 0a 20 20 69 6e 74 20 69 50 68 72  de */.  int iPhr
6bf0: 61 73 65 2c 20 20 20 20 20 20 20 20 20 20 20 20  ase,            
6c00: 20 20 20 20 20 20 20 20 2f 2a 20 50 68 72 61 73          /* Phras
6c10: 65 20 6e 75 6d 62 65 72 20 2a 2f 0a 20 20 76 6f  e number */.  vo
6c20: 69 64 20 2a 70 43 74 78 20 20 20 20 20 20 20 20  id *pCtx        
6c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
6c40: 20 50 6f 69 6e 74 65 72 20 74 6f 20 4d 61 74 63   Pointer to Matc
6c50: 68 49 6e 66 6f 20 73 74 72 75 63 74 75 72 65 20  hInfo structure 
6c60: 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d  */.){.  int rc =
6c70: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 4d 61   SQLITE_OK;.  Ma
6c80: 74 63 68 49 6e 66 6f 20 2a 70 20 3d 20 28 4d 61  tchInfo *p = (Ma
6c90: 74 63 68 49 6e 66 6f 20 2a 29 70 43 74 78 3b 0a  tchInfo *)pCtx;.
6ca0: 20 20 69 6e 74 20 69 53 74 61 72 74 20 3d 20 69    int iStart = i
6cb0: 50 68 72 61 73 65 20 2a 20 70 2d 3e 6e 43 6f 6c  Phrase * p->nCol
6cc0: 20 2a 20 33 3b 0a 20 20 69 6e 74 20 69 3b 0a 0a   * 3;.  int i;..
6cd0: 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70 2d 3e    for(i=0; i<p->
6ce0: 6e 43 6f 6c 20 26 26 20 72 63 3d 3d 53 51 4c 49  nCol && rc==SQLI
6cf0: 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b 0a 20 20 20  TE_OK; i++){.   
6d00: 20 63 68 61 72 20 2a 70 43 73 72 3b 0a 20 20 20   char *pCsr;.   
6d10: 20 72 63 20 3d 20 73 71 6c 69 74 65 33 46 74 73   rc = sqlite3Fts
6d20: 33 45 76 61 6c 50 68 72 61 73 65 50 6f 73 6c 69  3EvalPhrasePosli
6d30: 73 74 28 70 2d 3e 70 43 75 72 73 6f 72 2c 20 70  st(p->pCursor, p
6d40: 45 78 70 72 2c 20 69 2c 20 26 70 43 73 72 29 3b  Expr, i, &pCsr);
6d50: 0a 20 20 20 20 69 66 28 20 70 43 73 72 20 29 7b  .    if( pCsr ){
6d60: 0a 20 20 20 20 20 20 70 2d 3e 61 4d 61 74 63 68  .      p->aMatch
6d70: 69 6e 66 6f 5b 69 53 74 61 72 74 2b 69 2a 33 5d  info[iStart+i*3]
6d80: 20 3d 20 66 74 73 33 43 6f 6c 75 6d 6e 6c 69 73   = fts3Columnlis
6d90: 74 43 6f 75 6e 74 28 26 70 43 73 72 29 3b 0a 20  tCount(&pCsr);. 
6da0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
6db0: 70 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 69 53  p->aMatchinfo[iS
6dc0: 74 61 72 74 2b 69 2a 33 5d 20 3d 20 30 3b 0a 20  tart+i*3] = 0;. 
6dd0: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65 74 75     }.  }..  retu
6de0: 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63  rn rc;.}..static
6df0: 20 69 6e 74 20 66 74 73 33 4d 61 74 63 68 69 6e   int fts3Matchin
6e00: 66 6f 43 68 65 63 6b 28 0a 20 20 46 74 73 33 54  foCheck(.  Fts3T
6e10: 61 62 6c 65 20 2a 70 54 61 62 2c 20 0a 20 20 63  able *pTab, .  c
6e20: 68 61 72 20 63 41 72 67 2c 0a 20 20 63 68 61 72  har cArg,.  char
6e30: 20 2a 2a 70 7a 45 72 72 0a 29 7b 0a 20 20 69 66   **pzErr.){.  if
6e40: 28 20 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41  ( (cArg==FTS3_MA
6e50: 54 43 48 49 4e 46 4f 5f 4e 50 48 52 41 53 45 29  TCHINFO_NPHRASE)
6e60: 0a 20 20 20 7c 7c 20 28 63 41 72 67 3d 3d 46 54  .   || (cArg==FT
6e70: 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e 43 4f  S3_MATCHINFO_NCO
6e80: 4c 29 0a 20 20 20 7c 7c 20 28 63 41 72 67 3d 3d  L).   || (cArg==
6e90: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e  FTS3_MATCHINFO_N
6ea0: 44 4f 43 20 26 26 20 70 54 61 62 2d 3e 62 46 74  DOC && pTab->bFt
6eb0: 73 34 29 0a 20 20 20 7c 7c 20 28 63 41 72 67 3d  s4).   || (cArg=
6ec0: 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f  =FTS3_MATCHINFO_
6ed0: 41 56 47 4c 45 4e 47 54 48 20 26 26 20 70 54 61  AVGLENGTH && pTa
6ee0: 62 2d 3e 62 46 74 73 34 29 0a 20 20 20 7c 7c 20  b->bFts4).   || 
6ef0: 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41 54 43  (cArg==FTS3_MATC
6f00: 48 49 4e 46 4f 5f 4c 45 4e 47 54 48 20 26 26 20  HINFO_LENGTH && 
6f10: 70 54 61 62 2d 3e 62 48 61 73 44 6f 63 73 69 7a  pTab->bHasDocsiz
6f20: 65 29 0a 20 20 20 7c 7c 20 28 63 41 72 67 3d 3d  e).   || (cArg==
6f30: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c  FTS3_MATCHINFO_L
6f40: 43 53 29 0a 20 20 20 7c 7c 20 28 63 41 72 67 3d  CS).   || (cArg=
6f50: 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f  =FTS3_MATCHINFO_
6f60: 48 49 54 53 29 0a 20 20 29 7b 0a 20 20 20 20 72  HITS).  ){.    r
6f70: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b  eturn SQLITE_OK;
6f80: 0a 20 20 7d 0a 20 20 2a 70 7a 45 72 72 20 3d 20  .  }.  *pzErr = 
6f90: 73 71 6c 69 74 65 33 5f 6d 70 72 69 6e 74 66 28  sqlite3_mprintf(
6fa0: 22 75 6e 72 65 63 6f 67 6e 69 7a 65 64 20 6d 61  "unrecognized ma
6fb0: 74 63 68 69 6e 66 6f 20 72 65 71 75 65 73 74 3a  tchinfo request:
6fc0: 20 25 63 22 2c 20 63 41 72 67 29 3b 0a 20 20 72   %c", cArg);.  r
6fd0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 45 52 52  eturn SQLITE_ERR
6fe0: 4f 52 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e  OR;.}..static in
6ff0: 74 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 53  t fts3MatchinfoS
7000: 69 7a 65 28 4d 61 74 63 68 49 6e 66 6f 20 2a 70  ize(MatchInfo *p
7010: 49 6e 66 6f 2c 20 63 68 61 72 20 63 41 72 67 29  Info, char cArg)
7020: 7b 0a 20 20 69 6e 74 20 6e 56 61 6c 3b 20 20 20  {.  int nVal;   
7030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7040: 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66      /* Number of
7050: 20 69 6e 74 65 67 65 72 73 20 6f 75 74 70 75 74   integers output
7060: 20 62 79 20 63 41 72 67 20 2a 2f 0a 0a 20 20 73   by cArg */..  s
7070: 77 69 74 63 68 28 20 63 41 72 67 20 29 7b 0a 20  witch( cArg ){. 
7080: 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54     case FTS3_MAT
7090: 43 48 49 4e 46 4f 5f 4e 44 4f 43 3a 0a 20 20 20  CHINFO_NDOC:.   
70a0: 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54 43 48   case FTS3_MATCH
70b0: 49 4e 46 4f 5f 4e 50 48 52 41 53 45 3a 20 0a 20  INFO_NPHRASE: . 
70c0: 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54     case FTS3_MAT
70d0: 43 48 49 4e 46 4f 5f 4e 43 4f 4c 3a 20 0a 20 20  CHINFO_NCOL: .  
70e0: 20 20 20 20 6e 56 61 6c 20 3d 20 31 3b 0a 20 20      nVal = 1;.  
70f0: 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20      break;..    
7100: 63 61 73 65 20 46 54 53 33 5f 4d 41 54 43 48 49  case FTS3_MATCHI
7110: 4e 46 4f 5f 41 56 47 4c 45 4e 47 54 48 3a 0a 20  NFO_AVGLENGTH:. 
7120: 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54     case FTS3_MAT
7130: 43 48 49 4e 46 4f 5f 4c 45 4e 47 54 48 3a 0a 20  CHINFO_LENGTH:. 
7140: 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54     case FTS3_MAT
7150: 43 48 49 4e 46 4f 5f 4c 43 53 3a 0a 20 20 20 20  CHINFO_LCS:.    
7160: 20 20 6e 56 61 6c 20 3d 20 70 49 6e 66 6f 2d 3e    nVal = pInfo->
7170: 6e 43 6f 6c 3b 0a 20 20 20 20 20 20 62 72 65 61  nCol;.      brea
7180: 6b 3b 0a 0a 20 20 20 20 64 65 66 61 75 6c 74 3a  k;..    default:
7190: 0a 20 20 20 20 20 20 61 73 73 65 72 74 28 20 63  .      assert( c
71a0: 41 72 67 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49  Arg==FTS3_MATCHI
71b0: 4e 46 4f 5f 48 49 54 53 20 29 3b 0a 20 20 20 20  NFO_HITS );.    
71c0: 20 20 6e 56 61 6c 20 3d 20 70 49 6e 66 6f 2d 3e    nVal = pInfo->
71d0: 6e 43 6f 6c 20 2a 20 70 49 6e 66 6f 2d 3e 6e 50  nCol * pInfo->nP
71e0: 68 72 61 73 65 20 2a 20 33 3b 0a 20 20 20 20 20  hrase * 3;.     
71f0: 20 62 72 65 61 6b 3b 0a 20 20 7d 0a 0a 20 20 72   break;.  }..  r
7200: 65 74 75 72 6e 20 6e 56 61 6c 3b 0a 7d 0a 0a 73  eturn nVal;.}..s
7210: 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 4d 61  tatic int fts3Ma
7220: 74 63 68 69 6e 66 6f 53 65 6c 65 63 74 44 6f 63  tchinfoSelectDoc
7230: 74 6f 74 61 6c 28 0a 20 20 46 74 73 33 54 61 62  total(.  Fts3Tab
7240: 6c 65 20 2a 70 54 61 62 2c 0a 20 20 73 71 6c 69  le *pTab,.  sqli
7250: 74 65 33 5f 73 74 6d 74 20 2a 2a 70 70 53 74 6d  te3_stmt **ppStm
7260: 74 2c 0a 20 20 73 71 6c 69 74 65 33 5f 69 6e 74  t,.  sqlite3_int
7270: 36 34 20 2a 70 6e 44 6f 63 2c 0a 20 20 63 6f 6e  64 *pnDoc,.  con
7280: 73 74 20 63 68 61 72 20 2a 2a 70 61 4c 65 6e 0a  st char **paLen.
7290: 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f 73 74 6d  ){.  sqlite3_stm
72a0: 74 20 2a 70 53 74 6d 74 3b 0a 20 20 63 6f 6e 73  t *pStmt;.  cons
72b0: 74 20 63 68 61 72 20 2a 61 3b 0a 20 20 73 71 6c  t char *a;.  sql
72c0: 69 74 65 33 5f 69 6e 74 36 34 20 6e 44 6f 63 3b  ite3_int64 nDoc;
72d0: 0a 0a 20 20 69 66 28 20 21 2a 70 70 53 74 6d 74  ..  if( !*ppStmt
72e0: 20 29 7b 0a 20 20 20 20 69 6e 74 20 72 63 20 3d   ){.    int rc =
72f0: 20 73 71 6c 69 74 65 33 46 74 73 33 53 65 6c 65   sqlite3Fts3Sele
7300: 63 74 44 6f 63 74 6f 74 61 6c 28 70 54 61 62 2c  ctDoctotal(pTab,
7310: 20 70 70 53 74 6d 74 29 3b 0a 20 20 20 20 69 66   ppStmt);.    if
7320: 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc!=SQLITE_OK 
7330: 29 20 72 65 74 75 72 6e 20 72 63 3b 0a 20 20 7d  ) return rc;.  }
7340: 0a 20 20 70 53 74 6d 74 20 3d 20 2a 70 70 53 74  .  pStmt = *ppSt
7350: 6d 74 3b 0a 20 20 61 73 73 65 72 74 28 20 73 71  mt;.  assert( sq
7360: 6c 69 74 65 33 5f 64 61 74 61 5f 63 6f 75 6e 74  lite3_data_count
7370: 28 70 53 74 6d 74 29 3d 3d 31 20 29 3b 0a 0a 20  (pStmt)==1 );.. 
7380: 20 61 20 3d 20 73 71 6c 69 74 65 33 5f 63 6f 6c   a = sqlite3_col
7390: 75 6d 6e 5f 62 6c 6f 62 28 70 53 74 6d 74 2c 20  umn_blob(pStmt, 
73a0: 30 29 3b 0a 20 20 61 20 2b 3d 20 73 71 6c 69 74  0);.  a += sqlit
73b0: 65 33 46 74 73 33 47 65 74 56 61 72 69 6e 74 28  e3Fts3GetVarint(
73c0: 61 2c 20 26 6e 44 6f 63 29 3b 0a 20 20 69 66 28  a, &nDoc);.  if(
73d0: 20 6e 44 6f 63 3d 3d 30 20 29 20 72 65 74 75 72   nDoc==0 ) retur
73e0: 6e 20 46 54 53 5f 43 4f 52 52 55 50 54 5f 56 54  n FTS_CORRUPT_VT
73f0: 41 42 3b 0a 20 20 2a 70 6e 44 6f 63 20 3d 20 28  AB;.  *pnDoc = (
7400: 75 33 32 29 6e 44 6f 63 3b 0a 0a 20 20 69 66 28  u32)nDoc;..  if(
7410: 20 70 61 4c 65 6e 20 29 20 2a 70 61 4c 65 6e 20   paLen ) *paLen 
7420: 3d 20 61 3b 0a 20 20 72 65 74 75 72 6e 20 53 51  = a;.  return SQ
7430: 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a  LITE_OK;.}../*.*
7440: 2a 20 41 6e 20 69 6e 73 74 61 6e 63 65 20 6f 66  * An instance of
7450: 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 73   the following s
7460: 74 72 75 63 74 75 72 65 20 69 73 20 75 73 65 64  tructure is used
7470: 20 74 6f 20 73 74 6f 72 65 20 73 74 61 74 65 20   to store state 
7480: 77 68 69 6c 65 20 0a 2a 2a 20 69 74 65 72 61 74  while .** iterat
7490: 69 6e 67 20 74 68 72 6f 75 67 68 20 61 20 6d 75  ing through a mu
74a0: 6c 74 69 2d 63 6f 6c 75 6d 6e 20 70 6f 73 69 74  lti-column posit
74b0: 69 6f 6e 2d 6c 69 73 74 20 63 6f 72 72 65 73 70  ion-list corresp
74c0: 6f 6e 64 69 6e 67 20 74 6f 20 74 68 65 0a 2a 2a  onding to the.**
74d0: 20 68 69 74 73 20 66 6f 72 20 61 20 73 69 6e 67   hits for a sing
74e0: 6c 65 20 70 68 72 61 73 65 20 6f 6e 20 61 20 73  le phrase on a s
74f0: 69 6e 67 6c 65 20 72 6f 77 20 69 6e 20 6f 72 64  ingle row in ord
7500: 65 72 20 74 6f 20 63 61 6c 63 75 6c 61 74 65 20  er to calculate 
7510: 74 68 65 0a 2a 2a 20 76 61 6c 75 65 73 20 66 6f  the.** values fo
7520: 72 20 61 20 6d 61 74 63 68 69 6e 66 6f 28 29 20  r a matchinfo() 
7530: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c  FTS3_MATCHINFO_L
7540: 43 53 20 72 65 71 75 65 73 74 2e 0a 2a 2f 0a 74  CS request..*/.t
7550: 79 70 65 64 65 66 20 73 74 72 75 63 74 20 4c 63  ypedef struct Lc
7560: 73 49 74 65 72 61 74 6f 72 20 4c 63 73 49 74 65  sIterator LcsIte
7570: 72 61 74 6f 72 3b 0a 73 74 72 75 63 74 20 4c 63  rator;.struct Lc
7580: 73 49 74 65 72 61 74 6f 72 20 7b 0a 20 20 46 74  sIterator {.  Ft
7590: 73 33 45 78 70 72 20 2a 70 45 78 70 72 3b 20 20  s3Expr *pExpr;  
75a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
75b0: 20 50 6f 69 6e 74 65 72 20 74 6f 20 70 68 72 61   Pointer to phra
75c0: 73 65 20 65 78 70 72 65 73 73 69 6f 6e 20 2a 2f  se expression */
75d0: 0a 20 20 69 6e 74 20 69 50 6f 73 4f 66 66 73 65  .  int iPosOffse
75e0: 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  t;              
75f0: 20 20 20 2f 2a 20 54 6f 6b 65 6e 73 20 63 6f 75     /* Tokens cou
7600: 6e 74 20 75 70 20 74 6f 20 65 6e 64 20 6f 66 20  nt up to end of 
7610: 74 68 69 73 20 70 68 72 61 73 65 20 2a 2f 0a 20  this phrase */. 
7620: 20 63 68 61 72 20 2a 70 52 65 61 64 3b 20 20 20   char *pRead;   
7630: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7640: 20 2f 2a 20 43 75 72 73 6f 72 20 75 73 65 64 20   /* Cursor used 
7650: 74 6f 20 69 74 65 72 61 74 65 20 74 68 72 6f 75  to iterate throu
7660: 67 68 20 61 44 6f 63 6c 69 73 74 20 2a 2f 0a 20  gh aDoclist */. 
7670: 20 69 6e 74 20 69 50 6f 73 3b 20 20 20 20 20 20   int iPos;      
7680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7690: 20 2f 2a 20 43 75 72 72 65 6e 74 20 70 6f 73 69   /* Current posi
76a0: 74 69 6f 6e 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 20 0a  tion */.};../* .
76b0: 2a 2a 20 49 66 20 4c 63 73 49 74 65 72 61 74 6f  ** If LcsIterato
76c0: 72 2e 69 43 6f 6c 20 69 73 20 73 65 74 20 74 6f  r.iCol is set to
76d0: 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 76   the following v
76e0: 61 6c 75 65 2c 20 74 68 65 20 69 74 65 72 61 74  alue, the iterat
76f0: 6f 72 20 68 61 73 0a 2a 2a 20 66 69 6e 69 73 68  or has.** finish
7700: 65 64 20 69 74 65 72 61 74 69 6e 67 20 74 68 72  ed iterating thr
7710: 6f 75 67 68 20 61 6c 6c 20 6f 66 66 73 65 74 73  ough all offsets
7720: 20 66 6f 72 20 61 6c 6c 20 63 6f 6c 75 6d 6e 73   for all columns
7730: 2e 0a 2a 2f 0a 23 64 65 66 69 6e 65 20 4c 43 53  ..*/.#define LCS
7740: 5f 49 54 45 52 41 54 4f 52 5f 46 49 4e 49 53 48  _ITERATOR_FINISH
7750: 45 44 20 30 78 37 46 46 46 46 46 46 46 3b 0a 0a  ED 0x7FFFFFFF;..
7760: 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 4d  static int fts3M
7770: 61 74 63 68 69 6e 66 6f 4c 63 73 43 62 28 0a 20  atchinfoLcsCb(. 
7780: 20 46 74 73 33 45 78 70 72 20 2a 70 45 78 70 72   Fts3Expr *pExpr
7790: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
77a0: 20 2f 2a 20 50 68 72 61 73 65 20 65 78 70 72 65   /* Phrase expre
77b0: 73 73 69 6f 6e 20 6e 6f 64 65 20 2a 2f 0a 20 20  ssion node */.  
77c0: 69 6e 74 20 69 50 68 72 61 73 65 2c 20 20 20 20  int iPhrase,    
77d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
77e0: 2f 2a 20 50 68 72 61 73 65 20 6e 75 6d 62 65 72  /* Phrase number
77f0: 20 28 6e 75 6d 62 65 72 65 64 20 66 72 6f 6d 20   (numbered from 
7800: 7a 65 72 6f 29 20 2a 2f 0a 20 20 76 6f 69 64 20  zero) */.  void 
7810: 2a 70 43 74 78 20 20 20 20 20 20 20 20 20 20 20  *pCtx           
7820: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 6f             /* Po
7830: 69 6e 74 65 72 20 74 6f 20 4d 61 74 63 68 49 6e  inter to MatchIn
7840: 66 6f 20 73 74 72 75 63 74 75 72 65 20 2a 2f 0a  fo structure */.
7850: 29 7b 0a 20 20 4c 63 73 49 74 65 72 61 74 6f 72  ){.  LcsIterator
7860: 20 2a 61 49 74 65 72 20 3d 20 28 4c 63 73 49 74   *aIter = (LcsIt
7870: 65 72 61 74 6f 72 20 2a 29 70 43 74 78 3b 0a 20  erator *)pCtx;. 
7880: 20 61 49 74 65 72 5b 69 50 68 72 61 73 65 5d 2e   aIter[iPhrase].
7890: 70 45 78 70 72 20 3d 20 70 45 78 70 72 3b 0a 20  pExpr = pExpr;. 
78a0: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f   return SQLITE_O
78b0: 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 64 76 61  K;.}../*.** Adva
78c0: 6e 63 65 20 74 68 65 20 69 74 65 72 61 74 6f 72  nce the iterator
78d0: 20 70 61 73 73 65 64 20 61 73 20 61 6e 20 61 72   passed as an ar
78e0: 67 75 6d 65 6e 74 20 74 6f 20 74 68 65 20 6e 65  gument to the ne
78f0: 78 74 20 70 6f 73 69 74 69 6f 6e 2e 20 52 65 74  xt position. Ret
7900: 75 72 6e 0a 2a 2a 20 31 20 69 66 20 74 68 65 20  urn.** 1 if the 
7910: 69 74 65 72 61 74 6f 72 20 69 73 20 61 74 20 45  iterator is at E
7920: 4f 46 20 6f 72 20 69 66 20 69 74 20 6e 6f 77 20  OF or if it now 
7930: 70 6f 69 6e 74 73 20 74 6f 20 74 68 65 20 73 74  points to the st
7940: 61 72 74 20 6f 66 20 74 68 65 0a 2a 2a 20 70 6f  art of the.** po
7950: 73 69 74 69 6f 6e 20 6c 69 73 74 20 66 6f 72 20  sition list for 
7960: 74 68 65 20 6e 65 78 74 20 63 6f 6c 75 6d 6e 2e  the next column.
7970: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66  .*/.static int f
7980: 74 73 33 4c 63 73 49 74 65 72 61 74 6f 72 41 64  ts3LcsIteratorAd
7990: 76 61 6e 63 65 28 4c 63 73 49 74 65 72 61 74 6f  vance(LcsIterato
79a0: 72 20 2a 70 49 74 65 72 29 7b 0a 20 20 63 68 61  r *pIter){.  cha
79b0: 72 20 2a 70 52 65 61 64 20 3d 20 70 49 74 65 72  r *pRead = pIter
79c0: 2d 3e 70 52 65 61 64 3b 0a 20 20 73 71 6c 69 74  ->pRead;.  sqlit
79d0: 65 33 5f 69 6e 74 36 34 20 69 52 65 61 64 3b 0a  e3_int64 iRead;.
79e0: 20 20 69 6e 74 20 72 63 20 3d 20 30 3b 0a 0a 20    int rc = 0;.. 
79f0: 20 70 52 65 61 64 20 2b 3d 20 73 71 6c 69 74 65   pRead += sqlite
7a00: 33 46 74 73 33 47 65 74 56 61 72 69 6e 74 28 70  3Fts3GetVarint(p
7a10: 52 65 61 64 2c 20 26 69 52 65 61 64 29 3b 0a 20  Read, &iRead);. 
7a20: 20 69 66 28 20 69 52 65 61 64 3d 3d 30 20 7c 7c   if( iRead==0 ||
7a30: 20 69 52 65 61 64 3d 3d 31 20 29 7b 0a 20 20 20   iRead==1 ){.   
7a40: 20 70 52 65 61 64 20 3d 20 30 3b 0a 20 20 20 20   pRead = 0;.    
7a50: 72 63 20 3d 20 31 3b 0a 20 20 7d 65 6c 73 65 7b  rc = 1;.  }else{
7a60: 0a 20 20 20 20 70 49 74 65 72 2d 3e 69 50 6f 73  .    pIter->iPos
7a70: 20 2b 3d 20 28 69 6e 74 29 28 69 52 65 61 64 2d   += (int)(iRead-
7a80: 32 29 3b 0a 20 20 7d 0a 0a 20 20 70 49 74 65 72  2);.  }..  pIter
7a90: 2d 3e 70 52 65 61 64 20 3d 20 70 52 65 61 64 3b  ->pRead = pRead;
7aa0: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
7ab0: 20 20 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66 75    ./*.** This fu
7ac0: 6e 63 74 69 6f 6e 20 69 6d 70 6c 65 6d 65 6e 74  nction implement
7ad0: 73 20 74 68 65 20 46 54 53 33 5f 4d 41 54 43 48  s the FTS3_MATCH
7ae0: 49 4e 46 4f 5f 4c 43 53 20 6d 61 74 63 68 69 6e  INFO_LCS matchin
7af0: 66 6f 28 29 20 66 6c 61 67 2e 20 0a 2a 2a 0a 2a  fo() flag. .**.*
7b00: 2a 20 49 66 20 74 68 65 20 63 61 6c 6c 20 69 73  * If the call is
7b10: 20 73 75 63 63 65 73 73 66 75 6c 2c 20 74 68 65   successful, the
7b20: 20 6c 6f 6e 67 65 73 74 2d 63 6f 6d 6d 6f 6e 2d   longest-common-
7b30: 73 75 62 73 74 72 69 6e 67 20 6c 65 6e 67 74 68  substring length
7b40: 73 20 66 6f 72 20 65 61 63 68 0a 2a 2a 20 63 6f  s for each.** co
7b50: 6c 75 6d 6e 20 61 72 65 20 77 72 69 74 74 65 6e  lumn are written
7b60: 20 69 6e 74 6f 20 74 68 65 20 66 69 72 73 74 20   into the first 
7b70: 6e 43 6f 6c 20 65 6c 65 6d 65 6e 74 73 20 6f 66  nCol elements of
7b80: 20 74 68 65 20 70 49 6e 66 6f 2d 3e 61 4d 61 74   the pInfo->aMat
7b90: 63 68 69 6e 66 6f 5b 5d 20 0a 2a 2a 20 61 72 72  chinfo[] .** arr
7ba0: 61 79 20 62 65 66 6f 72 65 20 72 65 74 75 72 6e  ay before return
7bb0: 69 6e 67 2e 20 53 51 4c 49 54 45 5f 4f 4b 20 69  ing. SQLITE_OK i
7bc0: 73 20 72 65 74 75 72 6e 65 64 20 69 6e 20 74 68  s returned in th
7bd0: 69 73 20 63 61 73 65 2e 0a 2a 2a 0a 2a 2a 20 4f  is case..**.** O
7be0: 74 68 65 72 77 69 73 65 2c 20 69 66 20 61 6e 20  therwise, if an 
7bf0: 65 72 72 6f 72 20 6f 63 63 75 72 73 2c 20 61 6e  error occurs, an
7c00: 20 53 51 4c 69 74 65 20 65 72 72 6f 72 20 63 6f   SQLite error co
7c10: 64 65 20 69 73 20 72 65 74 75 72 6e 65 64 20 61  de is returned a
7c20: 6e 64 20 74 68 65 0a 2a 2a 20 64 61 74 61 20 77  nd the.** data w
7c30: 72 69 74 74 65 6e 20 74 6f 20 74 68 65 20 66 69  ritten to the fi
7c40: 72 73 74 20 6e 43 6f 6c 20 65 6c 65 6d 65 6e 74  rst nCol element
7c50: 73 20 6f 66 20 70 49 6e 66 6f 2d 3e 61 4d 61 74  s of pInfo->aMat
7c60: 63 68 69 6e 66 6f 5b 5d 20 69 73 20 0a 2a 2a 20  chinfo[] is .** 
7c70: 75 6e 64 65 66 69 6e 65 64 2e 0a 2a 2f 0a 73 74  undefined..*/.st
7c80: 61 74 69 63 20 69 6e 74 20 66 74 73 33 4d 61 74  atic int fts3Mat
7c90: 63 68 69 6e 66 6f 4c 63 73 28 46 74 73 33 43 75  chinfoLcs(Fts3Cu
7ca0: 72 73 6f 72 20 2a 70 43 73 72 2c 20 4d 61 74 63  rsor *pCsr, Matc
7cb0: 68 49 6e 66 6f 20 2a 70 49 6e 66 6f 29 7b 0a 20  hInfo *pInfo){. 
7cc0: 20 4c 63 73 49 74 65 72 61 74 6f 72 20 2a 61 49   LcsIterator *aI
7cd0: 74 65 72 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20  ter;.  int i;.  
7ce0: 69 6e 74 20 69 43 6f 6c 3b 0a 20 20 69 6e 74 20  int iCol;.  int 
7cf0: 6e 54 6f 6b 65 6e 20 3d 20 30 3b 0a 0a 20 20 2f  nToken = 0;..  /
7d00: 2a 20 41 6c 6c 6f 63 61 74 65 20 61 6e 64 20 70  * Allocate and p
7d10: 6f 70 75 6c 61 74 65 20 74 68 65 20 61 72 72 61  opulate the arra
7d20: 79 20 6f 66 20 4c 63 73 49 74 65 72 61 74 6f 72  y of LcsIterator
7d30: 20 6f 62 6a 65 63 74 73 2e 20 54 68 65 20 61 72   objects. The ar
7d40: 72 61 79 0a 20 20 2a 2a 20 63 6f 6e 74 61 69 6e  ray.  ** contain
7d50: 73 20 6f 6e 65 20 65 6c 65 6d 65 6e 74 20 66 6f  s one element fo
7d60: 72 20 65 61 63 68 20 6d 61 74 63 68 61 62 6c 65  r each matchable
7d70: 20 70 68 72 61 73 65 20 69 6e 20 74 68 65 20 71   phrase in the q
7d80: 75 65 72 79 2e 0a 20 20 2a 2a 2f 0a 20 20 61 49  uery..  **/.  aI
7d90: 74 65 72 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61  ter = sqlite3_ma
7da0: 6c 6c 6f 63 28 73 69 7a 65 6f 66 28 4c 63 73 49  lloc(sizeof(LcsI
7db0: 74 65 72 61 74 6f 72 29 20 2a 20 70 43 73 72 2d  terator) * pCsr-
7dc0: 3e 6e 50 68 72 61 73 65 29 3b 0a 20 20 69 66 28  >nPhrase);.  if(
7dd0: 20 21 61 49 74 65 72 20 29 20 72 65 74 75 72 6e   !aIter ) return
7de0: 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20   SQLITE_NOMEM;. 
7df0: 20 6d 65 6d 73 65 74 28 61 49 74 65 72 2c 20 30   memset(aIter, 0
7e00: 2c 20 73 69 7a 65 6f 66 28 4c 63 73 49 74 65 72  , sizeof(LcsIter
7e10: 61 74 6f 72 29 20 2a 20 70 43 73 72 2d 3e 6e 50  ator) * pCsr->nP
7e20: 68 72 61 73 65 29 3b 0a 20 20 28 76 6f 69 64 29  hrase);.  (void)
7e30: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 28  fts3ExprIterate(
7e40: 70 43 73 72 2d 3e 70 45 78 70 72 2c 20 66 74 73  pCsr->pExpr, fts
7e50: 33 4d 61 74 63 68 69 6e 66 6f 4c 63 73 43 62 2c  3MatchinfoLcsCb,
7e60: 20 28 76 6f 69 64 2a 29 61 49 74 65 72 29 3b 0a   (void*)aIter);.
7e70: 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70 49  .  for(i=0; i<pI
7e80: 6e 66 6f 2d 3e 6e 50 68 72 61 73 65 3b 20 69 2b  nfo->nPhrase; i+
7e90: 2b 29 7b 0a 20 20 20 20 4c 63 73 49 74 65 72 61  +){.    LcsItera
7ea0: 74 6f 72 20 2a 70 49 74 65 72 20 3d 20 26 61 49  tor *pIter = &aI
7eb0: 74 65 72 5b 69 5d 3b 0a 20 20 20 20 6e 54 6f 6b  ter[i];.    nTok
7ec0: 65 6e 20 2d 3d 20 70 49 74 65 72 2d 3e 70 45 78  en -= pIter->pEx
7ed0: 70 72 2d 3e 70 50 68 72 61 73 65 2d 3e 6e 54 6f  pr->pPhrase->nTo
7ee0: 6b 65 6e 3b 0a 20 20 20 20 70 49 74 65 72 2d 3e  ken;.    pIter->
7ef0: 69 50 6f 73 4f 66 66 73 65 74 20 3d 20 6e 54 6f  iPosOffset = nTo
7f00: 6b 65 6e 3b 0a 20 20 7d 0a 0a 20 20 66 6f 72 28  ken;.  }..  for(
7f10: 69 43 6f 6c 3d 30 3b 20 69 43 6f 6c 3c 70 49 6e  iCol=0; iCol<pIn
7f20: 66 6f 2d 3e 6e 43 6f 6c 3b 20 69 43 6f 6c 2b 2b  fo->nCol; iCol++
7f30: 29 7b 0a 20 20 20 20 69 6e 74 20 6e 4c 63 73 20  ){.    int nLcs 
7f40: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
7f50: 20 20 20 20 20 2f 2a 20 4c 43 53 20 76 61 6c 75       /* LCS valu
7f60: 65 20 66 6f 72 20 74 68 69 73 20 63 6f 6c 75 6d  e for this colum
7f70: 6e 20 2a 2f 0a 20 20 20 20 69 6e 74 20 6e 4c 69  n */.    int nLi
7f80: 76 65 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  ve = 0;         
7f90: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
7fa0: 20 6f 66 20 69 74 65 72 61 74 6f 72 73 20 69 6e   of iterators in
7fb0: 20 61 49 74 65 72 20 6e 6f 74 20 61 74 20 45 4f   aIter not at EO
7fc0: 46 20 2a 2f 0a 0a 20 20 20 20 66 6f 72 28 69 3d  F */..    for(i=
7fd0: 30 3b 20 69 3c 70 49 6e 66 6f 2d 3e 6e 50 68 72  0; i<pInfo->nPhr
7fe0: 61 73 65 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20  ase; i++){.     
7ff0: 20 69 6e 74 20 72 63 3b 0a 20 20 20 20 20 20 4c   int rc;.      L
8000: 63 73 49 74 65 72 61 74 6f 72 20 2a 70 49 74 20  csIterator *pIt 
8010: 3d 20 26 61 49 74 65 72 5b 69 5d 3b 0a 20 20 20  = &aIter[i];.   
8020: 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 46     rc = sqlite3F
8030: 74 73 33 45 76 61 6c 50 68 72 61 73 65 50 6f 73  ts3EvalPhrasePos
8040: 6c 69 73 74 28 70 43 73 72 2c 20 70 49 74 2d 3e  list(pCsr, pIt->
8050: 70 45 78 70 72 2c 20 69 43 6f 6c 2c 20 26 70 49  pExpr, iCol, &pI
8060: 74 2d 3e 70 52 65 61 64 29 3b 0a 20 20 20 20 20  t->pRead);.     
8070: 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f   if( rc!=SQLITE_
8080: 4f 4b 20 29 20 72 65 74 75 72 6e 20 72 63 3b 0a  OK ) return rc;.
8090: 20 20 20 20 20 20 69 66 28 20 70 49 74 2d 3e 70        if( pIt->p
80a0: 52 65 61 64 20 29 7b 0a 20 20 20 20 20 20 20 20  Read ){.        
80b0: 70 49 74 2d 3e 69 50 6f 73 20 3d 20 70 49 74 2d  pIt->iPos = pIt-
80c0: 3e 69 50 6f 73 4f 66 66 73 65 74 3b 0a 20 20 20  >iPosOffset;.   
80d0: 20 20 20 20 20 66 74 73 33 4c 63 73 49 74 65 72       fts3LcsIter
80e0: 61 74 6f 72 41 64 76 61 6e 63 65 28 26 61 49 74  atorAdvance(&aIt
80f0: 65 72 5b 69 5d 29 3b 0a 20 20 20 20 20 20 20 20  er[i]);.        
8100: 6e 4c 69 76 65 2b 2b 3b 0a 20 20 20 20 20 20 7d  nLive++;.      }
8110: 0a 20 20 20 20 7d 0a 0a 20 20 20 20 77 68 69 6c  .    }..    whil
8120: 65 28 20 6e 4c 69 76 65 3e 30 20 29 7b 0a 20 20  e( nLive>0 ){.  
8130: 20 20 20 20 4c 63 73 49 74 65 72 61 74 6f 72 20      LcsIterator 
8140: 2a 70 41 64 76 20 3d 20 30 3b 20 20 20 20 20 20  *pAdv = 0;      
8150: 2f 2a 20 54 68 65 20 69 74 65 72 61 74 6f 72 20  /* The iterator 
8160: 74 6f 20 61 64 76 61 6e 63 65 20 62 79 20 6f 6e  to advance by on
8170: 65 20 70 6f 73 69 74 69 6f 6e 20 2a 2f 0a 20 20  e position */.  
8180: 20 20 20 20 69 6e 74 20 6e 54 68 69 73 4c 63 73      int nThisLcs
8190: 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20   = 0;           
81a0: 2f 2a 20 4c 43 53 20 66 6f 72 20 74 68 65 20 63  /* LCS for the c
81b0: 75 72 72 65 6e 74 20 69 74 65 72 61 74 6f 72 20  urrent iterator 
81c0: 70 6f 73 69 74 69 6f 6e 73 20 2a 2f 0a 0a 20 20  positions */..  
81d0: 20 20 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70      for(i=0; i<p
81e0: 49 6e 66 6f 2d 3e 6e 50 68 72 61 73 65 3b 20 69  Info->nPhrase; i
81f0: 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 4c 63 73  ++){.        Lcs
8200: 49 74 65 72 61 74 6f 72 20 2a 70 49 74 65 72 20  Iterator *pIter 
8210: 3d 20 26 61 49 74 65 72 5b 69 5d 3b 0a 20 20 20  = &aIter[i];.   
8220: 20 20 20 20 20 69 66 28 20 70 49 74 65 72 2d 3e       if( pIter->
8230: 70 52 65 61 64 3d 3d 30 20 29 7b 0a 20 20 20 20  pRead==0 ){.    
8240: 20 20 20 20 20 20 2f 2a 20 54 68 69 73 20 69 74        /* This it
8250: 65 72 61 74 6f 72 20 69 73 20 61 6c 72 65 61 64  erator is alread
8260: 79 20 61 74 20 45 4f 46 20 66 6f 72 20 74 68 69  y at EOF for thi
8270: 73 20 63 6f 6c 75 6d 6e 2e 20 2a 2f 0a 20 20 20  s column. */.   
8280: 20 20 20 20 20 20 20 6e 54 68 69 73 4c 63 73 20         nThisLcs 
8290: 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c  = 0;.        }el
82a0: 73 65 7b 0a 20 20 20 20 20 20 20 20 20 20 69 66  se{.          if
82b0: 28 20 70 41 64 76 3d 3d 30 20 7c 7c 20 70 49 74  ( pAdv==0 || pIt
82c0: 65 72 2d 3e 69 50 6f 73 3c 70 41 64 76 2d 3e 69  er->iPos<pAdv->i
82d0: 50 6f 73 20 29 7b 0a 20 20 20 20 20 20 20 20 20  Pos ){.         
82e0: 20 20 20 70 41 64 76 20 3d 20 70 49 74 65 72 3b     pAdv = pIter;
82f0: 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20  .          }.   
8300: 20 20 20 20 20 20 20 69 66 28 20 6e 54 68 69 73         if( nThis
8310: 4c 63 73 3d 3d 30 20 7c 7c 20 70 49 74 65 72 2d  Lcs==0 || pIter-
8320: 3e 69 50 6f 73 3d 3d 70 49 74 65 72 5b 2d 31 5d  >iPos==pIter[-1]
8330: 2e 69 50 6f 73 20 29 7b 0a 20 20 20 20 20 20 20  .iPos ){.       
8340: 20 20 20 20 20 6e 54 68 69 73 4c 63 73 2b 2b 3b       nThisLcs++;
8350: 0a 20 20 20 20 20 20 20 20 20 20 7d 65 6c 73 65  .          }else
8360: 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 54  {.            nT
8370: 68 69 73 4c 63 73 20 3d 20 31 3b 0a 20 20 20 20  hisLcs = 1;.    
8380: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20        }.        
8390: 20 20 69 66 28 20 6e 54 68 69 73 4c 63 73 3e 6e    if( nThisLcs>n
83a0: 4c 63 73 20 29 20 6e 4c 63 73 20 3d 20 6e 54 68  Lcs ) nLcs = nTh
83b0: 69 73 4c 63 73 3b 0a 20 20 20 20 20 20 20 20 7d  isLcs;.        }
83c0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 69  .      }.      i
83d0: 66 28 20 66 74 73 33 4c 63 73 49 74 65 72 61 74  f( fts3LcsIterat
83e0: 6f 72 41 64 76 61 6e 63 65 28 70 41 64 76 29 20  orAdvance(pAdv) 
83f0: 29 20 6e 4c 69 76 65 2d 2d 3b 0a 20 20 20 20 7d  ) nLive--;.    }
8400: 0a 0a 20 20 20 20 70 49 6e 66 6f 2d 3e 61 4d 61  ..    pInfo->aMa
8410: 74 63 68 69 6e 66 6f 5b 69 43 6f 6c 5d 20 3d 20  tchinfo[iCol] = 
8420: 6e 4c 63 73 3b 0a 20 20 7d 0a 0a 20 20 73 71 6c  nLcs;.  }..  sql
8430: 69 74 65 33 5f 66 72 65 65 28 61 49 74 65 72 29  ite3_free(aIter)
8440: 3b 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  ;.  return SQLIT
8450: 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 50  E_OK;.}../*.** P
8460: 6f 70 75 6c 61 74 65 20 74 68 65 20 62 75 66 66  opulate the buff
8470: 65 72 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63 68  er pInfo->aMatch
8480: 69 6e 66 6f 5b 5d 20 77 69 74 68 20 61 6e 20 61  info[] with an a
8490: 72 72 61 79 20 6f 66 20 69 6e 74 65 67 65 72 73  rray of integers
84a0: 20 74 6f 0a 2a 2a 20 62 65 20 72 65 74 75 72 6e   to.** be return
84b0: 65 64 20 62 79 20 74 68 65 20 6d 61 74 63 68 69  ed by the matchi
84c0: 6e 66 6f 28 29 20 66 75 6e 63 74 69 6f 6e 2e 20  nfo() function. 
84d0: 41 72 67 75 6d 65 6e 74 20 7a 41 72 67 20 63 6f  Argument zArg co
84e0: 6e 74 61 69 6e 73 20 74 68 65 20 0a 2a 2a 20 66  ntains the .** f
84f0: 6f 72 6d 61 74 20 73 74 72 69 6e 67 20 70 61 73  ormat string pas
8500: 73 65 64 20 61 73 20 74 68 65 20 73 65 63 6f 6e  sed as the secon
8510: 64 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 6d 61  d argument to ma
8520: 74 63 68 69 6e 66 6f 20 28 6f 72 20 74 68 65 0a  tchinfo (or the.
8530: 2a 2a 20 64 65 66 61 75 6c 74 20 76 61 6c 75 65  ** default value
8540: 20 22 70 63 78 22 20 69 66 20 6e 6f 20 73 65 63   "pcx" if no sec
8550: 6f 6e 64 20 61 72 67 75 6d 65 6e 74 20 77 61 73  ond argument was
8560: 20 73 70 65 63 69 66 69 65 64 29 2e 20 54 68 65   specified). The
8570: 20 66 6f 72 6d 61 74 0a 2a 2a 20 73 74 72 69 6e   format.** strin
8580: 67 20 68 61 73 20 61 6c 72 65 61 64 79 20 62 65  g has already be
8590: 65 6e 20 76 61 6c 69 64 61 74 65 64 20 61 6e 64  en validated and
85a0: 20 74 68 65 20 70 49 6e 66 6f 2d 3e 61 4d 61 74   the pInfo->aMat
85b0: 63 68 69 6e 66 6f 5b 5d 20 61 72 72 61 79 0a 2a  chinfo[] array.*
85c0: 2a 20 69 73 20 67 75 61 72 61 6e 74 65 65 64 20  * is guaranteed 
85d0: 74 6f 20 62 65 20 6c 61 72 67 65 20 65 6e 6f 75  to be large enou
85e0: 67 68 20 66 6f 72 20 74 68 65 20 6f 75 74 70 75  gh for the outpu
85f0: 74 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 62 47 6c 6f  t..**.** If bGlo
8600: 62 61 6c 20 69 73 20 74 72 75 65 2c 20 74 68 65  bal is true, the
8610: 6e 20 70 6f 70 75 6c 61 74 65 20 61 6c 6c 20 66  n populate all f
8620: 69 65 6c 64 73 20 6f 66 20 74 68 65 20 6d 61 74  ields of the mat
8630: 63 68 69 6e 66 6f 28 29 20 6f 75 74 70 75 74 2e  chinfo() output.
8640: 0a 2a 2a 20 49 66 20 69 74 20 69 73 20 66 61 6c  .** If it is fal
8650: 73 65 2c 20 74 68 65 6e 20 61 73 73 75 6d 65 20  se, then assume 
8660: 74 68 61 74 20 74 68 6f 73 65 20 66 69 65 6c 64  that those field
8670: 73 20 74 68 61 74 20 64 6f 20 6e 6f 74 20 63 68  s that do not ch
8680: 61 6e 67 65 20 62 65 74 77 65 65 6e 0a 2a 2a 20  ange between.** 
8690: 72 6f 77 73 20 28 69 2e 65 2e 20 46 54 53 33 5f  rows (i.e. FTS3_
86a0: 4d 41 54 43 48 49 4e 46 4f 5f 4e 50 48 52 41 53  MATCHINFO_NPHRAS
86b0: 45 2c 20 4e 43 4f 4c 2c 20 4e 44 4f 43 2c 20 41  E, NCOL, NDOC, A
86c0: 56 47 4c 45 4e 47 54 48 20 61 6e 64 20 70 61 72  VGLENGTH and par
86d0: 74 20 6f 66 20 48 49 54 53 29 0a 2a 2a 20 68 61  t of HITS).** ha
86e0: 76 65 20 61 6c 72 65 61 64 79 20 62 65 65 6e 20  ve already been 
86f0: 70 6f 70 75 6c 61 74 65 64 2e 0a 2a 2a 0a 2a 2a  populated..**.**
8700: 20 52 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f   Return SQLITE_O
8710: 4b 20 69 66 20 73 75 63 63 65 73 73 66 75 6c 2c  K if successful,
8720: 20 6f 72 20 61 6e 20 53 51 4c 69 74 65 20 65 72   or an SQLite er
8730: 72 6f 72 20 63 6f 64 65 20 69 66 20 61 6e 20 65  ror code if an e
8740: 72 72 6f 72 20 0a 2a 2a 20 6f 63 63 75 72 73 2e  rror .** occurs.
8750: 20 49 66 20 61 20 76 61 6c 75 65 20 6f 74 68 65   If a value othe
8760: 72 20 74 68 61 6e 20 53 51 4c 49 54 45 5f 4f 4b  r than SQLITE_OK
8770: 20 69 73 20 72 65 74 75 72 6e 65 64 2c 20 74 68   is returned, th
8780: 65 20 73 74 61 74 65 20 74 68 65 0a 2a 2a 20 70  e state the.** p
8790: 49 6e 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f  Info->aMatchinfo
87a0: 5b 5d 20 62 75 66 66 65 72 20 69 73 20 6c 65 66  [] buffer is lef
87b0: 74 20 69 6e 20 69 73 20 75 6e 64 65 66 69 6e 65  t in is undefine
87c0: 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  d..*/.static int
87d0: 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 56 61   fts3MatchinfoVa
87e0: 6c 75 65 73 28 0a 20 20 46 74 73 33 43 75 72 73  lues(.  Fts3Curs
87f0: 6f 72 20 2a 70 43 73 72 2c 20 20 20 20 20 20 20  or *pCsr,       
8800: 20 20 20 20 20 20 20 20 2f 2a 20 46 54 53 33 20          /* FTS3 
8810: 63 75 72 73 6f 72 20 6f 62 6a 65 63 74 20 2a 2f  cursor object */
8820: 0a 20 20 69 6e 74 20 62 47 6c 6f 62 61 6c 2c 20  .  int bGlobal, 
8830: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8840: 20 20 20 2f 2a 20 54 72 75 65 20 74 6f 20 67 72     /* True to gr
8850: 61 62 20 74 68 65 20 67 6c 6f 62 61 6c 20 73 74  ab the global st
8860: 61 74 73 20 2a 2f 0a 20 20 4d 61 74 63 68 49 6e  ats */.  MatchIn
8870: 66 6f 20 2a 70 49 6e 66 6f 2c 20 20 20 20 20 20  fo *pInfo,      
8880: 20 20 20 20 20 20 20 20 20 2f 2a 20 4d 61 74 63           /* Matc
8890: 68 69 6e 66 6f 20 63 6f 6e 74 65 78 74 20 6f 62  hinfo context ob
88a0: 6a 65 63 74 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  ject */.  const 
88b0: 63 68 61 72 20 2a 7a 41 72 67 20 20 20 20 20 20  char *zArg      
88c0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4d 61 74            /* Mat
88d0: 63 68 69 6e 66 6f 20 66 6f 72 6d 61 74 20 73 74  chinfo format st
88e0: 72 69 6e 67 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74  ring */.){.  int
88f0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
8900: 0a 20 20 69 6e 74 20 69 3b 0a 20 20 46 74 73 33  .  int i;.  Fts3
8910: 54 61 62 6c 65 20 2a 70 54 61 62 20 3d 20 28 46  Table *pTab = (F
8920: 74 73 33 54 61 62 6c 65 20 2a 29 70 43 73 72 2d  ts3Table *)pCsr-
8930: 3e 62 61 73 65 2e 70 56 74 61 62 3b 0a 20 20 73  >base.pVtab;.  s
8940: 71 6c 69 74 65 33 5f 73 74 6d 74 20 2a 70 53 65  qlite3_stmt *pSe
8950: 6c 65 63 74 20 3d 20 30 3b 0a 0a 20 20 66 6f 72  lect = 0;..  for
8960: 28 69 3d 30 3b 20 72 63 3d 3d 53 51 4c 49 54 45  (i=0; rc==SQLITE
8970: 5f 4f 4b 20 26 26 20 7a 41 72 67 5b 69 5d 3b 20  _OK && zArg[i]; 
8980: 69 2b 2b 29 7b 0a 0a 20 20 20 20 73 77 69 74 63  i++){..    switc
8990: 68 28 20 7a 41 72 67 5b 69 5d 20 29 7b 0a 20 20  h( zArg[i] ){.  
89a0: 20 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41      case FTS3_MA
89b0: 54 43 48 49 4e 46 4f 5f 4e 50 48 52 41 53 45 3a  TCHINFO_NPHRASE:
89c0: 0a 20 20 20 20 20 20 20 20 69 66 28 20 62 47 6c  .        if( bGl
89d0: 6f 62 61 6c 20 29 20 70 49 6e 66 6f 2d 3e 61 4d  obal ) pInfo->aM
89e0: 61 74 63 68 69 6e 66 6f 5b 30 5d 20 3d 20 70 49  atchinfo[0] = pI
89f0: 6e 66 6f 2d 3e 6e 50 68 72 61 73 65 3b 0a 20 20  nfo->nPhrase;.  
8a00: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20        break;..  
8a10: 20 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41      case FTS3_MA
8a20: 54 43 48 49 4e 46 4f 5f 4e 43 4f 4c 3a 0a 20 20  TCHINFO_NCOL:.  
8a30: 20 20 20 20 20 20 69 66 28 20 62 47 6c 6f 62 61        if( bGloba
8a40: 6c 20 29 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63  l ) pInfo->aMatc
8a50: 68 69 6e 66 6f 5b 30 5d 20 3d 20 70 49 6e 66 6f  hinfo[0] = pInfo
8a60: 2d 3e 6e 43 6f 6c 3b 0a 20 20 20 20 20 20 20 20  ->nCol;.        
8a70: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 0a  break;.        .
8a80: 20 20 20 20 20 20 63 61 73 65 20 46 54 53 33 5f        case FTS3_
8a90: 4d 41 54 43 48 49 4e 46 4f 5f 4e 44 4f 43 3a 0a  MATCHINFO_NDOC:.
8aa0: 20 20 20 20 20 20 20 20 69 66 28 20 62 47 6c 6f          if( bGlo
8ab0: 62 61 6c 20 29 7b 0a 20 20 20 20 20 20 20 20 20  bal ){.         
8ac0: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 6e   sqlite3_int64 n
8ad0: 44 6f 63 20 3d 20 30 3b 0a 20 20 20 20 20 20 20  Doc = 0;.       
8ae0: 20 20 20 72 63 20 3d 20 66 74 73 33 4d 61 74 63     rc = fts3Matc
8af0: 68 69 6e 66 6f 53 65 6c 65 63 74 44 6f 63 74 6f  hinfoSelectDocto
8b00: 74 61 6c 28 70 54 61 62 2c 20 26 70 53 65 6c 65  tal(pTab, &pSele
8b10: 63 74 2c 20 26 6e 44 6f 63 2c 20 30 29 3b 0a 20  ct, &nDoc, 0);. 
8b20: 20 20 20 20 20 20 20 20 20 70 49 6e 66 6f 2d 3e           pInfo->
8b30: 61 4d 61 74 63 68 69 6e 66 6f 5b 30 5d 20 3d 20  aMatchinfo[0] = 
8b40: 28 75 33 32 29 6e 44 6f 63 3b 0a 20 20 20 20 20  (u32)nDoc;.     
8b50: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 62 72 65     }.        bre
8b60: 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65 20  ak;..      case 
8b70: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 41  FTS3_MATCHINFO_A
8b80: 56 47 4c 45 4e 47 54 48 3a 20 0a 20 20 20 20 20  VGLENGTH: .     
8b90: 20 20 20 69 66 28 20 62 47 6c 6f 62 61 6c 20 29     if( bGlobal )
8ba0: 7b 0a 20 20 20 20 20 20 20 20 20 20 73 71 6c 69  {.          sqli
8bb0: 74 65 33 5f 69 6e 74 36 34 20 6e 44 6f 63 3b 20  te3_int64 nDoc; 
8bc0: 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66      /* Number of
8bd0: 20 72 6f 77 73 20 69 6e 20 74 61 62 6c 65 20 2a   rows in table *
8be0: 2f 0a 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73  /.          cons
8bf0: 74 20 63 68 61 72 20 2a 61 3b 20 20 20 20 20 20  t char *a;      
8c00: 20 20 20 20 2f 2a 20 41 67 67 72 65 67 61 74 65      /* Aggregate
8c10: 20 63 6f 6c 75 6d 6e 20 6c 65 6e 67 74 68 20 61   column length a
8c20: 72 72 61 79 20 2a 2f 0a 0a 20 20 20 20 20 20 20  rray */..       
8c30: 20 20 20 72 63 20 3d 20 66 74 73 33 4d 61 74 63     rc = fts3Matc
8c40: 68 69 6e 66 6f 53 65 6c 65 63 74 44 6f 63 74 6f  hinfoSelectDocto
8c50: 74 61 6c 28 70 54 61 62 2c 20 26 70 53 65 6c 65  tal(pTab, &pSele
8c60: 63 74 2c 20 26 6e 44 6f 63 2c 20 26 61 29 3b 0a  ct, &nDoc, &a);.
8c70: 20 20 20 20 20 20 20 20 20 20 69 66 28 20 72 63            if( rc
8c80: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20  ==SQLITE_OK ){. 
8c90: 20 20 20 20 20 20 20 20 20 20 20 69 6e 74 20 69             int i
8ca0: 43 6f 6c 3b 0a 20 20 20 20 20 20 20 20 20 20 20  Col;.           
8cb0: 20 66 6f 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f   for(iCol=0; iCo
8cc0: 6c 3c 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 3b 20 69  l<pInfo->nCol; i
8cd0: 43 6f 6c 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20  Col++){.        
8ce0: 20 20 20 20 20 20 75 33 32 20 69 56 61 6c 3b 0a        u32 iVal;.
8cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 71                sq
8d00: 6c 69 74 65 33 5f 69 6e 74 36 34 20 6e 54 6f 6b  lite3_int64 nTok
8d10: 65 6e 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20  en;.            
8d20: 20 20 61 20 2b 3d 20 73 71 6c 69 74 65 33 46 74    a += sqlite3Ft
8d30: 73 33 47 65 74 56 61 72 69 6e 74 28 61 2c 20 26  s3GetVarint(a, &
8d40: 6e 54 6f 6b 65 6e 29 3b 0a 20 20 20 20 20 20 20  nToken);.       
8d50: 20 20 20 20 20 20 20 69 56 61 6c 20 3d 20 28 75         iVal = (u
8d60: 33 32 29 28 28 28 75 33 32 29 28 6e 54 6f 6b 65  32)(((u32)(nToke
8d70: 6e 26 30 78 66 66 66 66 66 66 66 66 29 2b 6e 44  n&0xffffffff)+nD
8d80: 6f 63 2f 32 29 2f 6e 44 6f 63 29 3b 0a 20 20 20  oc/2)/nDoc);.   
8d90: 20 20 20 20 20 20 20 20 20 20 20 70 49 6e 66 6f             pInfo
8da0: 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 69 43 6f  ->aMatchinfo[iCo
8db0: 6c 5d 20 3d 20 69 56 61 6c 3b 0a 20 20 20 20 20  l] = iVal;.     
8dc0: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
8dd0: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a 20     }.        }. 
8de0: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20         break;.. 
8df0: 20 20 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d       case FTS3_M
8e00: 41 54 43 48 49 4e 46 4f 5f 4c 45 4e 47 54 48 3a  ATCHINFO_LENGTH:
8e10: 20 7b 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74   {.        sqlit
8e20: 65 33 5f 73 74 6d 74 20 2a 70 53 65 6c 65 63 74  e3_stmt *pSelect
8e30: 44 6f 63 73 69 7a 65 20 3d 20 30 3b 0a 20 20 20  Docsize = 0;.   
8e40: 20 20 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65       rc = sqlite
8e50: 33 46 74 73 33 53 65 6c 65 63 74 44 6f 63 73 69  3Fts3SelectDocsi
8e60: 7a 65 28 70 54 61 62 2c 20 70 43 73 72 2d 3e 69  ze(pTab, pCsr->i
8e70: 50 72 65 76 49 64 2c 20 26 70 53 65 6c 65 63 74  PrevId, &pSelect
8e80: 44 6f 63 73 69 7a 65 29 3b 0a 20 20 20 20 20 20  Docsize);.      
8e90: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
8ea0: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20  _OK ){.         
8eb0: 20 69 6e 74 20 69 43 6f 6c 3b 0a 20 20 20 20 20   int iCol;.     
8ec0: 20 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20       const char 
8ed0: 2a 61 20 3d 20 73 71 6c 69 74 65 33 5f 63 6f 6c  *a = sqlite3_col
8ee0: 75 6d 6e 5f 62 6c 6f 62 28 70 53 65 6c 65 63 74  umn_blob(pSelect
8ef0: 44 6f 63 73 69 7a 65 2c 20 30 29 3b 0a 20 20 20  Docsize, 0);.   
8f00: 20 20 20 20 20 20 20 66 6f 72 28 69 43 6f 6c 3d         for(iCol=
8f10: 30 3b 20 69 43 6f 6c 3c 70 49 6e 66 6f 2d 3e 6e  0; iCol<pInfo->n
8f20: 43 6f 6c 3b 20 69 43 6f 6c 2b 2b 29 7b 0a 20 20  Col; iCol++){.  
8f30: 20 20 20 20 20 20 20 20 20 20 73 71 6c 69 74 65            sqlite
8f40: 33 5f 69 6e 74 36 34 20 6e 54 6f 6b 65 6e 3b 0a  3_int64 nToken;.
8f50: 20 20 20 20 20 20 20 20 20 20 20 20 61 20 2b 3d              a +=
8f60: 20 73 71 6c 69 74 65 33 46 74 73 33 47 65 74 56   sqlite3Fts3GetV
8f70: 61 72 69 6e 74 28 61 2c 20 26 6e 54 6f 6b 65 6e  arint(a, &nToken
8f80: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20 70  );.            p
8f90: 49 6e 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f  Info->aMatchinfo
8fa0: 5b 69 43 6f 6c 5d 20 3d 20 28 75 33 32 29 6e 54  [iCol] = (u32)nT
8fb0: 6f 6b 65 6e 3b 0a 20 20 20 20 20 20 20 20 20 20  oken;.          
8fc0: 7d 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  }.        }.    
8fd0: 20 20 20 20 73 71 6c 69 74 65 33 5f 72 65 73 65      sqlite3_rese
8fe0: 74 28 70 53 65 6c 65 63 74 44 6f 63 73 69 7a 65  t(pSelectDocsize
8ff0: 29 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b  );.        break
9000: 3b 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20  ;.      }..     
9010: 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54 43 48   case FTS3_MATCH
9020: 49 4e 46 4f 5f 4c 43 53 3a 0a 20 20 20 20 20 20  INFO_LCS:.      
9030: 20 20 72 63 20 3d 20 66 74 73 33 45 78 70 72 4c    rc = fts3ExprL
9040: 6f 61 64 44 6f 63 6c 69 73 74 73 28 70 43 73 72  oadDoclists(pCsr
9050: 2c 20 30 2c 20 30 29 3b 0a 20 20 20 20 20 20 20  , 0, 0);.       
9060: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
9070: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  OK ){.          
9080: 72 63 20 3d 20 66 74 73 33 4d 61 74 63 68 69 6e  rc = fts3Matchin
9090: 66 6f 4c 63 73 28 70 43 73 72 2c 20 70 49 6e 66  foLcs(pCsr, pInf
90a0: 6f 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20  o);.        }.  
90b0: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20        break;..  
90c0: 20 20 20 20 64 65 66 61 75 6c 74 3a 20 7b 0a 20      default: {. 
90d0: 20 20 20 20 20 20 20 46 74 73 33 45 78 70 72 20         Fts3Expr 
90e0: 2a 70 45 78 70 72 3b 0a 20 20 20 20 20 20 20 20  *pExpr;.        
90f0: 61 73 73 65 72 74 28 20 7a 41 72 67 5b 69 5d 3d  assert( zArg[i]=
9100: 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f  =FTS3_MATCHINFO_
9110: 48 49 54 53 20 29 3b 0a 20 20 20 20 20 20 20 20  HITS );.        
9120: 70 45 78 70 72 20 3d 20 70 43 73 72 2d 3e 70 45  pExpr = pCsr->pE
9130: 78 70 72 3b 0a 20 20 20 20 20 20 20 20 72 63 20  xpr;.        rc 
9140: 3d 20 66 74 73 33 45 78 70 72 4c 6f 61 64 44 6f  = fts3ExprLoadDo
9150: 63 6c 69 73 74 73 28 70 43 73 72 2c 20 30 2c 20  clists(pCsr, 0, 
9160: 30 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20  0);.        if( 
9170: 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20  rc!=SQLITE_OK ) 
9180: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 69  break;.        i
9190: 66 28 20 62 47 6c 6f 62 61 6c 20 29 7b 0a 20 20  f( bGlobal ){.  
91a0: 20 20 20 20 20 20 20 20 69 66 28 20 70 43 73 72          if( pCsr
91b0: 2d 3e 70 44 65 66 65 72 72 65 64 20 29 7b 0a 20  ->pDeferred ){. 
91c0: 20 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20             rc = 
91d0: 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 53 65 6c  fts3MatchinfoSel
91e0: 65 63 74 44 6f 63 74 6f 74 61 6c 28 70 54 61 62  ectDoctotal(pTab
91f0: 2c 20 26 70 53 65 6c 65 63 74 2c 20 26 70 49 6e  , &pSelect, &pIn
9200: 66 6f 2d 3e 6e 44 6f 63 2c 20 30 29 3b 0a 20 20  fo->nDoc, 0);.  
9210: 20 20 20 20 20 20 20 20 20 20 69 66 28 20 72 63            if( rc
9220: 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62 72  !=SQLITE_OK ) br
9230: 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 20 20 7d  eak;.          }
9240: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
9250: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 28  fts3ExprIterate(
9260: 70 45 78 70 72 2c 20 66 74 73 33 45 78 70 72 47  pExpr, fts3ExprG
9270: 6c 6f 62 61 6c 48 69 74 73 43 62 2c 28 76 6f 69  lobalHitsCb,(voi
9280: 64 2a 29 70 49 6e 66 6f 29 3b 0a 20 20 20 20 20  d*)pInfo);.     
9290: 20 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c       if( rc!=SQL
92a0: 49 54 45 5f 4f 4b 20 29 20 62 72 65 61 6b 3b 0a  ITE_OK ) break;.
92b0: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
92c0: 20 20 28 76 6f 69 64 29 66 74 73 33 45 78 70 72    (void)fts3Expr
92d0: 49 74 65 72 61 74 65 28 70 45 78 70 72 2c 20 66  Iterate(pExpr, f
92e0: 74 73 33 45 78 70 72 4c 6f 63 61 6c 48 69 74 73  ts3ExprLocalHits
92f0: 43 62 2c 28 76 6f 69 64 2a 29 70 49 6e 66 6f 29  Cb,(void*)pInfo)
9300: 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b  ;.        break;
9310: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a  .      }.    }..
9320: 20 20 20 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63      pInfo->aMatc
9330: 68 69 6e 66 6f 20 2b 3d 20 66 74 73 33 4d 61 74  hinfo += fts3Mat
9340: 63 68 69 6e 66 6f 53 69 7a 65 28 70 49 6e 66 6f  chinfoSize(pInfo
9350: 2c 20 7a 41 72 67 5b 69 5d 29 3b 0a 20 20 7d 0a  , zArg[i]);.  }.
9360: 0a 20 20 73 71 6c 69 74 65 33 5f 72 65 73 65 74  .  sqlite3_reset
9370: 28 70 53 65 6c 65 63 74 29 3b 0a 20 20 72 65 74  (pSelect);.  ret
9380: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a  urn rc;.}.../*.*
9390: 2a 20 50 6f 70 75 6c 61 74 65 20 70 43 73 72 2d  * Populate pCsr-
93a0: 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 5d 20 77 69  >aMatchinfo[] wi
93b0: 74 68 20 64 61 74 61 20 66 6f 72 20 74 68 65 20  th data for the 
93c0: 63 75 72 72 65 6e 74 20 72 6f 77 2e 20 54 68 65  current row. The
93d0: 20 0a 2a 2a 20 27 6d 61 74 63 68 69 6e 66 6f 27   .** 'matchinfo'
93e0: 20 64 61 74 61 20 69 73 20 61 6e 20 61 72 72 61   data is an arra
93f0: 79 20 6f 66 20 33 32 2d 62 69 74 20 75 6e 73 69  y of 32-bit unsi
9400: 67 6e 65 64 20 69 6e 74 65 67 65 72 73 20 28 43  gned integers (C
9410: 20 74 79 70 65 20 75 33 32 29 2e 0a 2a 2f 0a 73   type u32)..*/.s
9420: 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 47 65  tatic int fts3Ge
9430: 74 4d 61 74 63 68 69 6e 66 6f 28 0a 20 20 46 74  tMatchinfo(.  Ft
9440: 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72 2c 20  s3Cursor *pCsr, 
9450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
9460: 20 46 54 53 33 20 43 75 72 73 6f 72 20 6f 62 6a   FTS3 Cursor obj
9470: 65 63 74 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  ect */.  const c
9480: 68 61 72 20 2a 7a 41 72 67 20 20 20 20 20 20 20  har *zArg       
9490: 20 20 20 20 20 20 20 20 20 2f 2a 20 53 65 63 6f           /* Seco
94a0: 6e 64 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 6d  nd argument to m
94b0: 61 74 63 68 69 6e 66 6f 28 29 20 66 75 6e 63 74  atchinfo() funct
94c0: 69 6f 6e 20 2a 2f 0a 29 7b 0a 20 20 4d 61 74 63  ion */.){.  Matc
94d0: 68 49 6e 66 6f 20 73 49 6e 66 6f 3b 0a 20 20 46  hInfo sInfo;.  F
94e0: 74 73 33 54 61 62 6c 65 20 2a 70 54 61 62 20 3d  ts3Table *pTab =
94f0: 20 28 46 74 73 33 54 61 62 6c 65 20 2a 29 70 43   (Fts3Table *)pC
9500: 73 72 2d 3e 62 61 73 65 2e 70 56 74 61 62 3b 0a  sr->base.pVtab;.
9510: 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54    int rc = SQLIT
9520: 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20 62 47 6c 6f  E_OK;.  int bGlo
9530: 62 61 6c 20 3d 20 30 3b 20 20 20 20 20 20 20 20  bal = 0;        
9540: 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6c 6c 65          /* Colle
9550: 63 74 20 27 67 6c 6f 62 61 6c 27 20 73 74 61 74  ct 'global' stat
9560: 73 20 61 73 20 77 65 6c 6c 20 61 73 20 6c 6f 63  s as well as loc
9570: 61 6c 20 2a 2f 0a 0a 20 20 6d 65 6d 73 65 74 28  al */..  memset(
9580: 26 73 49 6e 66 6f 2c 20 30 2c 20 73 69 7a 65 6f  &sInfo, 0, sizeo
9590: 66 28 4d 61 74 63 68 49 6e 66 6f 29 29 3b 0a 20  f(MatchInfo));. 
95a0: 20 73 49 6e 66 6f 2e 70 43 75 72 73 6f 72 20 3d   sInfo.pCursor =
95b0: 20 70 43 73 72 3b 0a 20 20 73 49 6e 66 6f 2e 6e   pCsr;.  sInfo.n
95c0: 43 6f 6c 20 3d 20 70 54 61 62 2d 3e 6e 43 6f 6c  Col = pTab->nCol
95d0: 75 6d 6e 3b 0a 0a 20 20 2f 2a 20 49 66 20 74 68  umn;..  /* If th
95e0: 65 72 65 20 69 73 20 63 61 63 68 65 64 20 6d 61  ere is cached ma
95f0: 74 63 68 69 6e 66 6f 28 29 20 64 61 74 61 2c 20  tchinfo() data, 
9600: 62 75 74 20 74 68 65 20 66 6f 72 6d 61 74 20 73  but the format s
9610: 74 72 69 6e 67 20 66 6f 72 20 74 68 65 20 0a 20  tring for the . 
9620: 20 2a 2a 20 63 61 63 68 65 20 64 6f 65 73 20 6e   ** cache does n
9630: 6f 74 20 6d 61 74 63 68 20 74 68 65 20 66 6f 72  ot match the for
9640: 6d 61 74 20 73 74 72 69 6e 67 20 66 6f 72 20 74  mat string for t
9650: 68 69 73 20 72 65 71 75 65 73 74 2c 20 64 69 73  his request, dis
9660: 63 61 72 64 20 0a 20 20 2a 2a 20 74 68 65 20 63  card .  ** the c
9670: 61 63 68 65 64 20 64 61 74 61 2e 20 2a 2f 0a 20  ached data. */. 
9680: 20 69 66 28 20 70 43 73 72 2d 3e 7a 4d 61 74 63   if( pCsr->zMatc
9690: 68 69 6e 66 6f 20 26 26 20 73 74 72 63 6d 70 28  hinfo && strcmp(
96a0: 70 43 73 72 2d 3e 7a 4d 61 74 63 68 69 6e 66 6f  pCsr->zMatchinfo
96b0: 2c 20 7a 41 72 67 29 20 29 7b 0a 20 20 20 20 61  , zArg) ){.    a
96c0: 73 73 65 72 74 28 20 70 43 73 72 2d 3e 61 4d 61  ssert( pCsr->aMa
96d0: 74 63 68 69 6e 66 6f 20 29 3b 0a 20 20 20 20 73  tchinfo );.    s
96e0: 71 6c 69 74 65 33 5f 66 72 65 65 28 70 43 73 72  qlite3_free(pCsr
96f0: 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 29 3b 0a 20  ->aMatchinfo);. 
9700: 20 20 20 70 43 73 72 2d 3e 7a 4d 61 74 63 68 69     pCsr->zMatchi
9710: 6e 66 6f 20 3d 20 30 3b 0a 20 20 20 20 70 43 73  nfo = 0;.    pCs
9720: 72 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 20 3d 20  r->aMatchinfo = 
9730: 30 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49 66 20  0;.  }..  /* If 
9740: 46 74 73 33 43 75 72 73 6f 72 2e 61 4d 61 74 63  Fts3Cursor.aMatc
9750: 68 69 6e 66 6f 5b 5d 20 69 73 20 4e 55 4c 4c 2c  hinfo[] is NULL,
9760: 20 74 68 65 6e 20 74 68 69 73 20 69 73 20 74 68   then this is th
9770: 65 20 66 69 72 73 74 20 74 69 6d 65 20 74 68 65  e first time the
9780: 0a 20 20 2a 2a 20 6d 61 74 63 68 69 6e 66 6f 20  .  ** matchinfo 
9790: 66 75 6e 63 74 69 6f 6e 20 68 61 73 20 62 65 65  function has bee
97a0: 6e 20 63 61 6c 6c 65 64 20 66 6f 72 20 74 68 69  n called for thi
97b0: 73 20 71 75 65 72 79 2e 20 49 6e 20 74 68 69 73  s query. In this
97c0: 20 63 61 73 65 20 0a 20 20 2a 2a 20 61 6c 6c 6f   case .  ** allo
97d0: 63 61 74 65 20 74 68 65 20 61 72 72 61 79 20 75  cate the array u
97e0: 73 65 64 20 74 6f 20 61 63 63 75 6d 75 6c 61 74  sed to accumulat
97f0: 65 20 74 68 65 20 6d 61 74 63 68 69 6e 66 6f 20  e the matchinfo 
9800: 64 61 74 61 20 61 6e 64 0a 20 20 2a 2a 20 69 6e  data and.  ** in
9810: 69 74 69 61 6c 69 7a 65 20 74 68 6f 73 65 20 65  itialize those e
9820: 6c 65 6d 65 6e 74 73 20 74 68 61 74 20 61 72 65  lements that are
9830: 20 63 6f 6e 73 74 61 6e 74 20 66 6f 72 20 65 76   constant for ev
9840: 65 72 79 20 72 6f 77 2e 0a 20 20 2a 2f 0a 20 20  ery row..  */.  
9850: 69 66 28 20 70 43 73 72 2d 3e 61 4d 61 74 63 68  if( pCsr->aMatch
9860: 69 6e 66 6f 3d 3d 30 20 29 7b 0a 20 20 20 20 69  info==0 ){.    i
9870: 6e 74 20 6e 4d 61 74 63 68 69 6e 66 6f 20 3d 20  nt nMatchinfo = 
9880: 30 3b 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20  0;           /* 
9890: 4e 75 6d 62 65 72 20 6f 66 20 75 33 32 20 65 6c  Number of u32 el
98a0: 65 6d 65 6e 74 73 20 69 6e 20 6d 61 74 63 68 2d  ements in match-
98b0: 69 6e 66 6f 20 2a 2f 0a 20 20 20 20 69 6e 74 20  info */.    int 
98c0: 6e 41 72 67 3b 20 20 20 20 20 20 20 20 20 20 20  nArg;           
98d0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 42 79 74            /* Byt
98e0: 65 73 20 69 6e 20 7a 41 72 67 20 2a 2f 0a 20 20  es in zArg */.  
98f0: 20 20 69 6e 74 20 69 3b 20 20 20 20 20 20 20 20    int i;        
9900: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9910: 2f 2a 20 55 73 65 64 20 74 6f 20 69 74 65 72 61  /* Used to itera
9920: 74 65 20 74 68 72 6f 75 67 68 20 7a 41 72 67 20  te through zArg 
9930: 2a 2f 0a 0a 20 20 20 20 2f 2a 20 44 65 74 65 72  */..    /* Deter
9940: 6d 69 6e 65 20 74 68 65 20 6e 75 6d 62 65 72 20  mine the number 
9950: 6f 66 20 70 68 72 61 73 65 73 20 69 6e 20 74 68  of phrases in th
9960: 65 20 71 75 65 72 79 20 2a 2f 0a 20 20 20 20 70  e query */.    p
9970: 43 73 72 2d 3e 6e 50 68 72 61 73 65 20 3d 20 66  Csr->nPhrase = f
9980: 74 73 33 45 78 70 72 50 68 72 61 73 65 43 6f 75  ts3ExprPhraseCou
9990: 6e 74 28 70 43 73 72 2d 3e 70 45 78 70 72 29 3b  nt(pCsr->pExpr);
99a0: 0a 20 20 20 20 73 49 6e 66 6f 2e 6e 50 68 72 61  .    sInfo.nPhra
99b0: 73 65 20 3d 20 70 43 73 72 2d 3e 6e 50 68 72 61  se = pCsr->nPhra
99c0: 73 65 3b 0a 0a 20 20 20 20 2f 2a 20 44 65 74 65  se;..    /* Dete
99d0: 72 6d 69 6e 65 20 74 68 65 20 6e 75 6d 62 65 72  rmine the number
99e0: 20 6f 66 20 69 6e 74 65 67 65 72 73 20 69 6e 20   of integers in 
99f0: 74 68 65 20 62 75 66 66 65 72 20 72 65 74 75 72  the buffer retur
9a00: 6e 65 64 20 62 79 20 74 68 69 73 20 63 61 6c 6c  ned by this call
9a10: 2e 20 2a 2f 0a 20 20 20 20 66 6f 72 28 69 3d 30  . */.    for(i=0
9a20: 3b 20 7a 41 72 67 5b 69 5d 3b 20 69 2b 2b 29 7b  ; zArg[i]; i++){
9a30: 0a 20 20 20 20 20 20 6e 4d 61 74 63 68 69 6e 66  .      nMatchinf
9a40: 6f 20 2b 3d 20 66 74 73 33 4d 61 74 63 68 69 6e  o += fts3Matchin
9a50: 66 6f 53 69 7a 65 28 26 73 49 6e 66 6f 2c 20 7a  foSize(&sInfo, z
9a60: 41 72 67 5b 69 5d 29 3b 0a 20 20 20 20 7d 0a 0a  Arg[i]);.    }..
9a70: 20 20 20 20 2f 2a 20 41 6c 6c 6f 63 61 74 65 20      /* Allocate 
9a80: 73 70 61 63 65 20 66 6f 72 20 46 74 73 33 43 75  space for Fts3Cu
9a90: 72 73 6f 72 2e 61 4d 61 74 63 68 69 6e 66 6f 5b  rsor.aMatchinfo[
9aa0: 5d 20 61 6e 64 20 46 74 73 33 43 75 72 73 6f 72  ] and Fts3Cursor
9ab0: 2e 7a 4d 61 74 63 68 69 6e 66 6f 2e 20 2a 2f 0a  .zMatchinfo. */.
9ac0: 20 20 20 20 6e 41 72 67 20 3d 20 28 69 6e 74 29      nArg = (int)
9ad0: 73 74 72 6c 65 6e 28 7a 41 72 67 29 3b 0a 20 20  strlen(zArg);.  
9ae0: 20 20 70 43 73 72 2d 3e 61 4d 61 74 63 68 69 6e    pCsr->aMatchin
9af0: 66 6f 20 3d 20 28 75 33 32 20 2a 29 73 71 6c 69  fo = (u32 *)sqli
9b00: 74 65 33 5f 6d 61 6c 6c 6f 63 28 73 69 7a 65 6f  te3_malloc(sizeo
9b10: 66 28 75 33 32 29 2a 6e 4d 61 74 63 68 69 6e 66  f(u32)*nMatchinf
9b20: 6f 20 2b 20 6e 41 72 67 20 2b 20 31 29 3b 0a 20  o + nArg + 1);. 
9b30: 20 20 20 69 66 28 20 21 70 43 73 72 2d 3e 61 4d     if( !pCsr->aM
9b40: 61 74 63 68 69 6e 66 6f 20 29 20 72 65 74 75 72  atchinfo ) retur
9b50: 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a  n SQLITE_NOMEM;.
9b60: 0a 20 20 20 20 70 43 73 72 2d 3e 7a 4d 61 74 63  .    pCsr->zMatc
9b70: 68 69 6e 66 6f 20 3d 20 28 63 68 61 72 20 2a 29  hinfo = (char *)
9b80: 26 70 43 73 72 2d 3e 61 4d 61 74 63 68 69 6e 66  &pCsr->aMatchinf
9b90: 6f 5b 6e 4d 61 74 63 68 69 6e 66 6f 5d 3b 0a 20  o[nMatchinfo];. 
9ba0: 20 20 20 70 43 73 72 2d 3e 6e 4d 61 74 63 68 69     pCsr->nMatchi
9bb0: 6e 66 6f 20 3d 20 6e 4d 61 74 63 68 69 6e 66 6f  nfo = nMatchinfo
9bc0: 3b 0a 20 20 20 20 6d 65 6d 63 70 79 28 70 43 73  ;.    memcpy(pCs
9bd0: 72 2d 3e 7a 4d 61 74 63 68 69 6e 66 6f 2c 20 7a  r->zMatchinfo, z
9be0: 41 72 67 2c 20 6e 41 72 67 2b 31 29 3b 0a 20 20  Arg, nArg+1);.  
9bf0: 20 20 6d 65 6d 73 65 74 28 70 43 73 72 2d 3e 61    memset(pCsr->a
9c00: 4d 61 74 63 68 69 6e 66 6f 2c 20 30 2c 20 73 69  Matchinfo, 0, si
9c10: 7a 65 6f 66 28 75 33 32 29 2a 6e 4d 61 74 63 68  zeof(u32)*nMatch
9c20: 69 6e 66 6f 29 3b 0a 20 20 20 20 70 43 73 72 2d  info);.    pCsr-
9c30: 3e 69 73 4d 61 74 63 68 69 6e 66 6f 4e 65 65 64  >isMatchinfoNeed
9c40: 65 64 20 3d 20 31 3b 0a 20 20 20 20 62 47 6c 6f  ed = 1;.    bGlo
9c50: 62 61 6c 20 3d 20 31 3b 0a 20 20 7d 0a 0a 20 20  bal = 1;.  }..  
9c60: 73 49 6e 66 6f 2e 61 4d 61 74 63 68 69 6e 66 6f  sInfo.aMatchinfo
9c70: 20 3d 20 70 43 73 72 2d 3e 61 4d 61 74 63 68 69   = pCsr->aMatchi
9c80: 6e 66 6f 3b 0a 20 20 73 49 6e 66 6f 2e 6e 50 68  nfo;.  sInfo.nPh
9c90: 72 61 73 65 20 3d 20 70 43 73 72 2d 3e 6e 50 68  rase = pCsr->nPh
9ca0: 72 61 73 65 3b 0a 20 20 69 66 28 20 70 43 73 72  rase;.  if( pCsr
9cb0: 2d 3e 69 73 4d 61 74 63 68 69 6e 66 6f 4e 65 65  ->isMatchinfoNee
9cc0: 64 65 64 20 29 7b 0a 20 20 20 20 72 63 20 3d 20  ded ){.    rc = 
9cd0: 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 56 61 6c  fts3MatchinfoVal
9ce0: 75 65 73 28 70 43 73 72 2c 20 62 47 6c 6f 62 61  ues(pCsr, bGloba
9cf0: 6c 2c 20 26 73 49 6e 66 6f 2c 20 7a 41 72 67 29  l, &sInfo, zArg)
9d00: 3b 0a 20 20 20 20 70 43 73 72 2d 3e 69 73 4d 61  ;.    pCsr->isMa
9d10: 74 63 68 69 6e 66 6f 4e 65 65 64 65 64 20 3d 20  tchinfoNeeded = 
9d20: 30 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e  0;.  }..  return
9d30: 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6d   rc;.}../*.** Im
9d40: 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20  plementation of 
9d50: 73 6e 69 70 70 65 74 28 29 20 66 75 6e 63 74 69  snippet() functi
9d60: 6f 6e 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69  on..*/.void sqli
9d70: 74 65 33 46 74 73 33 53 6e 69 70 70 65 74 28 0a  te3Fts3Snippet(.
9d80: 20 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78    sqlite3_contex
9d90: 74 20 2a 70 43 74 78 2c 20 20 20 20 20 20 20 20  t *pCtx,        
9da0: 20 20 2f 2a 20 53 51 4c 69 74 65 20 66 75 6e 63    /* SQLite func
9db0: 74 69 6f 6e 20 63 61 6c 6c 20 63 6f 6e 74 65 78  tion call contex
9dc0: 74 20 2a 2f 0a 20 20 46 74 73 33 43 75 72 73 6f  t */.  Fts3Curso
9dd0: 72 20 2a 70 43 73 72 2c 20 20 20 20 20 20 20 20  r *pCsr,        
9de0: 20 20 20 20 20 20 20 2f 2a 20 43 75 72 73 6f 72         /* Cursor
9df0: 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 63 6f 6e   object */.  con
9e00: 73 74 20 63 68 61 72 20 2a 7a 53 74 61 72 74 2c  st char *zStart,
9e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
9e20: 53 6e 69 70 70 65 74 20 73 74 61 72 74 20 74 65  Snippet start te
9e30: 78 74 20 2d 20 22 3c 62 3e 22 20 2a 2f 0a 20 20  xt - "<b>" */.  
9e40: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 45 6e 64  const char *zEnd
9e50: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
9e60: 2f 2a 20 53 6e 69 70 70 65 74 20 65 6e 64 20 74  /* Snippet end t
9e70: 65 78 74 20 2d 20 22 3c 2f 62 3e 22 20 2a 2f 0a  ext - "</b>" */.
9e80: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 45    const char *zE
9e90: 6c 6c 69 70 73 69 73 2c 20 20 20 20 20 20 20 20  llipsis,        
9ea0: 20 20 2f 2a 20 53 6e 69 70 70 65 74 20 65 6c 6c    /* Snippet ell
9eb0: 69 70 73 69 73 20 74 65 78 74 20 2d 20 22 3c 62  ipsis text - "<b
9ec0: 3e 2e 2e 2e 3c 2f 62 3e 22 20 2a 2f 0a 20 20 69  >...</b>" */.  i
9ed0: 6e 74 20 69 43 6f 6c 2c 20 20 20 20 20 20 20 20  nt iCol,        
9ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
9ef0: 2a 20 45 78 74 72 61 63 74 20 73 6e 69 70 70 65  * Extract snippe
9f00: 74 20 66 72 6f 6d 20 74 68 69 73 20 63 6f 6c 75  t from this colu
9f10: 6d 6e 20 2a 2f 0a 20 20 69 6e 74 20 6e 54 6f 6b  mn */.  int nTok
9f20: 65 6e 20 20 20 20 20 20 20 20 20 20 20 20 20 20  en              
9f30: 20 20 20 20 20 20 20 20 2f 2a 20 41 70 70 72 6f          /* Appro
9f40: 78 69 6d 61 74 65 20 6e 75 6d 62 65 72 20 6f 66  ximate number of
9f50: 20 74 6f 6b 65 6e 73 20 69 6e 20 73 6e 69 70 70   tokens in snipp
9f60: 65 74 20 2a 2f 0a 29 7b 0a 20 20 46 74 73 33 54  et */.){.  Fts3T
9f70: 61 62 6c 65 20 2a 70 54 61 62 20 3d 20 28 46 74  able *pTab = (Ft
9f80: 73 33 54 61 62 6c 65 20 2a 29 70 43 73 72 2d 3e  s3Table *)pCsr->
9f90: 62 61 73 65 2e 70 56 74 61 62 3b 0a 20 20 69 6e  base.pVtab;.  in
9fa0: 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b  t rc = SQLITE_OK
9fb0: 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 53 74 72  ;.  int i;.  Str
9fc0: 42 75 66 66 65 72 20 72 65 73 20 3d 20 7b 30 2c  Buffer res = {0,
9fd0: 20 30 2c 20 30 7d 3b 0a 0a 20 20 2f 2a 20 54 68   0, 0};..  /* Th
9fe0: 65 20 72 65 74 75 72 6e 65 64 20 74 65 78 74 20  e returned text 
9ff0: 69 6e 63 6c 75 64 65 73 20 75 70 20 74 6f 20 66  includes up to f
a000: 6f 75 72 20 66 72 61 67 6d 65 6e 74 73 20 6f 66  our fragments of
a010: 20 74 65 78 74 20 65 78 74 72 61 63 74 65 64 20   text extracted 
a020: 66 72 6f 6d 0a 20 20 2a 2a 20 74 68 65 20 64 61  from.  ** the da
a030: 74 61 20 69 6e 20 74 68 65 20 63 75 72 72 65 6e  ta in the curren
a040: 74 20 72 6f 77 2e 20 54 68 65 20 66 69 72 73 74  t row. The first
a050: 20 69 74 65 72 61 74 69 6f 6e 20 6f 66 20 74 68   iteration of th
a060: 65 20 66 6f 72 28 2e 2e 2e 29 20 6c 6f 6f 70 0a  e for(...) loop.
a070: 20 20 2a 2a 20 62 65 6c 6f 77 20 61 74 74 65 6d    ** below attem
a080: 70 74 73 20 74 6f 20 6c 6f 63 61 74 65 20 61 20  pts to locate a 
a090: 73 69 6e 67 6c 65 20 66 72 61 67 6d 65 6e 74 20  single fragment 
a0a0: 6f 66 20 74 65 78 74 20 6e 54 6f 6b 65 6e 20 74  of text nToken t
a0b0: 6f 6b 65 6e 73 20 69 6e 20 0a 20 20 2a 2a 20 73  okens in .  ** s
a0c0: 69 7a 65 20 74 68 61 74 20 63 6f 6e 74 61 69 6e  ize that contain
a0d0: 73 20 61 74 20 6c 65 61 73 74 20 6f 6e 65 20 69  s at least one i
a0e0: 6e 73 74 61 6e 63 65 20 6f 66 20 61 6c 6c 20 70  nstance of all p
a0f0: 68 72 61 73 65 73 20 69 6e 20 74 68 65 20 71 75  hrases in the qu
a100: 65 72 79 0a 20 20 2a 2a 20 65 78 70 72 65 73 73  ery.  ** express
a110: 69 6f 6e 20 74 68 61 74 20 61 70 70 65 61 72 20  ion that appear 
a120: 69 6e 20 74 68 65 20 63 75 72 72 65 6e 74 20 72  in the current r
a130: 6f 77 2e 20 49 66 20 73 75 63 68 20 61 20 66 72  ow. If such a fr
a140: 61 67 6d 65 6e 74 20 6f 66 20 74 65 78 74 0a 20  agment of text. 
a150: 20 2a 2a 20 63 61 6e 6e 6f 74 20 62 65 20 66 6f   ** cannot be fo
a160: 75 6e 64 2c 20 74 68 65 20 73 65 63 6f 6e 64 20  und, the second 
a170: 69 74 65 72 61 74 69 6f 6e 20 6f 66 20 74 68 65  iteration of the
a180: 20 6c 6f 6f 70 20 61 74 74 65 6d 70 74 73 20 74   loop attempts t
a190: 6f 20 6c 6f 63 61 74 65 0a 20 20 2a 2a 20 61 20  o locate.  ** a 
a1a0: 70 61 69 72 20 6f 66 20 66 72 61 67 6d 65 6e 74  pair of fragment
a1b0: 73 2c 20 61 6e 64 20 73 6f 20 6f 6e 2e 0a 20 20  s, and so on..  
a1c0: 2a 2f 0a 20 20 69 6e 74 20 6e 53 6e 69 70 70 65  */.  int nSnippe
a1d0: 74 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20  t = 0;          
a1e0: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
a1f0: 66 20 66 72 61 67 6d 65 6e 74 73 20 69 6e 20 74  f fragments in t
a200: 68 69 73 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20  his snippet */. 
a210: 20 53 6e 69 70 70 65 74 46 72 61 67 6d 65 6e 74   SnippetFragment
a220: 20 61 53 6e 69 70 70 65 74 5b 34 5d 3b 20 20 20   aSnippet[4];   
a230: 20 2f 2a 20 4d 61 78 69 6d 75 6d 20 6f 66 20 34   /* Maximum of 4
a240: 20 66 72 61 67 6d 65 6e 74 73 20 70 65 72 20 73   fragments per s
a250: 6e 69 70 70 65 74 20 2a 2f 0a 20 20 69 6e 74 20  nippet */.  int 
a260: 6e 46 54 6f 6b 65 6e 20 3d 20 2d 31 3b 20 20 20  nFToken = -1;   
a270: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
a280: 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20  umber of tokens 
a290: 69 6e 20 65 61 63 68 20 66 72 61 67 6d 65 6e 74  in each fragment
a2a0: 20 2a 2f 0a 0a 20 20 69 66 28 20 21 70 43 73 72   */..  if( !pCsr
a2b0: 2d 3e 70 45 78 70 72 20 29 7b 0a 20 20 20 20 73  ->pExpr ){.    s
a2c0: 71 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 74 65  qlite3_result_te
a2d0: 78 74 28 70 43 74 78 2c 20 22 22 2c 20 30 2c 20  xt(pCtx, "", 0, 
a2e0: 53 51 4c 49 54 45 5f 53 54 41 54 49 43 29 3b 0a  SQLITE_STATIC);.
a2f0: 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a      return;.  }.
a300: 0a 20 20 66 6f 72 28 6e 53 6e 69 70 70 65 74 3d  .  for(nSnippet=
a310: 31 3b 20 31 3b 20 6e 53 6e 69 70 70 65 74 2b 2b  1; 1; nSnippet++
a320: 29 7b 0a 0a 20 20 20 20 69 6e 74 20 69 53 6e 69  ){..    int iSni
a330: 70 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  p;              
a340: 20 20 20 20 20 20 2f 2a 20 4c 6f 6f 70 20 63 6f        /* Loop co
a350: 75 6e 74 65 72 20 30 2e 2e 6e 53 6e 69 70 70 65  unter 0..nSnippe
a360: 74 2d 31 20 2a 2f 0a 20 20 20 20 75 36 34 20 6d  t-1 */.    u64 m
a370: 43 6f 76 65 72 65 64 20 3d 20 30 3b 20 20 20 20  Covered = 0;    
a380: 20 20 20 20 20 20 20 20 20 2f 2a 20 42 69 74 6d           /* Bitm
a390: 61 73 6b 20 6f 66 20 70 68 72 61 73 65 73 20 63  ask of phrases c
a3a0: 6f 76 65 72 65 64 20 62 79 20 73 6e 69 70 70 65  overed by snippe
a3b0: 74 20 2a 2f 0a 20 20 20 20 75 36 34 20 6d 53 65  t */.    u64 mSe
a3c0: 65 6e 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  en = 0;         
a3d0: 20 20 20 20 20 20 20 2f 2a 20 42 69 74 6d 61 73         /* Bitmas
a3e0: 6b 20 6f 66 20 70 68 72 61 73 65 73 20 73 65 65  k of phrases see
a3f0: 6e 20 62 79 20 42 65 73 74 53 6e 69 70 70 65 74  n by BestSnippet
a400: 28 29 20 2a 2f 0a 0a 20 20 20 20 69 66 28 20 6e  () */..    if( n
a410: 54 6f 6b 65 6e 3e 3d 30 20 29 7b 0a 20 20 20 20  Token>=0 ){.    
a420: 20 20 6e 46 54 6f 6b 65 6e 20 3d 20 28 6e 54 6f    nFToken = (nTo
a430: 6b 65 6e 2b 6e 53 6e 69 70 70 65 74 2d 31 29 20  ken+nSnippet-1) 
a440: 2f 20 6e 53 6e 69 70 70 65 74 3b 0a 20 20 20 20  / nSnippet;.    
a450: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 6e 46 54  }else{.      nFT
a460: 6f 6b 65 6e 20 3d 20 2d 31 20 2a 20 6e 54 6f 6b  oken = -1 * nTok
a470: 65 6e 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20 66  en;.    }..    f
a480: 6f 72 28 69 53 6e 69 70 3d 30 3b 20 69 53 6e 69  or(iSnip=0; iSni
a490: 70 3c 6e 53 6e 69 70 70 65 74 3b 20 69 53 6e 69  p<nSnippet; iSni
a4a0: 70 2b 2b 29 7b 0a 20 20 20 20 20 20 69 6e 74 20  p++){.      int 
a4b0: 69 42 65 73 74 53 63 6f 72 65 20 3d 20 2d 31 3b  iBestScore = -1;
a4c0: 20 20 20 20 20 20 20 20 2f 2a 20 42 65 73 74 20          /* Best 
a4d0: 73 63 6f 72 65 20 6f 66 20 63 6f 6c 75 6d 6e 73  score of columns
a4e0: 20 63 68 65 63 6b 65 64 20 73 6f 20 66 61 72 20   checked so far 
a4f0: 2a 2f 0a 20 20 20 20 20 20 69 6e 74 20 69 52 65  */.      int iRe
a500: 61 64 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  ad;             
a510: 20 20 20 20 20 2f 2a 20 55 73 65 64 20 74 6f 20       /* Used to 
a520: 69 74 65 72 61 74 65 20 74 68 72 6f 75 67 68 20  iterate through 
a530: 63 6f 6c 75 6d 6e 73 20 2a 2f 0a 20 20 20 20 20  columns */.     
a540: 20 53 6e 69 70 70 65 74 46 72 61 67 6d 65 6e 74   SnippetFragment
a550: 20 2a 70 46 72 61 67 6d 65 6e 74 20 3d 20 26 61   *pFragment = &a
a560: 53 6e 69 70 70 65 74 5b 69 53 6e 69 70 5d 3b 0a  Snippet[iSnip];.
a570: 0a 20 20 20 20 20 20 6d 65 6d 73 65 74 28 70 46  .      memset(pF
a580: 72 61 67 6d 65 6e 74 2c 20 30 2c 20 73 69 7a 65  ragment, 0, size
a590: 6f 66 28 2a 70 46 72 61 67 6d 65 6e 74 29 29 3b  of(*pFragment));
a5a0: 0a 0a 20 20 20 20 20 20 2f 2a 20 4c 6f 6f 70 20  ..      /* Loop 
a5b0: 74 68 72 6f 75 67 68 20 61 6c 6c 20 63 6f 6c 75  through all colu
a5c0: 6d 6e 73 20 6f 66 20 74 68 65 20 74 61 62 6c 65  mns of the table
a5d0: 20 62 65 69 6e 67 20 63 6f 6e 73 69 64 65 72 65   being considere
a5e0: 64 20 66 6f 72 20 73 6e 69 70 70 65 74 73 2e 0a  d for snippets..
a5f0: 20 20 20 20 20 20 2a 2a 20 49 66 20 74 68 65 20        ** If the 
a600: 69 43 6f 6c 20 61 72 67 75 6d 65 6e 74 20 74 6f  iCol argument to
a610: 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 77   this function w
a620: 61 73 20 6e 65 67 61 74 69 76 65 2c 20 74 68 69  as negative, thi
a630: 73 20 6d 65 61 6e 73 20 61 6c 6c 0a 20 20 20 20  s means all.    
a640: 20 20 2a 2a 20 63 6f 6c 75 6d 6e 73 20 6f 66 20    ** columns of 
a650: 74 68 65 20 46 54 53 33 20 74 61 62 6c 65 2e 20  the FTS3 table. 
a660: 4f 74 68 65 72 77 69 73 65 2c 20 6f 6e 6c 79 20  Otherwise, only 
a670: 63 6f 6c 75 6d 6e 20 69 43 6f 6c 20 69 73 20 63  column iCol is c
a680: 6f 6e 73 69 64 65 72 65 64 2e 0a 20 20 20 20 20  onsidered..     
a690: 20 2a 2f 0a 20 20 20 20 20 20 66 6f 72 28 69 52   */.      for(iR
a6a0: 65 61 64 3d 30 3b 20 69 52 65 61 64 3c 70 54 61  ead=0; iRead<pTa
a6b0: 62 2d 3e 6e 43 6f 6c 75 6d 6e 3b 20 69 52 65 61  b->nColumn; iRea
a6c0: 64 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 53 6e  d++){.        Sn
a6d0: 69 70 70 65 74 46 72 61 67 6d 65 6e 74 20 73 46  ippetFragment sF
a6e0: 20 3d 20 7b 30 2c 20 30 2c 20 30 2c 20 30 7d 3b   = {0, 0, 0, 0};
a6f0: 0a 20 20 20 20 20 20 20 20 69 6e 74 20 69 53 3b  .        int iS;
a700: 0a 20 20 20 20 20 20 20 20 69 66 28 20 69 43 6f  .        if( iCo
a710: 6c 3e 3d 30 20 26 26 20 69 52 65 61 64 21 3d 69  l>=0 && iRead!=i
a720: 43 6f 6c 20 29 20 63 6f 6e 74 69 6e 75 65 3b 0a  Col ) continue;.
a730: 0a 20 20 20 20 20 20 20 20 2f 2a 20 46 69 6e 64  .        /* Find
a740: 20 74 68 65 20 62 65 73 74 20 73 6e 69 70 70 65   the best snippe
a750: 74 20 6f 66 20 6e 46 54 6f 6b 65 6e 20 74 6f 6b  t of nFToken tok
a760: 65 6e 73 20 69 6e 20 63 6f 6c 75 6d 6e 20 69 52  ens in column iR
a770: 65 61 64 2e 20 2a 2f 0a 20 20 20 20 20 20 20 20  ead. */.        
a780: 72 63 20 3d 20 66 74 73 33 42 65 73 74 53 6e 69  rc = fts3BestSni
a790: 70 70 65 74 28 6e 46 54 6f 6b 65 6e 2c 20 70 43  ppet(nFToken, pC
a7a0: 73 72 2c 20 69 52 65 61 64 2c 20 6d 43 6f 76 65  sr, iRead, mCove
a7b0: 72 65 64 2c 20 26 6d 53 65 65 6e 2c 20 26 73 46  red, &mSeen, &sF
a7c0: 2c 20 26 69 53 29 3b 0a 20 20 20 20 20 20 20 20  , &iS);.        
a7d0: 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f  if( rc!=SQLITE_O
a7e0: 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 67  K ){.          g
a7f0: 6f 74 6f 20 73 6e 69 70 70 65 74 5f 6f 75 74 3b  oto snippet_out;
a800: 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20  .        }.     
a810: 20 20 20 69 66 28 20 69 53 3e 69 42 65 73 74 53     if( iS>iBestS
a820: 63 6f 72 65 20 29 7b 0a 20 20 20 20 20 20 20 20  core ){.        
a830: 20 20 2a 70 46 72 61 67 6d 65 6e 74 20 3d 20 73    *pFragment = s
a840: 46 3b 0a 20 20 20 20 20 20 20 20 20 20 69 42 65  F;.          iBe
a850: 73 74 53 63 6f 72 65 20 3d 20 69 53 3b 0a 20 20  stScore = iS;.  
a860: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a        }.      }.
a870: 0a 20 20 20 20 20 20 6d 43 6f 76 65 72 65 64 20  .      mCovered 
a880: 7c 3d 20 70 46 72 61 67 6d 65 6e 74 2d 3e 63 6f  |= pFragment->co
a890: 76 65 72 65 64 3b 0a 20 20 20 20 7d 0a 0a 20 20  vered;.    }..  
a8a0: 20 20 2f 2a 20 49 66 20 61 6c 6c 20 71 75 65 72    /* If all quer
a8b0: 79 20 70 68 72 61 73 65 73 20 73 65 65 6e 20 62  y phrases seen b
a8c0: 79 20 66 74 73 33 42 65 73 74 53 6e 69 70 70 65  y fts3BestSnippe
a8d0: 74 28 29 20 61 72 65 20 70 72 65 73 65 6e 74 20  t() are present 
a8e0: 69 6e 20 61 74 20 6c 65 61 73 74 0a 20 20 20 20  in at least.    
a8f0: 2a 2a 20 6f 6e 65 20 6f 66 20 74 68 65 20 6e 53  ** one of the nS
a900: 6e 69 70 70 65 74 20 73 6e 69 70 70 65 74 20 66  nippet snippet f
a910: 72 61 67 6d 65 6e 74 73 2c 20 62 72 65 61 6b 20  ragments, break 
a920: 6f 75 74 20 6f 66 20 74 68 65 20 6c 6f 6f 70 2e  out of the loop.
a930: 0a 20 20 20 20 2a 2f 0a 20 20 20 20 61 73 73 65  .    */.    asse
a940: 72 74 28 20 28 6d 43 6f 76 65 72 65 64 26 6d 53  rt( (mCovered&mS
a950: 65 65 6e 29 3d 3d 6d 43 6f 76 65 72 65 64 20 29  een)==mCovered )
a960: 3b 0a 20 20 20 20 69 66 28 20 6d 53 65 65 6e 3d  ;.    if( mSeen=
a970: 3d 6d 43 6f 76 65 72 65 64 20 7c 7c 20 6e 53 6e  =mCovered || nSn
a980: 69 70 70 65 74 3d 3d 53 69 7a 65 6f 66 41 72 72  ippet==SizeofArr
a990: 61 79 28 61 53 6e 69 70 70 65 74 29 20 29 20 62  ay(aSnippet) ) b
a9a0: 72 65 61 6b 3b 0a 20 20 7d 0a 0a 20 20 61 73 73  reak;.  }..  ass
a9b0: 65 72 74 28 20 6e 46 54 6f 6b 65 6e 3e 30 20 29  ert( nFToken>0 )
a9c0: 3b 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c  ;..  for(i=0; i<
a9d0: 6e 53 6e 69 70 70 65 74 20 26 26 20 72 63 3d 3d  nSnippet && rc==
a9e0: 53 51 4c 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b  SQLITE_OK; i++){
a9f0: 0a 20 20 20 20 72 63 20 3d 20 66 74 73 33 53 6e  .    rc = fts3Sn
aa00: 69 70 70 65 74 54 65 78 74 28 70 43 73 72 2c 20  ippetText(pCsr, 
aa10: 26 61 53 6e 69 70 70 65 74 5b 69 5d 2c 20 0a 20  &aSnippet[i], . 
aa20: 20 20 20 20 20 20 20 69 2c 20 28 69 3d 3d 6e 53         i, (i==nS
aa30: 6e 69 70 70 65 74 2d 31 29 2c 20 6e 46 54 6f 6b  nippet-1), nFTok
aa40: 65 6e 2c 20 7a 53 74 61 72 74 2c 20 7a 45 6e 64  en, zStart, zEnd
aa50: 2c 20 7a 45 6c 6c 69 70 73 69 73 2c 20 26 72 65  , zEllipsis, &re
aa60: 73 0a 20 20 20 20 29 3b 0a 20 20 7d 0a 0a 20 73  s.    );.  }.. s
aa70: 6e 69 70 70 65 74 5f 6f 75 74 3a 0a 20 20 73 71  nippet_out:.  sq
aa80: 6c 69 74 65 33 46 74 73 33 53 65 67 6d 65 6e 74  lite3Fts3Segment
aa90: 73 43 6c 6f 73 65 28 70 54 61 62 29 3b 0a 20 20  sClose(pTab);.  
aaa0: 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f  if( rc!=SQLITE_O
aab0: 4b 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33  K ){.    sqlite3
aac0: 5f 72 65 73 75 6c 74 5f 65 72 72 6f 72 5f 63 6f  _result_error_co
aad0: 64 65 28 70 43 74 78 2c 20 72 63 29 3b 0a 20 20  de(pCtx, rc);.  
aae0: 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 72    sqlite3_free(r
aaf0: 65 73 2e 7a 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a  es.z);.  }else{.
ab00: 20 20 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75      sqlite3_resu
ab10: 6c 74 5f 74 65 78 74 28 70 43 74 78 2c 20 72 65  lt_text(pCtx, re
ab20: 73 2e 7a 2c 20 2d 31 2c 20 73 71 6c 69 74 65 33  s.z, -1, sqlite3
ab30: 5f 66 72 65 65 29 3b 0a 20 20 7d 0a 7d 0a 0a 0a  _free);.  }.}...
ab40: 74 79 70 65 64 65 66 20 73 74 72 75 63 74 20 54  typedef struct T
ab50: 65 72 6d 4f 66 66 73 65 74 20 54 65 72 6d 4f 66  ermOffset TermOf
ab60: 66 73 65 74 3b 0a 74 79 70 65 64 65 66 20 73 74  fset;.typedef st
ab70: 72 75 63 74 20 54 65 72 6d 4f 66 66 73 65 74 43  ruct TermOffsetC
ab80: 74 78 20 54 65 72 6d 4f 66 66 73 65 74 43 74 78  tx TermOffsetCtx
ab90: 3b 0a 0a 73 74 72 75 63 74 20 54 65 72 6d 4f 66  ;..struct TermOf
aba0: 66 73 65 74 20 7b 0a 20 20 63 68 61 72 20 2a 70  fset {.  char *p
abb0: 4c 69 73 74 3b 20 20 20 20 20 20 20 20 20 20 20  List;           
abc0: 20 20 20 20 20 20 20 20 20 2f 2a 20 50 6f 73 69           /* Posi
abd0: 74 69 6f 6e 2d 6c 69 73 74 20 2a 2f 0a 20 20 69  tion-list */.  i
abe0: 6e 74 20 69 50 6f 73 3b 20 20 20 20 20 20 20 20  nt iPos;        
abf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
ac00: 2a 20 50 6f 73 69 74 69 6f 6e 20 6a 75 73 74 20  * Position just 
ac10: 72 65 61 64 20 66 72 6f 6d 20 70 4c 69 73 74 20  read from pList 
ac20: 2a 2f 0a 20 20 69 6e 74 20 69 4f 66 66 3b 20 20  */.  int iOff;  
ac30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ac40: 20 20 20 20 20 2f 2a 20 4f 66 66 73 65 74 20 6f       /* Offset o
ac50: 66 20 74 68 69 73 20 74 65 72 6d 20 66 72 6f 6d  f this term from
ac60: 20 72 65 61 64 20 70 6f 73 69 74 69 6f 6e 73 20   read positions 
ac70: 2a 2f 0a 7d 3b 0a 0a 73 74 72 75 63 74 20 54 65  */.};..struct Te
ac80: 72 6d 4f 66 66 73 65 74 43 74 78 20 7b 0a 20 20  rmOffsetCtx {.  
ac90: 46 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72  Fts3Cursor *pCsr
aca0: 3b 0a 20 20 69 6e 74 20 69 43 6f 6c 3b 20 20 20  ;.  int iCol;   
acb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
acc0: 20 20 20 20 2f 2a 20 43 6f 6c 75 6d 6e 20 6f 66      /* Column of
acd0: 20 74 61 62 6c 65 20 74 6f 20 70 6f 70 75 6c 61   table to popula
ace0: 74 65 20 61 54 65 72 6d 20 66 6f 72 20 2a 2f 0a  te aTerm for */.
acf0: 20 20 69 6e 74 20 69 54 65 72 6d 3b 0a 20 20 73    int iTerm;.  s
ad00: 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 44 6f  qlite3_int64 iDo
ad10: 63 69 64 3b 0a 20 20 54 65 72 6d 4f 66 66 73 65  cid;.  TermOffse
ad20: 74 20 2a 61 54 65 72 6d 3b 0a 7d 3b 0a 0a 2f 2a  t *aTerm;.};../*
ad30: 0a 2a 2a 20 54 68 69 73 20 66 75 6e 63 74 69 6f  .** This functio
ad40: 6e 20 69 73 20 61 6e 20 66 74 73 33 45 78 70 72  n is an fts3Expr
ad50: 49 74 65 72 61 74 65 28 29 20 63 61 6c 6c 62 61  Iterate() callba
ad60: 63 6b 20 75 73 65 64 20 62 79 20 73 71 6c 69 74  ck used by sqlit
ad70: 65 33 46 74 73 33 4f 66 66 73 65 74 73 28 29 2e  e3Fts3Offsets().
ad80: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66  .*/.static int f
ad90: 74 73 33 45 78 70 72 54 65 72 6d 4f 66 66 73 65  ts3ExprTermOffse
ada0: 74 49 6e 69 74 28 46 74 73 33 45 78 70 72 20 2a  tInit(Fts3Expr *
adb0: 70 45 78 70 72 2c 20 69 6e 74 20 69 50 68 72 61  pExpr, int iPhra
adc0: 73 65 2c 20 76 6f 69 64 20 2a 63 74 78 29 7b 0a  se, void *ctx){.
add0: 20 20 54 65 72 6d 4f 66 66 73 65 74 43 74 78 20    TermOffsetCtx 
ade0: 2a 70 20 3d 20 28 54 65 72 6d 4f 66 66 73 65 74  *p = (TermOffset
adf0: 43 74 78 20 2a 29 63 74 78 3b 0a 20 20 69 6e 74  Ctx *)ctx;.  int
ae00: 20 6e 54 65 72 6d 3b 20 20 20 20 20 20 20 20 20   nTerm;         
ae10: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
ae20: 4e 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73  Number of tokens
ae30: 20 69 6e 20 70 68 72 61 73 65 20 2a 2f 0a 20 20   in phrase */.  
ae40: 69 6e 74 20 69 54 65 72 6d 3b 20 20 20 20 20 20  int iTerm;      
ae50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ae60: 2f 2a 20 46 6f 72 20 6c 6f 6f 70 69 6e 67 20 74  /* For looping t
ae70: 68 72 6f 75 67 68 20 6e 54 65 72 6d 20 70 68 72  hrough nTerm phr
ae80: 61 73 65 20 74 65 72 6d 73 20 2a 2f 0a 20 20 63  ase terms */.  c
ae90: 68 61 72 20 2a 70 4c 69 73 74 3b 20 20 20 20 20  har *pList;     
aea0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
aeb0: 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20 70 6f 73  * Pointer to pos
aec0: 69 74 69 6f 6e 20 6c 69 73 74 20 66 6f 72 20 70  ition list for p
aed0: 68 72 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20 69  hrase */.  int i
aee0: 50 6f 73 20 3d 20 30 3b 20 20 20 20 20 20 20 20  Pos = 0;        
aef0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 69             /* Fi
af00: 72 73 74 20 70 6f 73 69 74 69 6f 6e 20 69 6e 20  rst position in 
af10: 70 6f 73 69 74 69 6f 6e 2d 6c 69 73 74 20 2a 2f  position-list */
af20: 0a 20 20 69 6e 74 20 72 63 3b 0a 0a 20 20 55 4e  .  int rc;..  UN
af30: 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 69  USED_PARAMETER(i
af40: 50 68 72 61 73 65 29 3b 0a 20 20 72 63 20 3d 20  Phrase);.  rc = 
af50: 73 71 6c 69 74 65 33 46 74 73 33 45 76 61 6c 50  sqlite3Fts3EvalP
af60: 68 72 61 73 65 50 6f 73 6c 69 73 74 28 70 2d 3e  hrasePoslist(p->
af70: 70 43 73 72 2c 20 70 45 78 70 72 2c 20 70 2d 3e  pCsr, pExpr, p->
af80: 69 43 6f 6c 2c 20 26 70 4c 69 73 74 29 3b 0a 20  iCol, &pList);. 
af90: 20 6e 54 65 72 6d 20 3d 20 70 45 78 70 72 2d 3e   nTerm = pExpr->
afa0: 70 50 68 72 61 73 65 2d 3e 6e 54 6f 6b 65 6e 3b  pPhrase->nToken;
afb0: 0a 20 20 69 66 28 20 70 4c 69 73 74 20 29 7b 0a  .  if( pList ){.
afc0: 20 20 20 20 66 74 73 33 47 65 74 44 65 6c 74 61      fts3GetDelta
afd0: 50 6f 73 69 74 69 6f 6e 28 26 70 4c 69 73 74 2c  Position(&pList,
afe0: 20 26 69 50 6f 73 29 3b 0a 20 20 20 20 61 73 73   &iPos);.    ass
aff0: 65 72 74 28 20 69 50 6f 73 3e 3d 30 20 29 3b 0a  ert( iPos>=0 );.
b000: 20 20 7d 0a 0a 20 20 66 6f 72 28 69 54 65 72 6d    }..  for(iTerm
b010: 3d 30 3b 20 69 54 65 72 6d 3c 6e 54 65 72 6d 3b  =0; iTerm<nTerm;
b020: 20 69 54 65 72 6d 2b 2b 29 7b 0a 20 20 20 20 54   iTerm++){.    T
b030: 65 72 6d 4f 66 66 73 65 74 20 2a 70 54 20 3d 20  ermOffset *pT = 
b040: 26 70 2d 3e 61 54 65 72 6d 5b 70 2d 3e 69 54 65  &p->aTerm[p->iTe
b050: 72 6d 2b 2b 5d 3b 0a 20 20 20 20 70 54 2d 3e 69  rm++];.    pT->i
b060: 4f 66 66 20 3d 20 6e 54 65 72 6d 2d 69 54 65 72  Off = nTerm-iTer
b070: 6d 2d 31 3b 0a 20 20 20 20 70 54 2d 3e 70 4c 69  m-1;.    pT->pLi
b080: 73 74 20 3d 20 70 4c 69 73 74 3b 0a 20 20 20 20  st = pList;.    
b090: 70 54 2d 3e 69 50 6f 73 20 3d 20 69 50 6f 73 3b  pT->iPos = iPos;
b0a0: 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 72  .  }..  return r
b0b0: 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6d 70 6c  c;.}../*.** Impl
b0c0: 65 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20 6f 66  ementation of of
b0d0: 66 73 65 74 73 28 29 20 66 75 6e 63 74 69 6f 6e  fsets() function
b0e0: 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74 65  ..*/.void sqlite
b0f0: 33 46 74 73 33 4f 66 66 73 65 74 73 28 0a 20 20  3Fts3Offsets(.  
b100: 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74 20  sqlite3_context 
b110: 2a 70 43 74 78 2c 20 20 20 20 20 20 20 20 20 20  *pCtx,          
b120: 2f 2a 20 53 51 4c 69 74 65 20 66 75 6e 63 74 69  /* SQLite functi
b130: 6f 6e 20 63 61 6c 6c 20 63 6f 6e 74 65 78 74 20  on call context 
b140: 2a 2f 0a 20 20 46 74 73 33 43 75 72 73 6f 72 20  */.  Fts3Cursor 
b150: 2a 70 43 73 72 20 20 20 20 20 20 20 20 20 20 20  *pCsr           
b160: 20 20 20 20 20 2f 2a 20 43 75 72 73 6f 72 20 6f       /* Cursor o
b170: 62 6a 65 63 74 20 2a 2f 0a 29 7b 0a 20 20 46 74  bject */.){.  Ft
b180: 73 33 54 61 62 6c 65 20 2a 70 54 61 62 20 3d 20  s3Table *pTab = 
b190: 28 46 74 73 33 54 61 62 6c 65 20 2a 29 70 43 73  (Fts3Table *)pCs
b1a0: 72 2d 3e 62 61 73 65 2e 70 56 74 61 62 3b 0a 20  r->base.pVtab;. 
b1b0: 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a   sqlite3_tokeniz
b1c0: 65 72 5f 6d 6f 64 75 6c 65 20 63 6f 6e 73 74 20  er_module const 
b1d0: 2a 70 4d 6f 64 20 3d 20 70 54 61 62 2d 3e 70 54  *pMod = pTab->pT
b1e0: 6f 6b 65 6e 69 7a 65 72 2d 3e 70 4d 6f 64 75 6c  okenizer->pModul
b1f0: 65 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  e;.  const char 
b200: 2a 5a 44 55 4d 4d 59 3b 20 20 20 20 20 20 20 20  *ZDUMMY;        
b210: 20 20 20 20 20 2f 2a 20 44 75 6d 6d 79 20 61 72       /* Dummy ar
b220: 67 75 6d 65 6e 74 20 75 73 65 64 20 77 69 74 68  gument used with
b230: 20 78 4e 65 78 74 28 29 20 2a 2f 0a 20 20 69 6e   xNext() */.  in
b240: 74 20 4e 44 55 4d 4d 59 3b 20 20 20 20 20 20 20  t NDUMMY;       
b250: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
b260: 20 44 75 6d 6d 79 20 61 72 67 75 6d 65 6e 74 20   Dummy argument 
b270: 75 73 65 64 20 77 69 74 68 20 78 4e 65 78 74 28  used with xNext(
b280: 29 20 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20 20  ) */.  int rc;  
b290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b2a0: 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e         /* Return
b2b0: 20 43 6f 64 65 20 2a 2f 0a 20 20 69 6e 74 20 6e   Code */.  int n
b2c0: 54 6f 6b 65 6e 3b 20 20 20 20 20 20 20 20 20 20  Token;          
b2d0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75             /* Nu
b2e0: 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20 69  mber of tokens i
b2f0: 6e 20 71 75 65 72 79 20 2a 2f 0a 20 20 69 6e 74  n query */.  int
b300: 20 69 43 6f 6c 3b 20 20 20 20 20 20 20 20 20 20   iCol;          
b310: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
b320: 43 6f 6c 75 6d 6e 20 63 75 72 72 65 6e 74 6c 79  Column currently
b330: 20 62 65 69 6e 67 20 70 72 6f 63 65 73 73 65 64   being processed
b340: 20 2a 2f 0a 20 20 53 74 72 42 75 66 66 65 72 20   */.  StrBuffer 
b350: 72 65 73 20 3d 20 7b 30 2c 20 30 2c 20 30 7d 3b  res = {0, 0, 0};
b360: 20 20 20 20 20 20 2f 2a 20 52 65 73 75 6c 74 20        /* Result 
b370: 73 74 72 69 6e 67 20 2a 2f 0a 20 20 54 65 72 6d  string */.  Term
b380: 4f 66 66 73 65 74 43 74 78 20 73 43 74 78 3b 20  OffsetCtx sCtx; 
b390: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43              /* C
b3a0: 6f 6e 74 65 78 74 20 66 6f 72 20 66 74 73 33 45  ontext for fts3E
b3b0: 78 70 72 54 65 72 6d 4f 66 66 73 65 74 49 6e 69  xprTermOffsetIni
b3c0: 74 28 29 20 2a 2f 0a 0a 20 20 69 66 28 20 21 70  t() */..  if( !p
b3d0: 43 73 72 2d 3e 70 45 78 70 72 20 29 7b 0a 20 20  Csr->pExpr ){.  
b3e0: 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74    sqlite3_result
b3f0: 5f 74 65 78 74 28 70 43 74 78 2c 20 22 22 2c 20  _text(pCtx, "", 
b400: 30 2c 20 53 51 4c 49 54 45 5f 53 54 41 54 49 43  0, SQLITE_STATIC
b410: 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a 20  );.    return;. 
b420: 20 7d 0a 0a 20 20 6d 65 6d 73 65 74 28 26 73 43   }..  memset(&sC
b430: 74 78 2c 20 30 2c 20 73 69 7a 65 6f 66 28 73 43  tx, 0, sizeof(sC
b440: 74 78 29 29 3b 0a 20 20 61 73 73 65 72 74 28 20  tx));.  assert( 
b450: 70 43 73 72 2d 3e 69 73 52 65 71 75 69 72 65 53  pCsr->isRequireS
b460: 65 65 6b 3d 3d 30 20 29 3b 0a 0a 20 20 2f 2a 20  eek==0 );..  /* 
b470: 43 6f 75 6e 74 20 74 68 65 20 6e 75 6d 62 65 72  Count the number
b480: 20 6f 66 20 74 65 72 6d 73 20 69 6e 20 74 68 65   of terms in the
b490: 20 71 75 65 72 79 20 2a 2f 0a 20 20 72 63 20 3d   query */.  rc =
b4a0: 20 66 74 73 33 45 78 70 72 4c 6f 61 64 44 6f 63   fts3ExprLoadDoc
b4b0: 6c 69 73 74 73 28 70 43 73 72 2c 20 30 2c 20 26  lists(pCsr, 0, &
b4c0: 6e 54 6f 6b 65 6e 29 3b 0a 20 20 69 66 28 20 72  nToken);.  if( r
b4d0: 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 67  c!=SQLITE_OK ) g
b4e0: 6f 74 6f 20 6f 66 66 73 65 74 73 5f 6f 75 74 3b  oto offsets_out;
b4f0: 0a 0a 20 20 2f 2a 20 41 6c 6c 6f 63 61 74 65 20  ..  /* Allocate 
b500: 74 68 65 20 61 72 72 61 79 20 6f 66 20 54 65 72  the array of Ter
b510: 6d 4f 66 66 73 65 74 20 69 74 65 72 61 74 6f 72  mOffset iterator
b520: 73 2e 20 2a 2f 0a 20 20 73 43 74 78 2e 61 54 65  s. */.  sCtx.aTe
b530: 72 6d 20 3d 20 28 54 65 72 6d 4f 66 66 73 65 74  rm = (TermOffset
b540: 20 2a 29 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f   *)sqlite3_mallo
b550: 63 28 73 69 7a 65 6f 66 28 54 65 72 6d 4f 66 66  c(sizeof(TermOff
b560: 73 65 74 29 2a 6e 54 6f 6b 65 6e 29 3b 0a 20 20  set)*nToken);.  
b570: 69 66 28 20 30 3d 3d 73 43 74 78 2e 61 54 65 72  if( 0==sCtx.aTer
b580: 6d 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 53 51  m ){.    rc = SQ
b590: 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20  LITE_NOMEM;.    
b5a0: 67 6f 74 6f 20 6f 66 66 73 65 74 73 5f 6f 75 74  goto offsets_out
b5b0: 3b 0a 20 20 7d 0a 20 20 73 43 74 78 2e 69 44 6f  ;.  }.  sCtx.iDo
b5c0: 63 69 64 20 3d 20 70 43 73 72 2d 3e 69 50 72 65  cid = pCsr->iPre
b5d0: 76 49 64 3b 0a 20 20 73 43 74 78 2e 70 43 73 72  vId;.  sCtx.pCsr
b5e0: 20 3d 20 70 43 73 72 3b 0a 0a 20 20 2f 2a 20 4c   = pCsr;..  /* L
b5f0: 6f 6f 70 20 74 68 72 6f 75 67 68 20 74 68 65 20  oop through the 
b600: 74 61 62 6c 65 20 63 6f 6c 75 6d 6e 73 2c 20 61  table columns, a
b610: 70 70 65 6e 64 69 6e 67 20 6f 66 66 73 65 74 20  ppending offset 
b620: 69 6e 66 6f 72 6d 61 74 69 6f 6e 20 74 6f 20 0a  information to .
b630: 20 20 2a 2a 20 73 74 72 69 6e 67 2d 62 75 66 66    ** string-buff
b640: 65 72 20 72 65 73 20 66 6f 72 20 65 61 63 68 20  er res for each 
b650: 63 6f 6c 75 6d 6e 2e 0a 20 20 2a 2f 0a 20 20 66  column..  */.  f
b660: 6f 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f 6c 3c  or(iCol=0; iCol<
b670: 70 54 61 62 2d 3e 6e 43 6f 6c 75 6d 6e 3b 20 69  pTab->nColumn; i
b680: 43 6f 6c 2b 2b 29 7b 0a 20 20 20 20 73 71 6c 69  Col++){.    sqli
b690: 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63 75  te3_tokenizer_cu
b6a0: 72 73 6f 72 20 2a 70 43 3b 20 2f 2a 20 54 6f 6b  rsor *pC; /* Tok
b6b0: 65 6e 69 7a 65 72 20 63 75 72 73 6f 72 20 2a 2f  enizer cursor */
b6c0: 0a 20 20 20 20 69 6e 74 20 69 53 74 61 72 74 3b  .    int iStart;
b6d0: 0a 20 20 20 20 69 6e 74 20 69 45 6e 64 3b 0a 20  .    int iEnd;. 
b6e0: 20 20 20 69 6e 74 20 69 43 75 72 72 65 6e 74 3b     int iCurrent;
b6f0: 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20  .    const char 
b700: 2a 7a 44 6f 63 3b 0a 20 20 20 20 69 6e 74 20 6e  *zDoc;.    int n
b710: 44 6f 63 3b 0a 0a 20 20 20 20 2f 2a 20 49 6e 69  Doc;..    /* Ini
b720: 74 69 61 6c 69 7a 65 20 74 68 65 20 63 6f 6e 74  tialize the cont
b730: 65 6e 74 73 20 6f 66 20 73 43 74 78 2e 61 54 65  ents of sCtx.aTe
b740: 72 6d 5b 5d 20 66 6f 72 20 63 6f 6c 75 6d 6e 20  rm[] for column 
b750: 69 43 6f 6c 2e 20 54 68 65 72 65 20 69 73 20 0a  iCol. There is .
b760: 20 20 20 20 2a 2a 20 6e 6f 20 77 61 79 20 74 68      ** no way th
b770: 61 74 20 74 68 69 73 20 6f 70 65 72 61 74 69 6f  at this operatio
b780: 6e 20 63 61 6e 20 66 61 69 6c 2c 20 73 6f 20 74  n can fail, so t
b790: 68 65 20 72 65 74 75 72 6e 20 63 6f 64 65 20 66  he return code f
b7a0: 72 6f 6d 0a 20 20 20 20 2a 2a 20 66 74 73 33 45  rom.    ** fts3E
b7b0: 78 70 72 49 74 65 72 61 74 65 28 29 20 63 61 6e  xprIterate() can
b7c0: 20 62 65 20 64 69 73 63 61 72 64 65 64 2e 0a 20   be discarded.. 
b7d0: 20 20 20 2a 2f 0a 20 20 20 20 73 43 74 78 2e 69     */.    sCtx.i
b7e0: 43 6f 6c 20 3d 20 69 43 6f 6c 3b 0a 20 20 20 20  Col = iCol;.    
b7f0: 73 43 74 78 2e 69 54 65 72 6d 20 3d 20 30 3b 0a  sCtx.iTerm = 0;.
b800: 20 20 20 20 28 76 6f 69 64 29 66 74 73 33 45 78      (void)fts3Ex
b810: 70 72 49 74 65 72 61 74 65 28 70 43 73 72 2d 3e  prIterate(pCsr->
b820: 70 45 78 70 72 2c 20 66 74 73 33 45 78 70 72 54  pExpr, fts3ExprT
b830: 65 72 6d 4f 66 66 73 65 74 49 6e 69 74 2c 20 28  ermOffsetInit, (
b840: 76 6f 69 64 20 2a 29 26 73 43 74 78 29 3b 0a 0a  void *)&sCtx);..
b850: 20 20 20 20 2f 2a 20 52 65 74 72 65 69 76 65 20      /* Retreive 
b860: 74 68 65 20 74 65 78 74 20 73 74 6f 72 65 64 20  the text stored 
b870: 69 6e 20 63 6f 6c 75 6d 6e 20 69 43 6f 6c 2e 20  in column iCol. 
b880: 49 66 20 61 6e 20 53 51 4c 20 4e 55 4c 4c 20 69  If an SQL NULL i
b890: 73 20 73 74 6f 72 65 64 20 0a 20 20 20 20 2a 2a  s stored .    **
b8a0: 20 69 6e 20 63 6f 6c 75 6d 6e 20 69 43 6f 6c 2c   in column iCol,
b8b0: 20 6a 75 6d 70 20 69 6d 6d 65 64 69 61 74 65 6c   jump immediatel
b8c0: 79 20 74 6f 20 74 68 65 20 6e 65 78 74 20 69 74  y to the next it
b8d0: 65 72 61 74 69 6f 6e 20 6f 66 20 74 68 65 20 6c  eration of the l
b8e0: 6f 6f 70 2e 0a 20 20 20 20 2a 2a 20 49 66 20 61  oop..    ** If a
b8f0: 6e 20 4f 4f 4d 20 6f 63 63 75 72 73 20 77 68 69  n OOM occurs whi
b900: 6c 65 20 72 65 74 72 69 65 76 69 6e 67 20 74 68  le retrieving th
b910: 65 20 64 61 74 61 20 28 74 68 69 73 20 63 61 6e  e data (this can
b920: 20 68 61 70 70 65 6e 20 69 66 20 53 51 4c 69 74   happen if SQLit
b930: 65 0a 20 20 20 20 2a 2a 20 6e 65 65 64 73 20 74  e.    ** needs t
b940: 6f 20 74 72 61 6e 73 66 6f 72 6d 20 74 68 65 20  o transform the 
b950: 64 61 74 61 20 66 72 6f 6d 20 75 74 66 2d 31 36  data from utf-16
b960: 20 74 6f 20 75 74 66 2d 38 29 2c 20 72 65 74 75   to utf-8), retu
b970: 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 20  rn SQLITE_NOMEM 
b980: 0a 20 20 20 20 2a 2a 20 74 6f 20 74 68 65 20 63  .    ** to the c
b990: 61 6c 6c 65 72 2e 20 0a 20 20 20 20 2a 2f 0a 20  aller. .    */. 
b9a0: 20 20 20 7a 44 6f 63 20 3d 20 28 63 6f 6e 73 74     zDoc = (const
b9b0: 20 63 68 61 72 20 2a 29 73 71 6c 69 74 65 33 5f   char *)sqlite3_
b9c0: 63 6f 6c 75 6d 6e 5f 74 65 78 74 28 70 43 73 72  column_text(pCsr
b9d0: 2d 3e 70 53 74 6d 74 2c 20 69 43 6f 6c 2b 31 29  ->pStmt, iCol+1)
b9e0: 3b 0a 20 20 20 20 6e 44 6f 63 20 3d 20 73 71 6c  ;.    nDoc = sql
b9f0: 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f 62 79 74 65  ite3_column_byte
ba00: 73 28 70 43 73 72 2d 3e 70 53 74 6d 74 2c 20 69  s(pCsr->pStmt, i
ba10: 43 6f 6c 2b 31 29 3b 0a 20 20 20 20 69 66 28 20  Col+1);.    if( 
ba20: 7a 44 6f 63 3d 3d 30 20 29 7b 0a 20 20 20 20 20  zDoc==0 ){.     
ba30: 20 69 66 28 20 73 71 6c 69 74 65 33 5f 63 6f 6c   if( sqlite3_col
ba40: 75 6d 6e 5f 74 79 70 65 28 70 43 73 72 2d 3e 70  umn_type(pCsr->p
ba50: 53 74 6d 74 2c 20 69 43 6f 6c 2b 31 29 3d 3d 53  Stmt, iCol+1)==S
ba60: 51 4c 49 54 45 5f 4e 55 4c 4c 20 29 7b 0a 20 20  QLITE_NULL ){.  
ba70: 20 20 20 20 20 20 63 6f 6e 74 69 6e 75 65 3b 0a        continue;.
ba80: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 72 63        }.      rc
ba90: 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b   = SQLITE_NOMEM;
baa0: 0a 20 20 20 20 20 20 67 6f 74 6f 20 6f 66 66 73  .      goto offs
bab0: 65 74 73 5f 6f 75 74 3b 0a 20 20 20 20 7d 0a 0a  ets_out;.    }..
bac0: 20 20 20 20 2f 2a 20 49 6e 69 74 69 61 6c 69 7a      /* Initializ
bad0: 65 20 61 20 74 6f 6b 65 6e 69 7a 65 72 20 69 74  e a tokenizer it
bae0: 65 72 61 74 6f 72 20 74 6f 20 69 74 65 72 61 74  erator to iterat
baf0: 65 20 74 68 72 6f 75 67 68 20 63 6f 6c 75 6d 6e  e through column
bb00: 20 69 43 6f 6c 2e 20 2a 2f 0a 20 20 20 20 72 63   iCol. */.    rc
bb10: 20 3d 20 73 71 6c 69 74 65 33 46 74 73 33 4f 70   = sqlite3Fts3Op
bb20: 65 6e 54 6f 6b 65 6e 69 7a 65 72 28 70 54 61 62  enTokenizer(pTab
bb30: 2d 3e 70 54 6f 6b 65 6e 69 7a 65 72 2c 20 70 43  ->pTokenizer, pC
bb40: 73 72 2d 3e 69 4c 61 6e 67 69 64 2c 0a 20 20 20  sr->iLangid,.   
bb50: 20 20 20 20 20 7a 44 6f 63 2c 20 6e 44 6f 63 2c       zDoc, nDoc,
bb60: 20 26 70 43 0a 20 20 20 20 29 3b 0a 20 20 20 20   &pC.    );.    
bb70: 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f  if( rc!=SQLITE_O
bb80: 4b 20 29 20 67 6f 74 6f 20 6f 66 66 73 65 74 73  K ) goto offsets
bb90: 5f 6f 75 74 3b 0a 0a 20 20 20 20 72 63 20 3d 20  _out;..    rc = 
bba0: 70 4d 6f 64 2d 3e 78 4e 65 78 74 28 70 43 2c 20  pMod->xNext(pC, 
bbb0: 26 5a 44 55 4d 4d 59 2c 20 26 4e 44 55 4d 4d 59  &ZDUMMY, &NDUMMY
bbc0: 2c 20 26 69 53 74 61 72 74 2c 20 26 69 45 6e 64  , &iStart, &iEnd
bbd0: 2c 20 26 69 43 75 72 72 65 6e 74 29 3b 0a 20 20  , &iCurrent);.  
bbe0: 20 20 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c    while( rc==SQL
bbf0: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  ITE_OK ){.      
bc00: 69 6e 74 20 69 3b 20 20 20 20 20 20 20 20 20 20  int i;          
bc10: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 55              /* U
bc20: 73 65 64 20 74 6f 20 6c 6f 6f 70 20 74 68 72 6f  sed to loop thro
bc30: 75 67 68 20 74 65 72 6d 73 20 2a 2f 0a 20 20 20  ugh terms */.   
bc40: 20 20 20 69 6e 74 20 69 4d 69 6e 50 6f 73 20 3d     int iMinPos =
bc50: 20 30 78 37 46 46 46 46 46 46 46 3b 20 20 20 2f   0x7FFFFFFF;   /
bc60: 2a 20 50 6f 73 69 74 69 6f 6e 20 6f 66 20 6e 65  * Position of ne
bc70: 78 74 20 74 6f 6b 65 6e 20 2a 2f 0a 20 20 20 20  xt token */.    
bc80: 20 20 54 65 72 6d 4f 66 66 73 65 74 20 2a 70 54    TermOffset *pT
bc90: 65 72 6d 20 3d 20 30 3b 20 20 20 20 20 20 2f 2a  erm = 0;      /*
bca0: 20 54 65 72 6d 4f 66 66 73 65 74 20 61 73 73 6f   TermOffset asso
bcb0: 63 69 61 74 65 64 20 77 69 74 68 20 6e 65 78 74  ciated with next
bcc0: 20 74 6f 6b 65 6e 20 2a 2f 0a 0a 20 20 20 20 20   token */..     
bcd0: 20 66 6f 72 28 69 3d 30 3b 20 69 3c 6e 54 6f 6b   for(i=0; i<nTok
bce0: 65 6e 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20  en; i++){.      
bcf0: 20 20 54 65 72 6d 4f 66 66 73 65 74 20 2a 70 54    TermOffset *pT
bd00: 20 3d 20 26 73 43 74 78 2e 61 54 65 72 6d 5b 69   = &sCtx.aTerm[i
bd10: 5d 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 70  ];.        if( p
bd20: 54 2d 3e 70 4c 69 73 74 20 26 26 20 28 70 54 2d  T->pList && (pT-
bd30: 3e 69 50 6f 73 2d 70 54 2d 3e 69 4f 66 66 29 3c  >iPos-pT->iOff)<
bd40: 69 4d 69 6e 50 6f 73 20 29 7b 0a 20 20 20 20 20  iMinPos ){.     
bd50: 20 20 20 20 20 69 4d 69 6e 50 6f 73 20 3d 20 70       iMinPos = p
bd60: 54 2d 3e 69 50 6f 73 2d 70 54 2d 3e 69 4f 66 66  T->iPos-pT->iOff
bd70: 3b 0a 20 20 20 20 20 20 20 20 20 20 70 54 65 72  ;.          pTer
bd80: 6d 20 3d 20 70 54 3b 0a 20 20 20 20 20 20 20 20  m = pT;.        
bd90: 7d 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20  }.      }..     
bda0: 20 69 66 28 20 21 70 54 65 72 6d 20 29 7b 0a 20   if( !pTerm ){. 
bdb0: 20 20 20 20 20 20 20 2f 2a 20 41 6c 6c 20 6f 66         /* All of
bdc0: 66 73 65 74 73 20 66 6f 72 20 74 68 69 73 20 63  fsets for this c
bdd0: 6f 6c 75 6d 6e 20 68 61 76 65 20 62 65 65 6e 20  olumn have been 
bde0: 67 61 74 68 65 72 65 64 2e 20 2a 2f 0a 20 20 20  gathered. */.   
bdf0: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
be00: 5f 44 4f 4e 45 3b 0a 20 20 20 20 20 20 7d 65 6c  _DONE;.      }el
be10: 73 65 7b 0a 20 20 20 20 20 20 20 20 61 73 73 65  se{.        asse
be20: 72 74 28 20 69 43 75 72 72 65 6e 74 3c 3d 69 4d  rt( iCurrent<=iM
be30: 69 6e 50 6f 73 20 29 3b 0a 20 20 20 20 20 20 20  inPos );.       
be40: 20 69 66 28 20 30 3d 3d 28 30 78 46 45 26 2a 70   if( 0==(0xFE&*p
be50: 54 65 72 6d 2d 3e 70 4c 69 73 74 29 20 29 7b 0a  Term->pList) ){.
be60: 20 20 20 20 20 20 20 20 20 20 70 54 65 72 6d 2d            pTerm-
be70: 3e 70 4c 69 73 74 20 3d 20 30 3b 0a 20 20 20 20  >pList = 0;.    
be80: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
be90: 20 20 20 20 20 66 74 73 33 47 65 74 44 65 6c 74       fts3GetDelt
bea0: 61 50 6f 73 69 74 69 6f 6e 28 26 70 54 65 72 6d  aPosition(&pTerm
beb0: 2d 3e 70 4c 69 73 74 2c 20 26 70 54 65 72 6d 2d  ->pList, &pTerm-
bec0: 3e 69 50 6f 73 29 3b 0a 20 20 20 20 20 20 20 20  >iPos);.        
bed0: 7d 0a 20 20 20 20 20 20 20 20 77 68 69 6c 65 28  }.        while(
bee0: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
bef0: 26 20 69 43 75 72 72 65 6e 74 3c 69 4d 69 6e 50  & iCurrent<iMinP
bf00: 6f 73 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  os ){.          
bf10: 72 63 20 3d 20 70 4d 6f 64 2d 3e 78 4e 65 78 74  rc = pMod->xNext
bf20: 28 70 43 2c 20 26 5a 44 55 4d 4d 59 2c 20 26 4e  (pC, &ZDUMMY, &N
bf30: 44 55 4d 4d 59 2c 20 26 69 53 74 61 72 74 2c 20  DUMMY, &iStart, 
bf40: 26 69 45 6e 64 2c 20 26 69 43 75 72 72 65 6e 74  &iEnd, &iCurrent
bf50: 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20  );.        }.   
bf60: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c       if( rc==SQL
bf70: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  ITE_OK ){.      
bf80: 20 20 20 20 63 68 61 72 20 61 42 75 66 66 65 72      char aBuffer
bf90: 5b 36 34 5d 3b 0a 20 20 20 20 20 20 20 20 20 20  [64];.          
bfa0: 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74 66  sqlite3_snprintf
bfb0: 28 73 69 7a 65 6f 66 28 61 42 75 66 66 65 72 29  (sizeof(aBuffer)
bfc0: 2c 20 61 42 75 66 66 65 72 2c 20 0a 20 20 20 20  , aBuffer, .    
bfd0: 20 20 20 20 20 20 20 20 20 20 22 25 64 20 25 64            "%d %d
bfe0: 20 25 64 20 25 64 20 22 2c 20 69 43 6f 6c 2c 20   %d %d ", iCol, 
bff0: 70 54 65 72 6d 2d 73 43 74 78 2e 61 54 65 72 6d  pTerm-sCtx.aTerm
c000: 2c 20 69 53 74 61 72 74 2c 20 69 45 6e 64 2d 69  , iStart, iEnd-i
c010: 53 74 61 72 74 0a 20 20 20 20 20 20 20 20 20 20  Start.          
c020: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20  );.          rc 
c030: 3d 20 66 74 73 33 53 74 72 69 6e 67 41 70 70 65  = fts3StringAppe
c040: 6e 64 28 26 72 65 73 2c 20 61 42 75 66 66 65 72  nd(&res, aBuffer
c050: 2c 20 2d 31 29 3b 0a 20 20 20 20 20 20 20 20 7d  , -1);.        }
c060: 65 6c 73 65 20 69 66 28 20 72 63 3d 3d 53 51 4c  else if( rc==SQL
c070: 49 54 45 5f 44 4f 4e 45 20 26 26 20 70 54 61 62  ITE_DONE && pTab
c080: 2d 3e 7a 43 6f 6e 74 65 6e 74 54 62 6c 3d 3d 30  ->zContentTbl==0
c090: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63   ){.          rc
c0a0: 20 3d 20 46 54 53 5f 43 4f 52 52 55 50 54 5f 56   = FTS_CORRUPT_V
c0b0: 54 41 42 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  TAB;.        }. 
c0c0: 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20       }.    }.   
c0d0: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
c0e0: 44 4f 4e 45 20 29 7b 0a 20 20 20 20 20 20 72 63  DONE ){.      rc
c0f0: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20   = SQLITE_OK;.  
c100: 20 20 7d 0a 0a 20 20 20 20 70 4d 6f 64 2d 3e 78    }..    pMod->x
c110: 43 6c 6f 73 65 28 70 43 29 3b 0a 20 20 20 20 69  Close(pC);.    i
c120: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
c130: 20 29 20 67 6f 74 6f 20 6f 66 66 73 65 74 73 5f   ) goto offsets_
c140: 6f 75 74 3b 0a 20 20 7d 0a 0a 20 6f 66 66 73 65  out;.  }.. offse
c150: 74 73 5f 6f 75 74 3a 0a 20 20 73 71 6c 69 74 65  ts_out:.  sqlite
c160: 33 5f 66 72 65 65 28 73 43 74 78 2e 61 54 65 72  3_free(sCtx.aTer
c170: 6d 29 3b 0a 20 20 61 73 73 65 72 74 28 20 72 63  m);.  assert( rc
c180: 21 3d 53 51 4c 49 54 45 5f 44 4f 4e 45 20 29 3b  !=SQLITE_DONE );
c190: 0a 20 20 73 71 6c 69 74 65 33 46 74 73 33 53 65  .  sqlite3Fts3Se
c1a0: 67 6d 65 6e 74 73 43 6c 6f 73 65 28 70 54 61 62  gmentsClose(pTab
c1b0: 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 53 51 4c  );.  if( rc!=SQL
c1c0: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 73 71  ITE_OK ){.    sq
c1d0: 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 65 72 72  lite3_result_err
c1e0: 6f 72 5f 63 6f 64 65 28 70 43 74 78 2c 20 20 72  or_code(pCtx,  r
c1f0: 63 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f  c);.    sqlite3_
c200: 66 72 65 65 28 72 65 73 2e 7a 29 3b 0a 20 20 7d  free(res.z);.  }
c210: 65 6c 73 65 7b 0a 20 20 20 20 73 71 6c 69 74 65  else{.    sqlite
c220: 33 5f 72 65 73 75 6c 74 5f 74 65 78 74 28 70 43  3_result_text(pC
c230: 74 78 2c 20 72 65 73 2e 7a 2c 20 72 65 73 2e 6e  tx, res.z, res.n
c240: 2d 31 2c 20 73 71 6c 69 74 65 33 5f 66 72 65 65  -1, sqlite3_free
c250: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 3b  );.  }.  return;
c260: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6d 70 6c 65 6d  .}../*.** Implem
c270: 65 6e 74 61 74 69 6f 6e 20 6f 66 20 6d 61 74 63  entation of matc
c280: 68 69 6e 66 6f 28 29 20 66 75 6e 63 74 69 6f 6e  hinfo() function
c290: 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74 65  ..*/.void sqlite
c2a0: 33 46 74 73 33 4d 61 74 63 68 69 6e 66 6f 28 0a  3Fts3Matchinfo(.
c2b0: 20 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78    sqlite3_contex
c2c0: 74 20 2a 70 43 6f 6e 74 65 78 74 2c 20 20 20 20  t *pContext,    
c2d0: 20 20 2f 2a 20 46 75 6e 63 74 69 6f 6e 20 63 61    /* Function ca
c2e0: 6c 6c 20 63 6f 6e 74 65 78 74 20 2a 2f 0a 20 20  ll context */.  
c2f0: 46 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72  Fts3Cursor *pCsr
c300: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
c310: 2f 2a 20 46 54 53 33 20 74 61 62 6c 65 20 63 75  /* FTS3 table cu
c320: 72 73 6f 72 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  rsor */.  const 
c330: 63 68 61 72 20 2a 7a 41 72 67 20 20 20 20 20 20  char *zArg      
c340: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 65 63            /* Sec
c350: 6f 6e 64 20 61 72 67 20 74 6f 20 6d 61 74 63 68  ond arg to match
c360: 69 6e 66 6f 28 29 20 66 75 6e 63 74 69 6f 6e 20  info() function 
c370: 2a 2f 0a 29 7b 0a 20 20 46 74 73 33 54 61 62 6c  */.){.  Fts3Tabl
c380: 65 20 2a 70 54 61 62 20 3d 20 28 46 74 73 33 54  e *pTab = (Fts3T
c390: 61 62 6c 65 20 2a 29 70 43 73 72 2d 3e 62 61 73  able *)pCsr->bas
c3a0: 65 2e 70 56 74 61 62 3b 0a 20 20 69 6e 74 20 72  e.pVtab;.  int r
c3b0: 63 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 63 6f  c;.  int i;.  co
c3c0: 6e 73 74 20 63 68 61 72 20 2a 7a 46 6f 72 6d 61  nst char *zForma
c3d0: 74 3b 0a 0a 20 20 69 66 28 20 7a 41 72 67 20 29  t;..  if( zArg )
c3e0: 7b 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b 20 7a  {.    for(i=0; z
c3f0: 41 72 67 5b 69 5d 3b 20 69 2b 2b 29 7b 0a 20 20  Arg[i]; i++){.  
c400: 20 20 20 20 63 68 61 72 20 2a 7a 45 72 72 20 3d      char *zErr =
c410: 20 30 3b 0a 20 20 20 20 20 20 69 66 28 20 66 74   0;.      if( ft
c420: 73 33 4d 61 74 63 68 69 6e 66 6f 43 68 65 63 6b  s3MatchinfoCheck
c430: 28 70 54 61 62 2c 20 7a 41 72 67 5b 69 5d 2c 20  (pTab, zArg[i], 
c440: 26 7a 45 72 72 29 20 29 7b 0a 20 20 20 20 20 20  &zErr) ){.      
c450: 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74    sqlite3_result
c460: 5f 65 72 72 6f 72 28 70 43 6f 6e 74 65 78 74 2c  _error(pContext,
c470: 20 7a 45 72 72 2c 20 2d 31 29 3b 0a 20 20 20 20   zErr, -1);.    
c480: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65      sqlite3_free
c490: 28 7a 45 72 72 29 3b 0a 20 20 20 20 20 20 20 20  (zErr);.        
c4a0: 72 65 74 75 72 6e 3b 0a 20 20 20 20 20 20 7d 0a  return;.      }.
c4b0: 20 20 20 20 7d 0a 20 20 20 20 7a 46 6f 72 6d 61      }.    zForma
c4c0: 74 20 3d 20 7a 41 72 67 3b 0a 20 20 7d 65 6c 73  t = zArg;.  }els
c4d0: 65 7b 0a 20 20 20 20 7a 46 6f 72 6d 61 74 20 3d  e{.    zFormat =
c4e0: 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f   FTS3_MATCHINFO_
c4f0: 44 45 46 41 55 4c 54 3b 0a 20 20 7d 0a 0a 20 20  DEFAULT;.  }..  
c500: 69 66 28 20 21 70 43 73 72 2d 3e 70 45 78 70 72  if( !pCsr->pExpr
c510: 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f   ){.    sqlite3_
c520: 72 65 73 75 6c 74 5f 62 6c 6f 62 28 70 43 6f 6e  result_blob(pCon
c530: 74 65 78 74 2c 20 22 22 2c 20 30 2c 20 53 51 4c  text, "", 0, SQL
c540: 49 54 45 5f 53 54 41 54 49 43 29 3b 0a 20 20 20  ITE_STATIC);.   
c550: 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 0a 20 20   return;.  }..  
c560: 2f 2a 20 52 65 74 72 69 65 76 65 20 6d 61 74 63  /* Retrieve matc
c570: 68 69 6e 66 6f 28 29 20 64 61 74 61 2e 20 2a 2f  hinfo() data. */
c580: 0a 20 20 72 63 20 3d 20 66 74 73 33 47 65 74 4d  .  rc = fts3GetM
c590: 61 74 63 68 69 6e 66 6f 28 70 43 73 72 2c 20 7a  atchinfo(pCsr, z
c5a0: 46 6f 72 6d 61 74 29 3b 0a 20 20 73 71 6c 69 74  Format);.  sqlit
c5b0: 65 33 46 74 73 33 53 65 67 6d 65 6e 74 73 43 6c  e3Fts3SegmentsCl
c5c0: 6f 73 65 28 70 54 61 62 29 3b 0a 0a 20 20 69 66  ose(pTab);..  if
c5d0: 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc!=SQLITE_OK 
c5e0: 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 72  ){.    sqlite3_r
c5f0: 65 73 75 6c 74 5f 65 72 72 6f 72 5f 63 6f 64 65  esult_error_code
c600: 28 70 43 6f 6e 74 65 78 74 2c 20 72 63 29 3b 0a  (pContext, rc);.
c610: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 69 6e 74    }else{.    int
c620: 20 6e 20 3d 20 70 43 73 72 2d 3e 6e 4d 61 74 63   n = pCsr->nMatc
c630: 68 69 6e 66 6f 20 2a 20 73 69 7a 65 6f 66 28 75  hinfo * sizeof(u
c640: 33 32 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33  32);.    sqlite3
c650: 5f 72 65 73 75 6c 74 5f 62 6c 6f 62 28 70 43 6f  _result_blob(pCo
c660: 6e 74 65 78 74 2c 20 70 43 73 72 2d 3e 61 4d 61  ntext, pCsr->aMa
c670: 74 63 68 69 6e 66 6f 2c 20 6e 2c 20 53 51 4c 49  tchinfo, n, SQLI
c680: 54 45 5f 54 52 41 4e 53 49 45 4e 54 29 3b 0a 20  TE_TRANSIENT);. 
c690: 20 7d 0a 7d 0a 0a 23 65 6e 64 69 66 0a            }.}..#endif.