/ Hex Artifact Content
Login

Artifact ac1f8945375d07076b7178de1fe549982e6ae6f050095e7f7e400ec4448f31df:


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 23 64 65  se values */.#de
03f0: 66 69 6e 65 20 46 54 53 33 5f 4d 41 54 43 48 49  fine FTS3_MATCHI
0400: 4e 46 4f 5f 4c 48 49 54 53 20 20 20 20 20 27 79  NFO_LHITS     'y
0410: 27 20 20 20 20 20 20 20 20 2f 2a 20 6e 43 6f 6c  '        /* nCol
0420: 2a 6e 50 68 72 61 73 65 20 76 61 6c 75 65 73 20  *nPhrase values 
0430: 2a 2f 0a 23 64 65 66 69 6e 65 20 46 54 53 33 5f  */.#define FTS3_
0440: 4d 41 54 43 48 49 4e 46 4f 5f 4c 48 49 54 53 5f  MATCHINFO_LHITS_
0450: 42 4d 20 20 27 62 27 20 20 20 20 20 20 20 20 2f  BM  'b'        /
0460: 2a 20 6e 43 6f 6c 2a 6e 50 68 72 61 73 65 20 76  * nCol*nPhrase v
0470: 61 6c 75 65 73 20 2a 2f 0a 0a 2f 2a 0a 2a 2a 20  alues */../*.** 
0480: 54 68 65 20 64 65 66 61 75 6c 74 20 76 61 6c 75  The default valu
0490: 65 20 66 6f 72 20 74 68 65 20 73 65 63 6f 6e 64  e for the second
04a0: 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 6d 61 74   argument to mat
04b0: 63 68 69 6e 66 6f 28 29 2e 20 0a 2a 2f 0a 23 64  chinfo(). .*/.#d
04c0: 65 66 69 6e 65 20 46 54 53 33 5f 4d 41 54 43 48  efine FTS3_MATCH
04d0: 49 4e 46 4f 5f 44 45 46 41 55 4c 54 20 20 20 22  INFO_DEFAULT   "
04e0: 70 63 78 22 0a 0a 0a 2f 2a 0a 2a 2a 20 55 73 65  pcx".../*.** Use
04f0: 64 20 61 73 20 61 6e 20 66 74 73 33 45 78 70 72  d as an fts3Expr
0500: 49 74 65 72 61 74 65 28 29 20 63 6f 6e 74 65 78  Iterate() contex
0510: 74 20 77 68 65 6e 20 6c 6f 61 64 69 6e 67 20 70  t when loading p
0520: 68 72 61 73 65 20 64 6f 63 6c 69 73 74 73 20 74  hrase doclists t
0530: 6f 0a 2a 2a 20 46 74 73 33 45 78 70 72 2e 61 44  o.** Fts3Expr.aD
0540: 6f 63 6c 69 73 74 5b 5d 2f 6e 44 6f 63 6c 69 73  oclist[]/nDoclis
0550: 74 2e 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73 74  t..*/.typedef st
0560: 72 75 63 74 20 4c 6f 61 64 44 6f 63 6c 69 73 74  ruct LoadDoclist
0570: 43 74 78 20 4c 6f 61 64 44 6f 63 6c 69 73 74 43  Ctx LoadDoclistC
0580: 74 78 3b 0a 73 74 72 75 63 74 20 4c 6f 61 64 44  tx;.struct LoadD
0590: 6f 63 6c 69 73 74 43 74 78 20 7b 0a 20 20 46 74  oclistCtx {.  Ft
05a0: 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72 3b 20  s3Cursor *pCsr; 
05b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
05c0: 20 46 54 53 33 20 43 75 72 73 6f 72 20 2a 2f 0a   FTS3 Cursor */.
05d0: 20 20 69 6e 74 20 6e 50 68 72 61 73 65 3b 20 20    int nPhrase;  
05e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
05f0: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 70    /* Number of p
0600: 68 72 61 73 65 73 20 73 65 65 6e 20 73 6f 20 66  hrases seen so f
0610: 61 72 20 2a 2f 0a 20 20 69 6e 74 20 6e 54 6f 6b  ar */.  int nTok
0620: 65 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  en;             
0630: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
0640: 72 20 6f 66 20 74 6f 6b 65 6e 73 20 73 65 65 6e  r of tokens seen
0650: 20 73 6f 20 66 61 72 20 2a 2f 0a 7d 3b 0a 0a 2f   so far */.};../
0660: 2a 0a 2a 2a 20 54 68 65 20 66 6f 6c 6c 6f 77 69  *.** The followi
0670: 6e 67 20 74 79 70 65 73 20 61 72 65 20 75 73 65  ng types are use
0680: 64 20 61 73 20 70 61 72 74 20 6f 66 20 74 68 65  d as part of the
0690: 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f 6e 20   implementation 
06a0: 6f 66 20 74 68 65 20 0a 2a 2a 20 66 74 73 33 42  of the .** fts3B
06b0: 65 73 74 53 6e 69 70 70 65 74 28 29 20 72 6f 75  estSnippet() rou
06c0: 74 69 6e 65 2e 0a 2a 2f 0a 74 79 70 65 64 65 66  tine..*/.typedef
06d0: 20 73 74 72 75 63 74 20 53 6e 69 70 70 65 74 49   struct SnippetI
06e0: 74 65 72 20 53 6e 69 70 70 65 74 49 74 65 72 3b  ter SnippetIter;
06f0: 0a 74 79 70 65 64 65 66 20 73 74 72 75 63 74 20  .typedef struct 
0700: 53 6e 69 70 70 65 74 50 68 72 61 73 65 20 53 6e  SnippetPhrase Sn
0710: 69 70 70 65 74 50 68 72 61 73 65 3b 0a 74 79 70  ippetPhrase;.typ
0720: 65 64 65 66 20 73 74 72 75 63 74 20 53 6e 69 70  edef struct Snip
0730: 70 65 74 46 72 61 67 6d 65 6e 74 20 53 6e 69 70  petFragment Snip
0740: 70 65 74 46 72 61 67 6d 65 6e 74 3b 0a 0a 73 74  petFragment;..st
0750: 72 75 63 74 20 53 6e 69 70 70 65 74 49 74 65 72  ruct SnippetIter
0760: 20 7b 0a 20 20 46 74 73 33 43 75 72 73 6f 72 20   {.  Fts3Cursor 
0770: 2a 70 43 73 72 3b 20 20 20 20 20 20 20 20 20 20  *pCsr;          
0780: 20 20 20 20 20 2f 2a 20 43 75 72 73 6f 72 20 73       /* Cursor s
0790: 6e 69 70 70 65 74 20 69 73 20 62 65 69 6e 67 20  nippet is being 
07a0: 67 65 6e 65 72 61 74 65 64 20 66 72 6f 6d 20 2a  generated from *
07b0: 2f 0a 20 20 69 6e 74 20 69 43 6f 6c 3b 20 20 20  /.  int iCol;   
07c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
07d0: 20 20 20 20 2f 2a 20 45 78 74 72 61 63 74 20 73      /* Extract s
07e0: 6e 69 70 70 65 74 20 66 72 6f 6d 20 74 68 69 73  nippet from this
07f0: 20 63 6f 6c 75 6d 6e 20 2a 2f 0a 20 20 69 6e 74   column */.  int
0800: 20 6e 53 6e 69 70 70 65 74 3b 20 20 20 20 20 20   nSnippet;      
0810: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
0820: 52 65 71 75 65 73 74 65 64 20 73 6e 69 70 70 65  Requested snippe
0830: 74 20 6c 65 6e 67 74 68 20 28 69 6e 20 74 6f 6b  t length (in tok
0840: 65 6e 73 29 20 2a 2f 0a 20 20 69 6e 74 20 6e 50  ens) */.  int nP
0850: 68 72 61 73 65 3b 20 20 20 20 20 20 20 20 20 20  hrase;          
0860: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d            /* Num
0870: 62 65 72 20 6f 66 20 70 68 72 61 73 65 73 20 69  ber of phrases i
0880: 6e 20 71 75 65 72 79 20 2a 2f 0a 20 20 53 6e 69  n query */.  Sni
0890: 70 70 65 74 50 68 72 61 73 65 20 2a 61 50 68 72  ppetPhrase *aPhr
08a0: 61 73 65 3b 20 20 20 20 20 20 20 20 20 2f 2a 20  ase;         /* 
08b0: 41 72 72 61 79 20 6f 66 20 73 69 7a 65 20 6e 50  Array of size nP
08c0: 68 72 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20 69  hrase */.  int i
08d0: 43 75 72 72 65 6e 74 3b 20 20 20 20 20 20 20 20  Current;        
08e0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 69             /* Fi
08f0: 72 73 74 20 74 6f 6b 65 6e 20 6f 66 20 63 75 72  rst token of cur
0900: 72 65 6e 74 20 73 6e 69 70 70 65 74 20 2a 2f 0a  rent snippet */.
0910: 7d 3b 0a 0a 73 74 72 75 63 74 20 53 6e 69 70 70  };..struct Snipp
0920: 65 74 50 68 72 61 73 65 20 7b 0a 20 20 69 6e 74  etPhrase {.  int
0930: 20 6e 54 6f 6b 65 6e 3b 20 20 20 20 20 20 20 20   nToken;        
0940: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
0950: 4e 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73  Number of tokens
0960: 20 69 6e 20 70 68 72 61 73 65 20 2a 2f 0a 20 20   in phrase */.  
0970: 63 68 61 72 20 2a 70 4c 69 73 74 3b 20 20 20 20  char *pList;    
0980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0990: 2f 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20 73 74  /* Pointer to st
09a0: 61 72 74 20 6f 66 20 70 68 72 61 73 65 20 70 6f  art of phrase po
09b0: 73 69 74 69 6f 6e 20 6c 69 73 74 20 2a 2f 0a 20  sition list */. 
09c0: 20 69 6e 74 20 69 48 65 61 64 3b 20 20 20 20 20   int iHead;     
09d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
09e0: 20 2f 2a 20 4e 65 78 74 20 76 61 6c 75 65 20 69   /* Next value i
09f0: 6e 20 70 6f 73 69 74 69 6f 6e 20 6c 69 73 74 20  n position list 
0a00: 2a 2f 0a 20 20 63 68 61 72 20 2a 70 48 65 61 64  */.  char *pHead
0a10: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
0a20: 20 20 20 20 20 2f 2a 20 50 6f 73 69 74 69 6f 6e       /* Position
0a30: 20 6c 69 73 74 20 64 61 74 61 20 66 6f 6c 6c 6f   list data follo
0a40: 77 69 6e 67 20 69 48 65 61 64 20 2a 2f 0a 20 20  wing iHead */.  
0a50: 69 6e 74 20 69 54 61 69 6c 3b 20 20 20 20 20 20  int iTail;      
0a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0a70: 2f 2a 20 4e 65 78 74 20 76 61 6c 75 65 20 69 6e  /* Next value in
0a80: 20 74 72 61 69 6c 69 6e 67 20 70 6f 73 69 74 69   trailing positi
0a90: 6f 6e 20 6c 69 73 74 20 2a 2f 0a 20 20 63 68 61  on list */.  cha
0aa0: 72 20 2a 70 54 61 69 6c 3b 20 20 20 20 20 20 20  r *pTail;       
0ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
0ac0: 50 6f 73 69 74 69 6f 6e 20 6c 69 73 74 20 64 61  Position list da
0ad0: 74 61 20 66 6f 6c 6c 6f 77 69 6e 67 20 69 54 61  ta following iTa
0ae0: 69 6c 20 2a 2f 0a 7d 3b 0a 0a 73 74 72 75 63 74  il */.};..struct
0af0: 20 53 6e 69 70 70 65 74 46 72 61 67 6d 65 6e 74   SnippetFragment
0b00: 20 7b 0a 20 20 69 6e 74 20 69 43 6f 6c 3b 20 20   {.  int iCol;  
0b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b20: 20 20 20 20 20 2f 2a 20 43 6f 6c 75 6d 6e 20 73       /* Column s
0b30: 6e 69 70 70 65 74 20 69 73 20 65 78 74 72 61 63  nippet is extrac
0b40: 74 65 64 20 66 72 6f 6d 20 2a 2f 0a 20 20 69 6e  ted from */.  in
0b50: 74 20 69 50 6f 73 3b 20 20 20 20 20 20 20 20 20  t iPos;         
0b60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
0b70: 20 49 6e 64 65 78 20 6f 66 20 66 69 72 73 74 20   Index of first 
0b80: 74 6f 6b 65 6e 20 69 6e 20 73 6e 69 70 70 65 74  token in snippet
0b90: 20 2a 2f 0a 20 20 75 36 34 20 63 6f 76 65 72 65   */.  u64 covere
0ba0: 64 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  d;              
0bb0: 20 20 20 20 20 20 2f 2a 20 4d 61 73 6b 20 6f 66        /* Mask of
0bc0: 20 71 75 65 72 79 20 70 68 72 61 73 65 73 20 63   query phrases c
0bd0: 6f 76 65 72 65 64 20 2a 2f 0a 20 20 75 36 34 20  overed */.  u64 
0be0: 68 6c 6d 61 73 6b 3b 20 20 20 20 20 20 20 20 20  hlmask;         
0bf0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4d              /* M
0c00: 61 73 6b 20 6f 66 20 73 6e 69 70 70 65 74 20 74  ask of snippet t
0c10: 65 72 6d 73 20 74 6f 20 68 69 67 68 6c 69 67 68  erms to highligh
0c20: 74 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 54  t */.};../*.** T
0c30: 68 69 73 20 74 79 70 65 20 69 73 20 75 73 65 64  his type is used
0c40: 20 61 73 20 61 6e 20 66 74 73 33 45 78 70 72 49   as an fts3ExprI
0c50: 74 65 72 61 74 65 28 29 20 63 6f 6e 74 65 78 74  terate() context
0c60: 20 6f 62 6a 65 63 74 20 77 68 69 6c 65 20 0a 2a   object while .*
0c70: 2a 20 61 63 63 75 6d 75 6c 61 74 69 6e 67 20 74  * accumulating t
0c80: 68 65 20 64 61 74 61 20 72 65 74 75 72 6e 65 64  he data returned
0c90: 20 62 79 20 74 68 65 20 6d 61 74 63 68 69 6e 66   by the matchinf
0ca0: 6f 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f  o() function..*/
0cb0: 0a 74 79 70 65 64 65 66 20 73 74 72 75 63 74 20  .typedef struct 
0cc0: 4d 61 74 63 68 49 6e 66 6f 20 4d 61 74 63 68 49  MatchInfo MatchI
0cd0: 6e 66 6f 3b 0a 73 74 72 75 63 74 20 4d 61 74 63  nfo;.struct Matc
0ce0: 68 49 6e 66 6f 20 7b 0a 20 20 46 74 73 33 43 75  hInfo {.  Fts3Cu
0cf0: 72 73 6f 72 20 2a 70 43 75 72 73 6f 72 3b 20 20  rsor *pCursor;  
0d00: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 54 53            /* FTS
0d10: 33 20 43 75 72 73 6f 72 20 2a 2f 0a 20 20 69 6e  3 Cursor */.  in
0d20: 74 20 6e 43 6f 6c 3b 20 20 20 20 20 20 20 20 20  t nCol;         
0d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
0d40: 20 4e 75 6d 62 65 72 20 6f 66 20 63 6f 6c 75 6d   Number of colum
0d50: 6e 73 20 69 6e 20 74 61 62 6c 65 20 2a 2f 0a 20  ns in table */. 
0d60: 20 69 6e 74 20 6e 50 68 72 61 73 65 3b 20 20 20   int nPhrase;   
0d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0d80: 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 6d 61   /* Number of ma
0d90: 74 63 68 61 62 6c 65 20 70 68 72 61 73 65 73 20  tchable phrases 
0da0: 69 6e 20 71 75 65 72 79 20 2a 2f 0a 20 20 73 71  in query */.  sq
0db0: 6c 69 74 65 33 5f 69 6e 74 36 34 20 6e 44 6f 63  lite3_int64 nDoc
0dc0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  ;             /*
0dd0: 20 4e 75 6d 62 65 72 20 6f 66 20 64 6f 63 73 20   Number of docs 
0de0: 69 6e 20 64 61 74 61 62 61 73 65 20 2a 2f 0a 20  in database */. 
0df0: 20 63 68 61 72 20 66 6c 61 67 3b 0a 20 20 75 33   char flag;.  u3
0e00: 32 20 2a 61 4d 61 74 63 68 69 6e 66 6f 3b 20 20  2 *aMatchinfo;  
0e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
0e20: 20 50 72 65 2d 61 6c 6c 6f 63 61 74 65 64 20 62   Pre-allocated b
0e30: 75 66 66 65 72 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a  uffer */.};../*.
0e40: 2a 2a 20 41 6e 20 69 6e 73 74 61 6e 63 65 20 6f  ** An instance o
0e50: 66 20 74 68 69 73 20 73 74 72 75 63 74 75 72 65  f this structure
0e60: 20 69 73 20 75 73 65 64 20 74 6f 20 6d 61 6e 61   is used to mana
0e70: 67 65 20 61 20 70 61 69 72 20 6f 66 20 62 75 66  ge a pair of buf
0e80: 66 65 72 73 2c 20 65 61 63 68 0a 2a 2a 20 28 6e  fers, each.** (n
0e90: 45 6c 65 6d 20 2a 20 73 69 7a 65 6f 66 28 75 33  Elem * sizeof(u3
0ea0: 32 29 29 20 62 79 74 65 73 20 69 6e 20 73 69 7a  2)) bytes in siz
0eb0: 65 2e 20 53 65 65 20 74 68 65 20 4d 61 74 63 68  e. See the Match
0ec0: 69 6e 66 6f 42 75 66 66 65 72 20 63 6f 64 65 20  infoBuffer code 
0ed0: 62 65 6c 6f 77 0a 2a 2a 20 66 6f 72 20 64 65 74  below.** for det
0ee0: 61 69 6c 73 2e 0a 2a 2f 0a 73 74 72 75 63 74 20  ails..*/.struct 
0ef0: 4d 61 74 63 68 69 6e 66 6f 42 75 66 66 65 72 20  MatchinfoBuffer 
0f00: 7b 0a 20 20 75 38 20 61 52 65 66 5b 33 5d 3b 0a  {.  u8 aRef[3];.
0f10: 20 20 69 6e 74 20 6e 45 6c 65 6d 3b 0a 20 20 69    int nElem;.  i
0f20: 6e 74 20 62 47 6c 6f 62 61 6c 3b 20 20 20 20 20  nt bGlobal;     
0f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0f40: 2a 20 53 65 74 20 69 66 20 67 6c 6f 62 61 6c 20  * Set if global 
0f50: 64 61 74 61 20 69 73 20 6c 6f 61 64 65 64 20 2a  data is loaded *
0f60: 2f 0a 20 20 63 68 61 72 20 2a 7a 4d 61 74 63 68  /.  char *zMatch
0f70: 69 6e 66 6f 3b 0a 20 20 75 33 32 20 61 4d 61 74  info;.  u32 aMat
0f80: 63 68 69 6e 66 6f 5b 31 5d 3b 0a 7d 3b 0a 0a 0a  chinfo[1];.};...
0f90: 2f 2a 0a 2a 2a 20 54 68 65 20 73 6e 69 70 70 65  /*.** The snippe
0fa0: 74 28 29 20 61 6e 64 20 6f 66 66 73 65 74 73 28  t() and offsets(
0fb0: 29 20 66 75 6e 63 74 69 6f 6e 73 20 62 6f 74 68  ) functions both
0fc0: 20 72 65 74 75 72 6e 20 74 65 78 74 20 76 61 6c   return text val
0fd0: 75 65 73 2e 20 41 6e 20 69 6e 73 74 61 6e 63 65  ues. An instance
0fe0: 0a 2a 2a 20 6f 66 20 74 68 65 20 66 6f 6c 6c 6f  .** of the follo
0ff0: 77 69 6e 67 20 73 74 72 75 63 74 75 72 65 20 69  wing structure i
1000: 73 20 75 73 65 64 20 74 6f 20 61 63 63 75 6d 75  s used to accumu
1010: 6c 61 74 65 20 74 68 6f 73 65 20 76 61 6c 75 65  late those value
1020: 73 20 77 68 69 6c 65 20 74 68 65 0a 2a 2a 20 66  s while the.** f
1030: 75 6e 63 74 69 6f 6e 73 20 61 72 65 20 72 75 6e  unctions are run
1040: 6e 69 6e 67 2e 20 53 65 65 20 66 74 73 33 53 74  ning. See fts3St
1050: 72 69 6e 67 41 70 70 65 6e 64 28 29 20 66 6f 72  ringAppend() for
1060: 20 64 65 74 61 69 6c 73 2e 0a 2a 2f 0a 74 79 70   details..*/.typ
1070: 65 64 65 66 20 73 74 72 75 63 74 20 53 74 72 42  edef struct StrB
1080: 75 66 66 65 72 20 53 74 72 42 75 66 66 65 72 3b  uffer StrBuffer;
1090: 0a 73 74 72 75 63 74 20 53 74 72 42 75 66 66 65  .struct StrBuffe
10a0: 72 20 7b 0a 20 20 63 68 61 72 20 2a 7a 3b 20 20  r {.  char *z;  
10b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
10c0: 20 20 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65 72        /* Pointer
10d0: 20 74 6f 20 62 75 66 66 65 72 20 63 6f 6e 74 61   to buffer conta
10e0: 69 6e 69 6e 67 20 73 74 72 69 6e 67 20 2a 2f 0a  ining string */.
10f0: 20 20 69 6e 74 20 6e 3b 20 20 20 20 20 20 20 20    int n;        
1100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1110: 20 20 2f 2a 20 4c 65 6e 67 74 68 20 6f 66 20 7a    /* Length of z
1120: 20 69 6e 20 62 79 74 65 73 20 28 65 78 63 6c 2e   in bytes (excl.
1130: 20 6e 75 6c 2d 74 65 72 6d 29 20 2a 2f 0a 20 20   nul-term) */.  
1140: 69 6e 74 20 6e 41 6c 6c 6f 63 3b 20 20 20 20 20  int nAlloc;     
1150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1160: 2f 2a 20 41 6c 6c 6f 63 61 74 65 64 20 73 69 7a  /* Allocated siz
1170: 65 20 6f 66 20 62 75 66 66 65 72 20 7a 20 69 6e  e of buffer z in
1180: 20 62 79 74 65 73 20 2a 2f 0a 7d 3b 0a 0a 0a 2f   bytes */.};.../
1190: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
11a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
11b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
11c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
11d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 2a 2a 20 53 74 61  *********.** Sta
11e0: 72 74 20 6f 66 20 4d 61 74 63 68 69 6e 66 6f 42  rt of MatchinfoB
11f0: 75 66 66 65 72 20 63 6f 64 65 2e 0a 2a 2f 0a 0a  uffer code..*/..
1200: 2f 2a 0a 2a 2a 20 41 6c 6c 6f 63 61 74 65 20 61  /*.** Allocate a
1210: 20 74 77 6f 2d 73 6c 6f 74 20 4d 61 74 63 68 69   two-slot Matchi
1220: 6e 66 6f 42 75 66 66 65 72 20 6f 62 6a 65 63 74  nfoBuffer object
1230: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 4d 61 74 63  ..*/.static Matc
1240: 68 69 6e 66 6f 42 75 66 66 65 72 20 2a 66 74 73  hinfoBuffer *fts
1250: 33 4d 49 42 75 66 66 65 72 4e 65 77 28 69 6e 74  3MIBufferNew(int
1260: 20 6e 45 6c 65 6d 2c 20 63 6f 6e 73 74 20 63 68   nElem, const ch
1270: 61 72 20 2a 7a 4d 61 74 63 68 69 6e 66 6f 29 7b  ar *zMatchinfo){
1280: 0a 20 20 4d 61 74 63 68 69 6e 66 6f 42 75 66 66  .  MatchinfoBuff
1290: 65 72 20 2a 70 52 65 74 3b 0a 20 20 69 6e 74 20  er *pRet;.  int 
12a0: 6e 42 79 74 65 20 3d 20 73 69 7a 65 6f 66 28 75  nByte = sizeof(u
12b0: 33 32 29 20 2a 20 28 32 2a 6e 45 6c 65 6d 20 2b  32) * (2*nElem +
12c0: 20 31 29 20 2b 20 73 69 7a 65 6f 66 28 4d 61 74   1) + sizeof(Mat
12d0: 63 68 69 6e 66 6f 42 75 66 66 65 72 29 3b 0a 20  chinfoBuffer);. 
12e0: 20 69 6e 74 20 6e 53 74 72 20 3d 20 28 69 6e 74   int nStr = (int
12f0: 29 73 74 72 6c 65 6e 28 7a 4d 61 74 63 68 69 6e  )strlen(zMatchin
1300: 66 6f 29 3b 0a 0a 20 20 70 52 65 74 20 3d 20 73  fo);..  pRet = s
1310: 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 6e 42  qlite3_malloc(nB
1320: 79 74 65 20 2b 20 6e 53 74 72 2b 31 29 3b 0a 20  yte + nStr+1);. 
1330: 20 69 66 28 20 70 52 65 74 20 29 7b 0a 20 20 20   if( pRet ){.   
1340: 20 6d 65 6d 73 65 74 28 70 52 65 74 2c 20 30 2c   memset(pRet, 0,
1350: 20 6e 42 79 74 65 29 3b 0a 20 20 20 20 70 52 65   nByte);.    pRe
1360: 74 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 30 5d  t->aMatchinfo[0]
1370: 20 3d 20 28 75 38 2a 29 28 26 70 52 65 74 2d 3e   = (u8*)(&pRet->
1380: 61 4d 61 74 63 68 69 6e 66 6f 5b 31 5d 29 20 2d  aMatchinfo[1]) -
1390: 20 28 75 38 2a 29 70 52 65 74 3b 0a 20 20 20 20   (u8*)pRet;.    
13a0: 70 52 65 74 2d 3e 61 4d 61 74 63 68 69 6e 66 6f  pRet->aMatchinfo
13b0: 5b 31 2b 6e 45 6c 65 6d 5d 20 3d 20 70 52 65 74  [1+nElem] = pRet
13c0: 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 30 5d 20  ->aMatchinfo[0] 
13d0: 2b 20 73 69 7a 65 6f 66 28 75 33 32 29 2a 28 6e  + sizeof(u32)*(n
13e0: 45 6c 65 6d 2b 31 29 3b 0a 20 20 20 20 70 52 65  Elem+1);.    pRe
13f0: 74 2d 3e 6e 45 6c 65 6d 20 3d 20 6e 45 6c 65 6d  t->nElem = nElem
1400: 3b 0a 20 20 20 20 70 52 65 74 2d 3e 7a 4d 61 74  ;.    pRet->zMat
1410: 63 68 69 6e 66 6f 20 3d 20 28 28 63 68 61 72 2a  chinfo = ((char*
1420: 29 70 52 65 74 29 20 2b 20 6e 42 79 74 65 3b 0a  )pRet) + nByte;.
1430: 20 20 20 20 6d 65 6d 63 70 79 28 70 52 65 74 2d      memcpy(pRet-
1440: 3e 7a 4d 61 74 63 68 69 6e 66 6f 2c 20 7a 4d 61  >zMatchinfo, zMa
1450: 74 63 68 69 6e 66 6f 2c 20 6e 53 74 72 2b 31 29  tchinfo, nStr+1)
1460: 3b 0a 20 20 20 20 70 52 65 74 2d 3e 61 52 65 66  ;.    pRet->aRef
1470: 5b 30 5d 20 3d 20 31 3b 0a 20 20 7d 0a 0a 20 20  [0] = 1;.  }..  
1480: 72 65 74 75 72 6e 20 70 52 65 74 3b 0a 7d 0a 0a  return pRet;.}..
1490: 73 74 61 74 69 63 20 76 6f 69 64 20 66 74 73 33  static void fts3
14a0: 4d 49 42 75 66 66 65 72 46 72 65 65 28 76 6f 69  MIBufferFree(voi
14b0: 64 20 2a 70 29 7b 0a 20 20 4d 61 74 63 68 69 6e  d *p){.  Matchin
14c0: 66 6f 42 75 66 66 65 72 20 2a 70 42 75 66 20 3d  foBuffer *pBuf =
14d0: 20 28 4d 61 74 63 68 69 6e 66 6f 42 75 66 66 65   (MatchinfoBuffe
14e0: 72 2a 29 28 28 75 38 2a 29 70 20 2d 20 28 28 75  r*)((u8*)p - ((u
14f0: 33 32 2a 29 70 29 5b 2d 31 5d 29 3b 0a 0a 20 20  32*)p)[-1]);..  
1500: 61 73 73 65 72 74 28 20 28 75 33 32 2a 29 70 3d  assert( (u32*)p=
1510: 3d 26 70 42 75 66 2d 3e 61 4d 61 74 63 68 69 6e  =&pBuf->aMatchin
1520: 66 6f 5b 31 5d 20 0a 20 20 20 20 20 20 20 7c 7c  fo[1] .       ||
1530: 20 28 75 33 32 2a 29 70 3d 3d 26 70 42 75 66 2d   (u32*)p==&pBuf-
1540: 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 70 42 75 66  >aMatchinfo[pBuf
1550: 2d 3e 6e 45 6c 65 6d 2b 32 5d 20 0a 20 20 29 3b  ->nElem+2] .  );
1560: 0a 20 20 69 66 28 20 28 75 33 32 2a 29 70 3d 3d  .  if( (u32*)p==
1570: 26 70 42 75 66 2d 3e 61 4d 61 74 63 68 69 6e 66  &pBuf->aMatchinf
1580: 6f 5b 31 5d 20 29 7b 0a 20 20 20 20 70 42 75 66  o[1] ){.    pBuf
1590: 2d 3e 61 52 65 66 5b 31 5d 20 3d 20 30 3b 0a 20  ->aRef[1] = 0;. 
15a0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 70 42 75 66   }else{.    pBuf
15b0: 2d 3e 61 52 65 66 5b 32 5d 20 3d 20 30 3b 0a 20  ->aRef[2] = 0;. 
15c0: 20 7d 0a 0a 20 20 69 66 28 20 70 42 75 66 2d 3e   }..  if( pBuf->
15d0: 61 52 65 66 5b 30 5d 3d 3d 30 20 26 26 20 70 42  aRef[0]==0 && pB
15e0: 75 66 2d 3e 61 52 65 66 5b 31 5d 3d 3d 30 20 26  uf->aRef[1]==0 &
15f0: 26 20 70 42 75 66 2d 3e 61 52 65 66 5b 32 5d 3d  & pBuf->aRef[2]=
1600: 3d 30 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65  =0 ){.    sqlite
1610: 33 5f 66 72 65 65 28 70 42 75 66 29 3b 0a 20 20  3_free(pBuf);.  
1620: 7d 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f 69 64  }.}..static void
1630: 20 28 2a 66 74 73 33 4d 49 42 75 66 66 65 72 41   (*fts3MIBufferA
1640: 6c 6c 6f 63 28 4d 61 74 63 68 69 6e 66 6f 42 75  lloc(MatchinfoBu
1650: 66 66 65 72 20 2a 70 2c 20 75 33 32 20 2a 2a 70  ffer *p, u32 **p
1660: 61 4f 75 74 29 29 28 76 6f 69 64 2a 29 7b 0a 20  aOut))(void*){. 
1670: 20 76 6f 69 64 20 28 2a 78 52 65 74 29 28 76 6f   void (*xRet)(vo
1680: 69 64 2a 29 20 3d 20 30 3b 0a 20 20 75 33 32 20  id*) = 0;.  u32 
1690: 2a 61 4f 75 74 20 3d 20 30 3b 0a 0a 20 20 69 66  *aOut = 0;..  if
16a0: 28 20 70 2d 3e 61 52 65 66 5b 31 5d 3d 3d 30 20  ( p->aRef[1]==0 
16b0: 29 7b 0a 20 20 20 20 70 2d 3e 61 52 65 66 5b 31  ){.    p->aRef[1
16c0: 5d 20 3d 20 31 3b 0a 20 20 20 20 61 4f 75 74 20  ] = 1;.    aOut 
16d0: 3d 20 26 70 2d 3e 61 4d 61 74 63 68 69 6e 66 6f  = &p->aMatchinfo
16e0: 5b 31 5d 3b 0a 20 20 20 20 78 52 65 74 20 3d 20  [1];.    xRet = 
16f0: 66 74 73 33 4d 49 42 75 66 66 65 72 46 72 65 65  fts3MIBufferFree
1700: 3b 0a 20 20 7d 0a 20 20 65 6c 73 65 20 69 66 28  ;.  }.  else if(
1710: 20 70 2d 3e 61 52 65 66 5b 32 5d 3d 3d 30 20 29   p->aRef[2]==0 )
1720: 7b 0a 20 20 20 20 70 2d 3e 61 52 65 66 5b 32 5d  {.    p->aRef[2]
1730: 20 3d 20 31 3b 0a 20 20 20 20 61 4f 75 74 20 3d   = 1;.    aOut =
1740: 20 26 70 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b   &p->aMatchinfo[
1750: 70 2d 3e 6e 45 6c 65 6d 2b 32 5d 3b 0a 20 20 20  p->nElem+2];.   
1760: 20 78 52 65 74 20 3d 20 66 74 73 33 4d 49 42 75   xRet = fts3MIBu
1770: 66 66 65 72 46 72 65 65 3b 0a 20 20 7d 65 6c 73  fferFree;.  }els
1780: 65 7b 0a 20 20 20 20 61 4f 75 74 20 3d 20 28 75  e{.    aOut = (u
1790: 33 32 2a 29 73 71 6c 69 74 65 33 5f 6d 61 6c 6c  32*)sqlite3_mall
17a0: 6f 63 36 34 28 70 2d 3e 6e 45 6c 65 6d 20 2a 20  oc64(p->nElem * 
17b0: 73 69 7a 65 6f 66 28 75 33 32 29 29 3b 0a 20 20  sizeof(u32));.  
17c0: 20 20 69 66 28 20 61 4f 75 74 20 29 7b 0a 20 20    if( aOut ){.  
17d0: 20 20 20 20 78 52 65 74 20 3d 20 73 71 6c 69 74      xRet = sqlit
17e0: 65 33 5f 66 72 65 65 3b 0a 20 20 20 20 20 20 69  e3_free;.      i
17f0: 66 28 20 70 2d 3e 62 47 6c 6f 62 61 6c 20 29 20  f( p->bGlobal ) 
1800: 6d 65 6d 63 70 79 28 61 4f 75 74 2c 20 26 70 2d  memcpy(aOut, &p-
1810: 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 31 5d 2c 20  >aMatchinfo[1], 
1820: 70 2d 3e 6e 45 6c 65 6d 2a 73 69 7a 65 6f 66 28  p->nElem*sizeof(
1830: 75 33 32 29 29 3b 0a 20 20 20 20 7d 0a 20 20 7d  u32));.    }.  }
1840: 0a 0a 20 20 2a 70 61 4f 75 74 20 3d 20 61 4f 75  ..  *paOut = aOu
1850: 74 3b 0a 20 20 72 65 74 75 72 6e 20 78 52 65 74  t;.  return xRet
1860: 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 76 6f 69 64  ;.}..static void
1870: 20 66 74 73 33 4d 49 42 75 66 66 65 72 53 65 74   fts3MIBufferSet
1880: 47 6c 6f 62 61 6c 28 4d 61 74 63 68 69 6e 66 6f  Global(Matchinfo
1890: 42 75 66 66 65 72 20 2a 70 29 7b 0a 20 20 70 2d  Buffer *p){.  p-
18a0: 3e 62 47 6c 6f 62 61 6c 20 3d 20 31 3b 0a 20 20  >bGlobal = 1;.  
18b0: 6d 65 6d 63 70 79 28 26 70 2d 3e 61 4d 61 74 63  memcpy(&p->aMatc
18c0: 68 69 6e 66 6f 5b 32 2b 70 2d 3e 6e 45 6c 65 6d  hinfo[2+p->nElem
18d0: 5d 2c 20 26 70 2d 3e 61 4d 61 74 63 68 69 6e 66  ], &p->aMatchinf
18e0: 6f 5b 31 5d 2c 20 70 2d 3e 6e 45 6c 65 6d 2a 73  o[1], p->nElem*s
18f0: 69 7a 65 6f 66 28 75 33 32 29 29 3b 0a 7d 0a 0a  izeof(u32));.}..
1900: 2f 2a 0a 2a 2a 20 46 72 65 65 20 61 20 4d 61 74  /*.** Free a Mat
1910: 63 68 69 6e 66 6f 42 75 66 66 65 72 20 6f 62 6a  chinfoBuffer obj
1920: 65 63 74 20 61 6c 6c 6f 63 61 74 65 64 20 75 73  ect allocated us
1930: 69 6e 67 20 66 74 73 33 4d 49 42 75 66 66 65 72  ing fts3MIBuffer
1940: 4e 65 77 28 29 0a 2a 2f 0a 76 6f 69 64 20 73 71  New().*/.void sq
1950: 6c 69 74 65 33 46 74 73 33 4d 49 42 75 66 66 65  lite3Fts3MIBuffe
1960: 72 46 72 65 65 28 4d 61 74 63 68 69 6e 66 6f 42  rFree(MatchinfoB
1970: 75 66 66 65 72 20 2a 70 29 7b 0a 20 20 69 66 28  uffer *p){.  if(
1980: 20 70 20 29 7b 0a 20 20 20 20 61 73 73 65 72 74   p ){.    assert
1990: 28 20 70 2d 3e 61 52 65 66 5b 30 5d 3d 3d 31 20  ( p->aRef[0]==1 
19a0: 29 3b 0a 20 20 20 20 70 2d 3e 61 52 65 66 5b 30  );.    p->aRef[0
19b0: 5d 20 3d 20 30 3b 0a 20 20 20 20 69 66 28 20 70  ] = 0;.    if( p
19c0: 2d 3e 61 52 65 66 5b 30 5d 3d 3d 30 20 26 26 20  ->aRef[0]==0 && 
19d0: 70 2d 3e 61 52 65 66 5b 31 5d 3d 3d 30 20 26 26  p->aRef[1]==0 &&
19e0: 20 70 2d 3e 61 52 65 66 5b 32 5d 3d 3d 30 20 29   p->aRef[2]==0 )
19f0: 7b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f  {.      sqlite3_
1a00: 66 72 65 65 28 70 29 3b 0a 20 20 20 20 7d 0a 20  free(p);.    }. 
1a10: 20 7d 0a 7d 0a 0a 2f 2a 20 0a 2a 2a 20 45 6e 64   }.}../* .** End
1a20: 20 6f 66 20 4d 61 74 63 68 69 6e 66 6f 42 75 66   of MatchinfoBuf
1a30: 66 65 72 20 63 6f 64 65 2e 0a 2a 2a 2a 2a 2a 2a  fer code..******
1a40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1a50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1a60: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1a70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1a80: 2a 2a 2a 2f 0a 0a 0a 2f 2a 0a 2a 2a 20 54 68 69  ***/.../*.** Thi
1a90: 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 75 73  s function is us
1aa0: 65 64 20 74 6f 20 68 65 6c 70 20 69 74 65 72 61  ed to help itera
1ab0: 74 65 20 74 68 72 6f 75 67 68 20 61 20 70 6f 73  te through a pos
1ac0: 69 74 69 6f 6e 2d 6c 69 73 74 2e 20 41 20 70 6f  ition-list. A po
1ad0: 73 69 74 69 6f 6e 0a 2a 2a 20 6c 69 73 74 20 69  sition.** list i
1ae0: 73 20 61 20 6c 69 73 74 20 6f 66 20 75 6e 69 71  s a list of uniq
1af0: 75 65 20 69 6e 74 65 67 65 72 73 2c 20 73 6f 72  ue integers, sor
1b00: 74 65 64 20 66 72 6f 6d 20 73 6d 61 6c 6c 65 73  ted from smalles
1b10: 74 20 74 6f 20 6c 61 72 67 65 73 74 2e 20 45 61  t to largest. Ea
1b20: 63 68 0a 2a 2a 20 65 6c 65 6d 65 6e 74 20 6f 66  ch.** element of
1b30: 20 74 68 65 20 6c 69 73 74 20 69 73 20 72 65 70   the list is rep
1b40: 72 65 73 65 6e 74 65 64 20 62 79 20 61 6e 20 46  resented by an F
1b50: 54 53 33 20 76 61 72 69 6e 74 20 74 68 61 74 20  TS3 varint that 
1b60: 74 61 6b 65 73 20 74 68 65 20 76 61 6c 75 65 0a  takes the value.
1b70: 2a 2a 20 6f 66 20 74 68 65 20 64 69 66 66 65 72  ** of the differ
1b80: 65 6e 63 65 20 62 65 74 77 65 65 6e 20 74 68 65  ence between the
1b90: 20 63 75 72 72 65 6e 74 20 65 6c 65 6d 65 6e 74   current element
1ba0: 20 61 6e 64 20 74 68 65 20 70 72 65 76 69 6f 75   and the previou
1bb0: 73 20 6f 6e 65 20 70 6c 75 73 0a 2a 2a 20 74 77  s one plus.** tw
1bc0: 6f 2e 20 46 6f 72 20 65 78 61 6d 70 6c 65 2c 20  o. For example, 
1bd0: 74 6f 20 73 74 6f 72 65 20 74 68 65 20 70 6f 73  to store the pos
1be0: 69 74 69 6f 6e 2d 6c 69 73 74 3a 0a 2a 2a 0a 2a  ition-list:.**.*
1bf0: 2a 20 20 20 20 20 34 20 39 20 31 31 33 0a 2a 2a  *     4 9 113.**
1c00: 0a 2a 2a 20 74 68 65 20 74 68 72 65 65 20 76 61  .** the three va
1c10: 72 69 6e 74 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 20  rints:.**.**    
1c20: 20 36 20 37 20 31 30 36 0a 2a 2a 0a 2a 2a 20 61   6 7 106.**.** a
1c30: 72 65 20 65 6e 63 6f 64 65 64 2e 0a 2a 2a 0a 2a  re encoded..**.*
1c40: 2a 20 57 68 65 6e 20 74 68 69 73 20 66 75 6e 63  * When this func
1c50: 74 69 6f 6e 20 69 73 20 63 61 6c 6c 65 64 2c 20  tion is called, 
1c60: 2a 70 70 20 70 6f 69 6e 74 73 20 74 6f 20 74 68  *pp points to th
1c70: 65 20 73 74 61 72 74 20 6f 66 20 61 6e 20 65 6c  e start of an el
1c80: 65 6d 65 6e 74 20 6f 66 0a 2a 2a 20 74 68 65 20  ement of.** the 
1c90: 6c 69 73 74 2e 20 2a 70 69 50 6f 73 20 63 6f 6e  list. *piPos con
1ca0: 74 61 69 6e 73 20 74 68 65 20 76 61 6c 75 65 20  tains the value 
1cb0: 6f 66 20 74 68 65 20 70 72 65 76 69 6f 75 73 20  of the previous 
1cc0: 65 6e 74 72 79 20 69 6e 20 74 68 65 20 6c 69 73  entry in the lis
1cd0: 74 2e 0a 2a 2a 20 41 66 74 65 72 20 69 74 20 72  t..** After it r
1ce0: 65 74 75 72 6e 73 2c 20 2a 70 69 50 6f 73 20 63  eturns, *piPos c
1cf0: 6f 6e 74 61 69 6e 73 20 74 68 65 20 76 61 6c 75  ontains the valu
1d00: 65 20 6f 66 20 74 68 65 20 6e 65 78 74 20 65 6c  e of the next el
1d10: 65 6d 65 6e 74 20 6f 66 20 74 68 65 0a 2a 2a 20  ement of the.** 
1d20: 6c 69 73 74 20 61 6e 64 20 2a 70 70 20 69 73 20  list and *pp is 
1d30: 61 64 76 61 6e 63 65 64 20 74 6f 20 74 68 65 20  advanced to the 
1d40: 66 6f 6c 6c 6f 77 69 6e 67 20 76 61 72 69 6e 74  following varint
1d50: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
1d60: 20 66 74 73 33 47 65 74 44 65 6c 74 61 50 6f 73   fts3GetDeltaPos
1d70: 69 74 69 6f 6e 28 63 68 61 72 20 2a 2a 70 70 2c  ition(char **pp,
1d80: 20 69 6e 74 20 2a 70 69 50 6f 73 29 7b 0a 20 20   int *piPos){.  
1d90: 69 6e 74 20 69 56 61 6c 3b 0a 20 20 2a 70 70 20  int iVal;.  *pp 
1da0: 2b 3d 20 66 74 73 33 47 65 74 56 61 72 69 6e 74  += fts3GetVarint
1db0: 33 32 28 2a 70 70 2c 20 26 69 56 61 6c 29 3b 0a  32(*pp, &iVal);.
1dc0: 20 20 2a 70 69 50 6f 73 20 2b 3d 20 28 69 56 61    *piPos += (iVa
1dd0: 6c 2d 32 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 48  l-2);.}../*.** H
1de0: 65 6c 70 65 72 20 66 75 6e 63 74 69 6f 6e 20 66  elper function f
1df0: 6f 72 20 66 74 73 33 45 78 70 72 49 74 65 72 61  or fts3ExprItera
1e00: 74 65 28 29 20 28 73 65 65 20 62 65 6c 6f 77 29  te() (see below)
1e10: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
1e20: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 32  fts3ExprIterate2
1e30: 28 0a 20 20 46 74 73 33 45 78 70 72 20 2a 70 45  (.  Fts3Expr *pE
1e40: 78 70 72 2c 20 20 20 20 20 20 20 20 20 20 20 20  xpr,            
1e50: 20 20 20 20 2f 2a 20 45 78 70 72 65 73 73 69 6f      /* Expressio
1e60: 6e 20 74 6f 20 69 74 65 72 61 74 65 20 70 68 72  n to iterate phr
1e70: 61 73 65 73 20 6f 66 20 2a 2f 0a 20 20 69 6e 74  ases of */.  int
1e80: 20 2a 70 69 50 68 72 61 73 65 2c 20 20 20 20 20   *piPhrase,     
1e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
1ea0: 50 6f 69 6e 74 65 72 20 74 6f 20 70 68 72 61 73  Pointer to phras
1eb0: 65 20 63 6f 75 6e 74 65 72 20 2a 2f 0a 20 20 69  e counter */.  i
1ec0: 6e 74 20 28 2a 78 29 28 46 74 73 33 45 78 70 72  nt (*x)(Fts3Expr
1ed0: 2a 2c 69 6e 74 2c 76 6f 69 64 2a 29 2c 20 20 2f  *,int,void*),  /
1ee0: 2a 20 43 61 6c 6c 62 61 63 6b 20 66 75 6e 63 74  * Callback funct
1ef0: 69 6f 6e 20 74 6f 20 69 6e 76 6f 6b 65 20 66 6f  ion to invoke fo
1f00: 72 20 70 68 72 61 73 65 73 20 2a 2f 0a 20 20 76  r phrases */.  v
1f10: 6f 69 64 20 2a 70 43 74 78 20 20 20 20 20 20 20  oid *pCtx       
1f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
1f30: 2a 20 53 65 63 6f 6e 64 20 61 72 67 75 6d 65 6e  * Second argumen
1f40: 74 20 74 6f 20 70 61 73 73 20 74 6f 20 63 61 6c  t to pass to cal
1f50: 6c 62 61 63 6b 20 2a 2f 0a 29 7b 0a 20 20 69 6e  lback */.){.  in
1f60: 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20  t rc;           
1f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
1f80: 20 52 65 74 75 72 6e 20 63 6f 64 65 20 2a 2f 0a   Return code */.
1f90: 20 20 69 6e 74 20 65 54 79 70 65 20 3d 20 70 45    int eType = pE
1fa0: 78 70 72 2d 3e 65 54 79 70 65 3b 20 20 20 20 20  xpr->eType;     
1fb0: 2f 2a 20 54 79 70 65 20 6f 66 20 65 78 70 72 65  /* Type of expre
1fc0: 73 73 69 6f 6e 20 6e 6f 64 65 20 70 45 78 70 72  ssion node pExpr
1fd0: 20 2a 2f 0a 0a 20 20 69 66 28 20 65 54 79 70 65   */..  if( eType
1fe0: 21 3d 46 54 53 51 55 45 52 59 5f 50 48 52 41 53  !=FTSQUERY_PHRAS
1ff0: 45 20 29 7b 0a 20 20 20 20 61 73 73 65 72 74 28  E ){.    assert(
2000: 20 70 45 78 70 72 2d 3e 70 4c 65 66 74 20 26 26   pExpr->pLeft &&
2010: 20 70 45 78 70 72 2d 3e 70 52 69 67 68 74 20 29   pExpr->pRight )
2020: 3b 0a 20 20 20 20 72 63 20 3d 20 66 74 73 33 45  ;.    rc = fts3E
2030: 78 70 72 49 74 65 72 61 74 65 32 28 70 45 78 70  xprIterate2(pExp
2040: 72 2d 3e 70 4c 65 66 74 2c 20 70 69 50 68 72 61  r->pLeft, piPhra
2050: 73 65 2c 20 78 2c 20 70 43 74 78 29 3b 0a 20 20  se, x, pCtx);.  
2060: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
2070: 5f 4f 4b 20 26 26 20 65 54 79 70 65 21 3d 46 54  _OK && eType!=FT
2080: 53 51 55 45 52 59 5f 4e 4f 54 20 29 7b 0a 20 20  SQUERY_NOT ){.  
2090: 20 20 20 20 72 63 20 3d 20 66 74 73 33 45 78 70      rc = fts3Exp
20a0: 72 49 74 65 72 61 74 65 32 28 70 45 78 70 72 2d  rIterate2(pExpr-
20b0: 3e 70 52 69 67 68 74 2c 20 70 69 50 68 72 61 73  >pRight, piPhras
20c0: 65 2c 20 78 2c 20 70 43 74 78 29 3b 0a 20 20 20  e, x, pCtx);.   
20d0: 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20   }.  }else{.    
20e0: 72 63 20 3d 20 78 28 70 45 78 70 72 2c 20 2a 70  rc = x(pExpr, *p
20f0: 69 50 68 72 61 73 65 2c 20 70 43 74 78 29 3b 0a  iPhrase, pCtx);.
2100: 20 20 20 20 28 2a 70 69 50 68 72 61 73 65 29 2b      (*piPhrase)+
2110: 2b 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  +;.  }.  return 
2120: 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 74 65  rc;.}../*.** Ite
2130: 72 61 74 65 20 74 68 72 6f 75 67 68 20 61 6c 6c  rate through all
2140: 20 70 68 72 61 73 65 20 6e 6f 64 65 73 20 69 6e   phrase nodes in
2150: 20 61 6e 20 46 54 53 33 20 71 75 65 72 79 2c 20   an FTS3 query, 
2160: 65 78 63 65 70 74 20 74 68 6f 73 65 20 74 68 61  except those tha
2170: 74 0a 2a 2a 20 61 72 65 20 70 61 72 74 20 6f 66  t.** are part of
2180: 20 61 20 73 75 62 2d 74 72 65 65 20 74 68 61 74   a sub-tree that
2190: 20 69 73 20 74 68 65 20 72 69 67 68 74 2d 68 61   is the right-ha
21a0: 6e 64 2d 73 69 64 65 20 6f 66 20 61 20 4e 4f 54  nd-side of a NOT
21b0: 20 6f 70 65 72 61 74 6f 72 2e 0a 2a 2a 20 46 6f   operator..** Fo
21c0: 72 20 65 61 63 68 20 70 68 72 61 73 65 20 6e 6f  r each phrase no
21d0: 64 65 20 66 6f 75 6e 64 2c 20 74 68 65 20 73 75  de found, the su
21e0: 70 70 6c 69 65 64 20 63 61 6c 6c 62 61 63 6b 20  pplied callback 
21f0: 66 75 6e 63 74 69 6f 6e 20 69 73 20 69 6e 76 6f  function is invo
2200: 6b 65 64 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 74 68  ked..**.** If th
2210: 65 20 63 61 6c 6c 62 61 63 6b 20 66 75 6e 63 74  e callback funct
2220: 69 6f 6e 20 72 65 74 75 72 6e 73 20 61 6e 79 74  ion returns anyt
2230: 68 69 6e 67 20 6f 74 68 65 72 20 74 68 61 6e 20  hing other than 
2240: 53 51 4c 49 54 45 5f 4f 4b 2c 20 0a 2a 2a 20 74  SQLITE_OK, .** t
2250: 68 65 20 69 74 65 72 61 74 69 6f 6e 20 69 73 20  he iteration is 
2260: 61 62 61 6e 64 6f 6e 65 64 20 61 6e 64 20 74 68  abandoned and th
2270: 65 20 65 72 72 6f 72 20 63 6f 64 65 20 72 65 74  e error code ret
2280: 75 72 6e 65 64 20 69 6d 6d 65 64 69 61 74 65 6c  urned immediatel
2290: 79 2e 0a 2a 2a 20 4f 74 68 65 72 77 69 73 65 2c  y..** Otherwise,
22a0: 20 53 51 4c 49 54 45 5f 4f 4b 20 69 73 20 72 65   SQLITE_OK is re
22b0: 74 75 72 6e 65 64 20 61 66 74 65 72 20 61 20 63  turned after a c
22c0: 61 6c 6c 62 61 63 6b 20 68 61 73 20 62 65 65 6e  allback has been
22d0: 20 6d 61 64 65 20 66 6f 72 0a 2a 2a 20 61 6c 6c   made for.** all
22e0: 20 65 6c 69 67 69 62 6c 65 20 70 68 72 61 73 65   eligible phrase
22f0: 20 6e 6f 64 65 73 2e 0a 2a 2f 0a 73 74 61 74 69   nodes..*/.stati
2300: 63 20 69 6e 74 20 66 74 73 33 45 78 70 72 49 74  c int fts3ExprIt
2310: 65 72 61 74 65 28 0a 20 20 46 74 73 33 45 78 70  erate(.  Fts3Exp
2320: 72 20 2a 70 45 78 70 72 2c 20 20 20 20 20 20 20  r *pExpr,       
2330: 20 20 20 20 20 20 20 20 20 2f 2a 20 45 78 70 72           /* Expr
2340: 65 73 73 69 6f 6e 20 74 6f 20 69 74 65 72 61 74  ession to iterat
2350: 65 20 70 68 72 61 73 65 73 20 6f 66 20 2a 2f 0a  e phrases of */.
2360: 20 20 69 6e 74 20 28 2a 78 29 28 46 74 73 33 45    int (*x)(Fts3E
2370: 78 70 72 2a 2c 69 6e 74 2c 76 6f 69 64 2a 29 2c  xpr*,int,void*),
2380: 20 20 2f 2a 20 43 61 6c 6c 62 61 63 6b 20 66 75    /* Callback fu
2390: 6e 63 74 69 6f 6e 20 74 6f 20 69 6e 76 6f 6b 65  nction to invoke
23a0: 20 66 6f 72 20 70 68 72 61 73 65 73 20 2a 2f 0a   for phrases */.
23b0: 20 20 76 6f 69 64 20 2a 70 43 74 78 20 20 20 20    void *pCtx    
23c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
23d0: 20 20 2f 2a 20 53 65 63 6f 6e 64 20 61 72 67 75    /* Second argu
23e0: 6d 65 6e 74 20 74 6f 20 70 61 73 73 20 74 6f 20  ment to pass to 
23f0: 63 61 6c 6c 62 61 63 6b 20 2a 2f 0a 29 7b 0a 20  callback */.){. 
2400: 20 69 6e 74 20 69 50 68 72 61 73 65 20 3d 20 30   int iPhrase = 0
2410: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
2420: 20 2f 2a 20 56 61 72 69 61 62 6c 65 20 75 73 65   /* Variable use
2430: 64 20 61 73 20 74 68 65 20 70 68 72 61 73 65 20  d as the phrase 
2440: 63 6f 75 6e 74 65 72 20 2a 2f 0a 20 20 72 65 74  counter */.  ret
2450: 75 72 6e 20 66 74 73 33 45 78 70 72 49 74 65 72  urn fts3ExprIter
2460: 61 74 65 32 28 70 45 78 70 72 2c 20 26 69 50 68  ate2(pExpr, &iPh
2470: 72 61 73 65 2c 20 78 2c 20 70 43 74 78 29 3b 0a  rase, x, pCtx);.
2480: 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69  }.../*.** This i
2490: 73 20 61 6e 20 66 74 73 33 45 78 70 72 49 74 65  s an fts3ExprIte
24a0: 72 61 74 65 28 29 20 63 61 6c 6c 62 61 63 6b 20  rate() callback 
24b0: 75 73 65 64 20 77 68 69 6c 65 20 6c 6f 61 64 69  used while loadi
24c0: 6e 67 20 74 68 65 20 64 6f 63 6c 69 73 74 73 0a  ng the doclists.
24d0: 2a 2a 20 66 6f 72 20 65 61 63 68 20 70 68 72 61  ** for each phra
24e0: 73 65 20 69 6e 74 6f 20 46 74 73 33 45 78 70 72  se into Fts3Expr
24f0: 2e 61 44 6f 63 6c 69 73 74 5b 5d 2f 6e 44 6f 63  .aDoclist[]/nDoc
2500: 6c 69 73 74 2e 20 53 65 65 20 61 6c 73 6f 0a 2a  list. See also.*
2510: 2a 20 66 74 73 33 45 78 70 72 4c 6f 61 64 44 6f  * fts3ExprLoadDo
2520: 63 6c 69 73 74 73 28 29 2e 0a 2a 2f 0a 73 74 61  clists()..*/.sta
2530: 74 69 63 20 69 6e 74 20 66 74 73 33 45 78 70 72  tic int fts3Expr
2540: 4c 6f 61 64 44 6f 63 6c 69 73 74 73 43 62 28 46  LoadDoclistsCb(F
2550: 74 73 33 45 78 70 72 20 2a 70 45 78 70 72 2c 20  ts3Expr *pExpr, 
2560: 69 6e 74 20 69 50 68 72 61 73 65 2c 20 76 6f 69  int iPhrase, voi
2570: 64 20 2a 63 74 78 29 7b 0a 20 20 69 6e 74 20 72  d *ctx){.  int r
2580: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
2590: 20 46 74 73 33 50 68 72 61 73 65 20 2a 70 50 68   Fts3Phrase *pPh
25a0: 72 61 73 65 20 3d 20 70 45 78 70 72 2d 3e 70 50  rase = pExpr->pP
25b0: 68 72 61 73 65 3b 0a 20 20 4c 6f 61 64 44 6f 63  hrase;.  LoadDoc
25c0: 6c 69 73 74 43 74 78 20 2a 70 20 3d 20 28 4c 6f  listCtx *p = (Lo
25d0: 61 64 44 6f 63 6c 69 73 74 43 74 78 20 2a 29 63  adDoclistCtx *)c
25e0: 74 78 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41  tx;..  UNUSED_PA
25f0: 52 41 4d 45 54 45 52 28 69 50 68 72 61 73 65 29  RAMETER(iPhrase)
2600: 3b 0a 0a 20 20 70 2d 3e 6e 50 68 72 61 73 65 2b  ;..  p->nPhrase+
2610: 2b 3b 0a 20 20 70 2d 3e 6e 54 6f 6b 65 6e 20 2b  +;.  p->nToken +
2620: 3d 20 70 50 68 72 61 73 65 2d 3e 6e 54 6f 6b 65  = pPhrase->nToke
2630: 6e 3b 0a 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  n;..  return rc;
2640: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4c 6f 61 64 20 74  .}../*.** Load t
2650: 68 65 20 64 6f 63 6c 69 73 74 73 20 66 6f 72 20  he doclists for 
2660: 65 61 63 68 20 70 68 72 61 73 65 20 69 6e 20 74  each phrase in t
2670: 68 65 20 71 75 65 72 79 20 61 73 73 6f 63 69 61  he query associa
2680: 74 65 64 20 77 69 74 68 20 46 54 53 33 20 63 75  ted with FTS3 cu
2690: 72 73 6f 72 0a 2a 2a 20 70 43 73 72 2e 20 0a 2a  rsor.** pCsr. .*
26a0: 2a 0a 2a 2a 20 49 66 20 70 6e 50 68 72 61 73 65  *.** If pnPhrase
26b0: 20 69 73 20 6e 6f 74 20 4e 55 4c 4c 2c 20 74 68   is not NULL, th
26c0: 65 6e 20 2a 70 6e 50 68 72 61 73 65 20 69 73 20  en *pnPhrase is 
26d0: 73 65 74 20 74 6f 20 74 68 65 20 6e 75 6d 62 65  set to the numbe
26e0: 72 20 6f 66 20 6d 61 74 63 68 61 62 6c 65 20 0a  r of matchable .
26f0: 2a 2a 20 70 68 72 61 73 65 73 20 69 6e 20 74 68  ** phrases in th
2700: 65 20 65 78 70 72 65 73 73 69 6f 6e 20 28 61 6c  e expression (al
2710: 6c 20 70 68 72 61 73 65 73 20 65 78 63 65 70 74  l phrases except
2720: 20 74 68 6f 73 65 20 64 69 72 65 63 74 6c 79 20   those directly 
2730: 6f 72 20 0a 2a 2a 20 69 6e 64 69 72 65 63 74 6c  or .** indirectl
2740: 79 20 64 65 73 63 65 6e 64 65 64 20 66 72 6f 6d  y descended from
2750: 20 74 68 65 20 72 69 67 68 74 2d 68 61 6e 64 2d   the right-hand-
2760: 73 69 64 65 20 6f 66 20 61 20 4e 4f 54 20 6f 70  side of a NOT op
2770: 65 72 61 74 6f 72 29 2e 20 49 66 20 0a 2a 2a 20  erator). If .** 
2780: 70 6e 54 6f 6b 65 6e 20 69 73 20 6e 6f 74 20 4e  pnToken is not N
2790: 55 4c 4c 2c 20 74 68 65 6e 20 69 74 20 69 73 20  ULL, then it is 
27a0: 73 65 74 20 74 6f 20 74 68 65 20 6e 75 6d 62 65  set to the numbe
27b0: 72 20 6f 66 20 74 6f 6b 65 6e 73 20 69 6e 20 61  r of tokens in a
27c0: 6c 6c 0a 2a 2a 20 6d 61 74 63 68 61 62 6c 65 20  ll.** matchable 
27d0: 70 68 72 61 73 65 73 20 6f 66 20 74 68 65 20 65  phrases of the e
27e0: 78 70 72 65 73 73 69 6f 6e 2e 0a 2a 2f 0a 73 74  xpression..*/.st
27f0: 61 74 69 63 20 69 6e 74 20 66 74 73 33 45 78 70  atic int fts3Exp
2800: 72 4c 6f 61 64 44 6f 63 6c 69 73 74 73 28 0a 20  rLoadDoclists(. 
2810: 20 46 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73   Fts3Cursor *pCs
2820: 72 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  r,              
2830: 20 2f 2a 20 46 74 73 33 20 63 75 72 73 6f 72 20   /* Fts3 cursor 
2840: 66 6f 72 20 63 75 72 72 65 6e 74 20 71 75 65 72  for current quer
2850: 79 20 2a 2f 0a 20 20 69 6e 74 20 2a 70 6e 50 68  y */.  int *pnPh
2860: 72 61 73 65 2c 20 20 20 20 20 20 20 20 20 20 20  rase,           
2870: 20 20 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 4e         /* OUT: N
2880: 75 6d 62 65 72 20 6f 66 20 70 68 72 61 73 65 73  umber of phrases
2890: 20 69 6e 20 71 75 65 72 79 20 2a 2f 0a 20 20 69   in query */.  i
28a0: 6e 74 20 2a 70 6e 54 6f 6b 65 6e 20 20 20 20 20  nt *pnToken     
28b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
28c0: 2a 20 4f 55 54 3a 20 4e 75 6d 62 65 72 20 6f 66  * OUT: Number of
28d0: 20 74 6f 6b 65 6e 73 20 69 6e 20 71 75 65 72 79   tokens in query
28e0: 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b   */.){.  int rc;
28f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2900: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75           /* Retu
2910: 72 6e 20 43 6f 64 65 20 2a 2f 0a 20 20 4c 6f 61  rn Code */.  Loa
2920: 64 44 6f 63 6c 69 73 74 43 74 78 20 73 43 74 78  dDoclistCtx sCtx
2930: 20 3d 20 7b 30 2c 30 2c 30 7d 3b 20 20 2f 2a 20   = {0,0,0};  /* 
2940: 43 6f 6e 74 65 78 74 20 66 6f 72 20 66 74 73 33  Context for fts3
2950: 45 78 70 72 49 74 65 72 61 74 65 28 29 20 2a 2f  ExprIterate() */
2960: 0a 20 20 73 43 74 78 2e 70 43 73 72 20 3d 20 70  .  sCtx.pCsr = p
2970: 43 73 72 3b 0a 20 20 72 63 20 3d 20 66 74 73 33  Csr;.  rc = fts3
2980: 45 78 70 72 49 74 65 72 61 74 65 28 70 43 73 72  ExprIterate(pCsr
2990: 2d 3e 70 45 78 70 72 2c 20 66 74 73 33 45 78 70  ->pExpr, fts3Exp
29a0: 72 4c 6f 61 64 44 6f 63 6c 69 73 74 73 43 62 2c  rLoadDoclistsCb,
29b0: 20 28 76 6f 69 64 20 2a 29 26 73 43 74 78 29 3b   (void *)&sCtx);
29c0: 0a 20 20 69 66 28 20 70 6e 50 68 72 61 73 65 20  .  if( pnPhrase 
29d0: 29 20 2a 70 6e 50 68 72 61 73 65 20 3d 20 73 43  ) *pnPhrase = sC
29e0: 74 78 2e 6e 50 68 72 61 73 65 3b 0a 20 20 69 66  tx.nPhrase;.  if
29f0: 28 20 70 6e 54 6f 6b 65 6e 20 29 20 2a 70 6e 54  ( pnToken ) *pnT
2a00: 6f 6b 65 6e 20 3d 20 73 43 74 78 2e 6e 54 6f 6b  oken = sCtx.nTok
2a10: 65 6e 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  en;.  return rc;
2a20: 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e 74 20 66  .}..static int f
2a30: 74 73 33 45 78 70 72 50 68 72 61 73 65 43 6f 75  ts3ExprPhraseCou
2a40: 6e 74 43 62 28 46 74 73 33 45 78 70 72 20 2a 70  ntCb(Fts3Expr *p
2a50: 45 78 70 72 2c 20 69 6e 74 20 69 50 68 72 61 73  Expr, int iPhras
2a60: 65 2c 20 76 6f 69 64 20 2a 63 74 78 29 7b 0a 20  e, void *ctx){. 
2a70: 20 28 2a 28 69 6e 74 20 2a 29 63 74 78 29 2b 2b   (*(int *)ctx)++
2a80: 3b 0a 20 20 70 45 78 70 72 2d 3e 69 50 68 72 61  ;.  pExpr->iPhra
2a90: 73 65 20 3d 20 69 50 68 72 61 73 65 3b 0a 20 20  se = iPhrase;.  
2aa0: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b  return SQLITE_OK
2ab0: 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 66  ;.}.static int f
2ac0: 74 73 33 45 78 70 72 50 68 72 61 73 65 43 6f 75  ts3ExprPhraseCou
2ad0: 6e 74 28 46 74 73 33 45 78 70 72 20 2a 70 45 78  nt(Fts3Expr *pEx
2ae0: 70 72 29 7b 0a 20 20 69 6e 74 20 6e 50 68 72 61  pr){.  int nPhra
2af0: 73 65 20 3d 20 30 3b 0a 20 20 28 76 6f 69 64 29  se = 0;.  (void)
2b00: 66 74 73 33 45 78 70 72 49 74 65 72 61 74 65 28  fts3ExprIterate(
2b10: 70 45 78 70 72 2c 20 66 74 73 33 45 78 70 72 50  pExpr, fts3ExprP
2b20: 68 72 61 73 65 43 6f 75 6e 74 43 62 2c 20 28 76  hraseCountCb, (v
2b30: 6f 69 64 20 2a 29 26 6e 50 68 72 61 73 65 29 3b  oid *)&nPhrase);
2b40: 0a 20 20 72 65 74 75 72 6e 20 6e 50 68 72 61 73  .  return nPhras
2b50: 65 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 64 76 61  e;.}../*.** Adva
2b60: 6e 63 65 20 74 68 65 20 70 6f 73 69 74 69 6f 6e  nce the position
2b70: 20 6c 69 73 74 20 69 74 65 72 61 74 6f 72 20 73   list iterator s
2b80: 70 65 63 69 66 69 65 64 20 62 79 20 74 68 65 20  pecified by the 
2b90: 66 69 72 73 74 20 74 77 6f 20 0a 2a 2a 20 61 72  first two .** ar
2ba0: 67 75 6d 65 6e 74 73 20 73 6f 20 74 68 61 74 20  guments so that 
2bb0: 69 74 20 70 6f 69 6e 74 73 20 74 6f 20 74 68 65  it points to the
2bc0: 20 66 69 72 73 74 20 65 6c 65 6d 65 6e 74 20 77   first element w
2bd0: 69 74 68 20 61 20 76 61 6c 75 65 20 67 72 65 61  ith a value grea
2be0: 74 65 72 0a 2a 2a 20 74 68 61 6e 20 6f 72 20 65  ter.** than or e
2bf0: 71 75 61 6c 20 74 6f 20 70 61 72 61 6d 65 74 65  qual to paramete
2c00: 72 20 69 4e 65 78 74 2e 0a 2a 2f 0a 73 74 61 74  r iNext..*/.stat
2c10: 69 63 20 76 6f 69 64 20 66 74 73 33 53 6e 69 70  ic void fts3Snip
2c20: 70 65 74 41 64 76 61 6e 63 65 28 63 68 61 72 20  petAdvance(char 
2c30: 2a 2a 70 70 49 74 65 72 2c 20 69 6e 74 20 2a 70  **ppIter, int *p
2c40: 69 49 74 65 72 2c 20 69 6e 74 20 69 4e 65 78 74  iIter, int iNext
2c50: 29 7b 0a 20 20 63 68 61 72 20 2a 70 49 74 65 72  ){.  char *pIter
2c60: 20 3d 20 2a 70 70 49 74 65 72 3b 0a 20 20 69 66   = *ppIter;.  if
2c70: 28 20 70 49 74 65 72 20 29 7b 0a 20 20 20 20 69  ( pIter ){.    i
2c80: 6e 74 20 69 49 74 65 72 20 3d 20 2a 70 69 49 74  nt iIter = *piIt
2c90: 65 72 3b 0a 0a 20 20 20 20 77 68 69 6c 65 28 20  er;..    while( 
2ca0: 69 49 74 65 72 3c 69 4e 65 78 74 20 29 7b 0a 20  iIter<iNext ){. 
2cb0: 20 20 20 20 20 69 66 28 20 30 3d 3d 28 2a 70 49       if( 0==(*pI
2cc0: 74 65 72 20 26 20 30 78 46 45 29 20 29 7b 0a 20  ter & 0xFE) ){. 
2cd0: 20 20 20 20 20 20 20 69 49 74 65 72 20 3d 20 2d         iIter = -
2ce0: 31 3b 0a 20 20 20 20 20 20 20 20 70 49 74 65 72  1;.        pIter
2cf0: 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 62 72   = 0;.        br
2d00: 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  eak;.      }.   
2d10: 20 20 20 66 74 73 33 47 65 74 44 65 6c 74 61 50     fts3GetDeltaP
2d20: 6f 73 69 74 69 6f 6e 28 26 70 49 74 65 72 2c 20  osition(&pIter, 
2d30: 26 69 49 74 65 72 29 3b 0a 20 20 20 20 7d 0a 0a  &iIter);.    }..
2d40: 20 20 20 20 2a 70 69 49 74 65 72 20 3d 20 69 49      *piIter = iI
2d50: 74 65 72 3b 0a 20 20 20 20 2a 70 70 49 74 65 72  ter;.    *ppIter
2d60: 20 3d 20 70 49 74 65 72 3b 0a 20 20 7d 0a 7d 0a   = pIter;.  }.}.
2d70: 0a 2f 2a 0a 2a 2a 20 41 64 76 61 6e 63 65 20 74  ./*.** Advance t
2d80: 68 65 20 73 6e 69 70 70 65 74 20 69 74 65 72 61  he snippet itera
2d90: 74 6f 72 20 74 6f 20 74 68 65 20 6e 65 78 74 20  tor to the next 
2da0: 63 61 6e 64 69 64 61 74 65 20 73 6e 69 70 70 65  candidate snippe
2db0: 74 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  t..*/.static int
2dc0: 20 66 74 73 33 53 6e 69 70 70 65 74 4e 65 78 74   fts3SnippetNext
2dd0: 43 61 6e 64 69 64 61 74 65 28 53 6e 69 70 70 65  Candidate(Snippe
2de0: 74 49 74 65 72 20 2a 70 49 74 65 72 29 7b 0a 20  tIter *pIter){. 
2df0: 20 69 6e 74 20 69 3b 20 20 20 20 20 20 20 20 20   int i;         
2e00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2e10: 20 2f 2a 20 4c 6f 6f 70 20 63 6f 75 6e 74 65 72   /* Loop counter
2e20: 20 2a 2f 0a 0a 20 20 69 66 28 20 70 49 74 65 72   */..  if( pIter
2e30: 2d 3e 69 43 75 72 72 65 6e 74 3c 30 20 29 7b 0a  ->iCurrent<0 ){.
2e40: 20 20 20 20 2f 2a 20 54 68 65 20 53 6e 69 70 70      /* The Snipp
2e50: 65 74 49 74 65 72 20 6f 62 6a 65 63 74 20 68 61  etIter object ha
2e60: 73 20 6a 75 73 74 20 62 65 65 6e 20 69 6e 69 74  s just been init
2e70: 69 61 6c 69 7a 65 64 2e 20 54 68 65 20 66 69 72  ialized. The fir
2e80: 73 74 20 73 6e 69 70 70 65 74 0a 20 20 20 20 2a  st snippet.    *
2e90: 2a 20 63 61 6e 64 69 64 61 74 65 20 61 6c 77 61  * candidate alwa
2ea0: 79 73 20 73 74 61 72 74 73 20 61 74 20 6f 66 66  ys starts at off
2eb0: 73 65 74 20 30 20 28 65 76 65 6e 20 69 66 20 74  set 0 (even if t
2ec0: 68 69 73 20 63 61 6e 64 69 64 61 74 65 20 68 61  his candidate ha
2ed0: 73 20 61 0a 20 20 20 20 2a 2a 20 73 63 6f 72 65  s a.    ** score
2ee0: 20 6f 66 20 30 2e 30 29 2e 0a 20 20 20 20 2a 2f   of 0.0)..    */
2ef0: 0a 20 20 20 20 70 49 74 65 72 2d 3e 69 43 75 72  .    pIter->iCur
2f00: 72 65 6e 74 20 3d 20 30 3b 0a 0a 20 20 20 20 2f  rent = 0;..    /
2f10: 2a 20 41 64 76 61 6e 63 65 20 74 68 65 20 27 68  * Advance the 'h
2f20: 65 61 64 27 20 69 74 65 72 61 74 6f 72 20 6f 66  ead' iterator of
2f30: 20 65 61 63 68 20 70 68 72 61 73 65 20 74 6f 20   each phrase to 
2f40: 74 68 65 20 66 69 72 73 74 20 6f 66 66 73 65 74  the first offset
2f50: 20 74 68 61 74 0a 20 20 20 20 2a 2a 20 69 73 20   that.    ** is 
2f60: 67 72 65 61 74 65 72 20 74 68 61 6e 20 6f 72 20  greater than or 
2f70: 65 71 75 61 6c 20 74 6f 20 28 69 4e 65 78 74 2b  equal to (iNext+
2f80: 6e 53 6e 69 70 70 65 74 29 2e 0a 20 20 20 20 2a  nSnippet)..    *
2f90: 2f 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b 20 69  /.    for(i=0; i
2fa0: 3c 70 49 74 65 72 2d 3e 6e 50 68 72 61 73 65 3b  <pIter->nPhrase;
2fb0: 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 53 6e 69   i++){.      Sni
2fc0: 70 70 65 74 50 68 72 61 73 65 20 2a 70 50 68 72  ppetPhrase *pPhr
2fd0: 61 73 65 20 3d 20 26 70 49 74 65 72 2d 3e 61 50  ase = &pIter->aP
2fe0: 68 72 61 73 65 5b 69 5d 3b 0a 20 20 20 20 20 20  hrase[i];.      
2ff0: 66 74 73 33 53 6e 69 70 70 65 74 41 64 76 61 6e  fts3SnippetAdvan
3000: 63 65 28 26 70 50 68 72 61 73 65 2d 3e 70 48 65  ce(&pPhrase->pHe
3010: 61 64 2c 20 26 70 50 68 72 61 73 65 2d 3e 69 48  ad, &pPhrase->iH
3020: 65 61 64 2c 20 70 49 74 65 72 2d 3e 6e 53 6e 69  ead, pIter->nSni
3030: 70 70 65 74 29 3b 0a 20 20 20 20 7d 0a 20 20 7d  ppet);.    }.  }
3040: 65 6c 73 65 7b 0a 20 20 20 20 69 6e 74 20 69 53  else{.    int iS
3050: 74 61 72 74 3b 0a 20 20 20 20 69 6e 74 20 69 45  tart;.    int iE
3060: 6e 64 20 3d 20 30 78 37 46 46 46 46 46 46 46 3b  nd = 0x7FFFFFFF;
3070: 0a 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b 20 69  ..    for(i=0; i
3080: 3c 70 49 74 65 72 2d 3e 6e 50 68 72 61 73 65 3b  <pIter->nPhrase;
3090: 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 53 6e 69   i++){.      Sni
30a0: 70 70 65 74 50 68 72 61 73 65 20 2a 70 50 68 72  ppetPhrase *pPhr
30b0: 61 73 65 20 3d 20 26 70 49 74 65 72 2d 3e 61 50  ase = &pIter->aP
30c0: 68 72 61 73 65 5b 69 5d 3b 0a 20 20 20 20 20 20  hrase[i];.      
30d0: 69 66 28 20 70 50 68 72 61 73 65 2d 3e 70 48 65  if( pPhrase->pHe
30e0: 61 64 20 26 26 20 70 50 68 72 61 73 65 2d 3e 69  ad && pPhrase->i
30f0: 48 65 61 64 3c 69 45 6e 64 20 29 7b 0a 20 20 20  Head<iEnd ){.   
3100: 20 20 20 20 20 69 45 6e 64 20 3d 20 70 50 68 72       iEnd = pPhr
3110: 61 73 65 2d 3e 69 48 65 61 64 3b 0a 20 20 20 20  ase->iHead;.    
3120: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 69 66    }.    }.    if
3130: 28 20 69 45 6e 64 3d 3d 30 78 37 46 46 46 46 46  ( iEnd==0x7FFFFF
3140: 46 46 20 29 7b 0a 20 20 20 20 20 20 72 65 74 75  FF ){.      retu
3150: 72 6e 20 31 3b 0a 20 20 20 20 7d 0a 0a 20 20 20  rn 1;.    }..   
3160: 20 70 49 74 65 72 2d 3e 69 43 75 72 72 65 6e 74   pIter->iCurrent
3170: 20 3d 20 69 53 74 61 72 74 20 3d 20 69 45 6e 64   = iStart = iEnd
3180: 20 2d 20 70 49 74 65 72 2d 3e 6e 53 6e 69 70 70   - pIter->nSnipp
3190: 65 74 20 2b 20 31 3b 0a 20 20 20 20 66 6f 72 28  et + 1;.    for(
31a0: 69 3d 30 3b 20 69 3c 70 49 74 65 72 2d 3e 6e 50  i=0; i<pIter->nP
31b0: 68 72 61 73 65 3b 20 69 2b 2b 29 7b 0a 20 20 20  hrase; i++){.   
31c0: 20 20 20 53 6e 69 70 70 65 74 50 68 72 61 73 65     SnippetPhrase
31d0: 20 2a 70 50 68 72 61 73 65 20 3d 20 26 70 49 74   *pPhrase = &pIt
31e0: 65 72 2d 3e 61 50 68 72 61 73 65 5b 69 5d 3b 0a  er->aPhrase[i];.
31f0: 20 20 20 20 20 20 66 74 73 33 53 6e 69 70 70 65        fts3Snippe
3200: 74 41 64 76 61 6e 63 65 28 26 70 50 68 72 61 73  tAdvance(&pPhras
3210: 65 2d 3e 70 48 65 61 64 2c 20 26 70 50 68 72 61  e->pHead, &pPhra
3220: 73 65 2d 3e 69 48 65 61 64 2c 20 69 45 6e 64 2b  se->iHead, iEnd+
3230: 31 29 3b 0a 20 20 20 20 20 20 66 74 73 33 53 6e  1);.      fts3Sn
3240: 69 70 70 65 74 41 64 76 61 6e 63 65 28 26 70 50  ippetAdvance(&pP
3250: 68 72 61 73 65 2d 3e 70 54 61 69 6c 2c 20 26 70  hrase->pTail, &p
3260: 50 68 72 61 73 65 2d 3e 69 54 61 69 6c 2c 20 69  Phrase->iTail, i
3270: 53 74 61 72 74 29 3b 0a 20 20 20 20 7d 0a 20 20  Start);.    }.  
3280: 7d 0a 0a 20 20 72 65 74 75 72 6e 20 30 3b 0a 7d  }..  return 0;.}
3290: 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 72 69 65 76 65  ../*.** Retrieve
32a0: 20 69 6e 66 6f 72 6d 61 74 69 6f 6e 20 61 62 6f   information abo
32b0: 75 74 20 74 68 65 20 63 75 72 72 65 6e 74 20 63  ut the current c
32c0: 61 6e 64 69 64 61 74 65 20 73 6e 69 70 70 65 74  andidate snippet
32d0: 20 6f 66 20 73 6e 69 70 70 65 74 20 0a 2a 2a 20   of snippet .** 
32e0: 69 74 65 72 61 74 6f 72 20 70 49 74 65 72 2e 0a  iterator pIter..
32f0: 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 66  */.static void f
3300: 74 73 33 53 6e 69 70 70 65 74 44 65 74 61 69 6c  ts3SnippetDetail
3310: 73 28 0a 20 20 53 6e 69 70 70 65 74 49 74 65 72  s(.  SnippetIter
3320: 20 2a 70 49 74 65 72 2c 20 20 20 20 20 20 20 20   *pIter,        
3330: 20 20 20 20 20 2f 2a 20 53 6e 69 70 70 65 74 20       /* Snippet 
3340: 69 74 65 72 61 74 6f 72 20 2a 2f 0a 20 20 75 36  iterator */.  u6
3350: 34 20 6d 43 6f 76 65 72 65 64 2c 20 20 20 20 20  4 mCovered,     
3360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
3370: 20 42 69 74 6d 61 73 6b 20 6f 66 20 70 68 72 61   Bitmask of phra
3380: 73 65 73 20 61 6c 72 65 61 64 79 20 63 6f 76 65  ses already cove
3390: 72 65 64 20 2a 2f 0a 20 20 69 6e 74 20 2a 70 69  red */.  int *pi
33a0: 54 6f 6b 65 6e 2c 20 20 20 20 20 20 20 20 20 20  Token,          
33b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 55 54 3a           /* OUT:
33c0: 20 46 69 72 73 74 20 74 6f 6b 65 6e 20 6f 66 20   First token of 
33d0: 70 72 6f 70 6f 73 65 64 20 73 6e 69 70 70 65 74  proposed snippet
33e0: 20 2a 2f 0a 20 20 69 6e 74 20 2a 70 69 53 63 6f   */.  int *piSco
33f0: 72 65 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  re,             
3400: 20 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 22 53        /* OUT: "S
3410: 63 6f 72 65 22 20 66 6f 72 20 74 68 69 73 20 73  core" for this s
3420: 6e 69 70 70 65 74 20 2a 2f 0a 20 20 75 36 34 20  nippet */.  u64 
3430: 2a 70 6d 43 6f 76 65 72 2c 20 20 20 20 20 20 20  *pmCover,       
3440: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f              /* O
3450: 55 54 3a 20 42 69 74 6d 61 73 6b 20 6f 66 20 70  UT: Bitmask of p
3460: 68 72 61 73 65 73 20 63 6f 76 65 72 65 64 20 2a  hrases covered *
3470: 2f 0a 20 20 75 36 34 20 2a 70 6d 48 69 67 68 6c  /.  u64 *pmHighl
3480: 69 67 68 74 20 20 20 20 20 20 20 20 20 20 20 20  ight            
3490: 20 20 20 20 2f 2a 20 4f 55 54 3a 20 42 69 74 6d      /* OUT: Bitm
34a0: 61 73 6b 20 6f 66 20 74 65 72 6d 73 20 74 6f 20  ask of terms to 
34b0: 68 69 67 68 6c 69 67 68 74 20 2a 2f 0a 29 7b 0a  highlight */.){.
34c0: 20 20 69 6e 74 20 69 53 74 61 72 74 20 3d 20 70    int iStart = p
34d0: 49 74 65 72 2d 3e 69 43 75 72 72 65 6e 74 3b 20  Iter->iCurrent; 
34e0: 20 20 2f 2a 20 46 69 72 73 74 20 74 6f 6b 65 6e    /* First token
34f0: 20 6f 66 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20   of snippet */. 
3500: 20 69 6e 74 20 69 53 63 6f 72 65 20 3d 20 30 3b   int iScore = 0;
3510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3520: 20 2f 2a 20 53 63 6f 72 65 20 6f 66 20 74 68 69   /* Score of thi
3530: 73 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20 69  s snippet */.  i
3540: 6e 74 20 69 3b 20 20 20 20 20 20 20 20 20 20 20  nt i;           
3550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
3560: 2a 20 4c 6f 6f 70 20 63 6f 75 6e 74 65 72 20 2a  * Loop counter *
3570: 2f 0a 20 20 75 36 34 20 6d 43 6f 76 65 72 20 3d  /.  u64 mCover =
3580: 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   0;             
3590: 20 20 20 20 2f 2a 20 4d 61 73 6b 20 6f 66 20 70      /* Mask of p
35a0: 68 72 61 73 65 73 20 63 6f 76 65 72 65 64 20 62  hrases covered b
35b0: 79 20 74 68 69 73 20 73 6e 69 70 70 65 74 20 2a  y this snippet *
35c0: 2f 0a 20 20 75 36 34 20 6d 48 69 67 68 6c 69 67  /.  u64 mHighlig
35d0: 68 74 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  ht = 0;         
35e0: 20 20 20 20 2f 2a 20 4d 61 73 6b 20 6f 66 20 74      /* Mask of t
35f0: 6f 6b 65 6e 73 20 74 6f 20 68 69 67 68 6c 69 67  okens to highlig
3600: 68 74 20 69 6e 20 73 6e 69 70 70 65 74 20 2a 2f  ht in snippet */
3610: 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70  ..  for(i=0; i<p
3620: 49 74 65 72 2d 3e 6e 50 68 72 61 73 65 3b 20 69  Iter->nPhrase; i
3630: 2b 2b 29 7b 0a 20 20 20 20 53 6e 69 70 70 65 74  ++){.    Snippet
3640: 50 68 72 61 73 65 20 2a 70 50 68 72 61 73 65 20  Phrase *pPhrase 
3650: 3d 20 26 70 49 74 65 72 2d 3e 61 50 68 72 61 73  = &pIter->aPhras
3660: 65 5b 69 5d 3b 0a 20 20 20 20 69 66 28 20 70 50  e[i];.    if( pP
3670: 68 72 61 73 65 2d 3e 70 54 61 69 6c 20 29 7b 0a  hrase->pTail ){.
3680: 20 20 20 20 20 20 63 68 61 72 20 2a 70 43 73 72        char *pCsr
3690: 20 3d 20 70 50 68 72 61 73 65 2d 3e 70 54 61 69   = pPhrase->pTai
36a0: 6c 3b 0a 20 20 20 20 20 20 69 6e 74 20 69 43 73  l;.      int iCs
36b0: 72 20 3d 20 70 50 68 72 61 73 65 2d 3e 69 54 61  r = pPhrase->iTa
36c0: 69 6c 3b 0a 0a 20 20 20 20 20 20 77 68 69 6c 65  il;..      while
36d0: 28 20 69 43 73 72 3c 28 69 53 74 61 72 74 2b 70  ( iCsr<(iStart+p
36e0: 49 74 65 72 2d 3e 6e 53 6e 69 70 70 65 74 29 20  Iter->nSnippet) 
36f0: 29 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20 6a  ){.        int j
3700: 3b 0a 20 20 20 20 20 20 20 20 75 36 34 20 6d 50  ;.        u64 mP
3710: 68 72 61 73 65 20 3d 20 28 75 36 34 29 31 20 3c  hrase = (u64)1 <
3720: 3c 20 69 3b 0a 20 20 20 20 20 20 20 20 75 36 34  < i;.        u64
3730: 20 6d 50 6f 73 20 3d 20 28 75 36 34 29 31 20 3c   mPos = (u64)1 <
3740: 3c 20 28 69 43 73 72 20 2d 20 69 53 74 61 72 74  < (iCsr - iStart
3750: 29 3b 0a 20 20 20 20 20 20 20 20 61 73 73 65 72  );.        asser
3760: 74 28 20 69 43 73 72 3e 3d 69 53 74 61 72 74 20  t( iCsr>=iStart 
3770: 26 26 20 28 69 43 73 72 20 2d 20 69 53 74 61 72  && (iCsr - iStar
3780: 74 29 3c 3d 36 34 20 29 3b 0a 20 20 20 20 20 20  t)<=64 );.      
3790: 20 20 61 73 73 65 72 74 28 20 69 3e 3d 30 20 26    assert( i>=0 &
37a0: 26 20 69 3c 3d 36 34 20 29 3b 0a 20 20 20 20 20  & i<=64 );.     
37b0: 20 20 20 69 66 28 20 28 6d 43 6f 76 65 72 7c 6d     if( (mCover|m
37c0: 43 6f 76 65 72 65 64 29 26 6d 50 68 72 61 73 65  Covered)&mPhrase
37d0: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 69 53   ){.          iS
37e0: 63 6f 72 65 2b 2b 3b 0a 20 20 20 20 20 20 20 20  core++;.        
37f0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20  }else{.         
3800: 20 69 53 63 6f 72 65 20 2b 3d 20 31 30 30 30 3b   iScore += 1000;
3810: 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20  .        }.     
3820: 20 20 20 6d 43 6f 76 65 72 20 7c 3d 20 6d 50 68     mCover |= mPh
3830: 72 61 73 65 3b 0a 0a 20 20 20 20 20 20 20 20 66  rase;..        f
3840: 6f 72 28 6a 3d 30 3b 20 6a 3c 70 50 68 72 61 73  or(j=0; j<pPhras
3850: 65 2d 3e 6e 54 6f 6b 65 6e 3b 20 6a 2b 2b 29 7b  e->nToken; j++){
3860: 0a 20 20 20 20 20 20 20 20 20 20 6d 48 69 67 68  .          mHigh
3870: 6c 69 67 68 74 20 7c 3d 20 28 6d 50 6f 73 3e 3e  light |= (mPos>>
3880: 6a 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 0a 20  j);.        }.. 
3890: 20 20 20 20 20 20 20 69 66 28 20 30 3d 3d 28 2a         if( 0==(*
38a0: 70 43 73 72 20 26 20 30 78 30 46 45 29 20 29 20  pCsr & 0x0FE) ) 
38b0: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 66  break;.        f
38c0: 74 73 33 47 65 74 44 65 6c 74 61 50 6f 73 69 74  ts3GetDeltaPosit
38d0: 69 6f 6e 28 26 70 43 73 72 2c 20 26 69 43 73 72  ion(&pCsr, &iCsr
38e0: 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d  );.      }.    }
38f0: 0a 20 20 7d 0a 0a 20 20 2f 2a 20 53 65 74 20 74  .  }..  /* Set t
3900: 68 65 20 6f 75 74 70 75 74 20 76 61 72 69 61 62  he output variab
3910: 6c 65 73 20 62 65 66 6f 72 65 20 72 65 74 75 72  les before retur
3920: 6e 69 6e 67 2e 20 2a 2f 0a 20 20 2a 70 69 54 6f  ning. */.  *piTo
3930: 6b 65 6e 20 3d 20 69 53 74 61 72 74 3b 0a 20 20  ken = iStart;.  
3940: 2a 70 69 53 63 6f 72 65 20 3d 20 69 53 63 6f 72  *piScore = iScor
3950: 65 3b 0a 20 20 2a 70 6d 43 6f 76 65 72 20 3d 20  e;.  *pmCover = 
3960: 6d 43 6f 76 65 72 3b 0a 20 20 2a 70 6d 48 69 67  mCover;.  *pmHig
3970: 68 6c 69 67 68 74 20 3d 20 6d 48 69 67 68 6c 69  hlight = mHighli
3980: 67 68 74 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68  ght;.}../*.** Th
3990: 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 61  is function is a
39a0: 6e 20 66 74 73 33 45 78 70 72 49 74 65 72 61 74  n fts3ExprIterat
39b0: 65 28 29 20 63 61 6c 6c 62 61 63 6b 20 75 73 65  e() callback use
39c0: 64 20 62 79 20 66 74 73 33 42 65 73 74 53 6e 69  d by fts3BestSni
39d0: 70 70 65 74 28 29 2e 0a 2a 2a 20 45 61 63 68 20  ppet()..** Each 
39e0: 69 6e 76 6f 63 61 74 69 6f 6e 20 70 6f 70 75 6c  invocation popul
39f0: 61 74 65 73 20 61 6e 20 65 6c 65 6d 65 6e 74 20  ates an element 
3a00: 6f 66 20 74 68 65 20 53 6e 69 70 70 65 74 49 74  of the SnippetIt
3a10: 65 72 2e 61 50 68 72 61 73 65 5b 5d 20 61 72 72  er.aPhrase[] arr
3a20: 61 79 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ay..*/.static in
3a30: 74 20 66 74 73 33 53 6e 69 70 70 65 74 46 69 6e  t fts3SnippetFin
3a40: 64 50 6f 73 69 74 69 6f 6e 73 28 46 74 73 33 45  dPositions(Fts3E
3a50: 78 70 72 20 2a 70 45 78 70 72 2c 20 69 6e 74 20  xpr *pExpr, int 
3a60: 69 50 68 72 61 73 65 2c 20 76 6f 69 64 20 2a 63  iPhrase, void *c
3a70: 74 78 29 7b 0a 20 20 53 6e 69 70 70 65 74 49 74  tx){.  SnippetIt
3a80: 65 72 20 2a 70 20 3d 20 28 53 6e 69 70 70 65 74  er *p = (Snippet
3a90: 49 74 65 72 20 2a 29 63 74 78 3b 0a 20 20 53 6e  Iter *)ctx;.  Sn
3aa0: 69 70 70 65 74 50 68 72 61 73 65 20 2a 70 50 68  ippetPhrase *pPh
3ab0: 72 61 73 65 20 3d 20 26 70 2d 3e 61 50 68 72 61  rase = &p->aPhra
3ac0: 73 65 5b 69 50 68 72 61 73 65 5d 3b 0a 20 20 63  se[iPhrase];.  c
3ad0: 68 61 72 20 2a 70 43 73 72 3b 0a 20 20 69 6e 74  har *pCsr;.  int
3ae0: 20 72 63 3b 0a 0a 20 20 70 50 68 72 61 73 65 2d   rc;..  pPhrase-
3af0: 3e 6e 54 6f 6b 65 6e 20 3d 20 70 45 78 70 72 2d  >nToken = pExpr-
3b00: 3e 70 50 68 72 61 73 65 2d 3e 6e 54 6f 6b 65 6e  >pPhrase->nToken
3b10: 3b 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33  ;.  rc = sqlite3
3b20: 46 74 73 33 45 76 61 6c 50 68 72 61 73 65 50 6f  Fts3EvalPhrasePo
3b30: 73 6c 69 73 74 28 70 2d 3e 70 43 73 72 2c 20 70  slist(p->pCsr, p
3b40: 45 78 70 72 2c 20 70 2d 3e 69 43 6f 6c 2c 20 26  Expr, p->iCol, &
3b50: 70 43 73 72 29 3b 0a 20 20 61 73 73 65 72 74 28  pCsr);.  assert(
3b60: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 7c   rc==SQLITE_OK |
3b70: 7c 20 70 43 73 72 3d 3d 30 20 29 3b 0a 20 20 69  | pCsr==0 );.  i
3b80: 66 28 20 70 43 73 72 20 29 7b 0a 20 20 20 20 69  f( pCsr ){.    i
3b90: 6e 74 20 69 46 69 72 73 74 20 3d 20 30 3b 0a 20  nt iFirst = 0;. 
3ba0: 20 20 20 70 50 68 72 61 73 65 2d 3e 70 4c 69 73     pPhrase->pLis
3bb0: 74 20 3d 20 70 43 73 72 3b 0a 20 20 20 20 66 74  t = pCsr;.    ft
3bc0: 73 33 47 65 74 44 65 6c 74 61 50 6f 73 69 74 69  s3GetDeltaPositi
3bd0: 6f 6e 28 26 70 43 73 72 2c 20 26 69 46 69 72 73  on(&pCsr, &iFirs
3be0: 74 29 3b 0a 20 20 20 20 69 66 28 20 69 46 69 72  t);.    if( iFir
3bf0: 73 74 3c 30 20 29 7b 0a 20 20 20 20 20 20 72 63  st<0 ){.      rc
3c00: 20 3d 20 46 54 53 5f 43 4f 52 52 55 50 54 5f 56   = FTS_CORRUPT_V
3c10: 54 41 42 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a  TAB;.    }else{.
3c20: 20 20 20 20 20 20 70 50 68 72 61 73 65 2d 3e 70        pPhrase->p
3c30: 48 65 61 64 20 3d 20 70 43 73 72 3b 0a 20 20 20  Head = pCsr;.   
3c40: 20 20 20 70 50 68 72 61 73 65 2d 3e 70 54 61 69     pPhrase->pTai
3c50: 6c 20 3d 20 70 43 73 72 3b 0a 20 20 20 20 20 20  l = pCsr;.      
3c60: 70 50 68 72 61 73 65 2d 3e 69 48 65 61 64 20 3d  pPhrase->iHead =
3c70: 20 69 46 69 72 73 74 3b 0a 20 20 20 20 20 20 70   iFirst;.      p
3c80: 50 68 72 61 73 65 2d 3e 69 54 61 69 6c 20 3d 20  Phrase->iTail = 
3c90: 69 46 69 72 73 74 3b 0a 20 20 20 20 7d 0a 20 20  iFirst;.    }.  
3ca0: 7d 65 6c 73 65 7b 0a 20 20 20 20 61 73 73 65 72  }else{.    asser
3cb0: 74 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  t( rc!=SQLITE_OK
3cc0: 20 7c 7c 20 28 0a 20 20 20 20 20 20 20 70 50 68   || (.       pPh
3cd0: 72 61 73 65 2d 3e 70 4c 69 73 74 3d 3d 30 20 26  rase->pList==0 &
3ce0: 26 20 70 50 68 72 61 73 65 2d 3e 70 48 65 61 64  & pPhrase->pHead
3cf0: 3d 3d 30 20 26 26 20 70 50 68 72 61 73 65 2d 3e  ==0 && pPhrase->
3d00: 70 54 61 69 6c 3d 3d 30 20 0a 20 20 20 20 29 29  pTail==0 .    ))
3d10: 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20  ;.  }..  return 
3d20: 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53 65 6c  rc;.}../*.** Sel
3d30: 65 63 74 20 74 68 65 20 66 72 61 67 6d 65 6e 74  ect the fragment
3d40: 20 6f 66 20 74 65 78 74 20 63 6f 6e 73 69 73 74   of text consist
3d50: 69 6e 67 20 6f 66 20 6e 46 72 61 67 6d 65 6e 74  ing of nFragment
3d60: 20 63 6f 6e 74 69 67 75 6f 75 73 20 74 6f 6b 65   contiguous toke
3d70: 6e 73 20 0a 2a 2a 20 66 72 6f 6d 20 63 6f 6c 75  ns .** from colu
3d80: 6d 6e 20 69 43 6f 6c 20 74 68 61 74 20 72 65 70  mn iCol that rep
3d90: 72 65 73 65 6e 74 20 74 68 65 20 22 62 65 73 74  resent the "best
3da0: 22 20 73 6e 69 70 70 65 74 2e 20 54 68 65 20 62  " snippet. The b
3db0: 65 73 74 20 73 6e 69 70 70 65 74 0a 2a 2a 20 69  est snippet.** i
3dc0: 73 20 74 68 65 20 73 6e 69 70 70 65 74 20 77 69  s the snippet wi
3dd0: 74 68 20 74 68 65 20 68 69 67 68 65 73 74 20 73  th the highest s
3de0: 63 6f 72 65 2c 20 77 68 65 72 65 20 73 63 6f 72  core, where scor
3df0: 65 73 20 61 72 65 20 63 61 6c 63 75 6c 61 74 65  es are calculate
3e00: 64 0a 2a 2a 20 62 79 20 61 64 64 69 6e 67 3a 0a  d.** by adding:.
3e10: 2a 2a 0a 2a 2a 20 20 20 28 61 29 20 2b 31 20 70  **.**   (a) +1 p
3e20: 6f 69 6e 74 20 66 6f 72 20 65 61 63 68 20 6f 63  oint for each oc
3e30: 63 75 72 72 65 6e 63 65 20 6f 66 20 61 20 6d 61  currence of a ma
3e40: 74 63 68 61 62 6c 65 20 70 68 72 61 73 65 20 69  tchable phrase i
3e50: 6e 20 74 68 65 20 73 6e 69 70 70 65 74 2e 0a 2a  n the snippet..*
3e60: 2a 0a 2a 2a 20 20 20 28 62 29 20 2b 31 30 30 30  *.**   (b) +1000
3e70: 20 70 6f 69 6e 74 73 20 66 6f 72 20 74 68 65 20   points for the 
3e80: 66 69 72 73 74 20 6f 63 63 75 72 72 65 6e 63 65  first occurrence
3e90: 20 6f 66 20 65 61 63 68 20 6d 61 74 63 68 61 62   of each matchab
3ea0: 6c 65 20 70 68 72 61 73 65 20 69 6e 20 0a 2a 2a  le phrase in .**
3eb0: 20 20 20 20 20 20 20 74 68 65 20 73 6e 69 70 70         the snipp
3ec0: 65 74 20 66 6f 72 20 77 68 69 63 68 20 74 68 65  et for which the
3ed0: 20 63 6f 72 72 65 73 70 6f 6e 64 69 6e 67 20 6d   corresponding m
3ee0: 43 6f 76 65 72 65 64 20 62 69 74 20 69 73 20 6e  Covered bit is n
3ef0: 6f 74 20 73 65 74 2e 0a 2a 2a 0a 2a 2a 20 54 68  ot set..**.** Th
3f00: 65 20 73 65 6c 65 63 74 65 64 20 73 6e 69 70 70  e selected snipp
3f10: 65 74 20 70 61 72 61 6d 65 74 65 72 73 20 61 72  et parameters ar
3f20: 65 20 73 74 6f 72 65 64 20 69 6e 20 73 74 72 75  e stored in stru
3f30: 63 74 75 72 65 20 2a 70 46 72 61 67 6d 65 6e 74  cture *pFragment
3f40: 20 62 65 66 6f 72 65 0a 2a 2a 20 72 65 74 75 72   before.** retur
3f50: 6e 69 6e 67 2e 20 54 68 65 20 73 63 6f 72 65 20  ning. The score 
3f60: 6f 66 20 74 68 65 20 73 65 6c 65 63 74 65 64 20  of the selected 
3f70: 73 6e 69 70 70 65 74 20 69 73 20 73 74 6f 72 65  snippet is store
3f80: 64 20 69 6e 20 2a 70 69 53 63 6f 72 65 0a 2a 2a  d in *piScore.**
3f90: 20 62 65 66 6f 72 65 20 72 65 74 75 72 6e 69 6e   before returnin
3fa0: 67 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  g..*/.static int
3fb0: 20 66 74 73 33 42 65 73 74 53 6e 69 70 70 65 74   fts3BestSnippet
3fc0: 28 0a 20 20 69 6e 74 20 6e 53 6e 69 70 70 65 74  (.  int nSnippet
3fd0: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
3fe0: 20 20 20 20 2f 2a 20 44 65 73 69 72 65 64 20 73      /* Desired s
3ff0: 6e 69 70 70 65 74 20 6c 65 6e 67 74 68 20 2a 2f  nippet length */
4000: 0a 20 20 46 74 73 33 43 75 72 73 6f 72 20 2a 70  .  Fts3Cursor *p
4010: 43 73 72 2c 20 20 20 20 20 20 20 20 20 20 20 20  Csr,            
4020: 20 20 20 2f 2a 20 43 75 72 73 6f 72 20 74 6f 20     /* Cursor to 
4030: 63 72 65 61 74 65 20 73 6e 69 70 70 65 74 20 66  create snippet f
4040: 6f 72 20 2a 2f 0a 20 20 69 6e 74 20 69 43 6f 6c  or */.  int iCol
4050: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
4060: 20 20 20 20 20 20 20 20 2f 2a 20 49 6e 64 65 78          /* Index
4070: 20 6f 66 20 63 6f 6c 75 6d 6e 20 74 6f 20 63 72   of column to cr
4080: 65 61 74 65 20 73 6e 69 70 70 65 74 20 66 72 6f  eate snippet fro
4090: 6d 20 2a 2f 0a 20 20 75 36 34 20 6d 43 6f 76 65  m */.  u64 mCove
40a0: 72 65 64 2c 20 20 20 20 20 20 20 20 20 20 20 20  red,            
40b0: 20 20 20 20 20 20 20 2f 2a 20 4d 61 73 6b 20 6f         /* Mask o
40c0: 66 20 70 68 72 61 73 65 73 20 61 6c 72 65 61 64  f phrases alread
40d0: 79 20 63 6f 76 65 72 65 64 20 2a 2f 0a 20 20 75  y covered */.  u
40e0: 36 34 20 2a 70 6d 53 65 65 6e 2c 20 20 20 20 20  64 *pmSeen,     
40f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
4100: 2a 20 49 4e 2f 4f 55 54 3a 20 4d 61 73 6b 20 6f  * IN/OUT: Mask o
4110: 66 20 70 68 72 61 73 65 73 20 73 65 65 6e 20 2a  f phrases seen *
4120: 2f 0a 20 20 53 6e 69 70 70 65 74 46 72 61 67 6d  /.  SnippetFragm
4130: 65 6e 74 20 2a 70 46 72 61 67 6d 65 6e 74 2c 20  ent *pFragment, 
4140: 20 20 20 20 2f 2a 20 4f 55 54 3a 20 42 65 73 74      /* OUT: Best
4150: 20 73 6e 69 70 70 65 74 20 66 6f 75 6e 64 20 2a   snippet found *
4160: 2f 0a 20 20 69 6e 74 20 2a 70 69 53 63 6f 72 65  /.  int *piScore
4170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4180: 20 20 20 20 2f 2a 20 4f 55 54 3a 20 53 63 6f 72      /* OUT: Scor
4190: 65 20 6f 66 20 73 6e 69 70 70 65 74 20 70 46 72  e of snippet pFr
41a0: 61 67 6d 65 6e 74 20 2a 2f 0a 29 7b 0a 20 20 69  agment */.){.  i
41b0: 6e 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20  nt rc;          
41c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
41d0: 2a 20 52 65 74 75 72 6e 20 43 6f 64 65 20 2a 2f  * Return Code */
41e0: 0a 20 20 69 6e 74 20 6e 4c 69 73 74 3b 20 20 20  .  int nList;   
41f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4200: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
4210: 70 68 72 61 73 65 73 20 69 6e 20 65 78 70 72 65  phrases in expre
4220: 73 73 69 6f 6e 20 2a 2f 0a 20 20 53 6e 69 70 70  ssion */.  Snipp
4230: 65 74 49 74 65 72 20 73 49 74 65 72 3b 20 20 20  etIter sIter;   
4240: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49 74             /* It
4250: 65 72 61 74 65 73 20 74 68 72 6f 75 67 68 20 73  erates through s
4260: 6e 69 70 70 65 74 20 63 61 6e 64 69 64 61 74 65  nippet candidate
4270: 73 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 69  s */.  sqlite3_i
4280: 6e 74 36 34 20 6e 42 79 74 65 3b 20 20 20 20 20  nt64 nByte;     
4290: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
42a0: 20 6f 66 20 62 79 74 65 73 20 6f 66 20 73 70 61   of bytes of spa
42b0: 63 65 20 74 6f 20 61 6c 6c 6f 63 61 74 65 20 2a  ce to allocate *
42c0: 2f 0a 20 20 69 6e 74 20 69 42 65 73 74 53 63 6f  /.  int iBestSco
42d0: 72 65 20 3d 20 2d 31 3b 20 20 20 20 20 20 20 20  re = -1;        
42e0: 20 20 20 20 2f 2a 20 42 65 73 74 20 73 6e 69 70      /* Best snip
42f0: 70 65 74 20 73 63 6f 72 65 20 66 6f 75 6e 64 20  pet score found 
4300: 73 6f 20 66 61 72 20 2a 2f 0a 20 20 69 6e 74 20  so far */.  int 
4310: 69 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  i;              
4320: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c              /* L
4330: 6f 6f 70 20 63 6f 75 6e 74 65 72 20 2a 2f 0a 0a  oop counter */..
4340: 20 20 6d 65 6d 73 65 74 28 26 73 49 74 65 72 2c    memset(&sIter,
4350: 20 30 2c 20 73 69 7a 65 6f 66 28 73 49 74 65 72   0, sizeof(sIter
4360: 29 29 3b 0a 0a 20 20 2f 2a 20 49 74 65 72 61 74  ));..  /* Iterat
4370: 65 20 74 68 72 6f 75 67 68 20 74 68 65 20 70 68  e through the ph
4380: 72 61 73 65 73 20 69 6e 20 74 68 65 20 65 78 70  rases in the exp
4390: 72 65 73 73 69 6f 6e 20 74 6f 20 63 6f 75 6e 74  ression to count
43a0: 20 74 68 65 6d 2e 20 54 68 65 20 73 61 6d 65 0a   them. The same.
43b0: 20 20 2a 2a 20 63 61 6c 6c 62 61 63 6b 20 6d 61    ** callback ma
43c0: 6b 65 73 20 73 75 72 65 20 74 68 65 20 64 6f 63  kes sure the doc
43d0: 6c 69 73 74 73 20 61 72 65 20 6c 6f 61 64 65 64  lists are loaded
43e0: 20 66 6f 72 20 65 61 63 68 20 70 68 72 61 73 65   for each phrase
43f0: 2e 0a 20 20 2a 2f 0a 20 20 72 63 20 3d 20 66 74  ..  */.  rc = ft
4400: 73 33 45 78 70 72 4c 6f 61 64 44 6f 63 6c 69 73  s3ExprLoadDoclis
4410: 74 73 28 70 43 73 72 2c 20 26 6e 4c 69 73 74 2c  ts(pCsr, &nList,
4420: 20 30 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 53   0);.  if( rc!=S
4430: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
4440: 72 65 74 75 72 6e 20 72 63 3b 0a 20 20 7d 0a 0a  return rc;.  }..
4450: 20 20 2f 2a 20 4e 6f 77 20 74 68 61 74 20 69 74    /* Now that it
4460: 20 69 73 20 6b 6e 6f 77 6e 20 68 6f 77 20 6d 61   is known how ma
4470: 6e 79 20 70 68 72 61 73 65 73 20 74 68 65 72 65  ny phrases there
4480: 20 61 72 65 2c 20 61 6c 6c 6f 63 61 74 65 20 61   are, allocate a
4490: 6e 64 20 7a 65 72 6f 0a 20 20 2a 2a 20 74 68 65  nd zero.  ** the
44a0: 20 72 65 71 75 69 72 65 64 20 73 70 61 63 65 20   required space 
44b0: 75 73 69 6e 67 20 6d 61 6c 6c 6f 63 28 29 2e 0a  using malloc()..
44c0: 20 20 2a 2f 0a 20 20 6e 42 79 74 65 20 3d 20 73    */.  nByte = s
44d0: 69 7a 65 6f 66 28 53 6e 69 70 70 65 74 50 68 72  izeof(SnippetPhr
44e0: 61 73 65 29 20 2a 20 6e 4c 69 73 74 3b 0a 20 20  ase) * nList;.  
44f0: 73 49 74 65 72 2e 61 50 68 72 61 73 65 20 3d 20  sIter.aPhrase = 
4500: 28 53 6e 69 70 70 65 74 50 68 72 61 73 65 20 2a  (SnippetPhrase *
4510: 29 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 36  )sqlite3_malloc6
4520: 34 28 6e 42 79 74 65 29 3b 0a 20 20 69 66 28 20  4(nByte);.  if( 
4530: 21 73 49 74 65 72 2e 61 50 68 72 61 73 65 20 29  !sIter.aPhrase )
4540: 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c  {.    return SQL
4550: 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 7d 0a 20  ITE_NOMEM;.  }. 
4560: 20 6d 65 6d 73 65 74 28 73 49 74 65 72 2e 61 50   memset(sIter.aP
4570: 68 72 61 73 65 2c 20 30 2c 20 6e 42 79 74 65 29  hrase, 0, nByte)
4580: 3b 0a 0a 20 20 2f 2a 20 49 6e 69 74 69 61 6c 69  ;..  /* Initiali
4590: 7a 65 20 74 68 65 20 63 6f 6e 74 65 6e 74 73 20  ze the contents 
45a0: 6f 66 20 74 68 65 20 53 6e 69 70 70 65 74 49 74  of the SnippetIt
45b0: 65 72 20 6f 62 6a 65 63 74 2e 20 54 68 65 6e 20  er object. Then 
45c0: 69 74 65 72 61 74 65 20 74 68 72 6f 75 67 68 0a  iterate through.
45d0: 20 20 2a 2a 20 74 68 65 20 73 65 74 20 6f 66 20    ** the set of 
45e0: 70 68 72 61 73 65 73 20 69 6e 20 74 68 65 20 65  phrases in the e
45f0: 78 70 72 65 73 73 69 6f 6e 20 74 6f 20 70 6f 70  xpression to pop
4600: 75 6c 61 74 65 20 74 68 65 20 61 50 68 72 61 73  ulate the aPhras
4610: 65 5b 5d 20 61 72 72 61 79 2e 0a 20 20 2a 2f 0a  e[] array..  */.
4620: 20 20 73 49 74 65 72 2e 70 43 73 72 20 3d 20 70    sIter.pCsr = p
4630: 43 73 72 3b 0a 20 20 73 49 74 65 72 2e 69 43 6f  Csr;.  sIter.iCo
4640: 6c 20 3d 20 69 43 6f 6c 3b 0a 20 20 73 49 74 65  l = iCol;.  sIte
4650: 72 2e 6e 53 6e 69 70 70 65 74 20 3d 20 6e 53 6e  r.nSnippet = nSn
4660: 69 70 70 65 74 3b 0a 20 20 73 49 74 65 72 2e 6e  ippet;.  sIter.n
4670: 50 68 72 61 73 65 20 3d 20 6e 4c 69 73 74 3b 0a  Phrase = nList;.
4680: 20 20 73 49 74 65 72 2e 69 43 75 72 72 65 6e 74    sIter.iCurrent
4690: 20 3d 20 2d 31 3b 0a 20 20 72 63 20 3d 20 66 74   = -1;.  rc = ft
46a0: 73 33 45 78 70 72 49 74 65 72 61 74 65 28 70 43  s3ExprIterate(pC
46b0: 73 72 2d 3e 70 45 78 70 72 2c 20 66 74 73 33 53  sr->pExpr, fts3S
46c0: 6e 69 70 70 65 74 46 69 6e 64 50 6f 73 69 74 69  nippetFindPositi
46d0: 6f 6e 73 2c 20 28 76 6f 69 64 2a 29 26 73 49 74  ons, (void*)&sIt
46e0: 65 72 29 3b 0a 20 20 69 66 28 20 72 63 3d 3d 53  er);.  if( rc==S
46f0: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 0a 20 20 20  QLITE_OK ){..   
4700: 20 2f 2a 20 53 65 74 20 74 68 65 20 2a 70 6d 53   /* Set the *pmS
4710: 65 65 6e 20 6f 75 74 70 75 74 20 76 61 72 69 61  een output varia
4720: 62 6c 65 2e 20 2a 2f 0a 20 20 20 20 66 6f 72 28  ble. */.    for(
4730: 69 3d 30 3b 20 69 3c 6e 4c 69 73 74 3b 20 69 2b  i=0; i<nList; i+
4740: 2b 29 7b 0a 20 20 20 20 20 20 69 66 28 20 73 49  +){.      if( sI
4750: 74 65 72 2e 61 50 68 72 61 73 65 5b 69 5d 2e 70  ter.aPhrase[i].p
4760: 48 65 61 64 20 29 7b 0a 20 20 20 20 20 20 20 20  Head ){.        
4770: 2a 70 6d 53 65 65 6e 20 7c 3d 20 28 75 36 34 29  *pmSeen |= (u64)
4780: 31 20 3c 3c 20 69 3b 0a 20 20 20 20 20 20 7d 0a  1 << i;.      }.
4790: 20 20 20 20 7d 0a 0a 20 20 20 20 2f 2a 20 4c 6f      }..    /* Lo
47a0: 6f 70 20 74 68 72 6f 75 67 68 20 61 6c 6c 20 63  op through all c
47b0: 61 6e 64 69 64 61 74 65 20 73 6e 69 70 70 65 74  andidate snippet
47c0: 73 2e 20 53 74 6f 72 65 20 74 68 65 20 62 65 73  s. Store the bes
47d0: 74 20 73 6e 69 70 70 65 74 20 69 6e 20 0a 20 20  t snippet in .  
47e0: 20 20 20 2a 2a 20 2a 70 46 72 61 67 6d 65 6e 74     ** *pFragment
47f0: 2e 20 53 74 6f 72 65 20 69 74 73 20 61 73 73 6f  . Store its asso
4800: 63 69 61 74 65 64 20 27 73 63 6f 72 65 27 20 69  ciated 'score' i
4810: 6e 20 69 42 65 73 74 53 63 6f 72 65 2e 0a 20 20  n iBestScore..  
4820: 20 20 20 2a 2f 0a 20 20 20 20 70 46 72 61 67 6d     */.    pFragm
4830: 65 6e 74 2d 3e 69 43 6f 6c 20 3d 20 69 43 6f 6c  ent->iCol = iCol
4840: 3b 0a 20 20 20 20 77 68 69 6c 65 28 20 21 66 74  ;.    while( !ft
4850: 73 33 53 6e 69 70 70 65 74 4e 65 78 74 43 61 6e  s3SnippetNextCan
4860: 64 69 64 61 74 65 28 26 73 49 74 65 72 29 20 29  didate(&sIter) )
4870: 7b 0a 20 20 20 20 20 20 69 6e 74 20 69 50 6f 73  {.      int iPos
4880: 3b 0a 20 20 20 20 20 20 69 6e 74 20 69 53 63 6f  ;.      int iSco
4890: 72 65 3b 0a 20 20 20 20 20 20 75 36 34 20 6d 43  re;.      u64 mC
48a0: 6f 76 65 72 3b 0a 20 20 20 20 20 20 75 36 34 20  over;.      u64 
48b0: 6d 48 69 67 68 6c 69 74 65 3b 0a 20 20 20 20 20  mHighlite;.     
48c0: 20 66 74 73 33 53 6e 69 70 70 65 74 44 65 74 61   fts3SnippetDeta
48d0: 69 6c 73 28 26 73 49 74 65 72 2c 20 6d 43 6f 76  ils(&sIter, mCov
48e0: 65 72 65 64 2c 20 26 69 50 6f 73 2c 20 26 69 53  ered, &iPos, &iS
48f0: 63 6f 72 65 2c 20 26 6d 43 6f 76 65 72 2c 26 6d  core, &mCover,&m
4900: 48 69 67 68 6c 69 74 65 29 3b 0a 20 20 20 20 20  Highlite);.     
4910: 20 61 73 73 65 72 74 28 20 69 53 63 6f 72 65 3e   assert( iScore>
4920: 3d 30 20 29 3b 0a 20 20 20 20 20 20 69 66 28 20  =0 );.      if( 
4930: 69 53 63 6f 72 65 3e 69 42 65 73 74 53 63 6f 72  iScore>iBestScor
4940: 65 20 29 7b 0a 20 20 20 20 20 20 20 20 70 46 72  e ){.        pFr
4950: 61 67 6d 65 6e 74 2d 3e 69 50 6f 73 20 3d 20 69  agment->iPos = i
4960: 50 6f 73 3b 0a 20 20 20 20 20 20 20 20 70 46 72  Pos;.        pFr
4970: 61 67 6d 65 6e 74 2d 3e 68 6c 6d 61 73 6b 20 3d  agment->hlmask =
4980: 20 6d 48 69 67 68 6c 69 74 65 3b 0a 20 20 20 20   mHighlite;.    
4990: 20 20 20 20 70 46 72 61 67 6d 65 6e 74 2d 3e 63      pFragment->c
49a0: 6f 76 65 72 65 64 20 3d 20 6d 43 6f 76 65 72 3b  overed = mCover;
49b0: 0a 20 20 20 20 20 20 20 20 69 42 65 73 74 53 63  .        iBestSc
49c0: 6f 72 65 20 3d 20 69 53 63 6f 72 65 3b 0a 20 20  ore = iScore;.  
49d0: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20 20      }.    }..   
49e0: 20 2a 70 69 53 63 6f 72 65 20 3d 20 69 42 65 73   *piScore = iBes
49f0: 74 53 63 6f 72 65 3b 0a 20 20 7d 0a 20 20 73 71  tScore;.  }.  sq
4a00: 6c 69 74 65 33 5f 66 72 65 65 28 73 49 74 65 72  lite3_free(sIter
4a10: 2e 61 50 68 72 61 73 65 29 3b 0a 20 20 72 65 74  .aPhrase);.  ret
4a20: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a  urn rc;.}.../*.*
4a30: 2a 20 41 70 70 65 6e 64 20 61 20 73 74 72 69 6e  * Append a strin
4a40: 67 20 74 6f 20 74 68 65 20 73 74 72 69 6e 67 2d  g to the string-
4a50: 62 75 66 66 65 72 20 70 61 73 73 65 64 20 61 73  buffer passed as
4a60: 20 74 68 65 20 66 69 72 73 74 20 61 72 67 75 6d   the first argum
4a70: 65 6e 74 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 6e 41  ent..**.** If nA
4a80: 70 70 65 6e 64 20 69 73 20 6e 65 67 61 74 69 76  ppend is negativ
4a90: 65 2c 20 74 68 65 6e 20 74 68 65 20 6c 65 6e 67  e, then the leng
4aa0: 74 68 20 6f 66 20 74 68 65 20 73 74 72 69 6e 67  th of the string
4ab0: 20 7a 41 70 70 65 6e 64 20 69 73 0a 2a 2a 20 64   zAppend is.** d
4ac0: 65 74 65 72 6d 69 6e 65 64 20 75 73 69 6e 67 20  etermined using 
4ad0: 73 74 72 6c 65 6e 28 29 2e 0a 2a 2f 0a 73 74 61  strlen()..*/.sta
4ae0: 74 69 63 20 69 6e 74 20 66 74 73 33 53 74 72 69  tic int fts3Stri
4af0: 6e 67 41 70 70 65 6e 64 28 0a 20 20 53 74 72 42  ngAppend(.  StrB
4b00: 75 66 66 65 72 20 2a 70 53 74 72 2c 20 20 20 20  uffer *pStr,    
4b10: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 42              /* B
4b20: 75 66 66 65 72 20 74 6f 20 61 70 70 65 6e 64 20  uffer to append 
4b30: 74 6f 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68  to */.  const ch
4b40: 61 72 20 2a 7a 41 70 70 65 6e 64 2c 20 20 20 20  ar *zAppend,    
4b50: 20 20 20 20 20 20 20 20 2f 2a 20 50 6f 69 6e 74          /* Point
4b60: 65 72 20 74 6f 20 64 61 74 61 20 74 6f 20 61 70  er to data to ap
4b70: 70 65 6e 64 20 74 6f 20 62 75 66 66 65 72 20 2a  pend to buffer *
4b80: 2f 0a 20 20 69 6e 74 20 6e 41 70 70 65 6e 64 20  /.  int nAppend 
4b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4ba0: 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20 7a      /* Size of z
4bb0: 41 70 70 65 6e 64 20 69 6e 20 62 79 74 65 73 20  Append in bytes 
4bc0: 28 6f 72 20 2d 31 29 20 2a 2f 0a 29 7b 0a 20 20  (or -1) */.){.  
4bd0: 69 66 28 20 6e 41 70 70 65 6e 64 3c 30 20 29 7b  if( nAppend<0 ){
4be0: 0a 20 20 20 20 6e 41 70 70 65 6e 64 20 3d 20 28  .    nAppend = (
4bf0: 69 6e 74 29 73 74 72 6c 65 6e 28 7a 41 70 70 65  int)strlen(zAppe
4c00: 6e 64 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49  nd);.  }..  /* I
4c10: 66 20 74 68 65 72 65 20 69 73 20 69 6e 73 75 66  f there is insuf
4c20: 66 69 63 69 65 6e 74 20 73 70 61 63 65 20 61 6c  ficient space al
4c30: 6c 6f 63 61 74 65 64 20 61 74 20 53 74 72 42 75  located at StrBu
4c40: 66 66 65 72 2e 7a 2c 20 75 73 65 20 72 65 61 6c  ffer.z, use real
4c50: 6c 6f 63 28 29 0a 20 20 2a 2a 20 74 6f 20 67 72  loc().  ** to gr
4c60: 6f 77 20 74 68 65 20 62 75 66 66 65 72 20 75 6e  ow the buffer un
4c70: 74 69 6c 20 73 6f 20 74 68 61 74 20 69 74 20 69  til so that it i
4c80: 73 20 62 69 67 20 65 6e 6f 75 67 68 20 74 6f 20  s big enough to 
4c90: 61 63 63 6f 6d 61 64 61 74 65 20 74 68 65 0a 20  accomadate the. 
4ca0: 20 2a 2a 20 61 70 70 65 6e 64 65 64 20 64 61 74   ** appended dat
4cb0: 61 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20 70 53  a..  */.  if( pS
4cc0: 74 72 2d 3e 6e 2b 6e 41 70 70 65 6e 64 2b 31 3e  tr->n+nAppend+1>
4cd0: 3d 70 53 74 72 2d 3e 6e 41 6c 6c 6f 63 20 29 7b  =pStr->nAlloc ){
4ce0: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e 74  .    sqlite3_int
4cf0: 36 34 20 6e 41 6c 6c 6f 63 20 3d 20 70 53 74 72  64 nAlloc = pStr
4d00: 2d 3e 6e 41 6c 6c 6f 63 2b 28 73 71 6c 69 74 65  ->nAlloc+(sqlite
4d10: 33 5f 69 6e 74 36 34 29 6e 41 70 70 65 6e 64 2b  3_int64)nAppend+
4d20: 31 30 30 3b 0a 20 20 20 20 63 68 61 72 20 2a 7a  100;.    char *z
4d30: 4e 65 77 20 3d 20 73 71 6c 69 74 65 33 5f 72 65  New = sqlite3_re
4d40: 61 6c 6c 6f 63 36 34 28 70 53 74 72 2d 3e 7a 2c  alloc64(pStr->z,
4d50: 20 6e 41 6c 6c 6f 63 29 3b 0a 20 20 20 20 69 66   nAlloc);.    if
4d60: 28 20 21 7a 4e 65 77 20 29 7b 0a 20 20 20 20 20  ( !zNew ){.     
4d70: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e   return SQLITE_N
4d80: 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20 20 20 20  OMEM;.    }.    
4d90: 70 53 74 72 2d 3e 7a 20 3d 20 7a 4e 65 77 3b 0a  pStr->z = zNew;.
4da0: 20 20 20 20 70 53 74 72 2d 3e 6e 41 6c 6c 6f 63      pStr->nAlloc
4db0: 20 3d 20 6e 41 6c 6c 6f 63 3b 0a 20 20 7d 0a 20   = nAlloc;.  }. 
4dc0: 20 61 73 73 65 72 74 28 20 70 53 74 72 2d 3e 7a   assert( pStr->z
4dd0: 21 3d 30 20 26 26 20 28 70 53 74 72 2d 3e 6e 41  !=0 && (pStr->nA
4de0: 6c 6c 6f 63 20 3e 3d 20 70 53 74 72 2d 3e 6e 2b  lloc >= pStr->n+
4df0: 6e 41 70 70 65 6e 64 2b 31 29 20 29 3b 0a 0a 20  nAppend+1) );.. 
4e00: 20 2f 2a 20 41 70 70 65 6e 64 20 74 68 65 20 64   /* Append the d
4e10: 61 74 61 20 74 6f 20 74 68 65 20 73 74 72 69 6e  ata to the strin
4e20: 67 20 62 75 66 66 65 72 2e 20 2a 2f 0a 20 20 6d  g buffer. */.  m
4e30: 65 6d 63 70 79 28 26 70 53 74 72 2d 3e 7a 5b 70  emcpy(&pStr->z[p
4e40: 53 74 72 2d 3e 6e 5d 2c 20 7a 41 70 70 65 6e 64  Str->n], zAppend
4e50: 2c 20 6e 41 70 70 65 6e 64 29 3b 0a 20 20 70 53  , nAppend);.  pS
4e60: 74 72 2d 3e 6e 20 2b 3d 20 6e 41 70 70 65 6e 64  tr->n += nAppend
4e70: 3b 0a 20 20 70 53 74 72 2d 3e 7a 5b 70 53 74 72  ;.  pStr->z[pStr
4e80: 2d 3e 6e 5d 20 3d 20 27 5c 30 27 3b 0a 0a 20 20  ->n] = '\0';..  
4e90: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b  return SQLITE_OK
4ea0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 65 20 66  ;.}../*.** The f
4eb0: 74 73 33 42 65 73 74 53 6e 69 70 70 65 74 28 29  ts3BestSnippet()
4ec0: 20 66 75 6e 63 74 69 6f 6e 20 6f 66 74 65 6e 20   function often 
4ed0: 73 65 6c 65 63 74 73 20 73 6e 69 70 70 65 74 73  selects snippets
4ee0: 20 74 68 61 74 20 65 6e 64 20 77 69 74 68 20 61   that end with a
4ef0: 0a 2a 2a 20 71 75 65 72 79 20 74 65 72 6d 2e 20  .** query term. 
4f00: 54 68 61 74 20 69 73 2c 20 74 68 65 20 66 69 6e  That is, the fin
4f10: 61 6c 20 74 65 72 6d 20 6f 66 20 74 68 65 20 73  al term of the s
4f20: 6e 69 70 70 65 74 20 69 73 20 61 6c 77 61 79 73  nippet is always
4f30: 20 61 20 74 65 72 6d 0a 2a 2a 20 74 68 61 74 20   a term.** that 
4f40: 72 65 71 75 69 72 65 73 20 68 69 67 68 6c 69 67  requires highlig
4f50: 68 74 69 6e 67 2e 20 46 6f 72 20 65 78 61 6d 70  hting. For examp
4f60: 6c 65 2c 20 69 66 20 27 58 27 20 69 73 20 61 20  le, if 'X' is a 
4f70: 68 69 67 68 6c 69 67 68 74 65 64 20 74 65 72 6d  highlighted term
4f80: 0a 2a 2a 20 61 6e 64 20 27 2e 27 20 69 73 20 61  .** and '.' is a
4f90: 20 6e 6f 6e 2d 68 69 67 68 6c 69 67 68 74 65 64   non-highlighted
4fa0: 20 74 65 72 6d 2c 20 42 65 73 74 53 6e 69 70 70   term, BestSnipp
4fb0: 65 74 28 29 20 6d 61 79 20 73 65 6c 65 63 74 3a  et() may select:
4fc0: 0a 2a 2a 0a 2a 2a 20 20 20 20 20 2e 2e 2e 2e 2e  .**.**     .....
4fd0: 2e 2e 2e 58 2e 2e 2e 2e 2e 58 0a 2a 2a 0a 2a 2a  ...X.....X.**.**
4fe0: 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 22   This function "
4ff0: 73 68 69 66 74 73 22 20 74 68 65 20 62 65 67 69  shifts" the begi
5000: 6e 6e 69 6e 67 20 6f 66 20 74 68 65 20 73 6e 69  nning of the sni
5010: 70 70 65 74 20 66 6f 72 77 61 72 64 20 69 6e 20  ppet forward in 
5020: 74 68 65 20 0a 2a 2a 20 64 6f 63 75 6d 65 6e 74  the .** document
5030: 20 73 6f 20 74 68 61 74 20 74 68 65 72 65 20 61   so that there a
5040: 72 65 20 61 70 70 72 6f 78 69 6d 61 74 65 6c 79  re approximately
5050: 20 74 68 65 20 73 61 6d 65 20 6e 75 6d 62 65 72   the same number
5060: 20 6f 66 20 0a 2a 2a 20 6e 6f 6e 2d 68 69 67 68   of .** non-high
5070: 6c 69 67 68 74 65 64 20 74 65 72 6d 73 20 74 6f  lighted terms to
5080: 20 74 68 65 20 72 69 67 68 74 20 6f 66 20 74 68   the right of th
5090: 65 20 66 69 6e 61 6c 20 68 69 67 68 6c 69 67 68  e final highligh
50a0: 74 65 64 20 74 65 72 6d 20 61 73 20 74 68 65 72  ted term as ther
50b0: 65 0a 2a 2a 20 61 72 65 20 74 6f 20 74 68 65 20  e.** are to the 
50c0: 6c 65 66 74 20 6f 66 20 74 68 65 20 66 69 72 73  left of the firs
50d0: 74 20 68 69 67 68 6c 69 67 68 74 65 64 20 74 65  t highlighted te
50e0: 72 6d 2e 20 46 6f 72 20 65 78 61 6d 70 6c 65 2c  rm. For example,
50f0: 20 74 6f 20 74 68 69 73 3a 0a 2a 2a 0a 2a 2a 20   to this:.**.** 
5100: 20 20 20 20 2e 2e 2e 2e 58 2e 2e 2e 2e 2e 58 2e      ....X.....X.
5110: 2e 2e 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 69  ....**.** This i
5120: 73 20 64 6f 6e 65 20 61 73 20 70 61 72 74 20 6f  s done as part o
5130: 66 20 65 78 74 72 61 63 74 69 6e 67 20 74 68 65  f extracting the
5140: 20 73 6e 69 70 70 65 74 20 74 65 78 74 2c 20 6e   snippet text, n
5150: 6f 74 20 77 68 65 6e 20 73 65 6c 65 63 74 69 6e  ot when selectin
5160: 67 0a 2a 2a 20 74 68 65 20 73 6e 69 70 70 65 74  g.** the snippet
5170: 2e 20 53 6e 69 70 70 65 74 20 73 65 6c 65 63 74  . Snippet select
5180: 69 6f 6e 20 69 73 20 64 6f 6e 65 20 62 61 73 65  ion is done base
5190: 64 20 6f 6e 20 64 6f 63 6c 69 73 74 73 20 6f 6e  d on doclists on
51a0: 6c 79 2c 20 73 6f 20 74 68 65 72 65 0a 2a 2a 20  ly, so there.** 
51b0: 69 73 20 6e 6f 20 77 61 79 20 66 6f 72 20 66 74  is no way for ft
51c0: 73 33 42 65 73 74 53 6e 69 70 70 65 74 28 29 20  s3BestSnippet() 
51d0: 74 6f 20 6b 6e 6f 77 20 77 68 65 74 68 65 72 20  to know whether 
51e0: 6f 72 20 6e 6f 74 20 74 68 65 20 64 6f 63 75 6d  or not the docum
51f0: 65 6e 74 20 0a 2a 2a 20 61 63 74 75 61 6c 6c 79  ent .** actually
5200: 20 63 6f 6e 74 61 69 6e 73 20 74 65 72 6d 73 20   contains terms 
5210: 74 68 61 74 20 66 6f 6c 6c 6f 77 20 74 68 65 20  that follow the 
5220: 66 69 6e 61 6c 20 68 69 67 68 6c 69 67 68 74 65  final highlighte
5230: 64 20 74 65 72 6d 2e 20 0a 2a 2f 0a 73 74 61 74  d term. .*/.stat
5240: 69 63 20 69 6e 74 20 66 74 73 33 53 6e 69 70 70  ic int fts3Snipp
5250: 65 74 53 68 69 66 74 28 0a 20 20 46 74 73 33 54  etShift(.  Fts3T
5260: 61 62 6c 65 20 2a 70 54 61 62 2c 20 20 20 20 20  able *pTab,     
5270: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 54             /* FT
5280: 53 33 20 74 61 62 6c 65 20 73 6e 69 70 70 65 74  S3 table snippet
5290: 20 63 6f 6d 65 73 20 66 72 6f 6d 20 2a 2f 0a 20   comes from */. 
52a0: 20 69 6e 74 20 69 4c 61 6e 67 69 64 2c 20 20 20   int iLangid,   
52b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
52c0: 20 2f 2a 20 4c 61 6e 67 75 61 67 65 20 69 64 20   /* Language id 
52d0: 74 6f 20 75 73 65 20 69 6e 20 74 6f 6b 65 6e 69  to use in tokeni
52e0: 7a 69 6e 67 20 2a 2f 0a 20 20 69 6e 74 20 6e 53  zing */.  int nS
52f0: 6e 69 70 70 65 74 2c 20 20 20 20 20 20 20 20 20  nippet,         
5300: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d            /* Num
5310: 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20 64 65  ber of tokens de
5320: 73 69 72 65 64 20 66 6f 72 20 73 6e 69 70 70 65  sired for snippe
5330: 74 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61  t */.  const cha
5340: 72 20 2a 7a 44 6f 63 2c 20 20 20 20 20 20 20 20  r *zDoc,        
5350: 20 20 20 20 20 20 20 2f 2a 20 44 6f 63 75 6d 65         /* Docume
5360: 6e 74 20 74 65 78 74 20 74 6f 20 65 78 74 72 61  nt text to extra
5370: 63 74 20 73 6e 69 70 70 65 74 20 66 72 6f 6d 20  ct snippet from 
5380: 2a 2f 0a 20 20 69 6e 74 20 6e 44 6f 63 2c 20 20  */.  int nDoc,  
5390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
53a0: 20 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20       /* Size of 
53b0: 62 75 66 66 65 72 20 7a 44 6f 63 20 69 6e 20 62  buffer zDoc in b
53c0: 79 74 65 73 20 2a 2f 0a 20 20 69 6e 74 20 2a 70  ytes */.  int *p
53d0: 69 50 6f 73 2c 20 20 20 20 20 20 20 20 20 20 20  iPos,           
53e0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49 4e 2f            /* IN/
53f0: 4f 55 54 3a 20 46 69 72 73 74 20 74 6f 6b 65 6e  OUT: First token
5400: 20 6f 66 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20   of snippet */. 
5410: 20 75 36 34 20 2a 70 48 6c 6d 61 73 6b 20 20 20   u64 *pHlmask   
5420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5430: 20 2f 2a 20 49 4e 2f 4f 55 54 3a 20 4d 61 73 6b   /* IN/OUT: Mask
5440: 20 6f 66 20 74 6f 6b 65 6e 73 20 74 6f 20 68 69   of tokens to hi
5450: 67 68 6c 69 67 68 74 20 2a 2f 0a 29 7b 0a 20 20  ghlight */.){.  
5460: 75 36 34 20 68 6c 6d 61 73 6b 20 3d 20 2a 70 48  u64 hlmask = *pH
5470: 6c 6d 61 73 6b 3b 20 20 20 20 20 20 20 20 20 20  lmask;          
5480: 2f 2a 20 4c 6f 63 61 6c 20 63 6f 70 79 20 6f 66  /* Local copy of
5490: 20 69 6e 69 74 69 61 6c 20 68 69 67 68 6c 69 67   initial highlig
54a0: 68 74 2d 6d 61 73 6b 20 2a 2f 0a 0a 20 20 69 66  ht-mask */..  if
54b0: 28 20 68 6c 6d 61 73 6b 20 29 7b 0a 20 20 20 20  ( hlmask ){.    
54c0: 69 6e 74 20 6e 4c 65 66 74 3b 20 20 20 20 20 20  int nLeft;      
54d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
54e0: 20 54 6f 6b 65 6e 73 20 74 6f 20 74 68 65 20 6c   Tokens to the l
54f0: 65 66 74 20 6f 66 20 66 69 72 73 74 20 68 69 67  eft of first hig
5500: 68 6c 69 67 68 74 20 2a 2f 0a 20 20 20 20 69 6e  hlight */.    in
5510: 74 20 6e 52 69 67 68 74 3b 20 20 20 20 20 20 20  t nRight;       
5520: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54              /* T
5530: 6f 6b 65 6e 73 20 74 6f 20 74 68 65 20 72 69 67  okens to the rig
5540: 68 74 20 6f 66 20 6c 61 73 74 20 68 69 67 68 6c  ht of last highl
5550: 69 67 68 74 20 2a 2f 0a 20 20 20 20 69 6e 74 20  ight */.    int 
5560: 6e 44 65 73 69 72 65 64 3b 20 20 20 20 20 20 20  nDesired;       
5570: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49 64 65            /* Ide
5580: 61 6c 20 6e 75 6d 62 65 72 20 6f 66 20 74 6f 6b  al number of tok
5590: 65 6e 73 20 74 6f 20 73 68 69 66 74 20 66 6f 72  ens to shift for
55a0: 77 61 72 64 20 2a 2f 0a 0a 20 20 20 20 66 6f 72  ward */..    for
55b0: 28 6e 4c 65 66 74 3d 30 3b 20 21 28 68 6c 6d 61  (nLeft=0; !(hlma
55c0: 73 6b 20 26 20 28 28 75 36 34 29 31 20 3c 3c 20  sk & ((u64)1 << 
55d0: 6e 4c 65 66 74 29 29 3b 20 6e 4c 65 66 74 2b 2b  nLeft)); nLeft++
55e0: 29 3b 0a 20 20 20 20 66 6f 72 28 6e 52 69 67 68  );.    for(nRigh
55f0: 74 3d 30 3b 20 21 28 68 6c 6d 61 73 6b 20 26 20  t=0; !(hlmask & 
5600: 28 28 75 36 34 29 31 20 3c 3c 20 28 6e 53 6e 69  ((u64)1 << (nSni
5610: 70 70 65 74 2d 31 2d 6e 52 69 67 68 74 29 29 29  ppet-1-nRight)))
5620: 3b 20 6e 52 69 67 68 74 2b 2b 29 3b 0a 20 20 20  ; nRight++);.   
5630: 20 61 73 73 65 72 74 28 20 28 6e 53 6e 69 70 70   assert( (nSnipp
5640: 65 74 2d 31 2d 6e 52 69 67 68 74 29 3c 3d 36 33  et-1-nRight)<=63
5650: 20 26 26 20 28 6e 53 6e 69 70 70 65 74 2d 31 2d   && (nSnippet-1-
5660: 6e 52 69 67 68 74 29 3e 3d 30 20 29 3b 0a 20 20  nRight)>=0 );.  
5670: 20 20 6e 44 65 73 69 72 65 64 20 3d 20 28 6e 4c    nDesired = (nL
5680: 65 66 74 2d 6e 52 69 67 68 74 29 2f 32 3b 0a 0a  eft-nRight)/2;..
5690: 20 20 20 20 2f 2a 20 49 64 65 61 6c 6c 79 2c 20      /* Ideally, 
56a0: 74 68 65 20 73 74 61 72 74 20 6f 66 20 74 68 65  the start of the
56b0: 20 73 6e 69 70 70 65 74 20 73 68 6f 75 6c 64 20   snippet should 
56c0: 62 65 20 70 75 73 68 65 64 20 66 6f 72 77 61 72  be pushed forwar
56d0: 64 20 69 6e 20 74 68 65 0a 20 20 20 20 2a 2a 20  d in the.    ** 
56e0: 64 6f 63 75 6d 65 6e 74 20 6e 44 65 73 69 72 65  document nDesire
56f0: 64 20 74 6f 6b 65 6e 73 2e 20 54 68 69 73 20 62  d tokens. This b
5700: 6c 6f 63 6b 20 63 68 65 63 6b 73 20 69 66 20 74  lock checks if t
5710: 68 65 72 65 20 61 72 65 20 61 63 74 75 61 6c 6c  here are actuall
5720: 79 0a 20 20 20 20 2a 2a 20 6e 44 65 73 69 72 65  y.    ** nDesire
5730: 64 20 74 6f 6b 65 6e 73 20 74 6f 20 74 68 65 20  d tokens to the 
5740: 72 69 67 68 74 20 6f 66 20 74 68 65 20 73 6e 69  right of the sni
5750: 70 70 65 74 2e 20 49 66 20 73 6f 2c 20 2a 70 69  ppet. If so, *pi
5760: 50 6f 73 20 61 6e 64 0a 20 20 20 20 2a 2a 20 2a  Pos and.    ** *
5770: 70 48 6c 4d 61 73 6b 20 61 72 65 20 75 70 64 61  pHlMask are upda
5780: 74 65 64 20 74 6f 20 73 68 69 66 74 20 74 68 65  ted to shift the
5790: 20 73 6e 69 70 70 65 74 20 6e 44 65 73 69 72 65   snippet nDesire
57a0: 64 20 74 6f 6b 65 6e 73 20 74 6f 20 74 68 65 0a  d tokens to the.
57b0: 20 20 20 20 2a 2a 20 72 69 67 68 74 2e 20 4f 74      ** right. Ot
57c0: 68 65 72 77 69 73 65 2c 20 74 68 65 20 73 6e 69  herwise, the sni
57d0: 70 70 65 74 20 69 73 20 73 68 69 66 74 65 64 20  ppet is shifted 
57e0: 62 79 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66  by the number of
57f0: 20 74 6f 6b 65 6e 73 0a 20 20 20 20 2a 2a 20 61   tokens.    ** a
5800: 76 61 69 6c 61 62 6c 65 2e 0a 20 20 20 20 2a 2f  vailable..    */
5810: 0a 20 20 20 20 69 66 28 20 6e 44 65 73 69 72 65  .    if( nDesire
5820: 64 3e 30 20 29 7b 0a 20 20 20 20 20 20 69 6e 74  d>0 ){.      int
5830: 20 6e 53 68 69 66 74 3b 20 20 20 20 20 20 20 20   nShift;        
5840: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62           /* Numb
5850: 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20 74 6f 20  er of tokens to 
5860: 73 68 69 66 74 20 73 6e 69 70 70 65 74 20 62 79  shift snippet by
5870: 20 2a 2f 0a 20 20 20 20 20 20 69 6e 74 20 69 43   */.      int iC
5880: 75 72 72 65 6e 74 20 3d 20 30 3b 20 20 20 20 20  urrent = 0;     
5890: 20 20 20 20 20 20 2f 2a 20 54 6f 6b 65 6e 20 63        /* Token c
58a0: 6f 75 6e 74 65 72 20 2a 2f 0a 20 20 20 20 20 20  ounter */.      
58b0: 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20 20 20  int rc;         
58c0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52              /* R
58d0: 65 74 75 72 6e 20 43 6f 64 65 20 2a 2f 0a 20 20  eturn Code */.  
58e0: 20 20 20 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65      sqlite3_toke
58f0: 6e 69 7a 65 72 5f 6d 6f 64 75 6c 65 20 2a 70 4d  nizer_module *pM
5900: 6f 64 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65  od;.      sqlite
5910: 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63 75 72 73  3_tokenizer_curs
5920: 6f 72 20 2a 70 43 3b 0a 20 20 20 20 20 20 70 4d  or *pC;.      pM
5930: 6f 64 20 3d 20 28 73 71 6c 69 74 65 33 5f 74 6f  od = (sqlite3_to
5940: 6b 65 6e 69 7a 65 72 5f 6d 6f 64 75 6c 65 20 2a  kenizer_module *
5950: 29 70 54 61 62 2d 3e 70 54 6f 6b 65 6e 69 7a 65  )pTab->pTokenize
5960: 72 2d 3e 70 4d 6f 64 75 6c 65 3b 0a 0a 20 20 20  r->pModule;..   
5970: 20 20 20 2f 2a 20 4f 70 65 6e 20 61 20 63 75 72     /* Open a cur
5980: 73 6f 72 20 6f 6e 20 7a 44 6f 63 2f 6e 44 6f 63  sor on zDoc/nDoc
5990: 2e 20 43 68 65 63 6b 20 69 66 20 74 68 65 72 65  . Check if there
59a0: 20 61 72 65 20 28 6e 53 6e 69 70 70 65 74 2b 6e   are (nSnippet+n
59b0: 44 65 73 69 72 65 64 29 0a 20 20 20 20 20 20 2a  Desired).      *
59c0: 2a 20 6f 72 20 6d 6f 72 65 20 74 6f 6b 65 6e 73  * or more tokens
59d0: 20 69 6e 20 7a 44 6f 63 2f 6e 44 6f 63 2e 0a 20   in zDoc/nDoc.. 
59e0: 20 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 72 63       */.      rc
59f0: 20 3d 20 73 71 6c 69 74 65 33 46 74 73 33 4f 70   = sqlite3Fts3Op
5a00: 65 6e 54 6f 6b 65 6e 69 7a 65 72 28 70 54 61 62  enTokenizer(pTab
5a10: 2d 3e 70 54 6f 6b 65 6e 69 7a 65 72 2c 20 69 4c  ->pTokenizer, iL
5a20: 61 6e 67 69 64 2c 20 7a 44 6f 63 2c 20 6e 44 6f  angid, zDoc, nDo
5a30: 63 2c 20 26 70 43 29 3b 0a 20 20 20 20 20 20 69  c, &pC);.      i
5a40: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
5a50: 20 29 7b 0a 20 20 20 20 20 20 20 20 72 65 74 75   ){.        retu
5a60: 72 6e 20 72 63 3b 0a 20 20 20 20 20 20 7d 0a 20  rn rc;.      }. 
5a70: 20 20 20 20 20 77 68 69 6c 65 28 20 72 63 3d 3d       while( rc==
5a80: 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 69 43 75  SQLITE_OK && iCu
5a90: 72 72 65 6e 74 3c 28 6e 53 6e 69 70 70 65 74 2b  rrent<(nSnippet+
5aa0: 6e 44 65 73 69 72 65 64 29 20 29 7b 0a 20 20 20  nDesired) ){.   
5ab0: 20 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20       const char 
5ac0: 2a 5a 44 55 4d 4d 59 3b 20 69 6e 74 20 44 55 4d  *ZDUMMY; int DUM
5ad0: 4d 59 31 20 3d 20 30 2c 20 44 55 4d 4d 59 32 20  MY1 = 0, DUMMY2 
5ae0: 3d 20 30 2c 20 44 55 4d 4d 59 33 20 3d 20 30 3b  = 0, DUMMY3 = 0;
5af0: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 4d  .        rc = pM
5b00: 6f 64 2d 3e 78 4e 65 78 74 28 70 43 2c 20 26 5a  od->xNext(pC, &Z
5b10: 44 55 4d 4d 59 2c 20 26 44 55 4d 4d 59 31 2c 20  DUMMY, &DUMMY1, 
5b20: 26 44 55 4d 4d 59 32 2c 20 26 44 55 4d 4d 59 33  &DUMMY2, &DUMMY3
5b30: 2c 20 26 69 43 75 72 72 65 6e 74 29 3b 0a 20 20  , &iCurrent);.  
5b40: 20 20 20 20 7d 0a 20 20 20 20 20 20 70 4d 6f 64      }.      pMod
5b50: 2d 3e 78 43 6c 6f 73 65 28 70 43 29 3b 0a 20 20  ->xClose(pC);.  
5b60: 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49      if( rc!=SQLI
5b70: 54 45 5f 4f 4b 20 26 26 20 72 63 21 3d 53 51 4c  TE_OK && rc!=SQL
5b80: 49 54 45 5f 44 4f 4e 45 20 29 7b 20 72 65 74 75  ITE_DONE ){ retu
5b90: 72 6e 20 72 63 3b 20 7d 0a 0a 20 20 20 20 20 20  rn rc; }..      
5ba0: 6e 53 68 69 66 74 20 3d 20 28 72 63 3d 3d 53 51  nShift = (rc==SQ
5bb0: 4c 49 54 45 5f 44 4f 4e 45 29 2b 69 43 75 72 72  LITE_DONE)+iCurr
5bc0: 65 6e 74 2d 6e 53 6e 69 70 70 65 74 3b 0a 20 20  ent-nSnippet;.  
5bd0: 20 20 20 20 61 73 73 65 72 74 28 20 6e 53 68 69      assert( nShi
5be0: 66 74 3c 3d 6e 44 65 73 69 72 65 64 20 29 3b 0a  ft<=nDesired );.
5bf0: 20 20 20 20 20 20 69 66 28 20 6e 53 68 69 66 74        if( nShift
5c00: 3e 30 20 29 7b 0a 20 20 20 20 20 20 20 20 2a 70  >0 ){.        *p
5c10: 69 50 6f 73 20 2b 3d 20 6e 53 68 69 66 74 3b 0a  iPos += nShift;.
5c20: 20 20 20 20 20 20 20 20 2a 70 48 6c 6d 61 73 6b          *pHlmask
5c30: 20 3d 20 68 6c 6d 61 73 6b 20 3e 3e 20 6e 53 68   = hlmask >> nSh
5c40: 69 66 74 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  ift;.      }.   
5c50: 20 7d 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20   }.  }.  return 
5c60: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  SQLITE_OK;.}../*
5c70: 0a 2a 2a 20 45 78 74 72 61 63 74 20 74 68 65 20  .** Extract the 
5c80: 73 6e 69 70 70 65 74 20 74 65 78 74 20 66 6f 72  snippet text for
5c90: 20 66 72 61 67 6d 65 6e 74 20 70 46 72 61 67 6d   fragment pFragm
5ca0: 65 6e 74 20 66 72 6f 6d 20 63 75 72 73 6f 72 20  ent from cursor 
5cb0: 70 43 73 72 20 61 6e 64 0a 2a 2a 20 61 70 70 65  pCsr and.** appe
5cc0: 6e 64 20 69 74 20 74 6f 20 73 74 72 69 6e 67 20  nd it to string 
5cd0: 62 75 66 66 65 72 20 70 4f 75 74 2e 0a 2a 2f 0a  buffer pOut..*/.
5ce0: 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 53  static int fts3S
5cf0: 6e 69 70 70 65 74 54 65 78 74 28 0a 20 20 46 74  nippetText(.  Ft
5d00: 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72 2c 20  s3Cursor *pCsr, 
5d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
5d20: 20 46 54 53 33 20 43 75 72 73 6f 72 20 2a 2f 0a   FTS3 Cursor */.
5d30: 20 20 53 6e 69 70 70 65 74 46 72 61 67 6d 65 6e    SnippetFragmen
5d40: 74 20 2a 70 46 72 61 67 6d 65 6e 74 2c 20 20 20  t *pFragment,   
5d50: 20 20 2f 2a 20 53 6e 69 70 70 65 74 20 74 6f 20    /* Snippet to 
5d60: 65 78 74 72 61 63 74 20 2a 2f 0a 20 20 69 6e 74  extract */.  int
5d70: 20 69 46 72 61 67 6d 65 6e 74 2c 20 20 20 20 20   iFragment,     
5d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
5d90: 46 72 61 67 6d 65 6e 74 20 6e 75 6d 62 65 72 20  Fragment number 
5da0: 2a 2f 0a 20 20 69 6e 74 20 69 73 4c 61 73 74 2c  */.  int isLast,
5db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5dc0: 20 20 20 20 20 2f 2a 20 54 72 75 65 20 66 6f 72       /* True for
5dd0: 20 66 69 6e 61 6c 20 66 72 61 67 6d 65 6e 74 20   final fragment 
5de0: 69 6e 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20  in snippet */.  
5df0: 69 6e 74 20 6e 53 6e 69 70 70 65 74 2c 20 20 20  int nSnippet,   
5e00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e10: 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 74 6f 6b  /* Number of tok
5e20: 65 6e 73 20 69 6e 20 65 78 74 72 61 63 74 65 64  ens in extracted
5e30: 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20 63 6f   snippet */.  co
5e40: 6e 73 74 20 63 68 61 72 20 2a 7a 4f 70 65 6e 2c  nst char *zOpen,
5e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
5e60: 20 53 74 72 69 6e 67 20 69 6e 73 65 72 74 65 64   String inserted
5e70: 20 62 65 66 6f 72 65 20 68 69 67 68 6c 69 67 68   before highligh
5e80: 74 65 64 20 74 65 72 6d 20 2a 2f 0a 20 20 63 6f  ted term */.  co
5e90: 6e 73 74 20 63 68 61 72 20 2a 7a 43 6c 6f 73 65  nst char *zClose
5ea0: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  ,             /*
5eb0: 20 53 74 72 69 6e 67 20 69 6e 73 65 72 74 65 64   String inserted
5ec0: 20 61 66 74 65 72 20 68 69 67 68 6c 69 67 68 74   after highlight
5ed0: 65 64 20 74 65 72 6d 20 2a 2f 0a 20 20 63 6f 6e  ed term */.  con
5ee0: 73 74 20 63 68 61 72 20 2a 7a 45 6c 6c 69 70 73  st char *zEllips
5ef0: 69 73 2c 20 20 20 20 20 20 20 20 20 20 2f 2a 20  is,          /* 
5f00: 53 74 72 69 6e 67 20 69 6e 73 65 72 74 65 64 20  String inserted 
5f10: 62 65 74 77 65 65 6e 20 73 6e 69 70 70 65 74 73  between snippets
5f20: 20 2a 2f 0a 20 20 53 74 72 42 75 66 66 65 72 20   */.  StrBuffer 
5f30: 2a 70 4f 75 74 20 20 20 20 20 20 20 20 20 20 20  *pOut           
5f40: 20 20 20 20 20 20 2f 2a 20 57 72 69 74 65 20 6f        /* Write o
5f50: 75 74 70 75 74 20 68 65 72 65 20 2a 2f 0a 29 7b  utput here */.){
5f60: 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a 70 54  .  Fts3Table *pT
5f70: 61 62 20 3d 20 28 46 74 73 33 54 61 62 6c 65 20  ab = (Fts3Table 
5f80: 2a 29 70 43 73 72 2d 3e 62 61 73 65 2e 70 56 74  *)pCsr->base.pVt
5f90: 61 62 3b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20  ab;.  int rc;   
5fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fb0: 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20        /* Return 
5fc0: 63 6f 64 65 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  code */.  const 
5fd0: 63 68 61 72 20 2a 7a 44 6f 63 3b 20 20 20 20 20  char *zDoc;     
5fe0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44 6f 63            /* Doc
5ff0: 75 6d 65 6e 74 20 74 65 78 74 20 74 6f 20 65 78  ument text to ex
6000: 74 72 61 63 74 20 73 6e 69 70 70 65 74 20 66 72  tract snippet fr
6010: 6f 6d 20 2a 2f 0a 20 20 69 6e 74 20 6e 44 6f 63  om */.  int nDoc
6020: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
6030: 20 20 20 20 20 20 20 20 2f 2a 20 53 69 7a 65 20          /* Size 
6040: 6f 66 20 7a 44 6f 63 20 69 6e 20 62 79 74 65 73  of zDoc in bytes
6050: 20 2a 2f 0a 20 20 69 6e 74 20 69 43 75 72 72 65   */.  int iCurre
6060: 6e 74 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  nt = 0;         
6070: 20 20 20 20 20 20 2f 2a 20 43 75 72 72 65 6e 74        /* Current
6080: 20 74 6f 6b 65 6e 20 6e 75 6d 62 65 72 20 6f 66   token number of
6090: 20 64 6f 63 75 6d 65 6e 74 20 2a 2f 0a 20 20 69   document */.  i
60a0: 6e 74 20 69 45 6e 64 20 3d 20 30 3b 20 20 20 20  nt iEnd = 0;    
60b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
60c0: 2a 20 42 79 74 65 20 6f 66 66 73 65 74 20 6f 66  * Byte offset of
60d0: 20 65 6e 64 20 6f 66 20 63 75 72 72 65 6e 74 20   end of current 
60e0: 74 6f 6b 65 6e 20 2a 2f 0a 20 20 69 6e 74 20 69  token */.  int i
60f0: 73 53 68 69 66 74 44 6f 6e 65 20 3d 20 30 3b 20  sShiftDone = 0; 
6100: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72             /* Tr
6110: 75 65 20 61 66 74 65 72 20 73 6e 69 70 70 65 74  ue after snippet
6120: 20 69 73 20 73 68 69 66 74 65 64 20 2a 2f 0a 20   is shifted */. 
6130: 20 69 6e 74 20 69 50 6f 73 20 3d 20 70 46 72 61   int iPos = pFra
6140: 67 6d 65 6e 74 2d 3e 69 50 6f 73 3b 20 20 20 20  gment->iPos;    
6150: 20 2f 2a 20 46 69 72 73 74 20 74 6f 6b 65 6e 20   /* First token 
6160: 6f 66 20 73 6e 69 70 70 65 74 20 2a 2f 0a 20 20  of snippet */.  
6170: 75 36 34 20 68 6c 6d 61 73 6b 20 3d 20 70 46 72  u64 hlmask = pFr
6180: 61 67 6d 65 6e 74 2d 3e 68 6c 6d 61 73 6b 3b 20  agment->hlmask; 
6190: 2f 2a 20 48 69 67 68 6c 69 67 68 74 2d 6d 61 73  /* Highlight-mas
61a0: 6b 20 66 6f 72 20 73 6e 69 70 70 65 74 20 2a 2f  k for snippet */
61b0: 0a 20 20 69 6e 74 20 69 43 6f 6c 20 3d 20 70 46  .  int iCol = pF
61c0: 72 61 67 6d 65 6e 74 2d 3e 69 43 6f 6c 2b 31 3b  ragment->iCol+1;
61d0: 20 20 20 2f 2a 20 51 75 65 72 79 20 63 6f 6c 75     /* Query colu
61e0: 6d 6e 20 74 6f 20 65 78 74 72 61 63 74 20 74 65  mn to extract te
61f0: 78 74 20 66 72 6f 6d 20 2a 2f 0a 20 20 73 71 6c  xt from */.  sql
6200: 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 6d  ite3_tokenizer_m
6210: 6f 64 75 6c 65 20 2a 70 4d 6f 64 3b 20 2f 2a 20  odule *pMod; /* 
6220: 54 6f 6b 65 6e 69 7a 65 72 20 6d 6f 64 75 6c 65  Tokenizer module
6230: 20 6d 65 74 68 6f 64 73 20 6f 62 6a 65 63 74 20   methods object 
6240: 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 74 6f 6b  */.  sqlite3_tok
6250: 65 6e 69 7a 65 72 5f 63 75 72 73 6f 72 20 2a 70  enizer_cursor *p
6260: 43 3b 20 20 20 2f 2a 20 54 6f 6b 65 6e 69 7a 65  C;   /* Tokenize
6270: 72 20 63 75 72 73 6f 72 20 6f 70 65 6e 20 6f 6e  r cursor open on
6280: 20 7a 44 6f 63 2f 6e 44 6f 63 20 2a 2f 0a 20 20   zDoc/nDoc */.  
6290: 0a 20 20 7a 44 6f 63 20 3d 20 28 63 6f 6e 73 74  .  zDoc = (const
62a0: 20 63 68 61 72 20 2a 29 73 71 6c 69 74 65 33 5f   char *)sqlite3_
62b0: 63 6f 6c 75 6d 6e 5f 74 65 78 74 28 70 43 73 72  column_text(pCsr
62c0: 2d 3e 70 53 74 6d 74 2c 20 69 43 6f 6c 29 3b 0a  ->pStmt, iCol);.
62d0: 20 20 69 66 28 20 7a 44 6f 63 3d 3d 30 20 29 7b    if( zDoc==0 ){
62e0: 0a 20 20 20 20 69 66 28 20 73 71 6c 69 74 65 33  .    if( sqlite3
62f0: 5f 63 6f 6c 75 6d 6e 5f 74 79 70 65 28 70 43 73  _column_type(pCs
6300: 72 2d 3e 70 53 74 6d 74 2c 20 69 43 6f 6c 29 21  r->pStmt, iCol)!
6310: 3d 53 51 4c 49 54 45 5f 4e 55 4c 4c 20 29 7b 0a  =SQLITE_NULL ){.
6320: 20 20 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c        return SQL
6330: 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d  ITE_NOMEM;.    }
6340: 0a 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49  .    return SQLI
6350: 54 45 5f 4f 4b 3b 0a 20 20 7d 0a 20 20 6e 44 6f  TE_OK;.  }.  nDo
6360: 63 20 3d 20 73 71 6c 69 74 65 33 5f 63 6f 6c 75  c = sqlite3_colu
6370: 6d 6e 5f 62 79 74 65 73 28 70 43 73 72 2d 3e 70  mn_bytes(pCsr->p
6380: 53 74 6d 74 2c 20 69 43 6f 6c 29 3b 0a 0a 20 20  Stmt, iCol);..  
6390: 2f 2a 20 4f 70 65 6e 20 61 20 74 6f 6b 65 6e 20  /* Open a token 
63a0: 63 75 72 73 6f 72 20 6f 6e 20 74 68 65 20 64 6f  cursor on the do
63b0: 63 75 6d 65 6e 74 2e 20 2a 2f 0a 20 20 70 4d 6f  cument. */.  pMo
63c0: 64 20 3d 20 28 73 71 6c 69 74 65 33 5f 74 6f 6b  d = (sqlite3_tok
63d0: 65 6e 69 7a 65 72 5f 6d 6f 64 75 6c 65 20 2a 29  enizer_module *)
63e0: 70 54 61 62 2d 3e 70 54 6f 6b 65 6e 69 7a 65 72  pTab->pTokenizer
63f0: 2d 3e 70 4d 6f 64 75 6c 65 3b 0a 20 20 72 63 20  ->pModule;.  rc 
6400: 3d 20 73 71 6c 69 74 65 33 46 74 73 33 4f 70 65  = sqlite3Fts3Ope
6410: 6e 54 6f 6b 65 6e 69 7a 65 72 28 70 54 61 62 2d  nTokenizer(pTab-
6420: 3e 70 54 6f 6b 65 6e 69 7a 65 72 2c 20 70 43 73  >pTokenizer, pCs
6430: 72 2d 3e 69 4c 61 6e 67 69 64 2c 20 7a 44 6f 63  r->iLangid, zDoc
6440: 2c 6e 44 6f 63 2c 26 70 43 29 3b 0a 20 20 69 66  ,nDoc,&pC);.  if
6450: 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc!=SQLITE_OK 
6460: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 72 63  ){.    return rc
6470: 3b 0a 20 20 7d 0a 0a 20 20 77 68 69 6c 65 28 20  ;.  }..  while( 
6480: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
6490: 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20  .    const char 
64a0: 2a 5a 44 55 4d 4d 59 3b 20 20 20 20 20 20 20 20  *ZDUMMY;        
64b0: 20 20 20 2f 2a 20 44 75 6d 6d 79 20 61 72 67 75     /* Dummy argu
64c0: 6d 65 6e 74 20 75 73 65 64 20 77 69 74 68 20 74  ment used with t
64d0: 6f 6b 65 6e 69 7a 65 72 20 2a 2f 0a 20 20 20 20  okenizer */.    
64e0: 69 6e 74 20 44 55 4d 4d 59 31 20 3d 20 2d 31 3b  int DUMMY1 = -1;
64f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
6500: 20 44 75 6d 6d 79 20 61 72 67 75 6d 65 6e 74 20   Dummy argument 
6510: 75 73 65 64 20 77 69 74 68 20 74 6f 6b 65 6e 69  used with tokeni
6520: 7a 65 72 20 2a 2f 0a 20 20 20 20 69 6e 74 20 69  zer */.    int i
6530: 42 65 67 69 6e 20 3d 20 30 3b 20 20 20 20 20 20  Begin = 0;      
6540: 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 66 66 73           /* Offs
6550: 65 74 20 69 6e 20 7a 44 6f 63 20 6f 66 20 73 74  et in zDoc of st
6560: 61 72 74 20 6f 66 20 74 6f 6b 65 6e 20 2a 2f 0a  art of token */.
6570: 20 20 20 20 69 6e 74 20 69 46 69 6e 20 3d 20 30      int iFin = 0
6580: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
6590: 20 20 2f 2a 20 4f 66 66 73 65 74 20 69 6e 20 7a    /* Offset in z
65a0: 44 6f 63 20 6f 66 20 65 6e 64 20 6f 66 20 74 6f  Doc of end of to
65b0: 6b 65 6e 20 2a 2f 0a 20 20 20 20 69 6e 74 20 69  ken */.    int i
65c0: 73 48 69 67 68 6c 69 67 68 74 20 3d 20 30 3b 20  sHighlight = 0; 
65d0: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65           /* True
65e0: 20 66 6f 72 20 68 69 67 68 6c 69 67 68 74 65 64   for highlighted
65f0: 20 74 65 72 6d 73 20 2a 2f 0a 0a 20 20 20 20 2f   terms */..    /
6600: 2a 20 56 61 72 69 61 62 6c 65 20 44 55 4d 4d 59  * Variable DUMMY
6610: 31 20 69 73 20 69 6e 69 74 69 61 6c 69 7a 65 64  1 is initialized
6620: 20 74 6f 20 61 20 6e 65 67 61 74 69 76 65 20 76   to a negative v
6630: 61 6c 75 65 20 61 62 6f 76 65 2e 20 45 6c 73 65  alue above. Else
6640: 77 68 65 72 65 0a 20 20 20 20 2a 2a 20 69 6e 20  where.    ** in 
6650: 74 68 65 20 46 54 53 20 63 6f 64 65 20 74 68 65  the FTS code the
6660: 20 76 61 72 69 61 62 6c 65 20 74 68 61 74 20 74   variable that t
6670: 68 65 20 74 68 69 72 64 20 61 72 67 75 6d 65 6e  he third argumen
6680: 74 20 74 6f 20 78 4e 65 78 74 20 70 6f 69 6e 74  t to xNext point
6690: 73 20 74 6f 0a 20 20 20 20 2a 2a 20 69 73 20 69  s to.    ** is i
66a0: 6e 69 74 69 61 6c 69 7a 65 64 20 74 6f 20 7a 65  nitialized to ze
66b0: 72 6f 20 62 65 66 6f 72 65 20 74 68 65 20 66 69  ro before the fi
66c0: 72 73 74 20 28 2a 62 75 74 20 6e 6f 74 20 6e 65  rst (*but not ne
66d0: 63 65 73 73 61 72 69 6c 79 0a 20 20 20 20 2a 2a  cessarily.    **
66e0: 20 73 75 62 73 65 71 75 65 6e 74 2a 29 20 63 61   subsequent*) ca
66f0: 6c 6c 20 74 6f 20 78 4e 65 78 74 28 29 2e 20 54  ll to xNext(). T
6700: 68 69 73 20 69 73 20 64 6f 6e 65 20 66 6f 72 20  his is done for 
6710: 61 20 70 61 72 74 69 63 75 6c 61 72 20 61 70 70  a particular app
6720: 6c 69 63 61 74 69 6f 6e 0a 20 20 20 20 2a 2a 20  lication.    ** 
6730: 74 68 61 74 20 6e 65 65 64 73 20 74 6f 20 6b 6e  that needs to kn
6740: 6f 77 20 77 68 65 74 68 65 72 20 6f 72 20 6e 6f  ow whether or no
6750: 74 20 74 68 65 20 74 6f 6b 65 6e 69 7a 65 72 20  t the tokenizer 
6760: 69 73 20 62 65 69 6e 67 20 75 73 65 64 20 66 6f  is being used fo
6770: 72 0a 20 20 20 20 2a 2a 20 73 6e 69 70 70 65 74  r.    ** snippet
6780: 20 67 65 6e 65 72 61 74 69 6f 6e 20 6f 72 20 66   generation or f
6790: 6f 72 20 73 6f 6d 65 20 6f 74 68 65 72 20 70 75  or some other pu
67a0: 72 70 6f 73 65 2e 0a 20 20 20 20 2a 2a 0a 20 20  rpose..    **.  
67b0: 20 20 2a 2a 20 45 78 74 72 65 6d 65 20 63 61 72    ** Extreme car
67c0: 65 20 69 73 20 72 65 71 75 69 72 65 64 20 77 68  e is required wh
67d0: 65 6e 20 77 72 69 74 69 6e 67 20 63 6f 64 65 20  en writing code 
67e0: 74 6f 20 64 65 70 65 6e 64 20 6f 6e 20 74 68 69  to depend on thi
67f0: 73 0a 20 20 20 20 2a 2a 20 69 6e 69 74 69 61 6c  s.    ** initial
6800: 69 7a 61 74 69 6f 6e 2e 20 49 74 20 69 73 20 6e  ization. It is n
6810: 6f 74 20 61 20 64 6f 63 75 6d 65 6e 74 65 64 20  ot a documented 
6820: 70 61 72 74 20 6f 66 20 74 68 65 20 74 6f 6b 65  part of the toke
6830: 6e 69 7a 65 72 20 69 6e 74 65 72 66 61 63 65 2e  nizer interface.
6840: 0a 20 20 20 20 2a 2a 20 49 66 20 61 20 74 6f 6b  .    ** If a tok
6850: 65 6e 69 7a 65 72 20 69 73 20 75 73 65 64 20 64  enizer is used d
6860: 69 72 65 63 74 6c 79 20 62 79 20 61 6e 79 20 63  irectly by any c
6870: 6f 64 65 20 6f 75 74 73 69 64 65 20 6f 66 20 46  ode outside of F
6880: 54 53 2c 20 74 68 69 73 0a 20 20 20 20 2a 2a 20  TS, this.    ** 
6890: 63 6f 6e 76 65 6e 74 69 6f 6e 20 6d 69 67 68 74  convention might
68a0: 20 6e 6f 74 20 62 65 20 72 65 73 70 65 63 74 65   not be respecte
68b0: 64 2e 20 20 2a 2f 0a 20 20 20 20 72 63 20 3d 20  d.  */.    rc = 
68c0: 70 4d 6f 64 2d 3e 78 4e 65 78 74 28 70 43 2c 20  pMod->xNext(pC, 
68d0: 26 5a 44 55 4d 4d 59 2c 20 26 44 55 4d 4d 59 31  &ZDUMMY, &DUMMY1
68e0: 2c 20 26 69 42 65 67 69 6e 2c 20 26 69 46 69 6e  , &iBegin, &iFin
68f0: 2c 20 26 69 43 75 72 72 65 6e 74 29 3b 0a 20 20  , &iCurrent);.  
6900: 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45    if( rc!=SQLITE
6910: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 69 66 28  _OK ){.      if(
6920: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 44 4f 4e 45   rc==SQLITE_DONE
6930: 20 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20 53   ){.        /* S
6940: 70 65 63 69 61 6c 20 63 61 73 65 20 2d 20 74 68  pecial case - th
6950: 65 20 6c 61 73 74 20 74 6f 6b 65 6e 20 6f 66 20  e last token of 
6960: 74 68 65 20 73 6e 69 70 70 65 74 20 69 73 20 61  the snippet is a
6970: 6c 73 6f 20 74 68 65 20 6c 61 73 74 20 74 6f 6b  lso the last tok
6980: 65 6e 0a 20 20 20 20 20 20 20 20 2a 2a 20 6f 66  en.        ** of
6990: 20 74 68 65 20 63 6f 6c 75 6d 6e 2e 20 41 70 70   the column. App
69a0: 65 6e 64 20 61 6e 79 20 70 75 6e 63 74 75 61 74  end any punctuat
69b0: 69 6f 6e 20 74 68 61 74 20 6f 63 63 75 72 72 65  ion that occurre
69c0: 64 20 62 65 74 77 65 65 6e 20 74 68 65 20 65 6e  d between the en
69d0: 64 0a 20 20 20 20 20 20 20 20 2a 2a 20 6f 66 20  d.        ** of 
69e0: 74 68 65 20 70 72 65 76 69 6f 75 73 20 74 6f 6b  the previous tok
69f0: 65 6e 20 61 6e 64 20 74 68 65 20 65 6e 64 20 6f  en and the end o
6a00: 66 20 74 68 65 20 64 6f 63 75 6d 65 6e 74 20 74  f the document t
6a10: 6f 20 74 68 65 20 6f 75 74 70 75 74 2e 20 0a 20  o the output. . 
6a20: 20 20 20 20 20 20 20 2a 2a 20 54 68 65 6e 20 62         ** Then b
6a30: 72 65 61 6b 20 6f 75 74 20 6f 66 20 74 68 65 20  reak out of the 
6a40: 6c 6f 6f 70 2e 20 2a 2f 0a 20 20 20 20 20 20 20  loop. */.       
6a50: 20 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67   rc = fts3String
6a60: 41 70 70 65 6e 64 28 70 4f 75 74 2c 20 26 7a 44  Append(pOut, &zD
6a70: 6f 63 5b 69 45 6e 64 5d 2c 20 2d 31 29 3b 0a 20  oc[iEnd], -1);. 
6a80: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62 72 65       }.      bre
6a90: 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66  ak;.    }.    if
6aa0: 28 20 69 43 75 72 72 65 6e 74 3c 69 50 6f 73 20  ( iCurrent<iPos 
6ab0: 29 7b 20 63 6f 6e 74 69 6e 75 65 3b 20 7d 0a 0a  ){ continue; }..
6ac0: 20 20 20 20 69 66 28 20 21 69 73 53 68 69 66 74      if( !isShift
6ad0: 44 6f 6e 65 20 29 7b 0a 20 20 20 20 20 20 69 6e  Done ){.      in
6ae0: 74 20 6e 20 3d 20 6e 44 6f 63 20 2d 20 69 42 65  t n = nDoc - iBe
6af0: 67 69 6e 3b 0a 20 20 20 20 20 20 72 63 20 3d 20  gin;.      rc = 
6b00: 66 74 73 33 53 6e 69 70 70 65 74 53 68 69 66 74  fts3SnippetShift
6b10: 28 0a 20 20 20 20 20 20 20 20 20 20 70 54 61 62  (.          pTab
6b20: 2c 20 70 43 73 72 2d 3e 69 4c 61 6e 67 69 64 2c  , pCsr->iLangid,
6b30: 20 6e 53 6e 69 70 70 65 74 2c 20 26 7a 44 6f 63   nSnippet, &zDoc
6b40: 5b 69 42 65 67 69 6e 5d 2c 20 6e 2c 20 26 69 50  [iBegin], n, &iP
6b50: 6f 73 2c 20 26 68 6c 6d 61 73 6b 0a 20 20 20 20  os, &hlmask.    
6b60: 20 20 29 3b 0a 20 20 20 20 20 20 69 73 53 68 69    );.      isShi
6b70: 66 74 44 6f 6e 65 20 3d 20 31 3b 0a 0a 20 20 20  ftDone = 1;..   
6b80: 20 20 20 2f 2a 20 4e 6f 77 20 74 68 61 74 20 74     /* Now that t
6b90: 68 65 20 73 68 69 66 74 20 68 61 73 20 62 65 65  he shift has bee
6ba0: 6e 20 64 6f 6e 65 2c 20 63 68 65 63 6b 20 69 66  n done, check if
6bb0: 20 74 68 65 20 69 6e 69 74 69 61 6c 20 22 2e 2e   the initial "..
6bc0: 2e 22 20 61 72 65 0a 20 20 20 20 20 20 2a 2a 20  ." are.      ** 
6bd0: 72 65 71 75 69 72 65 64 2e 20 54 68 65 79 20 61  required. They a
6be0: 72 65 20 72 65 71 75 69 72 65 64 20 69 66 20 28  re required if (
6bf0: 61 29 20 74 68 69 73 20 69 73 20 6e 6f 74 20 74  a) this is not t
6c00: 68 65 20 66 69 72 73 74 20 66 72 61 67 6d 65 6e  he first fragmen
6c10: 74 2c 0a 20 20 20 20 20 20 2a 2a 20 6f 72 20 28  t,.      ** or (
6c20: 62 29 20 74 68 69 73 20 66 72 61 67 6d 65 6e 74  b) this fragment
6c30: 20 64 6f 65 73 20 6e 6f 74 20 62 65 67 69 6e 20   does not begin 
6c40: 61 74 20 70 6f 73 69 74 69 6f 6e 20 30 20 6f 66  at position 0 of
6c50: 20 69 74 73 20 63 6f 6c 75 6d 6e 2e 20 0a 20 20   its column. .  
6c60: 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 69 66 28      */.      if(
6c70: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29   rc==SQLITE_OK )
6c80: 7b 0a 20 20 20 20 20 20 20 20 69 66 28 20 69 50  {.        if( iP
6c90: 6f 73 3e 30 20 7c 7c 20 69 46 72 61 67 6d 65 6e  os>0 || iFragmen
6ca0: 74 3e 30 20 29 7b 0a 20 20 20 20 20 20 20 20 20  t>0 ){.         
6cb0: 20 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67   rc = fts3String
6cc0: 41 70 70 65 6e 64 28 70 4f 75 74 2c 20 7a 45 6c  Append(pOut, zEl
6cd0: 6c 69 70 73 69 73 2c 20 2d 31 29 3b 0a 20 20 20  lipsis, -1);.   
6ce0: 20 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 69       }else if( i
6cf0: 42 65 67 69 6e 20 29 7b 0a 20 20 20 20 20 20 20  Begin ){.       
6d00: 20 20 20 72 63 20 3d 20 66 74 73 33 53 74 72 69     rc = fts3Stri
6d10: 6e 67 41 70 70 65 6e 64 28 70 4f 75 74 2c 20 7a  ngAppend(pOut, z
6d20: 44 6f 63 2c 20 69 42 65 67 69 6e 29 3b 0a 20 20  Doc, iBegin);.  
6d30: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a        }.      }.
6d40: 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53 51        if( rc!=SQ
6d50: 4c 49 54 45 5f 4f 4b 20 7c 7c 20 69 43 75 72 72  LITE_OK || iCurr
6d60: 65 6e 74 3c 69 50 6f 73 20 29 20 63 6f 6e 74 69  ent<iPos ) conti
6d70: 6e 75 65 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20  nue;.    }..    
6d80: 69 66 28 20 69 43 75 72 72 65 6e 74 3e 3d 28 69  if( iCurrent>=(i
6d90: 50 6f 73 2b 6e 53 6e 69 70 70 65 74 29 20 29 7b  Pos+nSnippet) ){
6da0: 0a 20 20 20 20 20 20 69 66 28 20 69 73 4c 61 73  .      if( isLas
6db0: 74 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20  t ){.        rc 
6dc0: 3d 20 66 74 73 33 53 74 72 69 6e 67 41 70 70 65  = fts3StringAppe
6dd0: 6e 64 28 70 4f 75 74 2c 20 7a 45 6c 6c 69 70 73  nd(pOut, zEllips
6de0: 69 73 2c 20 2d 31 29 3b 0a 20 20 20 20 20 20 7d  is, -1);.      }
6df0: 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20  .      break;.  
6e00: 20 20 7d 0a 0a 20 20 20 20 2f 2a 20 53 65 74 20    }..    /* Set 
6e10: 69 73 48 69 67 68 6c 69 67 68 74 20 74 6f 20 74  isHighlight to t
6e20: 72 75 65 20 69 66 20 74 68 69 73 20 74 65 72 6d  rue if this term
6e30: 20 73 68 6f 75 6c 64 20 62 65 20 68 69 67 68 6c   should be highl
6e40: 69 67 68 74 65 64 2e 20 2a 2f 0a 20 20 20 20 69  ighted. */.    i
6e50: 73 48 69 67 68 6c 69 67 68 74 20 3d 20 28 68 6c  sHighlight = (hl
6e60: 6d 61 73 6b 20 26 20 28 28 75 36 34 29 31 20 3c  mask & ((u64)1 <
6e70: 3c 20 28 69 43 75 72 72 65 6e 74 2d 69 50 6f 73  < (iCurrent-iPos
6e80: 29 29 29 21 3d 30 3b 0a 0a 20 20 20 20 69 66 28  )))!=0;..    if(
6e90: 20 69 43 75 72 72 65 6e 74 3e 69 50 6f 73 20 29   iCurrent>iPos )
6ea0: 20 72 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67   rc = fts3String
6eb0: 41 70 70 65 6e 64 28 70 4f 75 74 2c 20 26 7a 44  Append(pOut, &zD
6ec0: 6f 63 5b 69 45 6e 64 5d 2c 20 69 42 65 67 69 6e  oc[iEnd], iBegin
6ed0: 2d 69 45 6e 64 29 3b 0a 20 20 20 20 69 66 28 20  -iEnd);.    if( 
6ee0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
6ef0: 20 69 73 48 69 67 68 6c 69 67 68 74 20 29 20 72   isHighlight ) r
6f00: 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67 41 70  c = fts3StringAp
6f10: 70 65 6e 64 28 70 4f 75 74 2c 20 7a 4f 70 65 6e  pend(pOut, zOpen
6f20: 2c 20 2d 31 29 3b 0a 20 20 20 20 69 66 28 20 72  , -1);.    if( r
6f30: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72  c==SQLITE_OK ) r
6f40: 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67 41 70  c = fts3StringAp
6f50: 70 65 6e 64 28 70 4f 75 74 2c 20 26 7a 44 6f 63  pend(pOut, &zDoc
6f60: 5b 69 42 65 67 69 6e 5d 2c 20 69 46 69 6e 2d 69  [iBegin], iFin-i
6f70: 42 65 67 69 6e 29 3b 0a 20 20 20 20 69 66 28 20  Begin);.    if( 
6f80: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
6f90: 20 69 73 48 69 67 68 6c 69 67 68 74 20 29 20 72   isHighlight ) r
6fa0: 63 20 3d 20 66 74 73 33 53 74 72 69 6e 67 41 70  c = fts3StringAp
6fb0: 70 65 6e 64 28 70 4f 75 74 2c 20 7a 43 6c 6f 73  pend(pOut, zClos
6fc0: 65 2c 20 2d 31 29 3b 0a 0a 20 20 20 20 69 45 6e  e, -1);..    iEn
6fd0: 64 20 3d 20 69 46 69 6e 3b 0a 20 20 7d 0a 0a 20  d = iFin;.  }.. 
6fe0: 20 70 4d 6f 64 2d 3e 78 43 6c 6f 73 65 28 70 43   pMod->xClose(pC
6ff0: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
7000: 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66  }.../*.** This f
7010: 75 6e 63 74 69 6f 6e 20 69 73 20 75 73 65 64 20  unction is used 
7020: 74 6f 20 63 6f 75 6e 74 20 74 68 65 20 65 6e 74  to count the ent
7030: 72 69 65 73 20 69 6e 20 61 20 63 6f 6c 75 6d 6e  ries in a column
7040: 2d 6c 69 73 74 20 28 61 20 0a 2a 2a 20 64 65 6c  -list (a .** del
7050: 74 61 2d 65 6e 63 6f 64 65 64 20 6c 69 73 74 20  ta-encoded list 
7060: 6f 66 20 74 65 72 6d 20 6f 66 66 73 65 74 73 20  of term offsets 
7070: 77 69 74 68 69 6e 20 61 20 73 69 6e 67 6c 65 20  within a single 
7080: 63 6f 6c 75 6d 6e 20 6f 66 20 61 20 73 69 6e 67  column of a sing
7090: 6c 65 20 0a 2a 2a 20 72 6f 77 29 2e 20 57 68 65  le .** row). Whe
70a0: 6e 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20  n this function 
70b0: 69 73 20 63 61 6c 6c 65 64 2c 20 2a 70 70 43 6f  is called, *ppCo
70c0: 6c 6c 69 73 74 20 73 68 6f 75 6c 64 20 70 6f 69  llist should poi
70d0: 6e 74 20 74 6f 20 74 68 65 0a 2a 2a 20 62 65 67  nt to the.** beg
70e0: 69 6e 6e 69 6e 67 20 6f 66 20 74 68 65 20 66 69  inning of the fi
70f0: 72 73 74 20 76 61 72 69 6e 74 20 69 6e 20 74 68  rst varint in th
7100: 65 20 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 28 74  e column-list (t
7110: 68 65 20 76 61 72 69 6e 74 20 74 68 61 74 0a 2a  he varint that.*
7120: 2a 20 63 6f 6e 74 61 69 6e 73 20 74 68 65 20 70  * contains the p
7130: 6f 73 69 74 69 6f 6e 20 6f 66 20 74 68 65 20 66  osition of the f
7140: 69 72 73 74 20 6d 61 74 63 68 69 6e 67 20 74 65  irst matching te
7150: 72 6d 20 69 6e 20 74 68 65 20 63 6f 6c 75 6d 6e  rm in the column
7160: 20 64 61 74 61 29 2e 0a 2a 2a 20 42 65 66 6f 72   data)..** Befor
7170: 65 20 72 65 74 75 72 6e 69 6e 67 2c 20 2a 70 70  e returning, *pp
7180: 43 6f 6c 6c 69 73 74 20 69 73 20 73 65 74 20 74  Collist is set t
7190: 6f 20 70 6f 69 6e 74 20 74 6f 20 74 68 65 20 66  o point to the f
71a0: 69 72 73 74 20 62 79 74 65 20 61 66 74 65 72 0a  irst byte after.
71b0: 2a 2a 20 74 68 65 20 6c 61 73 74 20 76 61 72 69  ** the last vari
71c0: 6e 74 20 69 6e 20 74 68 65 20 63 6f 6c 75 6d 6e  nt in the column
71d0: 2d 6c 69 73 74 20 28 65 69 74 68 65 72 20 74 68  -list (either th
71e0: 65 20 30 78 30 30 20 73 69 67 6e 69 66 79 69 6e  e 0x00 signifyin
71f0: 67 20 74 68 65 20 65 6e 64 0a 2a 2a 20 6f 66 20  g the end.** of 
7200: 74 68 65 20 70 6f 73 69 74 69 6f 6e 2d 6c 69 73  the position-lis
7210: 74 2c 20 6f 72 20 74 68 65 20 30 78 30 31 20 74  t, or the 0x01 t
7220: 68 61 74 20 70 72 65 63 65 64 65 73 20 74 68 65  hat precedes the
7230: 20 63 6f 6c 75 6d 6e 20 6e 75 6d 62 65 72 20 6f   column number o
7240: 66 0a 2a 2a 20 74 68 65 20 6e 65 78 74 20 63 6f  f.** the next co
7250: 6c 75 6d 6e 20 69 6e 20 74 68 65 20 70 6f 73 69  lumn in the posi
7260: 74 69 6f 6e 2d 6c 69 73 74 29 2e 0a 2a 2a 0a 2a  tion-list)..**.*
7270: 2a 20 54 68 65 20 6e 75 6d 62 65 72 20 6f 66 20  * The number of 
7280: 65 6c 65 6d 65 6e 74 73 20 69 6e 20 74 68 65 20  elements in the 
7290: 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 69 73 20 72  column-list is r
72a0: 65 74 75 72 6e 65 64 2e 0a 2a 2f 0a 73 74 61 74  eturned..*/.stat
72b0: 69 63 20 69 6e 74 20 66 74 73 33 43 6f 6c 75 6d  ic int fts3Colum
72c0: 6e 6c 69 73 74 43 6f 75 6e 74 28 63 68 61 72 20  nlistCount(char 
72d0: 2a 2a 70 70 43 6f 6c 6c 69 73 74 29 7b 0a 20 20  **ppCollist){.  
72e0: 63 68 61 72 20 2a 70 45 6e 64 20 3d 20 2a 70 70  char *pEnd = *pp
72f0: 43 6f 6c 6c 69 73 74 3b 0a 20 20 63 68 61 72 20  Collist;.  char 
7300: 63 20 3d 20 30 3b 0a 20 20 69 6e 74 20 6e 45 6e  c = 0;.  int nEn
7310: 74 72 79 20 3d 20 30 3b 0a 0a 20 20 2f 2a 20 41  try = 0;..  /* A
7320: 20 63 6f 6c 75 6d 6e 2d 6c 69 73 74 20 69 73 20   column-list is 
7330: 74 65 72 6d 69 6e 61 74 65 64 20 62 79 20 65 69  terminated by ei
7340: 74 68 65 72 20 61 20 30 78 30 31 20 6f 72 20 30  ther a 0x01 or 0
7350: 78 30 30 2e 20 2a 2f 0a 20 20 77 68 69 6c 65 28  x00. */.  while(
7360: 20 30 78 46 45 20 26 20 28 2a 70 45 6e 64 20 7c   0xFE & (*pEnd |
7370: 20 63 29 20 29 7b 0a 20 20 20 20 63 20 3d 20 2a   c) ){.    c = *
7380: 70 45 6e 64 2b 2b 20 26 20 30 78 38 30 3b 0a 20  pEnd++ & 0x80;. 
7390: 20 20 20 69 66 28 20 21 63 20 29 20 6e 45 6e 74     if( !c ) nEnt
73a0: 72 79 2b 2b 3b 0a 20 20 7d 0a 0a 20 20 2a 70 70  ry++;.  }..  *pp
73b0: 43 6f 6c 6c 69 73 74 20 3d 20 70 45 6e 64 3b 0a  Collist = pEnd;.
73c0: 20 20 72 65 74 75 72 6e 20 6e 45 6e 74 72 79 3b    return nEntry;
73d0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66  .}../*.** This f
73e0: 75 6e 63 74 69 6f 6e 20 67 61 74 68 65 72 73 20  unction gathers 
73f0: 27 79 27 20 6f 72 20 27 62 27 20 64 61 74 61 20  'y' or 'b' data 
7400: 66 6f 72 20 61 20 73 69 6e 67 6c 65 20 70 68 72  for a single phr
7410: 61 73 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ase..*/.static i
7420: 6e 74 20 66 74 73 33 45 78 70 72 4c 48 69 74 73  nt fts3ExprLHits
7430: 28 0a 20 20 46 74 73 33 45 78 70 72 20 2a 70 45  (.  Fts3Expr *pE
7440: 78 70 72 2c 20 20 20 20 20 20 20 20 20 20 20 20  xpr,            
7450: 20 20 20 20 2f 2a 20 50 68 72 61 73 65 20 65 78      /* Phrase ex
7460: 70 72 65 73 73 69 6f 6e 20 6e 6f 64 65 20 2a 2f  pression node */
7470: 0a 20 20 4d 61 74 63 68 49 6e 66 6f 20 2a 70 20  .  MatchInfo *p 
7480: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7490: 20 20 20 2f 2a 20 4d 61 74 63 68 69 6e 66 6f 20     /* Matchinfo 
74a0: 63 6f 6e 74 65 78 74 20 2a 2f 0a 29 7b 0a 20 20  context */.){.  
74b0: 46 74 73 33 54 61 62 6c 65 20 2a 70 54 61 62 20  Fts3Table *pTab 
74c0: 3d 20 28 46 74 73 33 54 61 62 6c 65 20 2a 29 70  = (Fts3Table *)p
74d0: 2d 3e 70 43 75 72 73 6f 72 2d 3e 62 61 73 65 2e  ->pCursor->base.
74e0: 70 56 74 61 62 3b 0a 20 20 69 6e 74 20 69 53 74  pVtab;.  int iSt
74f0: 61 72 74 3b 0a 20 20 46 74 73 33 50 68 72 61 73  art;.  Fts3Phras
7500: 65 20 2a 70 50 68 72 61 73 65 20 3d 20 70 45 78  e *pPhrase = pEx
7510: 70 72 2d 3e 70 50 68 72 61 73 65 3b 0a 20 20 63  pr->pPhrase;.  c
7520: 68 61 72 20 2a 70 49 74 65 72 20 3d 20 70 50 68  har *pIter = pPh
7530: 72 61 73 65 2d 3e 64 6f 63 6c 69 73 74 2e 70 4c  rase->doclist.pL
7540: 69 73 74 3b 0a 20 20 69 6e 74 20 69 43 6f 6c 20  ist;.  int iCol 
7550: 3d 20 30 3b 0a 0a 20 20 61 73 73 65 72 74 28 20  = 0;..  assert( 
7560: 70 2d 3e 66 6c 61 67 3d 3d 46 54 53 33 5f 4d 41  p->flag==FTS3_MA
7570: 54 43 48 49 4e 46 4f 5f 4c 48 49 54 53 5f 42 4d  TCHINFO_LHITS_BM
7580: 20 7c 7c 20 70 2d 3e 66 6c 61 67 3d 3d 46 54 53   || p->flag==FTS
7590: 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c 48 49 54  3_MATCHINFO_LHIT
75a0: 53 20 29 3b 0a 20 20 69 66 28 20 70 2d 3e 66 6c  S );.  if( p->fl
75b0: 61 67 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e  ag==FTS3_MATCHIN
75c0: 46 4f 5f 4c 48 49 54 53 20 29 7b 0a 20 20 20 20  FO_LHITS ){.    
75d0: 69 53 74 61 72 74 20 3d 20 70 45 78 70 72 2d 3e  iStart = pExpr->
75e0: 69 50 68 72 61 73 65 20 2a 20 70 2d 3e 6e 43 6f  iPhrase * p->nCo
75f0: 6c 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  l;.  }else{.    
7600: 69 53 74 61 72 74 20 3d 20 70 45 78 70 72 2d 3e  iStart = pExpr->
7610: 69 50 68 72 61 73 65 20 2a 20 28 28 70 2d 3e 6e  iPhrase * ((p->n
7620: 43 6f 6c 20 2b 20 33 31 29 20 2f 20 33 32 29 3b  Col + 31) / 32);
7630: 0a 20 20 7d 0a 0a 20 20 77 68 69 6c 65 28 20 31  .  }..  while( 1
7640: 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e 48 69 74   ){.    int nHit
7650: 20 3d 20 66 74 73 33 43 6f 6c 75 6d 6e 6c 69 73   = fts3Columnlis
7660: 74 43 6f 75 6e 74 28 26 70 49 74 65 72 29 3b 0a  tCount(&pIter);.
7670: 20 20 20 20 69 66 28 20 28 70 50 68 72 61 73 65      if( (pPhrase
7680: 2d 3e 69 43 6f 6c 75 6d 6e 3e 3d 70 54 61 62 2d  ->iColumn>=pTab-
7690: 3e 6e 43 6f 6c 75 6d 6e 20 7c 7c 20 70 50 68 72  >nColumn || pPhr
76a0: 61 73 65 2d 3e 69 43 6f 6c 75 6d 6e 3d 3d 69 43  ase->iColumn==iC
76b0: 6f 6c 29 20 29 7b 0a 20 20 20 20 20 20 69 66 28  ol) ){.      if(
76c0: 20 70 2d 3e 66 6c 61 67 3d 3d 46 54 53 33 5f 4d   p->flag==FTS3_M
76d0: 41 54 43 48 49 4e 46 4f 5f 4c 48 49 54 53 20 29  ATCHINFO_LHITS )
76e0: 7b 0a 20 20 20 20 20 20 20 20 70 2d 3e 61 4d 61  {.        p->aMa
76f0: 74 63 68 69 6e 66 6f 5b 69 53 74 61 72 74 20 2b  tchinfo[iStart +
7700: 20 69 43 6f 6c 5d 20 3d 20 28 75 33 32 29 6e 48   iCol] = (u32)nH
7710: 69 74 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 20  it;.      }else 
7720: 69 66 28 20 6e 48 69 74 20 29 7b 0a 20 20 20 20  if( nHit ){.    
7730: 20 20 20 20 70 2d 3e 61 4d 61 74 63 68 69 6e 66      p->aMatchinf
7740: 6f 5b 69 53 74 61 72 74 20 2b 20 28 69 43 6f 6c  o[iStart + (iCol
7750: 2b 31 29 2f 33 32 5d 20 7c 3d 20 28 31 20 3c 3c  +1)/32] |= (1 <<
7760: 20 28 69 43 6f 6c 26 30 78 31 46 29 29 3b 0a 20   (iCol&0x1F));. 
7770: 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20       }.    }.   
7780: 20 61 73 73 65 72 74 28 20 2a 70 49 74 65 72 3d   assert( *pIter=
7790: 3d 30 78 30 30 20 7c 7c 20 2a 70 49 74 65 72 3d  =0x00 || *pIter=
77a0: 3d 30 78 30 31 20 29 3b 0a 20 20 20 20 69 66 28  =0x01 );.    if(
77b0: 20 2a 70 49 74 65 72 21 3d 30 78 30 31 20 29 20   *pIter!=0x01 ) 
77c0: 62 72 65 61 6b 3b 0a 20 20 20 20 70 49 74 65 72  break;.    pIter
77d0: 2b 2b 3b 0a 20 20 20 20 70 49 74 65 72 20 2b 3d  ++;.    pIter +=
77e0: 20 66 74 73 33 47 65 74 56 61 72 69 6e 74 33 32   fts3GetVarint32
77f0: 28 70 49 74 65 72 2c 20 26 69 43 6f 6c 29 3b 0a  (pIter, &iCol);.
7800: 20 20 20 20 69 66 28 20 69 43 6f 6c 3e 3d 70 2d      if( iCol>=p-
7810: 3e 6e 43 6f 6c 20 29 20 72 65 74 75 72 6e 20 46  >nCol ) return F
7820: 54 53 5f 43 4f 52 52 55 50 54 5f 56 54 41 42 3b  TS_CORRUPT_VTAB;
7830: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51  .  }.  return SQ
7840: 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a  LITE_OK;.}../*.*
7850: 2a 20 47 61 74 68 65 72 20 74 68 65 20 72 65 73  * Gather the res
7860: 75 6c 74 73 20 66 6f 72 20 6d 61 74 63 68 69 6e  ults for matchin
7870: 66 6f 20 64 69 72 65 63 74 69 76 65 73 20 27 79  fo directives 'y
7880: 27 20 61 6e 64 20 27 62 27 2e 0a 2a 2f 0a 73 74  ' and 'b'..*/.st
7890: 61 74 69 63 20 69 6e 74 20 66 74 73 33 45 78 70  atic int fts3Exp
78a0: 72 4c 48 69 74 47 61 74 68 65 72 28 0a 20 20 46  rLHitGather(.  F
78b0: 74 73 33 45 78 70 72 20 2a 70 45 78 70 72 2c 0a  ts3Expr *pExpr,.
78c0: 20 20 4d 61 74 63 68 49 6e 66 6f 20 2a 70 0a 29    MatchInfo *p.)
78d0: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  {.  int rc = SQL
78e0: 49 54 45 5f 4f 4b 3b 0a 20 20 61 73 73 65 72 74  ITE_OK;.  assert
78f0: 28 20 28 70 45 78 70 72 2d 3e 70 4c 65 66 74 3d  ( (pExpr->pLeft=
7900: 3d 30 29 3d 3d 28 70 45 78 70 72 2d 3e 70 52 69  =0)==(pExpr->pRi
7910: 67 68 74 3d 3d 30 29 20 29 3b 0a 20 20 69 66 28  ght==0) );.  if(
7920: 20 70 45 78 70 72 2d 3e 62 45 6f 66 3d 3d 30 20   pExpr->bEof==0 
7930: 26 26 20 70 45 78 70 72 2d 3e 69 44 6f 63 69 64  && pExpr->iDocid
7940: 3d 3d 70 2d 3e 70 43 75 72 73 6f 72 2d 3e 69 50  ==p->pCursor->iP
7950: 72 65 76 49 64 20 29 7b 0a 20 20 20 20 69 66 28  revId ){.    if(
7960: 20 70 45 78 70 72 2d 3e 70 4c 65 66 74 20 29 7b   pExpr->pLeft ){
7970: 0a 20 20 20 20 20 20 72 63 20 3d 20 66 74 73 33  .      rc = fts3
7980: 45 78 70 72 4c 48 69 74 47 61 74 68 65 72 28 70  ExprLHitGather(p
7990: 45 78 70 72 2d 3e 70 4c 65 66 74 2c 20 70 29 3b  Expr->pLeft, p);
79a0: 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53  .      if( rc==S
79b0: 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63 20 3d 20  QLITE_OK ) rc = 
79c0: 66 74 73 33 45 78 70 72 4c 48 69 74 47 61 74 68  fts3ExprLHitGath
79d0: 65 72 28 70 45 78 70 72 2d 3e 70 52 69 67 68 74  er(pExpr->pRight
79e0: 2c 20 70 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  , p);.    }else{
79f0: 0a 20 20 20 20 20 20 72 63 20 3d 20 66 74 73 33  .      rc = fts3
7a00: 45 78 70 72 4c 48 69 74 73 28 70 45 78 70 72 2c  ExprLHits(pExpr,
7a10: 20 70 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20   p);.    }.  }. 
7a20: 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f   return rc;.}../
7a30: 2a 0a 2a 2a 20 66 74 73 33 45 78 70 72 49 74 65  *.** fts3ExprIte
7a40: 72 61 74 65 28 29 20 63 61 6c 6c 62 61 63 6b 20  rate() callback 
7a50: 75 73 65 64 20 74 6f 20 63 6f 6c 6c 65 63 74 20  used to collect 
7a60: 74 68 65 20 22 67 6c 6f 62 61 6c 22 20 6d 61 74  the "global" mat
7a70: 63 68 69 6e 66 6f 20 73 74 61 74 73 0a 2a 2a 20  chinfo stats.** 
7a80: 66 6f 72 20 61 20 73 69 6e 67 6c 65 20 71 75 65  for a single que
7a90: 72 79 2e 20 0a 2a 2a 0a 2a 2a 20 66 74 73 33 45  ry. .**.** fts3E
7aa0: 78 70 72 49 74 65 72 61 74 65 28 29 20 63 61 6c  xprIterate() cal
7ab0: 6c 62 61 63 6b 20 74 6f 20 6c 6f 61 64 20 74 68  lback to load th
7ac0: 65 20 27 67 6c 6f 62 61 6c 27 20 65 6c 65 6d 65  e 'global' eleme
7ad0: 6e 74 73 20 6f 66 20 61 0a 2a 2a 20 46 54 53 33  nts of a.** FTS3
7ae0: 5f 4d 41 54 43 48 49 4e 46 4f 5f 48 49 54 53 20  _MATCHINFO_HITS 
7af0: 6d 61 74 63 68 69 6e 66 6f 20 61 72 72 61 79 2e  matchinfo array.
7b00: 20 54 68 65 20 67 6c 6f 62 61 6c 20 73 74 61 74   The global stat
7b10: 73 20 61 72 65 20 74 68 6f 73 65 20 65 6c 65 6d  s are those elem
7b20: 65 6e 74 73 20 0a 2a 2a 20 6f 66 20 74 68 65 20  ents .** of the 
7b30: 6d 61 74 63 68 69 6e 66 6f 20 61 72 72 61 79 20  matchinfo array 
7b40: 74 68 61 74 20 61 72 65 20 63 6f 6e 73 74 61 6e  that are constan
7b50: 74 20 66 6f 72 20 61 6c 6c 20 72 6f 77 73 20 72  t for all rows r
7b60: 65 74 75 72 6e 65 64 20 62 79 20 74 68 65 20 0a  eturned by the .
7b70: 2a 2a 20 63 75 72 72 65 6e 74 20 71 75 65 72 79  ** current query
7b80: 2e 0a 2a 2a 0a 2a 2a 20 41 72 67 75 6d 65 6e 74  ..**.** Argument
7b90: 20 70 43 74 78 20 69 73 20 61 63 74 75 61 6c 6c   pCtx is actuall
7ba0: 79 20 61 20 70 6f 69 6e 74 65 72 20 74 6f 20 61  y a pointer to a
7bb0: 20 73 74 72 75 63 74 20 6f 66 20 74 79 70 65 20   struct of type 
7bc0: 4d 61 74 63 68 49 6e 66 6f 2e 20 54 68 69 73 0a  MatchInfo. This.
7bd0: 2a 2a 20 66 75 6e 63 74 69 6f 6e 20 70 6f 70 75  ** function popu
7be0: 6c 61 74 65 73 20 4d 61 74 63 68 69 6e 66 6f 2e  lates Matchinfo.
7bf0: 61 4d 61 74 63 68 69 6e 66 6f 5b 5d 20 61 73 20  aMatchinfo[] as 
7c00: 66 6f 6c 6c 6f 77 73 3a 0a 2a 2a 0a 2a 2a 20 20  follows:.**.**  
7c10: 20 66 6f 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f   for(iCol=0; iCo
7c20: 6c 3c 6e 43 6f 6c 3b 20 69 43 6f 6c 2b 2b 29 7b  l<nCol; iCol++){
7c30: 0a 2a 2a 20 20 20 20 20 61 4d 61 74 63 68 69 6e  .**     aMatchin
7c40: 66 6f 5b 33 2a 69 50 68 72 61 73 65 2a 6e 43 6f  fo[3*iPhrase*nCo
7c50: 6c 20 2b 20 33 2a 69 43 6f 6c 20 2b 20 31 5d 20  l + 3*iCol + 1] 
7c60: 3d 20 58 3b 0a 2a 2a 20 20 20 20 20 61 4d 61 74  = X;.**     aMat
7c70: 63 68 69 6e 66 6f 5b 33 2a 69 50 68 72 61 73 65  chinfo[3*iPhrase
7c80: 2a 6e 43 6f 6c 20 2b 20 33 2a 69 43 6f 6c 20 2b  *nCol + 3*iCol +
7c90: 20 32 5d 20 3d 20 59 3b 0a 2a 2a 20 20 20 7d 0a   2] = Y;.**   }.
7ca0: 2a 2a 0a 2a 2a 20 77 68 65 72 65 20 58 20 69 73  **.** where X is
7cb0: 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 6d   the number of m
7cc0: 61 74 63 68 65 73 20 66 6f 72 20 70 68 72 61 73  atches for phras
7cd0: 65 20 69 50 68 72 61 73 65 20 69 73 20 63 6f 6c  e iPhrase is col
7ce0: 75 6d 6e 20 69 43 6f 6c 20 6f 66 20 61 6c 6c 0a  umn iCol of all.
7cf0: 2a 2a 20 72 6f 77 73 20 6f 66 20 74 68 65 20 74  ** rows of the t
7d00: 61 62 6c 65 2e 20 59 20 69 73 20 74 68 65 20 6e  able. Y is the n
7d10: 75 6d 62 65 72 20 6f 66 20 72 6f 77 73 20 66 6f  umber of rows fo
7d20: 72 20 77 68 69 63 68 20 63 6f 6c 75 6d 6e 20 69  r which column i
7d30: 43 6f 6c 20 63 6f 6e 74 61 69 6e 73 0a 2a 2a 20  Col contains.** 
7d40: 61 74 20 6c 65 61 73 74 20 6f 6e 65 20 69 6e 73  at least one ins
7d50: 74 61 6e 63 65 20 6f 66 20 70 68 72 61 73 65 20  tance of phrase 
7d60: 69 50 68 72 61 73 65 2e 0a 2a 2a 0a 2a 2a 20 49  iPhrase..**.** I
7d70: 66 20 74 68 65 20 70 68 72 61 73 65 20 70 45 78  f the phrase pEx
7d80: 70 72 20 63 6f 6e 73 69 73 74 73 20 65 6e 74 69  pr consists enti
7d90: 72 65 6c 79 20 6f 66 20 64 65 66 65 72 72 65 64  rely of deferred
7da0: 20 74 6f 6b 65 6e 73 2c 20 74 68 65 6e 20 61 6c   tokens, then al
7db0: 6c 20 58 20 61 6e 64 0a 2a 2a 20 59 20 76 61 6c  l X and.** Y val
7dc0: 75 65 73 20 61 72 65 20 73 65 74 20 74 6f 20 6e  ues are set to n
7dd0: 44 6f 63 2c 20 77 68 65 72 65 20 6e 44 6f 63 20  Doc, where nDoc 
7de0: 69 73 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66  is the number of
7df0: 20 64 6f 63 75 6d 65 6e 74 73 20 69 6e 20 74 68   documents in th
7e00: 65 20 0a 2a 2a 20 66 69 6c 65 20 73 79 73 74 65  e .** file syste
7e10: 6d 2e 20 54 68 69 73 20 69 73 20 64 6f 6e 65 20  m. This is done 
7e20: 62 65 63 61 75 73 65 20 74 68 65 20 66 75 6c 6c  because the full
7e30: 2d 74 65 78 74 20 69 6e 64 65 78 20 64 6f 63 6c  -text index docl
7e40: 69 73 74 20 69 73 20 72 65 71 75 69 72 65 64 0a  ist is required.
7e50: 2a 2a 20 74 6f 20 63 61 6c 63 75 6c 61 74 65 20  ** to calculate 
7e60: 74 68 65 73 65 20 76 61 6c 75 65 73 20 70 72 6f  these values pro
7e70: 70 65 72 6c 79 2c 20 61 6e 64 20 74 68 65 20 66  perly, and the f
7e80: 75 6c 6c 2d 74 65 78 74 20 69 6e 64 65 78 20 64  ull-text index d
7e90: 6f 63 6c 69 73 74 20 69 73 0a 2a 2a 20 6e 6f 74  oclist is.** not
7ea0: 20 61 76 61 69 6c 61 62 6c 65 20 66 6f 72 20 64   available for d
7eb0: 65 66 65 72 72 65 64 20 74 6f 6b 65 6e 73 2e 0a  eferred tokens..
7ec0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74  */.static int ft
7ed0: 73 33 45 78 70 72 47 6c 6f 62 61 6c 48 69 74 73  s3ExprGlobalHits
7ee0: 43 62 28 0a 20 20 46 74 73 33 45 78 70 72 20 2a  Cb(.  Fts3Expr *
7ef0: 70 45 78 70 72 2c 20 20 20 20 20 20 20 20 20 20  pExpr,          
7f00: 20 20 20 20 20 20 2f 2a 20 50 68 72 61 73 65 20        /* Phrase 
7f10: 65 78 70 72 65 73 73 69 6f 6e 20 6e 6f 64 65 20  expression node 
7f20: 2a 2f 0a 20 20 69 6e 74 20 69 50 68 72 61 73 65  */.  int iPhrase
7f30: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
7f40: 20 20 20 20 20 2f 2a 20 50 68 72 61 73 65 20 6e       /* Phrase n
7f50: 75 6d 62 65 72 20 28 6e 75 6d 62 65 72 65 64 20  umber (numbered 
7f60: 66 72 6f 6d 20 7a 65 72 6f 29 20 2a 2f 0a 20 20  from zero) */.  
7f70: 76 6f 69 64 20 2a 70 43 74 78 20 20 20 20 20 20  void *pCtx      
7f80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7f90: 2f 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20 4d 61  /* Pointer to Ma
7fa0: 74 63 68 49 6e 66 6f 20 73 74 72 75 63 74 75 72  tchInfo structur
7fb0: 65 20 2a 2f 0a 29 7b 0a 20 20 4d 61 74 63 68 49  e */.){.  MatchI
7fc0: 6e 66 6f 20 2a 70 20 3d 20 28 4d 61 74 63 68 49  nfo *p = (MatchI
7fd0: 6e 66 6f 20 2a 29 70 43 74 78 3b 0a 20 20 72 65  nfo *)pCtx;.  re
7fe0: 74 75 72 6e 20 73 71 6c 69 74 65 33 46 74 73 33  turn sqlite3Fts3
7ff0: 45 76 61 6c 50 68 72 61 73 65 53 74 61 74 73 28  EvalPhraseStats(
8000: 0a 20 20 20 20 20 20 70 2d 3e 70 43 75 72 73 6f  .      p->pCurso
8010: 72 2c 20 70 45 78 70 72 2c 20 26 70 2d 3e 61 4d  r, pExpr, &p->aM
8020: 61 74 63 68 69 6e 66 6f 5b 33 2a 69 50 68 72 61  atchinfo[3*iPhra
8030: 73 65 2a 70 2d 3e 6e 43 6f 6c 5d 0a 20 20 29 3b  se*p->nCol].  );
8040: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 66 74 73 33 45 78  .}../*.** fts3Ex
8050: 70 72 49 74 65 72 61 74 65 28 29 20 63 61 6c 6c  prIterate() call
8060: 62 61 63 6b 20 75 73 65 64 20 74 6f 20 63 6f 6c  back used to col
8070: 6c 65 63 74 20 74 68 65 20 22 6c 6f 63 61 6c 22  lect the "local"
8080: 20 70 61 72 74 20 6f 66 20 74 68 65 0a 2a 2a 20   part of the.** 
8090: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 48  FTS3_MATCHINFO_H
80a0: 49 54 53 20 61 72 72 61 79 2e 20 54 68 65 20 6c  ITS array. The l
80b0: 6f 63 61 6c 20 73 74 61 74 73 20 61 72 65 20 74  ocal stats are t
80c0: 68 6f 73 65 20 65 6c 65 6d 65 6e 74 73 20 6f 66  hose elements of
80d0: 20 74 68 65 20 0a 2a 2a 20 61 72 72 61 79 20 74   the .** array t
80e0: 68 61 74 20 61 72 65 20 64 69 66 66 65 72 65 6e  hat are differen
80f0: 74 20 66 6f 72 20 65 61 63 68 20 72 6f 77 20 72  t for each row r
8100: 65 74 75 72 6e 65 64 20 62 79 20 74 68 65 20 71  eturned by the q
8110: 75 65 72 79 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  uery..*/.static 
8120: 69 6e 74 20 66 74 73 33 45 78 70 72 4c 6f 63 61  int fts3ExprLoca
8130: 6c 48 69 74 73 43 62 28 0a 20 20 46 74 73 33 45  lHitsCb(.  Fts3E
8140: 78 70 72 20 2a 70 45 78 70 72 2c 20 20 20 20 20  xpr *pExpr,     
8150: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 68             /* Ph
8160: 72 61 73 65 20 65 78 70 72 65 73 73 69 6f 6e 20  rase expression 
8170: 6e 6f 64 65 20 2a 2f 0a 20 20 69 6e 74 20 69 50  node */.  int iP
8180: 68 72 61 73 65 2c 20 20 20 20 20 20 20 20 20 20  hrase,          
8190: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 68 72            /* Phr
81a0: 61 73 65 20 6e 75 6d 62 65 72 20 2a 2f 0a 20 20  ase number */.  
81b0: 76 6f 69 64 20 2a 70 43 74 78 20 20 20 20 20 20  void *pCtx      
81c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
81d0: 2f 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20 4d 61  /* Pointer to Ma
81e0: 74 63 68 49 6e 66 6f 20 73 74 72 75 63 74 75 72  tchInfo structur
81f0: 65 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 72 63  e */.){.  int rc
8200: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20   = SQLITE_OK;.  
8210: 4d 61 74 63 68 49 6e 66 6f 20 2a 70 20 3d 20 28  MatchInfo *p = (
8220: 4d 61 74 63 68 49 6e 66 6f 20 2a 29 70 43 74 78  MatchInfo *)pCtx
8230: 3b 0a 20 20 69 6e 74 20 69 53 74 61 72 74 20 3d  ;.  int iStart =
8240: 20 69 50 68 72 61 73 65 20 2a 20 70 2d 3e 6e 43   iPhrase * p->nC
8250: 6f 6c 20 2a 20 33 3b 0a 20 20 69 6e 74 20 69 3b  ol * 3;.  int i;
8260: 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70  ..  for(i=0; i<p
8270: 2d 3e 6e 43 6f 6c 20 26 26 20 72 63 3d 3d 53 51  ->nCol && rc==SQ
8280: 4c 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b 0a 20  LITE_OK; i++){. 
8290: 20 20 20 63 68 61 72 20 2a 70 43 73 72 3b 0a 20     char *pCsr;. 
82a0: 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 46     rc = sqlite3F
82b0: 74 73 33 45 76 61 6c 50 68 72 61 73 65 50 6f 73  ts3EvalPhrasePos
82c0: 6c 69 73 74 28 70 2d 3e 70 43 75 72 73 6f 72 2c  list(p->pCursor,
82d0: 20 70 45 78 70 72 2c 20 69 2c 20 26 70 43 73 72   pExpr, i, &pCsr
82e0: 29 3b 0a 20 20 20 20 69 66 28 20 70 43 73 72 20  );.    if( pCsr 
82f0: 29 7b 0a 20 20 20 20 20 20 70 2d 3e 61 4d 61 74  ){.      p->aMat
8300: 63 68 69 6e 66 6f 5b 69 53 74 61 72 74 2b 69 2a  chinfo[iStart+i*
8310: 33 5d 20 3d 20 66 74 73 33 43 6f 6c 75 6d 6e 6c  3] = fts3Columnl
8320: 69 73 74 43 6f 75 6e 74 28 26 70 43 73 72 29 3b  istCount(&pCsr);
8330: 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  .    }else{.    
8340: 20 20 70 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b    p->aMatchinfo[
8350: 69 53 74 61 72 74 2b 69 2a 33 5d 20 3d 20 30 3b  iStart+i*3] = 0;
8360: 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65  .    }.  }..  re
8370: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74  turn rc;.}..stat
8380: 69 63 20 69 6e 74 20 66 74 73 33 4d 61 74 63 68  ic int fts3Match
8390: 69 6e 66 6f 43 68 65 63 6b 28 0a 20 20 46 74 73  infoCheck(.  Fts
83a0: 33 54 61 62 6c 65 20 2a 70 54 61 62 2c 20 0a 20  3Table *pTab, . 
83b0: 20 63 68 61 72 20 63 41 72 67 2c 0a 20 20 63 68   char cArg,.  ch
83c0: 61 72 20 2a 2a 70 7a 45 72 72 0a 29 7b 0a 20 20  ar **pzErr.){.  
83d0: 69 66 28 20 28 63 41 72 67 3d 3d 46 54 53 33 5f  if( (cArg==FTS3_
83e0: 4d 41 54 43 48 49 4e 46 4f 5f 4e 50 48 52 41 53  MATCHINFO_NPHRAS
83f0: 45 29 0a 20 20 20 7c 7c 20 28 63 41 72 67 3d 3d  E).   || (cArg==
8400: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e  FTS3_MATCHINFO_N
8410: 43 4f 4c 29 0a 20 20 20 7c 7c 20 28 63 41 72 67  COL).   || (cArg
8420: 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f  ==FTS3_MATCHINFO
8430: 5f 4e 44 4f 43 20 26 26 20 70 54 61 62 2d 3e 62  _NDOC && pTab->b
8440: 46 74 73 34 29 0a 20 20 20 7c 7c 20 28 63 41 72  Fts4).   || (cAr
8450: 67 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  g==FTS3_MATCHINF
8460: 4f 5f 41 56 47 4c 45 4e 47 54 48 20 26 26 20 70  O_AVGLENGTH && p
8470: 54 61 62 2d 3e 62 46 74 73 34 29 0a 20 20 20 7c  Tab->bFts4).   |
8480: 7c 20 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41  | (cArg==FTS3_MA
8490: 54 43 48 49 4e 46 4f 5f 4c 45 4e 47 54 48 20 26  TCHINFO_LENGTH &
84a0: 26 20 70 54 61 62 2d 3e 62 48 61 73 44 6f 63 73  & pTab->bHasDocs
84b0: 69 7a 65 29 0a 20 20 20 7c 7c 20 28 63 41 72 67  ize).   || (cArg
84c0: 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f  ==FTS3_MATCHINFO
84d0: 5f 4c 43 53 29 0a 20 20 20 7c 7c 20 28 63 41 72  _LCS).   || (cAr
84e0: 67 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  g==FTS3_MATCHINF
84f0: 4f 5f 48 49 54 53 29 0a 20 20 20 7c 7c 20 28 63  O_HITS).   || (c
8500: 41 72 67 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49  Arg==FTS3_MATCHI
8510: 4e 46 4f 5f 4c 48 49 54 53 29 0a 20 20 20 7c 7c  NFO_LHITS).   ||
8520: 20 28 63 41 72 67 3d 3d 46 54 53 33 5f 4d 41 54   (cArg==FTS3_MAT
8530: 43 48 49 4e 46 4f 5f 4c 48 49 54 53 5f 42 4d 29  CHINFO_LHITS_BM)
8540: 0a 20 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  .  ){.    return
8550: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 7d 0a   SQLITE_OK;.  }.
8560: 20 20 73 71 6c 69 74 65 33 46 74 73 33 45 72 72    sqlite3Fts3Err
8570: 4d 73 67 28 70 7a 45 72 72 2c 20 22 75 6e 72 65  Msg(pzErr, "unre
8580: 63 6f 67 6e 69 7a 65 64 20 6d 61 74 63 68 69 6e  cognized matchin
8590: 66 6f 20 72 65 71 75 65 73 74 3a 20 25 63 22 2c  fo request: %c",
85a0: 20 63 41 72 67 29 3b 0a 20 20 72 65 74 75 72 6e   cArg);.  return
85b0: 20 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 7d   SQLITE_ERROR;.}
85c0: 0a 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74 73  ..static int fts
85d0: 33 4d 61 74 63 68 69 6e 66 6f 53 69 7a 65 28 4d  3MatchinfoSize(M
85e0: 61 74 63 68 49 6e 66 6f 20 2a 70 49 6e 66 6f 2c  atchInfo *pInfo,
85f0: 20 63 68 61 72 20 63 41 72 67 29 7b 0a 20 20 69   char cArg){.  i
8600: 6e 74 20 6e 56 61 6c 3b 20 20 20 20 20 20 20 20  nt nVal;        
8610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
8620: 2a 20 4e 75 6d 62 65 72 20 6f 66 20 69 6e 74 65  * Number of inte
8630: 67 65 72 73 20 6f 75 74 70 75 74 20 62 79 20 63  gers output by c
8640: 41 72 67 20 2a 2f 0a 0a 20 20 73 77 69 74 63 68  Arg */..  switch
8650: 28 20 63 41 72 67 20 29 7b 0a 20 20 20 20 63 61  ( cArg ){.    ca
8660: 73 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  se FTS3_MATCHINF
8670: 4f 5f 4e 44 4f 43 3a 0a 20 20 20 20 63 61 73 65  O_NDOC:.    case
8680: 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f   FTS3_MATCHINFO_
8690: 4e 50 48 52 41 53 45 3a 20 0a 20 20 20 20 63 61  NPHRASE: .    ca
86a0: 73 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  se FTS3_MATCHINF
86b0: 4f 5f 4e 43 4f 4c 3a 20 0a 20 20 20 20 20 20 6e  O_NCOL: .      n
86c0: 56 61 6c 20 3d 20 31 3b 0a 20 20 20 20 20 20 62  Val = 1;.      b
86d0: 72 65 61 6b 3b 0a 0a 20 20 20 20 63 61 73 65 20  reak;..    case 
86e0: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 41  FTS3_MATCHINFO_A
86f0: 56 47 4c 45 4e 47 54 48 3a 0a 20 20 20 20 63 61  VGLENGTH:.    ca
8700: 73 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  se FTS3_MATCHINF
8710: 4f 5f 4c 45 4e 47 54 48 3a 0a 20 20 20 20 63 61  O_LENGTH:.    ca
8720: 73 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46  se FTS3_MATCHINF
8730: 4f 5f 4c 43 53 3a 0a 20 20 20 20 20 20 6e 56 61  O_LCS:.      nVa
8740: 6c 20 3d 20 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 3b  l = pInfo->nCol;
8750: 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20  .      break;.. 
8760: 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54     case FTS3_MAT
8770: 43 48 49 4e 46 4f 5f 4c 48 49 54 53 3a 0a 20 20  CHINFO_LHITS:.  
8780: 20 20 20 20 6e 56 61 6c 20 3d 20 70 49 6e 66 6f      nVal = pInfo
8790: 2d 3e 6e 43 6f 6c 20 2a 20 70 49 6e 66 6f 2d 3e  ->nCol * pInfo->
87a0: 6e 50 68 72 61 73 65 3b 0a 20 20 20 20 20 20 62  nPhrase;.      b
87b0: 72 65 61 6b 3b 0a 0a 20 20 20 20 63 61 73 65 20  reak;..    case 
87c0: 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c  FTS3_MATCHINFO_L
87d0: 48 49 54 53 5f 42 4d 3a 0a 20 20 20 20 20 20 6e  HITS_BM:.      n
87e0: 56 61 6c 20 3d 20 70 49 6e 66 6f 2d 3e 6e 50 68  Val = pInfo->nPh
87f0: 72 61 73 65 20 2a 20 28 28 70 49 6e 66 6f 2d 3e  rase * ((pInfo->
8800: 6e 43 6f 6c 20 2b 20 33 31 29 20 2f 20 33 32 29  nCol + 31) / 32)
8810: 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a  ;.      break;..
8820: 20 20 20 20 64 65 66 61 75 6c 74 3a 0a 20 20 20      default:.   
8830: 20 20 20 61 73 73 65 72 74 28 20 63 41 72 67 3d     assert( cArg=
8840: 3d 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f  =FTS3_MATCHINFO_
8850: 48 49 54 53 20 29 3b 0a 20 20 20 20 20 20 6e 56  HITS );.      nV
8860: 61 6c 20 3d 20 70 49 6e 66 6f 2d 3e 6e 43 6f 6c  al = pInfo->nCol
8870: 20 2a 20 70 49 6e 66 6f 2d 3e 6e 50 68 72 61 73   * pInfo->nPhras
8880: 65 20 2a 20 33 3b 0a 20 20 20 20 20 20 62 72 65  e * 3;.      bre
8890: 61 6b 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72  ak;.  }..  retur
88a0: 6e 20 6e 56 61 6c 3b 0a 7d 0a 0a 73 74 61 74 69  n nVal;.}..stati
88b0: 63 20 69 6e 74 20 66 74 73 33 4d 61 74 63 68 69  c int fts3Matchi
88c0: 6e 66 6f 53 65 6c 65 63 74 44 6f 63 74 6f 74 61  nfoSelectDoctota
88d0: 6c 28 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a  l(.  Fts3Table *
88e0: 70 54 61 62 2c 0a 20 20 73 71 6c 69 74 65 33 5f  pTab,.  sqlite3_
88f0: 73 74 6d 74 20 2a 2a 70 70 53 74 6d 74 2c 0a 20  stmt **ppStmt,. 
8900: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 2a   sqlite3_int64 *
8910: 70 6e 44 6f 63 2c 0a 20 20 63 6f 6e 73 74 20 63  pnDoc,.  const c
8920: 68 61 72 20 2a 2a 70 61 4c 65 6e 0a 29 7b 0a 20  har **paLen.){. 
8930: 20 73 71 6c 69 74 65 33 5f 73 74 6d 74 20 2a 70   sqlite3_stmt *p
8940: 53 74 6d 74 3b 0a 20 20 63 6f 6e 73 74 20 63 68  Stmt;.  const ch
8950: 61 72 20 2a 61 3b 0a 20 20 73 71 6c 69 74 65 33  ar *a;.  sqlite3
8960: 5f 69 6e 74 36 34 20 6e 44 6f 63 3b 0a 0a 20 20  _int64 nDoc;..  
8970: 69 66 28 20 21 2a 70 70 53 74 6d 74 20 29 7b 0a  if( !*ppStmt ){.
8980: 20 20 20 20 69 6e 74 20 72 63 20 3d 20 73 71 6c      int rc = sql
8990: 69 74 65 33 46 74 73 33 53 65 6c 65 63 74 44 6f  ite3Fts3SelectDo
89a0: 63 74 6f 74 61 6c 28 70 54 61 62 2c 20 70 70 53  ctotal(pTab, ppS
89b0: 74 6d 74 29 3b 0a 20 20 20 20 69 66 28 20 72 63  tmt);.    if( rc
89c0: 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 65  !=SQLITE_OK ) re
89d0: 74 75 72 6e 20 72 63 3b 0a 20 20 7d 0a 20 20 70  turn rc;.  }.  p
89e0: 53 74 6d 74 20 3d 20 2a 70 70 53 74 6d 74 3b 0a  Stmt = *ppStmt;.
89f0: 20 20 61 73 73 65 72 74 28 20 73 71 6c 69 74 65    assert( sqlite
8a00: 33 5f 64 61 74 61 5f 63 6f 75 6e 74 28 70 53 74  3_data_count(pSt
8a10: 6d 74 29 3d 3d 31 20 29 3b 0a 0a 20 20 61 20 3d  mt)==1 );..  a =
8a20: 20 73 71 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f   sqlite3_column_
8a30: 62 6c 6f 62 28 70 53 74 6d 74 2c 20 30 29 3b 0a  blob(pStmt, 0);.
8a40: 20 20 61 20 2b 3d 20 73 71 6c 69 74 65 33 46 74    a += sqlite3Ft
8a50: 73 33 47 65 74 56 61 72 69 6e 74 28 61 2c 20 26  s3GetVarint(a, &
8a60: 6e 44 6f 63 29 3b 0a 20 20 69 66 28 20 6e 44 6f  nDoc);.  if( nDo
8a70: 63 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 46 54  c==0 ) return FT
8a80: 53 5f 43 4f 52 52 55 50 54 5f 56 54 41 42 3b 0a  S_CORRUPT_VTAB;.
8a90: 20 20 2a 70 6e 44 6f 63 20 3d 20 28 75 33 32 29    *pnDoc = (u32)
8aa0: 6e 44 6f 63 3b 0a 0a 20 20 69 66 28 20 70 61 4c  nDoc;..  if( paL
8ab0: 65 6e 20 29 20 2a 70 61 4c 65 6e 20 3d 20 61 3b  en ) *paLen = a;
8ac0: 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45  .  return SQLITE
8ad0: 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 6e  _OK;.}../*.** An
8ae0: 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65   instance of the
8af0: 20 66 6f 6c 6c 6f 77 69 6e 67 20 73 74 72 75 63   following struc
8b00: 74 75 72 65 20 69 73 20 75 73 65 64 20 74 6f 20  ture is used to 
8b10: 73 74 6f 72 65 20 73 74 61 74 65 20 77 68 69 6c  store state whil
8b20: 65 20 0a 2a 2a 20 69 74 65 72 61 74 69 6e 67 20  e .** iterating 
8b30: 74 68 72 6f 75 67 68 20 61 20 6d 75 6c 74 69 2d  through a multi-
8b40: 63 6f 6c 75 6d 6e 20 70 6f 73 69 74 69 6f 6e 2d  column position-
8b50: 6c 69 73 74 20 63 6f 72 72 65 73 70 6f 6e 64 69  list correspondi
8b60: 6e 67 20 74 6f 20 74 68 65 0a 2a 2a 20 68 69 74  ng to the.** hit
8b70: 73 20 66 6f 72 20 61 20 73 69 6e 67 6c 65 20 70  s for a single p
8b80: 68 72 61 73 65 20 6f 6e 20 61 20 73 69 6e 67 6c  hrase on a singl
8b90: 65 20 72 6f 77 20 69 6e 20 6f 72 64 65 72 20 74  e row in order t
8ba0: 6f 20 63 61 6c 63 75 6c 61 74 65 20 74 68 65 0a  o calculate the.
8bb0: 2a 2a 20 76 61 6c 75 65 73 20 66 6f 72 20 61 20  ** values for a 
8bc0: 6d 61 74 63 68 69 6e 66 6f 28 29 20 46 54 53 33  matchinfo() FTS3
8bd0: 5f 4d 41 54 43 48 49 4e 46 4f 5f 4c 43 53 20 72  _MATCHINFO_LCS r
8be0: 65 71 75 65 73 74 2e 0a 2a 2f 0a 74 79 70 65 64  equest..*/.typed
8bf0: 65 66 20 73 74 72 75 63 74 20 4c 63 73 49 74 65  ef struct LcsIte
8c00: 72 61 74 6f 72 20 4c 63 73 49 74 65 72 61 74 6f  rator LcsIterato
8c10: 72 3b 0a 73 74 72 75 63 74 20 4c 63 73 49 74 65  r;.struct LcsIte
8c20: 72 61 74 6f 72 20 7b 0a 20 20 46 74 73 33 45 78  rator {.  Fts3Ex
8c30: 70 72 20 2a 70 45 78 70 72 3b 20 20 20 20 20 20  pr *pExpr;      
8c40: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 6f 69            /* Poi
8c50: 6e 74 65 72 20 74 6f 20 70 68 72 61 73 65 20 65  nter to phrase e
8c60: 78 70 72 65 73 73 69 6f 6e 20 2a 2f 0a 20 20 69  xpression */.  i
8c70: 6e 74 20 69 50 6f 73 4f 66 66 73 65 74 3b 20 20  nt iPosOffset;  
8c80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
8c90: 2a 20 54 6f 6b 65 6e 73 20 63 6f 75 6e 74 20 75  * Tokens count u
8ca0: 70 20 74 6f 20 65 6e 64 20 6f 66 20 74 68 69 73  p to end of this
8cb0: 20 70 68 72 61 73 65 20 2a 2f 0a 20 20 63 68 61   phrase */.  cha
8cc0: 72 20 2a 70 52 65 61 64 3b 20 20 20 20 20 20 20  r *pRead;       
8cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
8ce0: 43 75 72 73 6f 72 20 75 73 65 64 20 74 6f 20 69  Cursor used to i
8cf0: 74 65 72 61 74 65 20 74 68 72 6f 75 67 68 20 61  terate through a
8d00: 44 6f 63 6c 69 73 74 20 2a 2f 0a 20 20 69 6e 74  Doclist */.  int
8d10: 20 69 50 6f 73 3b 20 20 20 20 20 20 20 20 20 20   iPos;          
8d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
8d30: 43 75 72 72 65 6e 74 20 70 6f 73 69 74 69 6f 6e  Current position
8d40: 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 20 0a 2a 2a 20 49   */.};../* .** I
8d50: 66 20 4c 63 73 49 74 65 72 61 74 6f 72 2e 69 43  f LcsIterator.iC
8d60: 6f 6c 20 69 73 20 73 65 74 20 74 6f 20 74 68 65  ol is set to the
8d70: 20 66 6f 6c 6c 6f 77 69 6e 67 20 76 61 6c 75 65   following value
8d80: 2c 20 74 68 65 20 69 74 65 72 61 74 6f 72 20 68  , the iterator h
8d90: 61 73 0a 2a 2a 20 66 69 6e 69 73 68 65 64 20 69  as.** finished i
8da0: 74 65 72 61 74 69 6e 67 20 74 68 72 6f 75 67 68  terating through
8db0: 20 61 6c 6c 20 6f 66 66 73 65 74 73 20 66 6f 72   all offsets for
8dc0: 20 61 6c 6c 20 63 6f 6c 75 6d 6e 73 2e 0a 2a 2f   all columns..*/
8dd0: 0a 23 64 65 66 69 6e 65 20 4c 43 53 5f 49 54 45  .#define LCS_ITE
8de0: 52 41 54 4f 52 5f 46 49 4e 49 53 48 45 44 20 30  RATOR_FINISHED 0
8df0: 78 37 46 46 46 46 46 46 46 3b 0a 0a 73 74 61 74  x7FFFFFFF;..stat
8e00: 69 63 20 69 6e 74 20 66 74 73 33 4d 61 74 63 68  ic int fts3Match
8e10: 69 6e 66 6f 4c 63 73 43 62 28 0a 20 20 46 74 73  infoLcsCb(.  Fts
8e20: 33 45 78 70 72 20 2a 70 45 78 70 72 2c 20 20 20  3Expr *pExpr,   
8e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
8e40: 50 68 72 61 73 65 20 65 78 70 72 65 73 73 69 6f  Phrase expressio
8e50: 6e 20 6e 6f 64 65 20 2a 2f 0a 20 20 69 6e 74 20  n node */.  int 
8e60: 69 50 68 72 61 73 65 2c 20 20 20 20 20 20 20 20  iPhrase,        
8e70: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50              /* P
8e80: 68 72 61 73 65 20 6e 75 6d 62 65 72 20 28 6e 75  hrase number (nu
8e90: 6d 62 65 72 65 64 20 66 72 6f 6d 20 7a 65 72 6f  mbered from zero
8ea0: 29 20 2a 2f 0a 20 20 76 6f 69 64 20 2a 70 43 74  ) */.  void *pCt
8eb0: 78 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  x               
8ec0: 20 20 20 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65         /* Pointe
8ed0: 72 20 74 6f 20 4d 61 74 63 68 49 6e 66 6f 20 73  r to MatchInfo s
8ee0: 74 72 75 63 74 75 72 65 20 2a 2f 0a 29 7b 0a 20  tructure */.){. 
8ef0: 20 4c 63 73 49 74 65 72 61 74 6f 72 20 2a 61 49   LcsIterator *aI
8f00: 74 65 72 20 3d 20 28 4c 63 73 49 74 65 72 61 74  ter = (LcsIterat
8f10: 6f 72 20 2a 29 70 43 74 78 3b 0a 20 20 61 49 74  or *)pCtx;.  aIt
8f20: 65 72 5b 69 50 68 72 61 73 65 5d 2e 70 45 78 70  er[iPhrase].pExp
8f30: 72 20 3d 20 70 45 78 70 72 3b 0a 20 20 72 65 74  r = pExpr;.  ret
8f40: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d  urn SQLITE_OK;.}
8f50: 0a 0a 2f 2a 0a 2a 2a 20 41 64 76 61 6e 63 65 20  ../*.** Advance 
8f60: 74 68 65 20 69 74 65 72 61 74 6f 72 20 70 61 73  the iterator pas
8f70: 73 65 64 20 61 73 20 61 6e 20 61 72 67 75 6d 65  sed as an argume
8f80: 6e 74 20 74 6f 20 74 68 65 20 6e 65 78 74 20 70  nt to the next p
8f90: 6f 73 69 74 69 6f 6e 2e 20 52 65 74 75 72 6e 0a  osition. Return.
8fa0: 2a 2a 20 31 20 69 66 20 74 68 65 20 69 74 65 72  ** 1 if the iter
8fb0: 61 74 6f 72 20 69 73 20 61 74 20 45 4f 46 20 6f  ator is at EOF o
8fc0: 72 20 69 66 20 69 74 20 6e 6f 77 20 70 6f 69 6e  r if it now poin
8fd0: 74 73 20 74 6f 20 74 68 65 20 73 74 61 72 74 20  ts to the start 
8fe0: 6f 66 20 74 68 65 0a 2a 2a 20 70 6f 73 69 74 69  of the.** positi
8ff0: 6f 6e 20 6c 69 73 74 20 66 6f 72 20 74 68 65 20  on list for the 
9000: 6e 65 78 74 20 63 6f 6c 75 6d 6e 2e 0a 2a 2f 0a  next column..*/.
9010: 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 4c  static int fts3L
9020: 63 73 49 74 65 72 61 74 6f 72 41 64 76 61 6e 63  csIteratorAdvanc
9030: 65 28 4c 63 73 49 74 65 72 61 74 6f 72 20 2a 70  e(LcsIterator *p
9040: 49 74 65 72 29 7b 0a 20 20 63 68 61 72 20 2a 70  Iter){.  char *p
9050: 52 65 61 64 20 3d 20 70 49 74 65 72 2d 3e 70 52  Read = pIter->pR
9060: 65 61 64 3b 0a 20 20 73 71 6c 69 74 65 33 5f 69  ead;.  sqlite3_i
9070: 6e 74 36 34 20 69 52 65 61 64 3b 0a 20 20 69 6e  nt64 iRead;.  in
9080: 74 20 72 63 20 3d 20 30 3b 0a 0a 20 20 70 52 65  t rc = 0;..  pRe
9090: 61 64 20 2b 3d 20 73 71 6c 69 74 65 33 46 74 73  ad += sqlite3Fts
90a0: 33 47 65 74 56 61 72 69 6e 74 28 70 52 65 61 64  3GetVarint(pRead
90b0: 2c 20 26 69 52 65 61 64 29 3b 0a 20 20 69 66 28  , &iRead);.  if(
90c0: 20 69 52 65 61 64 3d 3d 30 20 7c 7c 20 69 52 65   iRead==0 || iRe
90d0: 61 64 3d 3d 31 20 29 7b 0a 20 20 20 20 70 52 65  ad==1 ){.    pRe
90e0: 61 64 20 3d 20 30 3b 0a 20 20 20 20 72 63 20 3d  ad = 0;.    rc =
90f0: 20 31 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20   1;.  }else{.   
9100: 20 70 49 74 65 72 2d 3e 69 50 6f 73 20 2b 3d 20   pIter->iPos += 
9110: 28 69 6e 74 29 28 69 52 65 61 64 2d 32 29 3b 0a  (int)(iRead-2);.
9120: 20 20 7d 0a 0a 20 20 70 49 74 65 72 2d 3e 70 52    }..  pIter->pR
9130: 65 61 64 20 3d 20 70 52 65 61 64 3b 0a 20 20 72  ead = pRead;.  r
9140: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 20 20 0a 2f  eturn rc;.}.  ./
9150: 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e 63 74 69  *.** This functi
9160: 6f 6e 20 69 6d 70 6c 65 6d 65 6e 74 73 20 74 68  on implements th
9170: 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f  e FTS3_MATCHINFO
9180: 5f 4c 43 53 20 6d 61 74 63 68 69 6e 66 6f 28 29  _LCS matchinfo()
9190: 20 66 6c 61 67 2e 20 0a 2a 2a 0a 2a 2a 20 49 66   flag. .**.** If
91a0: 20 74 68 65 20 63 61 6c 6c 20 69 73 20 73 75 63   the call is suc
91b0: 63 65 73 73 66 75 6c 2c 20 74 68 65 20 6c 6f 6e  cessful, the lon
91c0: 67 65 73 74 2d 63 6f 6d 6d 6f 6e 2d 73 75 62 73  gest-common-subs
91d0: 74 72 69 6e 67 20 6c 65 6e 67 74 68 73 20 66 6f  tring lengths fo
91e0: 72 20 65 61 63 68 0a 2a 2a 20 63 6f 6c 75 6d 6e  r each.** column
91f0: 20 61 72 65 20 77 72 69 74 74 65 6e 20 69 6e 74   are written int
9200: 6f 20 74 68 65 20 66 69 72 73 74 20 6e 43 6f 6c  o the first nCol
9210: 20 65 6c 65 6d 65 6e 74 73 20 6f 66 20 74 68 65   elements of the
9220: 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63 68 69 6e   pInfo->aMatchin
9230: 66 6f 5b 5d 20 0a 2a 2a 20 61 72 72 61 79 20 62  fo[] .** array b
9240: 65 66 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e  efore returning.
9250: 20 53 51 4c 49 54 45 5f 4f 4b 20 69 73 20 72 65   SQLITE_OK is re
9260: 74 75 72 6e 65 64 20 69 6e 20 74 68 69 73 20 63  turned in this c
9270: 61 73 65 2e 0a 2a 2a 0a 2a 2a 20 4f 74 68 65 72  ase..**.** Other
9280: 77 69 73 65 2c 20 69 66 20 61 6e 20 65 72 72 6f  wise, if an erro
9290: 72 20 6f 63 63 75 72 73 2c 20 61 6e 20 53 51 4c  r occurs, an SQL
92a0: 69 74 65 20 65 72 72 6f 72 20 63 6f 64 65 20 69  ite error code i
92b0: 73 20 72 65 74 75 72 6e 65 64 20 61 6e 64 20 74  s returned and t
92c0: 68 65 0a 2a 2a 20 64 61 74 61 20 77 72 69 74 74  he.** data writt
92d0: 65 6e 20 74 6f 20 74 68 65 20 66 69 72 73 74 20  en to the first 
92e0: 6e 43 6f 6c 20 65 6c 65 6d 65 6e 74 73 20 6f 66  nCol elements of
92f0: 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63 68 69 6e   pInfo->aMatchin
9300: 66 6f 5b 5d 20 69 73 20 0a 2a 2a 20 75 6e 64 65  fo[] is .** unde
9310: 66 69 6e 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  fined..*/.static
9320: 20 69 6e 74 20 66 74 73 33 4d 61 74 63 68 69 6e   int fts3Matchin
9330: 66 6f 4c 63 73 28 46 74 73 33 43 75 72 73 6f 72  foLcs(Fts3Cursor
9340: 20 2a 70 43 73 72 2c 20 4d 61 74 63 68 49 6e 66   *pCsr, MatchInf
9350: 6f 20 2a 70 49 6e 66 6f 29 7b 0a 20 20 4c 63 73  o *pInfo){.  Lcs
9360: 49 74 65 72 61 74 6f 72 20 2a 61 49 74 65 72 3b  Iterator *aIter;
9370: 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69 6e 74 20  .  int i;.  int 
9380: 69 43 6f 6c 3b 0a 20 20 69 6e 74 20 6e 54 6f 6b  iCol;.  int nTok
9390: 65 6e 20 3d 20 30 3b 0a 20 20 69 6e 74 20 72 63  en = 0;.  int rc
93a0: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 0a 20   = SQLITE_OK;.. 
93b0: 20 2f 2a 20 41 6c 6c 6f 63 61 74 65 20 61 6e 64   /* Allocate and
93c0: 20 70 6f 70 75 6c 61 74 65 20 74 68 65 20 61 72   populate the ar
93d0: 72 61 79 20 6f 66 20 4c 63 73 49 74 65 72 61 74  ray of LcsIterat
93e0: 6f 72 20 6f 62 6a 65 63 74 73 2e 20 54 68 65 20  or objects. The 
93f0: 61 72 72 61 79 0a 20 20 2a 2a 20 63 6f 6e 74 61  array.  ** conta
9400: 69 6e 73 20 6f 6e 65 20 65 6c 65 6d 65 6e 74 20  ins one element 
9410: 66 6f 72 20 65 61 63 68 20 6d 61 74 63 68 61 62  for each matchab
9420: 6c 65 20 70 68 72 61 73 65 20 69 6e 20 74 68 65  le phrase in the
9430: 20 71 75 65 72 79 2e 0a 20 20 2a 2a 2f 0a 20 20   query..  **/.  
9440: 61 49 74 65 72 20 3d 20 73 71 6c 69 74 65 33 5f  aIter = sqlite3_
9450: 6d 61 6c 6c 6f 63 36 34 28 73 69 7a 65 6f 66 28  malloc64(sizeof(
9460: 4c 63 73 49 74 65 72 61 74 6f 72 29 20 2a 20 70  LcsIterator) * p
9470: 43 73 72 2d 3e 6e 50 68 72 61 73 65 29 3b 0a 20  Csr->nPhrase);. 
9480: 20 69 66 28 20 21 61 49 74 65 72 20 29 20 72 65   if( !aIter ) re
9490: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45  turn SQLITE_NOME
94a0: 4d 3b 0a 20 20 6d 65 6d 73 65 74 28 61 49 74 65  M;.  memset(aIte
94b0: 72 2c 20 30 2c 20 73 69 7a 65 6f 66 28 4c 63 73  r, 0, sizeof(Lcs
94c0: 49 74 65 72 61 74 6f 72 29 20 2a 20 70 43 73 72  Iterator) * pCsr
94d0: 2d 3e 6e 50 68 72 61 73 65 29 3b 0a 20 20 28 76  ->nPhrase);.  (v
94e0: 6f 69 64 29 66 74 73 33 45 78 70 72 49 74 65 72  oid)fts3ExprIter
94f0: 61 74 65 28 70 43 73 72 2d 3e 70 45 78 70 72 2c  ate(pCsr->pExpr,
9500: 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f 4c 63   fts3MatchinfoLc
9510: 73 43 62 2c 20 28 76 6f 69 64 2a 29 61 49 74 65  sCb, (void*)aIte
9520: 72 29 3b 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20  r);..  for(i=0; 
9530: 69 3c 70 49 6e 66 6f 2d 3e 6e 50 68 72 61 73 65  i<pInfo->nPhrase
9540: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 4c 63 73 49  ; i++){.    LcsI
9550: 74 65 72 61 74 6f 72 20 2a 70 49 74 65 72 20 3d  terator *pIter =
9560: 20 26 61 49 74 65 72 5b 69 5d 3b 0a 20 20 20 20   &aIter[i];.    
9570: 6e 54 6f 6b 65 6e 20 2d 3d 20 70 49 74 65 72 2d  nToken -= pIter-
9580: 3e 70 45 78 70 72 2d 3e 70 50 68 72 61 73 65 2d  >pExpr->pPhrase-
9590: 3e 6e 54 6f 6b 65 6e 3b 0a 20 20 20 20 70 49 74  >nToken;.    pIt
95a0: 65 72 2d 3e 69 50 6f 73 4f 66 66 73 65 74 20 3d  er->iPosOffset =
95b0: 20 6e 54 6f 6b 65 6e 3b 0a 20 20 7d 0a 0a 20 20   nToken;.  }..  
95c0: 66 6f 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f 6c  for(iCol=0; iCol
95d0: 3c 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 3b 20 69 43  <pInfo->nCol; iC
95e0: 6f 6c 2b 2b 29 7b 0a 20 20 20 20 69 6e 74 20 6e  ol++){.    int n
95f0: 4c 63 73 20 3d 20 30 3b 20 20 20 20 20 20 20 20  Lcs = 0;        
9600: 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 43 53 20           /* LCS 
9610: 76 61 6c 75 65 20 66 6f 72 20 74 68 69 73 20 63  value for this c
9620: 6f 6c 75 6d 6e 20 2a 2f 0a 20 20 20 20 69 6e 74  olumn */.    int
9630: 20 6e 4c 69 76 65 20 3d 20 30 3b 20 20 20 20 20   nLive = 0;     
9640: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75             /* Nu
9650: 6d 62 65 72 20 6f 66 20 69 74 65 72 61 74 6f 72  mber of iterator
9660: 73 20 69 6e 20 61 49 74 65 72 20 6e 6f 74 20 61  s in aIter not a
9670: 74 20 45 4f 46 20 2a 2f 0a 0a 20 20 20 20 66 6f  t EOF */..    fo
9680: 72 28 69 3d 30 3b 20 69 3c 70 49 6e 66 6f 2d 3e  r(i=0; i<pInfo->
9690: 6e 50 68 72 61 73 65 3b 20 69 2b 2b 29 7b 0a 20  nPhrase; i++){. 
96a0: 20 20 20 20 20 4c 63 73 49 74 65 72 61 74 6f 72       LcsIterator
96b0: 20 2a 70 49 74 20 3d 20 26 61 49 74 65 72 5b 69   *pIt = &aIter[i
96c0: 5d 3b 0a 20 20 20 20 20 20 72 63 20 3d 20 73 71  ];.      rc = sq
96d0: 6c 69 74 65 33 46 74 73 33 45 76 61 6c 50 68 72  lite3Fts3EvalPhr
96e0: 61 73 65 50 6f 73 6c 69 73 74 28 70 43 73 72 2c  asePoslist(pCsr,
96f0: 20 70 49 74 2d 3e 70 45 78 70 72 2c 20 69 43 6f   pIt->pExpr, iCo
9700: 6c 2c 20 26 70 49 74 2d 3e 70 52 65 61 64 29 3b  l, &pIt->pRead);
9710: 0a 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53  .      if( rc!=S
9720: 51 4c 49 54 45 5f 4f 4b 20 29 20 67 6f 74 6f 20  QLITE_OK ) goto 
9730: 6d 61 74 63 68 69 6e 66 6f 5f 6c 63 73 5f 6f 75  matchinfo_lcs_ou
9740: 74 3b 0a 20 20 20 20 20 20 69 66 28 20 70 49 74  t;.      if( pIt
9750: 2d 3e 70 52 65 61 64 20 29 7b 0a 20 20 20 20 20  ->pRead ){.     
9760: 20 20 20 70 49 74 2d 3e 69 50 6f 73 20 3d 20 70     pIt->iPos = p
9770: 49 74 2d 3e 69 50 6f 73 4f 66 66 73 65 74 3b 0a  It->iPosOffset;.
9780: 20 20 20 20 20 20 20 20 66 74 73 33 4c 63 73 49          fts3LcsI
9790: 74 65 72 61 74 6f 72 41 64 76 61 6e 63 65 28 70  teratorAdvance(p
97a0: 49 74 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28  It);.        if(
97b0: 20 70 49 74 2d 3e 70 52 65 61 64 3d 3d 30 20 29   pIt->pRead==0 )
97c0: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
97d0: 20 46 54 53 5f 43 4f 52 52 55 50 54 5f 56 54 41   FTS_CORRUPT_VTA
97e0: 42 3b 0a 20 20 20 20 20 20 20 20 20 20 67 6f 74  B;.          got
97f0: 6f 20 6d 61 74 63 68 69 6e 66 6f 5f 6c 63 73 5f  o matchinfo_lcs_
9800: 6f 75 74 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  out;.        }. 
9810: 20 20 20 20 20 20 20 6e 4c 69 76 65 2b 2b 3b 0a         nLive++;.
9820: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20        }.    }.. 
9830: 20 20 20 77 68 69 6c 65 28 20 6e 4c 69 76 65 3e     while( nLive>
9840: 30 20 29 7b 0a 20 20 20 20 20 20 4c 63 73 49 74  0 ){.      LcsIt
9850: 65 72 61 74 6f 72 20 2a 70 41 64 76 20 3d 20 30  erator *pAdv = 0
9860: 3b 20 20 20 20 20 20 2f 2a 20 54 68 65 20 69 74  ;      /* The it
9870: 65 72 61 74 6f 72 20 74 6f 20 61 64 76 61 6e 63  erator to advanc
9880: 65 20 62 79 20 6f 6e 65 20 70 6f 73 69 74 69 6f  e by one positio
9890: 6e 20 2a 2f 0a 20 20 20 20 20 20 69 6e 74 20 6e  n */.      int n
98a0: 54 68 69 73 4c 63 73 20 3d 20 30 3b 20 20 20 20  ThisLcs = 0;    
98b0: 20 20 20 20 20 20 20 2f 2a 20 4c 43 53 20 66 6f         /* LCS fo
98c0: 72 20 74 68 65 20 63 75 72 72 65 6e 74 20 69 74  r the current it
98d0: 65 72 61 74 6f 72 20 70 6f 73 69 74 69 6f 6e 73  erator positions
98e0: 20 2a 2f 0a 0a 20 20 20 20 20 20 66 6f 72 28 69   */..      for(i
98f0: 3d 30 3b 20 69 3c 70 49 6e 66 6f 2d 3e 6e 50 68  =0; i<pInfo->nPh
9900: 72 61 73 65 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  rase; i++){.    
9910: 20 20 20 20 4c 63 73 49 74 65 72 61 74 6f 72 20      LcsIterator 
9920: 2a 70 49 74 65 72 20 3d 20 26 61 49 74 65 72 5b  *pIter = &aIter[
9930: 69 5d 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20  i];.        if( 
9940: 70 49 74 65 72 2d 3e 70 52 65 61 64 3d 3d 30 20  pIter->pRead==0 
9950: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 2f 2a 20  ){.          /* 
9960: 54 68 69 73 20 69 74 65 72 61 74 6f 72 20 69 73  This iterator is
9970: 20 61 6c 72 65 61 64 79 20 61 74 20 45 4f 46 20   already at EOF 
9980: 66 6f 72 20 74 68 69 73 20 63 6f 6c 75 6d 6e 2e  for this column.
9990: 20 2a 2f 0a 20 20 20 20 20 20 20 20 20 20 6e 54   */.          nT
99a0: 68 69 73 4c 63 73 20 3d 20 30 3b 0a 20 20 20 20  hisLcs = 0;.    
99b0: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
99c0: 20 20 20 20 20 69 66 28 20 70 41 64 76 3d 3d 30       if( pAdv==0
99d0: 20 7c 7c 20 70 49 74 65 72 2d 3e 69 50 6f 73 3c   || pIter->iPos<
99e0: 70 41 64 76 2d 3e 69 50 6f 73 20 29 7b 0a 20 20  pAdv->iPos ){.  
99f0: 20 20 20 20 20 20 20 20 20 20 70 41 64 76 20 3d            pAdv =
9a00: 20 70 49 74 65 72 3b 0a 20 20 20 20 20 20 20 20   pIter;.        
9a10: 20 20 7d 0a 20 20 20 20 20 20 20 20 20 20 69 66    }.          if
9a20: 28 20 6e 54 68 69 73 4c 63 73 3d 3d 30 20 7c 7c  ( nThisLcs==0 ||
9a30: 20 70 49 74 65 72 2d 3e 69 50 6f 73 3d 3d 70 49   pIter->iPos==pI
9a40: 74 65 72 5b 2d 31 5d 2e 69 50 6f 73 20 29 7b 0a  ter[-1].iPos ){.
9a50: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 68 69              nThi
9a60: 73 4c 63 73 2b 2b 3b 0a 20 20 20 20 20 20 20 20  sLcs++;.        
9a70: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
9a80: 20 20 20 20 20 6e 54 68 69 73 4c 63 73 20 3d 20       nThisLcs = 
9a90: 31 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20  1;.          }. 
9aa0: 20 20 20 20 20 20 20 20 20 69 66 28 20 6e 54 68           if( nTh
9ab0: 69 73 4c 63 73 3e 6e 4c 63 73 20 29 20 6e 4c 63  isLcs>nLcs ) nLc
9ac0: 73 20 3d 20 6e 54 68 69 73 4c 63 73 3b 0a 20 20  s = nThisLcs;.  
9ad0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a        }.      }.
9ae0: 20 20 20 20 20 20 69 66 28 20 66 74 73 33 4c 63        if( fts3Lc
9af0: 73 49 74 65 72 61 74 6f 72 41 64 76 61 6e 63 65  sIteratorAdvance
9b00: 28 70 41 64 76 29 20 29 20 6e 4c 69 76 65 2d 2d  (pAdv) ) nLive--
9b10: 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20 70 49 6e  ;.    }..    pIn
9b20: 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 69  fo->aMatchinfo[i
9b30: 43 6f 6c 5d 20 3d 20 6e 4c 63 73 3b 0a 20 20 7d  Col] = nLcs;.  }
9b40: 0a 0a 20 6d 61 74 63 68 69 6e 66 6f 5f 6c 63 73  .. matchinfo_lcs
9b50: 5f 6f 75 74 3a 0a 20 20 73 71 6c 69 74 65 33 5f  _out:.  sqlite3_
9b60: 66 72 65 65 28 61 49 74 65 72 29 3b 0a 20 20 72  free(aIter);.  r
9b70: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a  eturn rc;.}../*.
9b80: 2a 2a 20 50 6f 70 75 6c 61 74 65 20 74 68 65 20  ** Populate the 
9b90: 62 75 66 66 65 72 20 70 49 6e 66 6f 2d 3e 61 4d  buffer pInfo->aM
9ba0: 61 74 63 68 69 6e 66 6f 5b 5d 20 77 69 74 68 20  atchinfo[] with 
9bb0: 61 6e 20 61 72 72 61 79 20 6f 66 20 69 6e 74 65  an array of inte
9bc0: 67 65 72 73 20 74 6f 0a 2a 2a 20 62 65 20 72 65  gers to.** be re
9bd0: 74 75 72 6e 65 64 20 62 79 20 74 68 65 20 6d 61  turned by the ma
9be0: 74 63 68 69 6e 66 6f 28 29 20 66 75 6e 63 74 69  tchinfo() functi
9bf0: 6f 6e 2e 20 41 72 67 75 6d 65 6e 74 20 7a 41 72  on. Argument zAr
9c00: 67 20 63 6f 6e 74 61 69 6e 73 20 74 68 65 20 0a  g contains the .
9c10: 2a 2a 20 66 6f 72 6d 61 74 20 73 74 72 69 6e 67  ** format string
9c20: 20 70 61 73 73 65 64 20 61 73 20 74 68 65 20 73   passed as the s
9c30: 65 63 6f 6e 64 20 61 72 67 75 6d 65 6e 74 20 74  econd argument t
9c40: 6f 20 6d 61 74 63 68 69 6e 66 6f 20 28 6f 72 20  o matchinfo (or 
9c50: 74 68 65 0a 2a 2a 20 64 65 66 61 75 6c 74 20 76  the.** default v
9c60: 61 6c 75 65 20 22 70 63 78 22 20 69 66 20 6e 6f  alue "pcx" if no
9c70: 20 73 65 63 6f 6e 64 20 61 72 67 75 6d 65 6e 74   second argument
9c80: 20 77 61 73 20 73 70 65 63 69 66 69 65 64 29 2e   was specified).
9c90: 20 54 68 65 20 66 6f 72 6d 61 74 0a 2a 2a 20 73   The format.** s
9ca0: 74 72 69 6e 67 20 68 61 73 20 61 6c 72 65 61 64  tring has alread
9cb0: 79 20 62 65 65 6e 20 76 61 6c 69 64 61 74 65 64  y been validated
9cc0: 20 61 6e 64 20 74 68 65 20 70 49 6e 66 6f 2d 3e   and the pInfo->
9cd0: 61 4d 61 74 63 68 69 6e 66 6f 5b 5d 20 61 72 72  aMatchinfo[] arr
9ce0: 61 79 0a 2a 2a 20 69 73 20 67 75 61 72 61 6e 74  ay.** is guarant
9cf0: 65 65 64 20 74 6f 20 62 65 20 6c 61 72 67 65 20  eed to be large 
9d00: 65 6e 6f 75 67 68 20 66 6f 72 20 74 68 65 20 6f  enough for the o
9d10: 75 74 70 75 74 2e 0a 2a 2a 0a 2a 2a 20 49 66 20  utput..**.** If 
9d20: 62 47 6c 6f 62 61 6c 20 69 73 20 74 72 75 65 2c  bGlobal is true,
9d30: 20 74 68 65 6e 20 70 6f 70 75 6c 61 74 65 20 61   then populate a
9d40: 6c 6c 20 66 69 65 6c 64 73 20 6f 66 20 74 68 65  ll fields of the
9d50: 20 6d 61 74 63 68 69 6e 66 6f 28 29 20 6f 75 74   matchinfo() out
9d60: 70 75 74 2e 0a 2a 2a 20 49 66 20 69 74 20 69 73  put..** If it is
9d70: 20 66 61 6c 73 65 2c 20 74 68 65 6e 20 61 73 73   false, then ass
9d80: 75 6d 65 20 74 68 61 74 20 74 68 6f 73 65 20 66  ume that those f
9d90: 69 65 6c 64 73 20 74 68 61 74 20 64 6f 20 6e 6f  ields that do no
9da0: 74 20 63 68 61 6e 67 65 20 62 65 74 77 65 65 6e  t change between
9db0: 0a 2a 2a 20 72 6f 77 73 20 28 69 2e 65 2e 20 46  .** rows (i.e. F
9dc0: 54 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 4e 50  TS3_MATCHINFO_NP
9dd0: 48 52 41 53 45 2c 20 4e 43 4f 4c 2c 20 4e 44 4f  HRASE, NCOL, NDO
9de0: 43 2c 20 41 56 47 4c 45 4e 47 54 48 20 61 6e 64  C, AVGLENGTH and
9df0: 20 70 61 72 74 20 6f 66 20 48 49 54 53 29 0a 2a   part of HITS).*
9e00: 2a 20 68 61 76 65 20 61 6c 72 65 61 64 79 20 62  * have already b
9e10: 65 65 6e 20 70 6f 70 75 6c 61 74 65 64 2e 0a 2a  een populated..*
9e20: 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 53 51 4c 49  *.** Return SQLI
9e30: 54 45 5f 4f 4b 20 69 66 20 73 75 63 63 65 73 73  TE_OK if success
9e40: 66 75 6c 2c 20 6f 72 20 61 6e 20 53 51 4c 69 74  ful, or an SQLit
9e50: 65 20 65 72 72 6f 72 20 63 6f 64 65 20 69 66 20  e error code if 
9e60: 61 6e 20 65 72 72 6f 72 20 0a 2a 2a 20 6f 63 63  an error .** occ
9e70: 75 72 73 2e 20 49 66 20 61 20 76 61 6c 75 65 20  urs. If a value 
9e80: 6f 74 68 65 72 20 74 68 61 6e 20 53 51 4c 49 54  other than SQLIT
9e90: 45 5f 4f 4b 20 69 73 20 72 65 74 75 72 6e 65 64  E_OK is returned
9ea0: 2c 20 74 68 65 20 73 74 61 74 65 20 74 68 65 0a  , the state the.
9eb0: 2a 2a 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63 68  ** pInfo->aMatch
9ec0: 69 6e 66 6f 5b 5d 20 62 75 66 66 65 72 20 69 73  info[] buffer is
9ed0: 20 6c 65 66 74 20 69 6e 20 69 73 20 75 6e 64 65   left in is unde
9ee0: 66 69 6e 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  fined..*/.static
9ef0: 20 69 6e 74 20 66 74 73 33 4d 61 74 63 68 69 6e   int fts3Matchin
9f00: 66 6f 56 61 6c 75 65 73 28 0a 20 20 46 74 73 33  foValues(.  Fts3
9f10: 43 75 72 73 6f 72 20 2a 70 43 73 72 2c 20 20 20  Cursor *pCsr,   
9f20: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46              /* F
9f30: 54 53 33 20 63 75 72 73 6f 72 20 6f 62 6a 65 63  TS3 cursor objec
9f40: 74 20 2a 2f 0a 20 20 69 6e 74 20 62 47 6c 6f 62  t */.  int bGlob
9f50: 61 6c 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  al,             
9f60: 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 74         /* True t
9f70: 6f 20 67 72 61 62 20 74 68 65 20 67 6c 6f 62 61  o grab the globa
9f80: 6c 20 73 74 61 74 73 20 2a 2f 0a 20 20 4d 61 74  l stats */.  Mat
9f90: 63 68 49 6e 66 6f 20 2a 70 49 6e 66 6f 2c 20 20  chInfo *pInfo,  
9fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
9fb0: 4d 61 74 63 68 69 6e 66 6f 20 63 6f 6e 74 65 78  Matchinfo contex
9fc0: 74 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 63 6f  t object */.  co
9fd0: 6e 73 74 20 63 68 61 72 20 2a 7a 41 72 67 20 20  nst char *zArg  
9fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
9ff0: 20 4d 61 74 63 68 69 6e 66 6f 20 66 6f 72 6d 61   Matchinfo forma
a000: 74 20 73 74 72 69 6e 67 20 2a 2f 0a 29 7b 0a 20  t string */.){. 
a010: 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45   int rc = SQLITE
a020: 5f 4f 4b 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20  _OK;.  int i;.  
a030: 46 74 73 33 54 61 62 6c 65 20 2a 70 54 61 62 20  Fts3Table *pTab 
a040: 3d 20 28 46 74 73 33 54 61 62 6c 65 20 2a 29 70  = (Fts3Table *)p
a050: 43 73 72 2d 3e 62 61 73 65 2e 70 56 74 61 62 3b  Csr->base.pVtab;
a060: 0a 20 20 73 71 6c 69 74 65 33 5f 73 74 6d 74 20  .  sqlite3_stmt 
a070: 2a 70 53 65 6c 65 63 74 20 3d 20 30 3b 0a 0a 20  *pSelect = 0;.. 
a080: 20 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 53 51   for(i=0; rc==SQ
a090: 4c 49 54 45 5f 4f 4b 20 26 26 20 7a 41 72 67 5b  LITE_OK && zArg[
a0a0: 69 5d 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 70 49  i]; i++){.    pI
a0b0: 6e 66 6f 2d 3e 66 6c 61 67 20 3d 20 7a 41 72 67  nfo->flag = zArg
a0c0: 5b 69 5d 3b 0a 20 20 20 20 73 77 69 74 63 68 28  [i];.    switch(
a0d0: 20 7a 41 72 67 5b 69 5d 20 29 7b 0a 20 20 20 20   zArg[i] ){.    
a0e0: 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54 43    case FTS3_MATC
a0f0: 48 49 4e 46 4f 5f 4e 50 48 52 41 53 45 3a 0a 20  HINFO_NPHRASE:. 
a100: 20 20 20 20 20 20 20 69 66 28 20 62 47 6c 6f 62         if( bGlob
a110: 61 6c 20 29 20 70 49 6e 66 6f 2d 3e 61 4d 61 74  al ) pInfo->aMat
a120: 63 68 69 6e 66 6f 5b 30 5d 20 3d 20 70 49 6e 66  chinfo[0] = pInf
a130: 6f 2d 3e 6e 50 68 72 61 73 65 3b 0a 20 20 20 20  o->nPhrase;.    
a140: 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20      break;..    
a150: 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54 43    case FTS3_MATC
a160: 48 49 4e 46 4f 5f 4e 43 4f 4c 3a 0a 20 20 20 20  HINFO_NCOL:.    
a170: 20 20 20 20 69 66 28 20 62 47 6c 6f 62 61 6c 20      if( bGlobal 
a180: 29 20 70 49 6e 66 6f 2d 3e 61 4d 61 74 63 68 69  ) pInfo->aMatchi
a190: 6e 66 6f 5b 30 5d 20 3d 20 70 49 6e 66 6f 2d 3e  nfo[0] = pInfo->
a1a0: 6e 43 6f 6c 3b 0a 20 20 20 20 20 20 20 20 62 72  nCol;.        br
a1b0: 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 0a 20 20  eak;.        .  
a1c0: 20 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41      case FTS3_MA
a1d0: 54 43 48 49 4e 46 4f 5f 4e 44 4f 43 3a 0a 20 20  TCHINFO_NDOC:.  
a1e0: 20 20 20 20 20 20 69 66 28 20 62 47 6c 6f 62 61        if( bGloba
a1f0: 6c 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 73  l ){.          s
a200: 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 6e 44 6f  qlite3_int64 nDo
a210: 63 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 20  c = 0;.         
a220: 20 72 63 20 3d 20 66 74 73 33 4d 61 74 63 68 69   rc = fts3Matchi
a230: 6e 66 6f 53 65 6c 65 63 74 44 6f 63 74 6f 74 61  nfoSelectDoctota
a240: 6c 28 70 54 61 62 2c 20 26 70 53 65 6c 65 63 74  l(pTab, &pSelect
a250: 2c 20 26 6e 44 6f 63 2c 20 30 29 3b 0a 20 20 20  , &nDoc, 0);.   
a260: 20 20 20 20 20 20 20 70 49 6e 66 6f 2d 3e 61 4d         pInfo->aM
a270: 61 74 63 68 69 6e 66 6f 5b 30 5d 20 3d 20 28 75  atchinfo[0] = (u
a280: 33 32 29 6e 44 6f 63 3b 0a 20 20 20 20 20 20 20  32)nDoc;.       
a290: 20 7d 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b   }.        break
a2a0: 3b 0a 0a 20 20 20 20 20 20 63 61 73 65 20 46 54  ;..      case FT
a2b0: 53 33 5f 4d 41 54 43 48 49 4e 46 4f 5f 41 56 47  S3_MATCHINFO_AVG
a2c0: 4c 45 4e 47 54 48 3a 20 0a 20 20 20 20 20 20 20  LENGTH: .       
a2d0: 20 69 66 28 20 62 47 6c 6f 62 61 6c 20 29 7b 0a   if( bGlobal ){.
a2e0: 20 20 20 20 20 20 20 20 20 20 73 71 6c 69 74 65            sqlite
a2f0: 33 5f 69 6e 74 36 34 20 6e 44 6f 63 3b 20 20 20  3_int64 nDoc;   
a300: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 72    /* Number of r
a310: 6f 77 73 20 69 6e 20 74 61 62 6c 65 20 2a 2f 0a  ows in table */.
a320: 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73 74 20            const 
a330: 63 68 61 72 20 2a 61 3b 20 20 20 20 20 20 20 20  char *a;        
a340: 20 20 2f 2a 20 41 67 67 72 65 67 61 74 65 20 63    /* Aggregate c
a350: 6f 6c 75 6d 6e 20 6c 65 6e 67 74 68 20 61 72 72  olumn length arr
a360: 61 79 20 2a 2f 0a 0a 20 20 20 20 20 20 20 20 20  ay */..         
a370: 20 72 63 20 3d 20 66 74 73 33 4d 61 74 63 68 69   rc = fts3Matchi
a380: 6e 66 6f 53 65 6c 65 63 74 44 6f 63 74 6f 74 61  nfoSelectDoctota
a390: 6c 28 70 54 61 62 2c 20 26 70 53 65 6c 65 63 74  l(pTab, &pSelect
a3a0: 2c 20 26 6e 44 6f 63 2c 20 26 61 29 3b 0a 20 20  , &nDoc, &a);.  
a3b0: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d          if( rc==
a3c0: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
a3d0: 20 20 20 20 20 20 20 20 20 69 6e 74 20 69 43 6f           int iCo
a3e0: 6c 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20 66  l;.            f
a3f0: 6f 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f 6c 3c  or(iCol=0; iCol<
a400: 70 49 6e 66 6f 2d 3e 6e 43 6f 6c 3b 20 69 43 6f  pInfo->nCol; iCo
a410: 6c 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 20 20  l++){.          
a420: 20 20 20 20 75 33 32 20 69 56 61 6c 3b 0a 20 20      u32 iVal;.  
a430: 20 20 20 20 20 20 20 20 20 20 20 20 73 71 6c 69              sqli
a440: 74 65 33 5f 69 6e 74 36 34 20 6e 54 6f 6b 65 6e  te3_int64 nToken
a450: 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;.              
a460: 61 20 2b 3d 20 73 71 6c 69 74 65 33 46 74 73 33  a += sqlite3Fts3
a470: 47 65 74 56 61 72 69 6e 74 28 61 2c 20 26 6e 54  GetVarint(a, &nT
a480: 6f 6b 65 6e 29 3b 0a 20 20 20 20 20 20 20 20 20  oken);.         
a490: 20 20 20 20 20 69 56 61 6c 20 3d 20 28 75 33 32       iVal = (u32
a4a0: 29 28 28 28 75 33 32 29 28 6e 54 6f 6b 65 6e 26  )(((u32)(nToken&
a4b0: 30 78 66 66 66 66 66 66 66 66 29 2b 6e 44 6f 63  0xffffffff)+nDoc
a4c0: 2f 32 29 2f 6e 44 6f 63 29 3b 0a 20 20 20 20 20  /2)/nDoc);.     
a4d0: 20 20 20 20 20 20 20 20 20 70 49 6e 66 6f 2d 3e           pInfo->
a4e0: 61 4d 61 74 63 68 69 6e 66 6f 5b 69 43 6f 6c 5d  aMatchinfo[iCol]
a4f0: 20 3d 20 69 56 61 6c 3b 0a 20 20 20 20 20 20 20   = iVal;.       
a500: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20       }.         
a510: 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20   }.        }.   
a520: 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20       break;..   
a530: 20 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54     case FTS3_MAT
a540: 43 48 49 4e 46 4f 5f 4c 45 4e 47 54 48 3a 20 7b  CHINFO_LENGTH: {
a550: 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33  .        sqlite3
a560: 5f 73 74 6d 74 20 2a 70 53 65 6c 65 63 74 44 6f  _stmt *pSelectDo
a570: 63 73 69 7a 65 20 3d 20 30 3b 0a 20 20 20 20 20  csize = 0;.     
a580: 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 46     rc = sqlite3F
a590: 74 73 33 53 65 6c 65 63 74 44 6f 63 73 69 7a 65  ts3SelectDocsize
a5a0: 28 70 54 61 62 2c 20 70 43 73 72 2d 3e 69 50 72  (pTab, pCsr->iPr
a5b0: 65 76 49 64 2c 20 26 70 53 65 6c 65 63 74 44 6f  evId, &pSelectDo
a5c0: 63 73 69 7a 65 29 3b 0a 20 20 20 20 20 20 20 20  csize);.        
a5d0: 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f  if( rc==SQLITE_O
a5e0: 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 69  K ){.          i
a5f0: 6e 74 20 69 43 6f 6c 3b 0a 20 20 20 20 20 20 20  nt iCol;.       
a600: 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 61     const char *a
a610: 20 3d 20 73 71 6c 69 74 65 33 5f 63 6f 6c 75 6d   = sqlite3_colum
a620: 6e 5f 62 6c 6f 62 28 70 53 65 6c 65 63 74 44 6f  n_blob(pSelectDo
a630: 63 73 69 7a 65 2c 20 30 29 3b 0a 20 20 20 20 20  csize, 0);.     
a640: 20 20 20 20 20 66 6f 72 28 69 43 6f 6c 3d 30 3b       for(iCol=0;
a650: 20 69 43 6f 6c 3c 70 49 6e 66 6f 2d 3e 6e 43 6f   iCol<pInfo->nCo
a660: 6c 3b 20 69 43 6f 6c 2b 2b 29 7b 0a 20 20 20 20  l; iCol++){.    
a670: 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f          sqlite3_
a680: 69 6e 74 36 34 20 6e 54 6f 6b 65 6e 3b 0a 20 20  int64 nToken;.  
a690: 20 20 20 20 20 20 20 20 20 20 61 20 2b 3d 20 73            a += s
a6a0: 71 6c 69 74 65 33 46 74 73 33 47 65 74 56 61 72  qlite3Fts3GetVar
a6b0: 69 6e 74 28 61 2c 20 26 6e 54 6f 6b 65 6e 29 3b  int(a, &nToken);
a6c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 49 6e  .            pIn
a6d0: 66 6f 2d 3e 61 4d 61 74 63 68 69 6e 66 6f 5b 69  fo->aMatchinfo[i
a6e0: 43 6f 6c 5d 20 3d 20 28 75 33 32 29 6e 54 6f 6b  Col] = (u32)nTok
a6f0: 65 6e 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a  en;.          }.
a700: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
a710: 20 20 73 71 6c 69 74 65 33 5f 72 65 73 65 74 28    sqlite3_reset(
a720: 70 53 65 6c 65 63 74 44 6f 63 73 69 7a 65 29 3b  pSelectDocsize);
a730: 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  .        break;.
a740: 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 63        }..      c
a750: 61 73 65 20 46 54 53 33 5f 4d 41 54 43 48 49 4e  ase FTS3_MATCHIN
a760: 46 4f 5f 4c 43 53 3a 0a 20 20 20 20 20 20 20 20  FO_LCS:.        
a770: 72 63 20 3d 20 66 74 73 33 45 78 70 72 4c 6f 61  rc = fts3ExprLoa
a780: 64 44 6f 63 6c 69 73 74 73 28 70 43 73 72 2c 20  dDoclists(pCsr, 
a790: 30 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20 69  0, 0);.        i
a7a0: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
a7b0: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63   ){.          rc
a7c0: 20 3d 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f   = fts3Matchinfo
a7d0: 4c 63 73 28 70 43 73 72 2c 20 70 49 6e 66 6f 29  Lcs(pCsr, pInfo)
a7e0: 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  ;.        }.    
a7f0: 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20      break;..    
a800: 20 20 63 61 73 65 20 46 54 53 33 5f 4d 41 54 43    case FTS3_MATC
a810: 48 49 4e 46 4f 5f 4c 48 49 54 53 5f 42 4d 3a 0a  HINFO_LHITS_BM:.
a820: 20 20 20 20 20 20 63 61 73 65 20 46 54 53 33 5f        case FTS3_
a830: 4d 41 54 43 48 49 4e 46 4f 5f 4c 48 49 54 53 3a  MATCHINFO_LHITS:
a840: 20 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20 6e   {.        int n
a850: 5a 65 72 6f 20 3d 20 66 74 73 33 4d 61 74 63 68  Zero = fts3Match
a860: 69 6e 66 6f 53 69 7a 65 28 70 49 6e 66 6f 2c 20  infoSize(pInfo, 
a870: 7a 41 72 67 5b 69 5d 29 20 2a 20 73 69 7a 65 6f  zArg[i]) * sizeo
a880: 66 28 75 33 32 29 3b 0a 20 20 20 20 20 20 20 20  f(u32);.        
a890: 6d 65 6d 73 65 74 28 70 49 6e 66 6f 2d 3e 61 4d  memset(pInfo->aM
a8a0: 61 74 63 68 69 6e 66 6f 2c 20 30 2c 20 6e 5a 65  atchinfo, 0, nZe
a8b0: 72 6f 29 3b 0a 20 20 20 20 20 20 20 20 72 63 20  ro);.        rc 
a8c0: 3d 20 66 74 73 33 45 78 70 72 4c 48 69 74 47 61  = fts3ExprLHitGa
a8d0: 74 68 65 72 28 70 43 73 72 2d 3e 70 45 78 70 72  ther(pCsr->pExpr
a8e0: 2c 20 70 49 6e 66 6f 29 3b 0a 20 20 20 20 20 20  , pInfo);.      
a8f0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d    break;.      }
a900: 0a 0a 20 20 20 20 20 20 64 65 66 61 75 6c 74 3a  ..      default:
a910: 20 7b 0a 20 20 20 20 20 20 20 20 46 74 73 33 45   {.        Fts3E
a920: 78 70 72 20 2a 70 45 78 70 72 3b 0a 20 20 20 20  xpr *pExpr;.    
a930: 20 20 20 20 61 73 73 65 72 74 28 20 7a 41 72 67      assert( zArg
a940: 5b 69 5d 3d 3d 46 54 53 33 5f 4d 41 54 43 48 49  [i]==FTS3_MATCHI
a950: 4e 46 4f 5f 48 49 54 53 20 29 3b 0a 20 20 20 20  NFO_HITS );.    
a960: 20 20 20 20 70 45 78 70 72 20 3d 20 70 43 73 72      pExpr = pCsr
a970: 2d 3e 70 45 78 70 72 3b 0a 20 20 20 20 20 20 20  ->pExpr;.       
a980: 20 72 63 20 3d 20 66 74 73 33 45 78 70 72 4c 6f   rc = fts3ExprLo
a990: 61 64 44 6f 63 6c 69 73 74 73 28 70 43 73 72 2c  adDoclists(pCsr,
a9a0: 20 30 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20   0, 0);.        
a9b0: 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f  if( rc!=SQLITE_O
a9c0: 4b 20 29 20 62 72 65 61 6b 3b 0a 20 20 20 20 20  K ) break;.     
a9d0: 20 20 20 69 66 28 20 62 47 6c 6f 62 61 6c 20 29     if( bGlobal )
a9e0: 7b 0a 20 20 20 20 20 20 20 20 20 20 69 66 28 20  {.          if( 
a9f0: 70 43 73 72 2d 3e 70 44 65 66 65 72 72 65 64 20  pCsr->pDeferred 
aa00: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  ){.            r
aa10: 63 20 3d 20 66 74 73 33 4d 61 74 63 68 69 6e 66  c = fts3Matchinf
aa20: 6f 53 65 6c 65 63 74 44 6f 63 74 6f 74 61 6c 28  oSelectDoctotal(
aa30: 70 54 61 62 2c 20 26 70 53 65 6c 65 63 74 2c 20  pTab, &pSelect, 
aa40: 26 70 49 6e 66 6f 2d 3e 6e 44 6f 63 2c 20 30 29  &pInfo->nDoc, 0)
aa50: 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ;.            if
aa60: 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc!=SQLITE_OK 
aa70: 29 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20  ) break;.       
aa80: 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20 20 72     }.          r
aa90: 63 20 3d 20 66 74 73 33 45 78 70 72 49 74 65 72  c = fts3ExprIter
aaa0: 61 74 65 28 70 45 78 70 72 2c 20 66 74 73 33 45  ate(pExpr, fts3E
aab0: 78 70 72 47 6c 6f 62 61 6c 48 69 74 73 43 62 2c  xprGlobalHitsCb,
aac0: 28 76 6f 69 64 2a 29 70 49 6e 66 6f 29 3b 0a 20  (void*)pInfo);. 
aad0: 20 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33           sqlite3
aae0: 46 74 73 33 45 76 61 6c 54 65 73 74 44 65 66 65  Fts3EvalTestDefe
aaf0: 72 72 65 64 28 70 43 73 72 2c 20 26 72 63 29 3b  rred(pCsr, &rc);
ab00: 0a 20 20 20 20 20 20 20 20 20 20 69 66 28 20 72  .          if( r
ab10: 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62  c!=SQLITE_OK ) b
ab20: 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 7d 0a  reak;.        }.
ab30: 20 20 20 20 20 20 20 20 28 76 6f 69 64 29 66 74          (void)ft
ab40: 73 33 45 78 70 72 49 74 65 72 61 74 65 28 70 45  s3ExprIterate(pE
ab50: 78 70 72 2c 20 66 74 73 33 45 78 70 72 4c 6f 63  xpr, fts3ExprLoc
ab60: 61 6c 48 69 74 73 43 62 2c 28 76 6f 69 64 2a 29  alHitsCb,(void*)
ab70: 70 49 6e 66 6f 29 3b 0a 20 20 20 20 20 20 20 20  pInfo);.        
ab80: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 20  break;.      }. 
ab90: 20 20 20 7d 0a 0a 20 20 20 20 70 49 6e 66 6f 2d     }..    pInfo-
aba0: 3e 61 4d 61 74 63 68 69 6e 66 6f 20 2b 3d 20 66  >aMatchinfo += f
abb0: 74 73 33 4d 61 74 63 68 69 6e 66 6f 53 69 7a 65  ts3MatchinfoSize
abc0: 28 70 49 6e 66 6f 2c 20 7a 41 72 67 5b 69 5d 29  (pInfo, zArg[i])
abd0: 3b 0a 20 20 7d 0a 0a 20 20 73 71 6c 69 74 65 33  ;.  }..  sqlite3
abe0: 5f 72 65 73 65 74 28 70 53 65 6c 65 63 74 29 3b  _reset(pSelect);
abf0: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
ac00: 0a 0a 2f 2a 0a 2a 2a 20 50 6f 70 75 6c 61 74 65  ../*.** Populate
ac10: 20 70 43 73 72 2d 3e 61 4d 61 74 63 68 69 6e 66   pCsr->aMatchinf
ac20: 6f 5b 5d 20 77 69 74 68 20 64 61 74 61 20 66 6f  o[] with data fo
ac30: 72 20 74 68 65 20 63 75 72 72 65 6e 74 20 72 6f  r the current ro
ac40: 77 2e 20 54 68 65 20 0a 2a 2a 20 27 6d 61 74 63  w. The .** 'matc
ac50: 68 69 6e 66 6f 27 20 64 61 74 61 20 69 73 20 61  hinfo' data is a
ac60: 6e 20 61 72 72 61 79 20 6f 66 20 33 32 2d 62 69  n array of 32-bi
ac70: 74 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 65 67  t unsigned integ
ac80: 65 72 73 20 28 43 20 74 79 70 65 20 75 33 32 29  ers (C type u32)
ac90: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
aca0: 20 66 74 73 33 47 65 74 4d 61 74 63 68 69 6e 66   fts3GetMatchinf
acb0: 6f 28 0a 20 20 73 71 6c 69 74 65 33 5f 63 6f 6e  o(.  sqlite3_con
acc0: 74 65 78 74 20 2a 70 43 74 78 2c 20 20 20 20 20  text *pCtx,     
acd0: 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 72 65 73     /* Return res
ace0: 75 6c 74 73 20 68 65 72 65 20 2a 2f 0a 20 20 46  ults here */.  F
acf0: 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72 2c  ts3Cursor *pCsr,
ad00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
ad10: 2a 20 46 54 53 33 20 43 75 72 73 6f 72 20 6f 62  * FTS3 Cursor ob
ad20: 6a 65 63 74 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  ject */.  const 
ad30: 63 68 61 72 20 2a 7a 41 72 67 20 20 20 20 20 20  char *zArg      
ad40: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 65 63            /* Sec
ad50: 6f 6e 64 20 61 72 67 75 6d 65 6e 74 20 74 6f 20  ond argument to 
ad60: 6d 61 74 63 68 69 6e 66 6f 28 29 20 66 75 6e 63  matchinfo() func
ad70: 74 69 6f 6e 20 2a 2f 0a 29 7b 0a 20 20 4d 61 74  tion */.){.  Mat
ad80: 63 68 49 6e 66 6f 20 73 49 6e 66 6f 3b 0a 20 20  chInfo sInfo;.  
ad90: 46 74 73 33 54 61 62 6c 65 20 2a 70 54 61 62 20  Fts3Table *pTab 
ada0: 3d 20 28 46 74 73 33 54 61 62 6c 65 20 2a 29 70  = (Fts3Table *)p
adb0: 43 73 72 2d 3e 62 61 73 65 2e 70 56 74 61 62 3b  Csr->base.pVtab;
adc0: 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49  .  int rc = SQLI
add0: 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20 62 47 6c  TE_OK;.  int bGl
ade0: 6f 62 61 6c 20 3d 20 30 3b 20 20 20 20 20 20 20  obal = 0;       
adf0: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6c 6c           /* Coll
ae00: 65 63 74 20 27 67 6c 6f 62 61 6c 27 20 73 74 61  ect 'global' sta
ae10: 74 73 20 61 73 20 77 65 6c 6c 20 61 73 20 6c 6f  ts as well as lo
ae20: 63 61 6c 20 2a 2f 0a 0a 20 20 75 33 32 20 2a 61  cal */..  u32 *a
ae30: 4f 75 74 20 3d 20 30 3b 0a 20 20 76 6f 69 64 20  Out = 0;.  void 
ae40: 28 2a 78 44 65 73 74 72 6f 79 4f 75 74 29 28 76  (*xDestroyOut)(v
ae50: 6f 69 64 2a 29 20 3d 20 30 3b 0a 0a 20 20 6d 65  oid*) = 0;..  me
ae60: 6d 73 65 74 28 26 73 49 6e 66 6f 2c 20 30 2c 20  mset(&sInfo, 0, 
ae70: 73 69 7a 65 6f 66 28 4d 61 74 63 68 49 6e 66 6f  sizeof(MatchInfo
ae80: 29 29 3b 0a 20 20 73 49 6e 66 6f 2e 70 43 75 72  ));.  sInfo.pCur
ae90: 73 6f 72 20 3d 20 70 43 73 72 3b 0a 20 20 73 49  sor = pCsr;.  sI
aea0: 6e 66 6f 2e 6e 43 6f 6c 20 3d 20 70 54 61 62 2d  nfo.nCol = pTab-
aeb0: 3e 6e 43 6f 6c 75 6d 6e 3b 0a 0a 20 20 2f 2a 20  >nColumn;..  /* 
aec0: 49 66 20 74 68 65 72 65 20 69 73 20 63 61 63 68  If there is cach
aed0: 65 64 20 6d 61 74 63 68 69 6e 66 6f 28 29 20 64  ed matchinfo() d
aee0: 61 74 61 2c 20 62 75 74 20 74 68 65 20 66 6f 72  ata, but the for
aef0: 6d 61 74 20 73 74 72 69 6e 67 20 66 6f 72 20 74  mat string for t
af00: 68 65 20 0a 20 20 2a 2a 20 63 61 63 68 65 20 64  he .  ** cache d
af10: 6f 65 73 20 6e 6f 74 20 6d 61 74 63 68 20 74 68  oes not match th
af20: 65 20 66 6f 72 6d 61 74 20 73 74 72 69 6e 67 20  e format string 
af30: 66 6f 72 20 74 68 69 73 20 72 65 71 75 65 73 74  for this request
af40: 2c 20 64 69 73 63 61 72 64 20 0a 20 20 2a 2a 20  , discard .  ** 
af50: 74 68 65 20 63 61 63 68 65 64 20 64 61 74 61 2e  the cached data.
af60: 20 2a 2f 0a 20 20 69 66 28 20 70 43 73 72 2d 3e   */.  if( pCsr->
af70: 70 4d 49 42 75 66 66 65 72 20 26 26 20 73 74 72  pMIBuffer && str
af80: 63 6d 70 28 70 43 73 72 2d 3e 70 4d 49 42 75 66  cmp(pCsr->pMIBuf
af90: 66 65 72 2d 3e 7a 4d 61 74 63 68 69 6e 66 6f 2c  fer->zMatchinfo,
afa0: 20 7a 41 72 67 29 20 29 7b 0a 20 20 20 20 73 71   zArg) ){.    sq
afb0: 6c 69 74 65 33 46 74 73 33 4d 49 42 75 66 66 65  lite3Fts3MIBuffe
afc0: 72 46 72 65 65 28 70 43 73 72 2d 3e 70 4d 49 42  rFree(pCsr->pMIB
afd0: 75 66 66 65 72 29 3b 0a 20 20 20 20 70 43 73 72  uffer);.    pCsr
afe0: 2d 3e 70 4d 49 42 75 66 66 65 72 20 3d 20 30 3b  ->pMIBuffer = 0;
aff0: 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49 66 20 46 74  .  }..  /* If Ft
b000: 73 33 43 75 72 73 6f 72 2e 70 4d 49 42 75 66 66  s3Cursor.pMIBuff
b010: 65 72 20 69 73 20 4e 55 4c 4c 2c 20 74 68 65 6e  er is NULL, then
b020: 20 74 68 69 73 20 69 73 20 74 68 65 20 66 69 72   this is the fir
b030: 73 74 20 74 69 6d 65 20 74 68 65 0a 20 20 2a 2a  st time the.  **
b040: 20 6d 61 74 63 68 69 6e 66 6f 20 66 75 6e 63 74   matchinfo funct
b050: 69 6f 6e 20 68 61 73 20 62 65 65 6e 20 63 61 6c  ion has been cal
b060: 6c 65 64 20 66 6f 72 20 74 68 69 73 20 71 75 65  led for this que
b070: 72 79 2e 20 49 6e 20 74 68 69 73 20 63 61 73 65  ry. In this case
b080: 20 0a 20 20 2a 2a 20 61 6c 6c 6f 63 61 74 65 20   .  ** allocate 
b090: 74 68 65 20 61 72 72 61 79 20 75 73 65 64 20 74  the array used t
b0a0: 6f 20 61 63 63 75 6d 75 6c 61 74 65 20 74 68 65  o accumulate the
b0b0: 20 6d 61 74 63 68 69 6e 66 6f 20 64 61 74 61 20   matchinfo data 
b0c0: 61 6e 64 0a 20 20 2a 2a 20 69 6e 69 74 69 61 6c  and.  ** initial
b0d0: 69 7a 65 20 74 68 6f 73 65 20 65 6c 65 6d 65 6e  ize those elemen
b0e0: 74 73 20 74 68 61 74 20 61 72 65 20 63 6f 6e 73  ts that are cons
b0f0: 74 61 6e 74 20 66 6f 72 20 65 76 65 72 79 20 72  tant for every r
b100: 6f 77 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20 70  ow..  */.  if( p
b110: 43 73 72 2d 3e 70 4d 49 42 75 66 66 65 72 3d 3d  Csr->pMIBuffer==
b120: 30 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e 4d 61  0 ){.    int nMa
b130: 74 63 68 69 6e 66 6f 20 3d 20 30 3b 20 20 20 20  tchinfo = 0;    
b140: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
b150: 20 6f 66 20 75 33 32 20 65 6c 65 6d 65 6e 74 73   of u32 elements
b160: 20 69 6e 20 6d 61 74 63 68 2d 69 6e 66 6f 20 2a   in match-info *
b170: 2f 0a 20 20 20 20 69 6e 74 20 69 3b 20 20 20 20  /.    int i;    
b180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b190: 20 20 20 20 2f 2a 20 55 73 65 64 20 74 6f 20 69      /* Used to i
b1a0: 74 65 72 61 74 65 20 74 68 72 6f 75 67 68 20 7a  terate through z
b1b0: 41 72 67 20 2a 2f 0a 0a 20 20 20 20 2f 2a 20 44  Arg */..    /* D
b1c0: 65 74 65 72 6d 69 6e 65 20 74 68 65 20 6e 75 6d  etermine the num
b1d0: 62 65 72 20 6f 66 20 70 68 72 61 73 65 73 20 69  ber of phrases i
b1e0: 6e 20 74 68 65 20 71 75 65 72 79 20 2a 2f 0a 20  n the query */. 
b1f0: 20 20 20 70 43 73 72 2d 3e 6e 50 68 72 61 73 65     pCsr->nPhrase
b200: 20 3d 20 66 74 73 33 45 78 70 72 50 68 72 61 73   = fts3ExprPhras
b210: 65 43 6f 75 6e 74 28 70 43 73 72 2d 3e 70 45 78  eCount(pCsr->pEx
b220: 70 72 29 3b 0a 20 20 20 20 73 49 6e 66 6f 2e 6e  pr);.    sInfo.n
b230: 50 68 72 61 73 65 20 3d 20 70 43 73 72 2d 3e 6e  Phrase = pCsr->n
b240: 50 68 72 61 73 65 3b 0a 0a 20 20 20 20 2f 2a 20  Phrase;..    /* 
b250: 44 65 74 65 72 6d 69 6e 65 20 74 68 65 20 6e 75  Determine the nu
b260: 6d 62 65 72 20 6f 66 20 69 6e 74 65 67 65 72 73  mber of integers
b270: 20 69 6e 20 74 68 65 20 62 75 66 66 65 72 20 72   in the buffer r
b280: 65 74 75 72 6e 65 64 20 62 79 20 74 68 69 73 20  eturned by this 
b290: 63 61 6c 6c 2e 20 2a 2f 0a 20 20 20 20 66 6f 72  call. */.    for
b2a0: 28 69 3d 30 3b 20 7a 41 72 67 5b 69 5d 3b 20 69  (i=0; zArg[i]; i
b2b0: 2b 2b 29 7b 0a 20 20 20 20 20 20 63 68 61 72 20  ++){.      char 
b2c0: 2a 7a 45 72 72 20 3d 20 30 3b 0a 20 20 20 20 20  *zErr = 0;.     
b2d0: 20 69 66 28 20 66 74 73 33 4d 61 74 63 68 69 6e   if( fts3Matchin
b2e0: 66 6f 43 68 65 63 6b 28 70 54 61 62 2c 20 7a 41  foCheck(pTab, zA
b2f0: 72 67 5b 69 5d 2c 20 26 7a 45 72 72 29 20 29 7b  rg[i], &zErr) ){
b300: 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33  .        sqlite3
b310: 5f 72 65 73 75 6c 74 5f 65 72 72 6f 72 28 70 43  _result_error(pC
b320: 74 78 2c 20 7a 45 72 72 2c 20 2d 31 29 3b 0a 20  tx, zErr, -1);. 
b330: 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66         sqlite3_f
b340: 72 65 65 28 7a 45 72 72 29 3b 0a 20 20 20 20 20  ree(zErr);.     
b350: 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 20 20 20     return;.     
b360: 20 7d 0a 20 20 20 20 20 20 6e 4d 61 74 63 68 69   }.      nMatchi
b370: 6e 66 6f 20 2b 3d 20 66 74 73 33 4d 61 74 63 68  nfo += fts3Match
b380: 69 6e 66 6f 53 69 7a 65 28 26 73 49 6e 66 6f 2c  infoSize(&sInfo,
b390: 20 7a 41 72 67 5b 69 5d 29 3b 0a 20 20 20 20 7d   zArg[i]);.    }
b3a0: 0a 0a 20 20 20 20 2f 2a 20 41 6c 6c 6f 63 61 74  ..    /* Allocat
b3b0: 65 20 73 70 61 63 65 20 66 6f 72 20 46 74 73 33  e space for Fts3
b3c0: 43 75 72 73 6f 72 2e 61 4d 61 74 63 68 69 6e 66  Cursor.aMatchinf
b3d0: 6f 5b 5d 20 61 6e 64 20 46 74 73 33 43 75 72 73  o[] and Fts3Curs
b3e0: 6f 72 2e 7a 4d 61 74 63 68 69 6e 66 6f 2e 20 2a  or.zMatchinfo. *
b3f0: 2f 0a 20 20 20 20 70 43 73 72 2d 3e 70 4d 49 42  /.    pCsr->pMIB
b400: 75 66 66 65 72 20 3d 20 66 74 73 33 4d 49 42 75  uffer = fts3MIBu
b410: 66 66 65 72 4e 65 77 28 6e 4d 61 74 63 68 69 6e  fferNew(nMatchin
b420: 66 6f 2c 20 7a 41 72 67 29 3b 0a 20 20 20 20 69  fo, zArg);.    i
b430: 66 28 20 21 70 43 73 72 2d 3e 70 4d 49 42 75 66  f( !pCsr->pMIBuf
b440: 66 65 72 20 29 20 72 63 20 3d 20 53 51 4c 49 54  fer ) rc = SQLIT
b450: 45 5f 4e 4f 4d 45 4d 3b 0a 0a 20 20 20 20 70 43  E_NOMEM;..    pC
b460: 73 72 2d 3e 69 73 4d 61 74 63 68 69 6e 66 6f 4e  sr->isMatchinfoN
b470: 65 65 64 65 64 20 3d 20 31 3b 0a 20 20 20 20 62  eeded = 1;.    b
b480: 47 6c 6f 62 61 6c 20 3d 20 31 3b 0a 20 20 7d 0a  Global = 1;.  }.
b490: 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54  .  if( rc==SQLIT
b4a0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 78 44 65 73  E_OK ){.    xDes
b4b0: 74 72 6f 79 4f 75 74 20 3d 20 66 74 73 33 4d 49  troyOut = fts3MI
b4c0: 42 75 66 66 65 72 41 6c 6c 6f 63 28 70 43 73 72  BufferAlloc(pCsr
b4d0: 2d 3e 70 4d 49 42 75 66 66 65 72 2c 20 26 61 4f  ->pMIBuffer, &aO
b4e0: 75 74 29 3b 0a 20 20 20 20 69 66 28 20 78 44 65  ut);.    if( xDe
b4f0: 73 74 72 6f 79 4f 75 74 3d 3d 30 20 29 7b 0a 20  stroyOut==0 ){. 
b500: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
b510: 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20 20  _NOMEM;.    }.  
b520: 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  }..  if( rc==SQL
b530: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 73 49  ITE_OK ){.    sI
b540: 6e 66 6f 2e 61 4d 61 74 63 68 69 6e 66 6f 20 3d  nfo.aMatchinfo =
b550: 20 61 4f 75 74 3b 0a 20 20 20 20 73 49 6e 66 6f   aOut;.    sInfo
b560: 2e 6e 50 68 72 61 73 65 20 3d 20 70 43 73 72 2d  .nPhrase = pCsr-
b570: 3e 6e 50 68 72 61 73 65 3b 0a 20 20 20 20 72 63  >nPhrase;.    rc
b580: 20 3d 20 66 74 73 33 4d 61 74 63 68 69 6e 66 6f   = fts3Matchinfo
b590: 56 61 6c 75 65 73 28 70 43 73 72 2c 20 62 47 6c  Values(pCsr, bGl
b5a0: 6f 62 61 6c 2c 20 26 73 49 6e 66 6f 2c 20 7a 41  obal, &sInfo, zA
b5b0: 72 67 29 3b 0a 20 20 20 20 69 66 28 20 62 47 6c  rg);.    if( bGl
b5c0: 6f 62 61 6c 20 29 7b 0a 20 20 20 20 20 20 66 74  obal ){.      ft
b5d0: 73 33 4d 49 42 75 66 66 65 72 53 65 74 47 6c 6f  s3MIBufferSetGlo
b5e0: 62 61 6c 28 70 43 73 72 2d 3e 70 4d 49 42 75 66  bal(pCsr->pMIBuf
b5f0: 66 65 72 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  fer);.    }.  }.
b600: 0a 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54  .  if( rc!=SQLIT
b610: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 73 71 6c 69  E_OK ){.    sqli
b620: 74 65 33 5f 72 65 73 75 6c 74 5f 65 72 72 6f 72  te3_result_error
b630: 5f 63 6f 64 65 28 70 43 74 78 2c 20 72 63 29 3b  _code(pCtx, rc);
b640: 0a 20 20 20 20 69 66 28 20 78 44 65 73 74 72 6f  .    if( xDestro
b650: 79 4f 75 74 20 29 20 78 44 65 73 74 72 6f 79 4f  yOut ) xDestroyO
b660: 75 74 28 61 4f 75 74 29 3b 0a 20 20 7d 65 6c 73  ut(aOut);.  }els
b670: 65 7b 0a 20 20 20 20 69 6e 74 20 6e 20 3d 20 70  e{.    int n = p
b680: 43 73 72 2d 3e 70 4d 49 42 75 66 66 65 72 2d 3e  Csr->pMIBuffer->
b690: 6e 45 6c 65 6d 20 2a 20 73 69 7a 65 6f 66 28 75  nElem * sizeof(u
b6a0: 33 32 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33  32);.    sqlite3
b6b0: 5f 72 65 73 75 6c 74 5f 62 6c 6f 62 28 70 43 74  _result_blob(pCt
b6c0: 78 2c 20 61 4f 75 74 2c 20 6e 2c 20 78 44 65 73  x, aOut, n, xDes
b6d0: 74 72 6f 79 4f 75 74 29 3b 0a 20 20 7d 0a 7d 0a  troyOut);.  }.}.
b6e0: 0a 2f 2a 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e 74  ./*.** Implement
b6f0: 61 74 69 6f 6e 20 6f 66 20 73 6e 69 70 70 65 74  ation of snippet
b700: 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a  () function..*/.
b710: 76 6f 69 64 20 73 71 6c 69 74 65 33 46 74 73 33  void sqlite3Fts3
b720: 53 6e 69 70 70 65 74 28 0a 20 20 73 71 6c 69 74  Snippet(.  sqlit
b730: 65 33 5f 63 6f 6e 74 65 78 74 20 2a 70 43 74 78  e3_context *pCtx
b740: 2c 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 51  ,          /* SQ
b750: 4c 69 74 65 20 66 75 6e 63 74 69 6f 6e 20 63 61  Lite function ca
b760: 6c 6c 20 63 6f 6e 74 65 78 74 20 2a 2f 0a 20 20  ll context */.  
b770: 46 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72  Fts3Cursor *pCsr
b780: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
b790: 2f 2a 20 43 75 72 73 6f 72 20 6f 62 6a 65 63 74  /* Cursor object
b7a0: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
b7b0: 20 2a 7a 53 74 61 72 74 2c 20 20 20 20 20 20 20   *zStart,       
b7c0: 20 20 20 20 20 20 2f 2a 20 53 6e 69 70 70 65 74        /* Snippet
b7d0: 20 73 74 61 72 74 20 74 65 78 74 20 2d 20 22 3c   start text - "<
b7e0: 62 3e 22 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  b>" */.  const c
b7f0: 68 61 72 20 2a 7a 45 6e 64 2c 20 20 20 20 20 20  har *zEnd,      
b800: 20 20 20 20 20 20 20 20 20 2f 2a 20 53 6e 69 70           /* Snip
b810: 70 65 74 20 65 6e 64 20 74 65 78 74 20 2d 20 22  pet end text - "
b820: 3c 2f 62 3e 22 20 2a 2f 0a 20 20 63 6f 6e 73 74  </b>" */.  const
b830: 20 63 68 61 72 20 2a 7a 45 6c 6c 69 70 73 69 73   char *zEllipsis
b840: 2c 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 6e  ,          /* Sn
b850: 69 70 70 65 74 20 65 6c 6c 69 70 73 69 73 20 74  ippet ellipsis t
b860: 65 78 74 20 2d 20 22 3c 62 3e 2e 2e 2e 3c 2f 62  ext - "<b>...</b
b870: 3e 22 20 2a 2f 0a 20 20 69 6e 74 20 69 43 6f 6c  >" */.  int iCol
b880: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
b890: 20 20 20 20 20 20 20 20 2f 2a 20 45 78 74 72 61          /* Extra
b8a0: 63 74 20 73 6e 69 70 70 65 74 20 66 72 6f 6d 20  ct snippet from 
b8b0: 74 68 69 73 20 63 6f 6c 75 6d 6e 20 2a 2f 0a 20  this column */. 
b8c0: 20 69 6e 74 20 6e 54 6f 6b 65 6e 20 20 20 20 20   int nToken     
b8d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b8e0: 20 2f 2a 20 41 70 70 72 6f 78 69 6d 61 74 65 20   /* Approximate 
b8f0: 6e 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73  number of tokens
b900: 20 69 6e 20 73 6e 69 70 70 65 74 20 2a 2f 0a 29   in snippet */.)
b910: 7b 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a 70  {.  Fts3Table *p
b920: 54 61 62 20 3d 20 28 46 74 73 33 54 61 62 6c 65  Tab = (Fts3Table
b930: 20 2a 29 70 43 73 72 2d 3e 62 61 73 65 2e 70 56   *)pCsr->base.pV
b940: 74 61 62 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20  tab;.  int rc = 
b950: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74  SQLITE_OK;.  int
b960: 20 69 3b 0a 20 20 53 74 72 42 75 66 66 65 72 20   i;.  StrBuffer 
b970: 72 65 73 20 3d 20 7b 30 2c 20 30 2c 20 30 7d 3b  res = {0, 0, 0};
b980: 0a 0a 20 20 2f 2a 20 54 68 65 20 72 65 74 75 72  ..  /* The retur
b990: 6e 65 64 20 74 65 78 74 20 69 6e 63 6c 75 64 65  ned text include
b9a0: 73 20 75 70 20 74 6f 20 66 6f 75 72 20 66 72 61  s up to four fra
b9b0: 67 6d 65 6e 74 73 20 6f 66 20 74 65 78 74 20 65  gments of text e
b9c0: 78 74 72 61 63 74 65 64 20 66 72 6f 6d 0a 20 20  xtracted from.  
b9d0: 2a 2a 20 74 68 65 20 64 61 74 61 20 69 6e 20 74  ** the data in t
b9e0: 68 65 20 63 75 72 72 65 6e 74 20 72 6f 77 2e 20  he current row. 
b9f0: 54 68 65 20 66 69 72 73 74 20 69 74 65 72 61 74  The first iterat
ba00: 69 6f 6e 20 6f 66 20 74 68 65 20 66 6f 72 28 2e  ion of the for(.
ba10: 2e 2e 29 20 6c 6f 6f 70 0a 20 20 2a 2a 20 62 65  ..) loop.  ** be
ba20: 6c 6f 77 20 61 74 74 65 6d 70 74 73 20 74 6f 20  low attempts to 
ba30: 6c 6f 63 61 74 65 20 61 20 73 69 6e 67 6c 65 20  locate a single 
ba40: 66 72 61 67 6d 65 6e 74 20 6f 66 20 74 65 78 74  fragment of text
ba50: 20 6e 54 6f 6b 65 6e 20 74 6f 6b 65 6e 73 20 69   nToken tokens i
ba60: 6e 20 0a 20 20 2a 2a 20 73 69 7a 65 20 74 68 61  n .  ** size tha
ba70: 74 20 63 6f 6e 74 61 69 6e 73 20 61 74 20 6c 65  t contains at le
ba80: 61 73 74 20 6f 6e 65 20 69 6e 73 74 61 6e 63 65  ast one instance
ba90: 20 6f 66 20 61 6c 6c 20 70 68 72 61 73 65 73 20   of all phrases 
baa0: 69 6e 20 74 68 65 20 71 75 65 72 79 0a 20 20 2a  in the query.  *
bab0: 2a 20 65 78 70 72 65 73 73 69 6f 6e 20 74 68 61  * expression tha
bac0: 74 20 61 70 70 65 61 72 20 69 6e 20 74 68 65 20  t appear in the 
bad0: 63 75 72 72 65 6e 74 20 72 6f 77 2e 20 49 66 20  current row. If 
bae0: 73 75 63 68 20 61 20 66 72 61 67 6d 65 6e 74 20  such a fragment 
baf0: 6f 66 20 74 65 78 74 0a 20 20 2a 2a 20 63 61 6e  of text.  ** can
bb00: 6e 6f 74 20 62 65 20 66 6f 75 6e 64 2c 20 74 68  not be found, th
bb10: 65 20 73 65 63 6f 6e 64 20 69 74 65 72 61 74 69  e second iterati
bb20: 6f 6e 20 6f 66 20 74 68 65 20 6c 6f 6f 70 20 61  on of the loop a
bb30: 74 74 65 6d 70 74 73 20 74 6f 20 6c 6f 63 61 74  ttempts to locat
bb40: 65 0a 20 20 2a 2a 20 61 20 70 61 69 72 20 6f 66  e.  ** a pair of
bb50: 20 66 72 61 67 6d 65 6e 74 73 2c 20 61 6e 64 20   fragments, and 
bb60: 73 6f 20 6f 6e 2e 0a 20 20 2a 2f 0a 20 20 69 6e  so on..  */.  in
bb70: 74 20 6e 53 6e 69 70 70 65 74 20 3d 20 30 3b 20  t nSnippet = 0; 
bb80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
bb90: 20 4e 75 6d 62 65 72 20 6f 66 20 66 72 61 67 6d   Number of fragm
bba0: 65 6e 74 73 20 69 6e 20 74 68 69 73 20 73 6e 69  ents in this sni
bbb0: 70 70 65 74 20 2a 2f 0a 20 20 53 6e 69 70 70 65  ppet */.  Snippe
bbc0: 74 46 72 61 67 6d 65 6e 74 20 61 53 6e 69 70 70  tFragment aSnipp
bbd0: 65 74 5b 34 5d 3b 20 20 20 20 2f 2a 20 4d 61 78  et[4];    /* Max
bbe0: 69 6d 75 6d 20 6f 66 20 34 20 66 72 61 67 6d 65  imum of 4 fragme
bbf0: 6e 74 73 20 70 65 72 20 73 6e 69 70 70 65 74 20  nts per snippet 
bc00: 2a 2f 0a 20 20 69 6e 74 20 6e 46 54 6f 6b 65 6e  */.  int nFToken
bc10: 20 3d 20 2d 31 3b 20 20 20 20 20 20 20 20 20 20   = -1;          
bc20: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
bc30: 66 20 74 6f 6b 65 6e 73 20 69 6e 20 65 61 63 68  f tokens in each
bc40: 20 66 72 61 67 6d 65 6e 74 20 2a 2f 0a 0a 20 20   fragment */..  
bc50: 69 66 28 20 21 70 43 73 72 2d 3e 70 45 78 70 72  if( !pCsr->pExpr
bc60: 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f   ){.    sqlite3_
bc70: 72 65 73 75 6c 74 5f 74 65 78 74 28 70 43 74 78  result_text(pCtx
bc80: 2c 20 22 22 2c 20 30 2c 20 53 51 4c 49 54 45 5f  , "", 0, SQLITE_
bc90: 53 54 41 54 49 43 29 3b 0a 20 20 20 20 72 65 74  STATIC);.    ret
bca0: 75 72 6e 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 4c  urn;.  }..  /* L
bcb0: 69 6d 69 74 20 74 68 65 20 73 6e 69 70 70 65 74  imit the snippet
bcc0: 20 6c 65 6e 67 74 68 20 74 6f 20 36 34 20 74 6f   length to 64 to
bcd0: 6b 65 6e 73 2e 20 2a 2f 0a 20 20 69 66 28 20 6e  kens. */.  if( n
bce0: 54 6f 6b 65 6e 3c 2d 36 34 20 29 20 6e 54 6f 6b  Token<-64 ) nTok
bcf0: 65 6e 20 3d 20 2d 36 34 3b 0a 20 20 69 66 28 20  en = -64;.  if( 
bd00: 6e 54 6f 6b 65 6e 3e 2b 36 34 20 29 20 6e 54 6f  nToken>+64 ) nTo
bd10: 6b 65 6e 20 3d 20 2b 36 34 3b 0a 0a 20 20 66 6f  ken = +64;..  fo
bd20: 72 28 6e 53 6e 69 70 70 65 74 3d 31 3b 20 31 3b  r(nSnippet=1; 1;
bd30: 20 6e 53 6e 69 70 70 65 74 2b 2b 29 7b 0a 0a 20   nSnippet++){.. 
bd40: 20 20 20 69 6e 74 20 69 53 6e 69 70 3b 20 20 20     int iSnip;   
bd50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
bd60: 20 2f 2a 20 4c 6f 6f 70 20 63 6f 75 6e 74 65 72   /* Loop counter
bd70: 20 30 2e 2e 6e 53 6e 69 70 70 65 74 2d 31 20 2a   0..nSnippet-1 *
bd80: 2f 0a 20 20 20 20 75 36 34 20 6d 43 6f 76 65 72  /.    u64 mCover
bd90: 65 64 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  ed = 0;         
bda0: 20 20 20 20 2f 2a 20 42 69 74 6d 61 73 6b 20 6f      /* Bitmask o
bdb0: 66 20 70 68 72 61 73 65 73 20 63 6f 76 65 72 65  f phrases covere
bdc0: 64 20 62 79 20 73 6e 69 70 70 65 74 20 2a 2f 0a  d by snippet */.
bdd0: 20 20 20 20 75 36 34 20 6d 53 65 65 6e 20 3d 20      u64 mSeen = 
bde0: 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0;              
bdf0: 20 20 2f 2a 20 42 69 74 6d 61 73 6b 20 6f 66 20    /* Bitmask of 
be00: 70 68 72 61 73 65 73 20 73 65 65 6e 20 62 79 20  phrases seen by 
be10: 42 65 73 74 53 6e 69 70 70 65 74 28 29 20 2a 2f  BestSnippet() */
be20: 0a 0a 20 20 20 20 69 66 28 20 6e 54 6f 6b 65 6e  ..    if( nToken
be30: 3e 3d 30 20 29 7b 0a 20 20 20 20 20 20 6e 46 54  >=0 ){.      nFT
be40: 6f 6b 65 6e 20 3d 20 28 6e 54 6f 6b 65 6e 2b 6e  oken = (nToken+n
be50: 53 6e 69 70 70 65 74 2d 31 29 20 2f 20 6e 53 6e  Snippet-1) / nSn
be60: 69 70 70 65 74 3b 0a 20 20 20 20 7d 65 6c 73 65  ippet;.    }else
be70: 7b 0a 20 20 20 20 20 20 6e 46 54 6f 6b 65 6e 20  {.      nFToken 
be80: 3d 20 2d 31 20 2a 20 6e 54 6f 6b 65 6e 3b 0a 20  = -1 * nToken;. 
be90: 20 20 20 7d 0a 0a 20 20 20 20 66 6f 72 28 69 53     }..    for(iS
bea0: 6e 69 70 3d 30 3b 20 69 53 6e 69 70 3c 6e 53 6e  nip=0; iSnip<nSn
beb0: 69 70 70 65 74 3b 20 69 53 6e 69 70 2b 2b 29 7b  ippet; iSnip++){
bec0: 0a 20 20 20 20 20 20 69 6e 74 20 69 42 65 73 74  .      int iBest
bed0: 53 63 6f 72 65 20 3d 20 2d 31 3b 20 20 20 20 20  Score = -1;     
bee0: 20 20 20 2f 2a 20 42 65 73 74 20 73 63 6f 72 65     /* Best score
bef0: 20 6f 66 20 63 6f 6c 75 6d 6e 73 20 63 68 65 63   of columns chec
bf00: 6b 65 64 20 73 6f 20 66 61 72 20 2a 2f 0a 20 20  ked so far */.  
bf10: 20 20 20 20 69 6e 74 20 69 52 65 61 64 3b 20 20      int iRead;  
bf20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
bf30: 2f 2a 20 55 73 65 64 20 74 6f 20 69 74 65 72 61  /* Used to itera
bf40: 74 65 20 74 68 72 6f 75 67 68 20 63 6f 6c 75 6d  te through colum
bf50: 6e 73 20 2a 2f 0a 20 20 20 20 20 20 53 6e 69 70  ns */.      Snip
bf60: 70 65 74 46 72 61 67 6d 65 6e 74 20 2a 70 46 72  petFragment *pFr
bf70: 61 67 6d 65 6e 74 20 3d 20 26 61 53 6e 69 70 70  agment = &aSnipp
bf80: 65 74 5b 69 53 6e 69 70 5d 3b 0a 0a 20 20 20 20  et[iSnip];..    
bf90: 20 20 6d 65 6d 73 65 74 28 70 46 72 61 67 6d 65    memset(pFragme
bfa0: 6e 74 2c 20 30 2c 20 73 69 7a 65 6f 66 28 2a 70  nt, 0, sizeof(*p
bfb0: 46 72 61 67 6d 65 6e 74 29 29 3b 0a 0a 20 20 20  Fragment));..   
bfc0: 20 20 20 2f 2a 20 4c 6f 6f 70 20 74 68 72 6f 75     /* Loop throu
bfd0: 67 68 20 61 6c 6c 20 63 6f 6c 75 6d 6e 73 20 6f  gh all columns o
bfe0: 66 20 74 68 65 20 74 61 62 6c 65 20 62 65 69 6e  f the table bein
bff0: 67 20 63 6f 6e 73 69 64 65 72 65 64 20 66 6f 72  g considered for
c000: 20 73 6e 69 70 70 65 74 73 2e 0a 20 20 20 20 20   snippets..     
c010: 20 2a 2a 20 49 66 20 74 68 65 20 69 43 6f 6c 20   ** If the iCol 
c020: 61 72 67 75 6d 65 6e 74 20 74 6f 20 74 68 69 73  argument to this
c030: 20 66 75 6e 63 74 69 6f 6e 20 77 61 73 20 6e 65   function was ne
c040: 67 61 74 69 76 65 2c 20 74 68 69 73 20 6d 65 61  gative, this mea
c050: 6e 73 20 61 6c 6c 0a 20 20 20 20 20 20 2a 2a 20  ns all.      ** 
c060: 63 6f 6c 75 6d 6e 73 20 6f 66 20 74 68 65 20 46  columns of the F
c070: 54 53 33 20 74 61 62 6c 65 2e 20 4f 74 68 65 72  TS3 table. Other
c080: 77 69 73 65 2c 20 6f 6e 6c 79 20 63 6f 6c 75 6d  wise, only colum
c090: 6e 20 69 43 6f 6c 20 69 73 20 63 6f 6e 73 69 64  n iCol is consid
c0a0: 65 72 65 64 2e 0a 20 20 20 20 20 20 2a 2f 0a 20  ered..      */. 
c0b0: 20 20 20 20 20 66 6f 72 28 69 52 65 61 64 3d 30       for(iRead=0
c0c0: 3b 20 69 52 65 61 64 3c 70 54 61 62 2d 3e 6e 43  ; iRead<pTab->nC
c0d0: 6f 6c 75 6d 6e 3b 20 69 52 65 61 64 2b 2b 29 7b  olumn; iRead++){
c0e0: 0a 20 20 20 20 20 20 20 20 53 6e 69 70 70 65 74  .        Snippet
c0f0: 46 72 61 67 6d 65 6e 74 20 73 46 20 3d 20 7b 30  Fragment sF = {0
c100: 2c 20 30 2c 20 30 2c 20 30 7d 3b 0a 20 20 20 20  , 0, 0, 0};.    
c110: 20 20 20 20 69 6e 74 20 69 53 20 3d 20 30 3b 0a      int iS = 0;.
c120: 20 20 20 20 20 20 20 20 69 66 28 20 69 43 6f 6c          if( iCol
c130: 3e 3d 30 20 26 26 20 69 52 65 61 64 21 3d 69 43  >=0 && iRead!=iC
c140: 6f 6c 20 29 20 63 6f 6e 74 69 6e 75 65 3b 0a 0a  ol ) continue;..
c150: 20 20 20 20 20 20 20 20 2f 2a 20 46 69 6e 64 20          /* Find 
c160: 74 68 65 20 62 65 73 74 20 73 6e 69 70 70 65 74  the best snippet
c170: 20 6f 66 20 6e 46 54 6f 6b 65 6e 20 74 6f 6b 65   of nFToken toke
c180: 6e 73 20 69 6e 20 63 6f 6c 75 6d 6e 20 69 52 65  ns in column iRe
c190: 61 64 2e 20 2a 2f 0a 20 20 20 20 20 20 20 20 72  ad. */.        r
c1a0: 63 20 3d 20 66 74 73 33 42 65 73 74 53 6e 69 70  c = fts3BestSnip
c1b0: 70 65 74 28 6e 46 54 6f 6b 65 6e 2c 20 70 43 73  pet(nFToken, pCs
c1c0: 72 2c 20 69 52 65 61 64 2c 20 6d 43 6f 76 65 72  r, iRead, mCover
c1d0: 65 64 2c 20 26 6d 53 65 65 6e 2c 20 26 73 46 2c  ed, &mSeen, &sF,
c1e0: 20 26 69 53 29 3b 0a 20 20 20 20 20 20 20 20 69   &iS);.        i
c1f0: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
c200: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 67 6f   ){.          go
c210: 74 6f 20 73 6e 69 70 70 65 74 5f 6f 75 74 3b 0a  to snippet_out;.
c220: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
c230: 20 20 69 66 28 20 69 53 3e 69 42 65 73 74 53 63    if( iS>iBestSc
c240: 6f 72 65 20 29 7b 0a 20 20 20 20 20 20 20 20 20  ore ){.         
c250: 20 2a 70 46 72 61 67 6d 65 6e 74 20 3d 20 73 46   *pFragment = sF
c260: 3b 0a 20 20 20 20 20 20 20 20 20 20 69 42 65 73  ;.          iBes
c270: 74 53 63 6f 72 65 20 3d 20 69 53 3b 0a 20 20 20  tScore = iS;.   
c280: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 0a       }.      }..
c290: 20 20 20 20 20 20 6d 43 6f 76 65 72 65 64 20 7c        mCovered |
c2a0: 3d 20 70 46 72 61 67 6d 65 6e 74 2d 3e 63 6f 76  = pFragment->cov
c2b0: 65 72 65 64 3b 0a 20 20 20 20 7d 0a 0a 20 20 20  ered;.    }..   
c2c0: 20 2f 2a 20 49 66 20 61 6c 6c 20 71 75 65 72 79   /* If all query
c2d0: 20 70 68 72 61 73 65 73 20 73 65 65 6e 20 62 79   phrases seen by
c2e0: 20 66 74 73 33 42 65 73 74 53 6e 69 70 70 65 74   fts3BestSnippet
c2f0: 28 29 20 61 72 65 20 70 72 65 73 65 6e 74 20 69  () are present i
c300: 6e 20 61 74 20 6c 65 61 73 74 0a 20 20 20 20 2a  n at least.    *
c310: 2a 20 6f 6e 65 20 6f 66 20 74 68 65 20 6e 53 6e  * one of the nSn
c320: 69 70 70 65 74 20 73 6e 69 70 70 65 74 20 66 72  ippet snippet fr
c330: 61 67 6d 65 6e 74 73 2c 20 62 72 65 61 6b 20 6f  agments, break o
c340: 75 74 20 6f 66 20 74 68 65 20 6c 6f 6f 70 2e 0a  ut of the loop..
c350: 20 20 20 20 2a 2f 0a 20 20 20 20 61 73 73 65 72      */.    asser
c360: 74 28 20 28 6d 43 6f 76 65 72 65 64 26 6d 53 65  t( (mCovered&mSe
c370: 65 6e 29 3d 3d 6d 43 6f 76 65 72 65 64 20 29 3b  en)==mCovered );
c380: 0a 20 20 20 20 69 66 28 20 6d 53 65 65 6e 3d 3d  .    if( mSeen==
c390: 6d 43 6f 76 65 72 65 64 20 7c 7c 20 6e 53 6e 69  mCovered || nSni
c3a0: 70 70 65 74 3d 3d 53 69 7a 65 6f 66 41 72 72 61  ppet==SizeofArra
c3b0: 79 28 61 53 6e 69 70 70 65 74 29 20 29 20 62 72  y(aSnippet) ) br
c3c0: 65 61 6b 3b 0a 20 20 7d 0a 0a 20 20 61 73 73 65  eak;.  }..  asse
c3d0: 72 74 28 20 6e 46 54 6f 6b 65 6e 3e 30 20 29 3b  rt( nFToken>0 );
c3e0: 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 6e  ..  for(i=0; i<n
c3f0: 53 6e 69 70 70 65 74 20 26 26 20 72 63 3d 3d 53  Snippet && rc==S
c400: 51 4c 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b 0a  QLITE_OK; i++){.
c410: 20 20 20 20 72 63 20 3d 20 66 74 73 33 53 6e 69      rc = fts3Sni
c420: 70 70 65 74 54 65 78 74 28 70 43 73 72 2c 20 26  ppetText(pCsr, &
c430: 61 53 6e 69 70 70 65 74 5b 69 5d 2c 20 0a 20 20  aSnippet[i], .  
c440: 20 20 20 20 20 20 69 2c 20 28 69 3d 3d 6e 53 6e        i, (i==nSn
c450: 69 70 70 65 74 2d 31 29 2c 20 6e 46 54 6f 6b 65  ippet-1), nFToke
c460: 6e 2c 20 7a 53 74 61 72 74 2c 20 7a 45 6e 64 2c  n, zStart, zEnd,
c470: 20 7a 45 6c 6c 69 70 73 69 73 2c 20 26 72 65 73   zEllipsis, &res
c480: 0a 20 20 20 20 29 3b 0a 20 20 7d 0a 0a 20 73 6e  .    );.  }.. sn
c490: 69 70 70 65 74 5f 6f 75 74 3a 0a 20 20 73 71 6c  ippet_out:.  sql
c4a0: 69 74 65 33 46 74 73 33 53 65 67 6d 65 6e 74 73  ite3Fts3Segments
c4b0: 43 6c 6f 73 65 28 70 54 61 62 29 3b 0a 20 20 69  Close(pTab);.  i
c4c0: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
c4d0: 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f   ){.    sqlite3_
c4e0: 72 65 73 75 6c 74 5f 65 72 72 6f 72 5f 63 6f 64  result_error_cod
c4f0: 65 28 70 43 74 78 2c 20 72 63 29 3b 0a 20 20 20  e(pCtx, rc);.   
c500: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 72 65   sqlite3_free(re
c510: 73 2e 7a 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20  s.z);.  }else{. 
c520: 20 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c     sqlite3_resul
c530: 74 5f 74 65 78 74 28 70 43 74 78 2c 20 72 65 73  t_text(pCtx, res
c540: 2e 7a 2c 20 2d 31 2c 20 73 71 6c 69 74 65 33 5f  .z, -1, sqlite3_
c550: 66 72 65 65 29 3b 0a 20 20 7d 0a 7d 0a 0a 0a 74  free);.  }.}...t
c560: 79 70 65 64 65 66 20 73 74 72 75 63 74 20 54 65  ypedef struct Te
c570: 72 6d 4f 66 66 73 65 74 20 54 65 72 6d 4f 66 66  rmOffset TermOff
c580: 73 65 74 3b 0a 74 79 70 65 64 65 66 20 73 74 72  set;.typedef str
c590: 75 63 74 20 54 65 72 6d 4f 66 66 73 65 74 43 74  uct TermOffsetCt
c5a0: 78 20 54 65 72 6d 4f 66 66 73 65 74 43 74 78 3b  x TermOffsetCtx;
c5b0: 0a 0a 73 74 72 75 63 74 20 54 65 72 6d 4f 66 66  ..struct TermOff
c5c0: 73 65 74 20 7b 0a 20 20 63 68 61 72 20 2a 70 4c  set {.  char *pL
c5d0: 69 73 74 3b 20 20 20 20 20 20 20 20 20 20 20 20  ist;            
c5e0: 20 20 20 20 20 20 20 20 2f 2a 20 50 6f 73 69 74          /* Posit
c5f0: 69 6f 6e 2d 6c 69 73 74 20 2a 2f 0a 20 20 69 6e  ion-list */.  in
c600: 74 20 69 50 6f 73 3b 20 20 20 20 20 20 20 20 20  t iPos;         
c610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
c620: 20 50 6f 73 69 74 69 6f 6e 20 6a 75 73 74 20 72   Position just r
c630: 65 61 64 20 66 72 6f 6d 20 70 4c 69 73 74 20 2a  ead from pList *
c640: 2f 0a 20 20 69 6e 74 20 69 4f 66 66 3b 20 20 20  /.  int iOff;   
c650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
c660: 20 20 20 20 2f 2a 20 4f 66 66 73 65 74 20 6f 66      /* Offset of
c670: 20 74 68 69 73 20 74 65 72 6d 20 66 72 6f 6d 20   this term from 
c680: 72 65 61 64 20 70 6f 73 69 74 69 6f 6e 73 20 2a  read positions *
c690: 2f 0a 7d 3b 0a 0a 73 74 72 75 63 74 20 54 65 72  /.};..struct Ter
c6a0: 6d 4f 66 66 73 65 74 43 74 78 20 7b 0a 20 20 46  mOffsetCtx {.  F
c6b0: 74 73 33 43 75 72 73 6f 72 20 2a 70 43 73 72 3b  ts3Cursor *pCsr;
c6c0: 0a 20 20 69 6e 74 20 69 43 6f 6c 3b 20 20 20 20  .  int iCol;    
c6d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
c6e0: 20 20 20 2f 2a 20 43 6f 6c 75 6d 6e 20 6f 66 20     /* Column of 
c6f0: 74 61 62 6c 65 20 74 6f 20 70 6f 70 75 6c 61 74  table to populat
c700: 65 20 61 54 65 72 6d 20 66 6f 72 20 2a 2f 0a 20  e aTerm for */. 
c710: 20 69 6e 74 20 69 54 65 72 6d 3b 0a 20 20 73 71   int iTerm;.  sq
c720: 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 44 6f 63  lite3_int64 iDoc
c730: 69 64 3b 0a 20 20 54 65 72 6d 4f 66 66 73 65 74  id;.  TermOffset
c740: 20 2a 61 54 65 72 6d 3b 0a 7d 3b 0a 0a 2f 2a 0a   *aTerm;.};../*.
c750: 2a 2a 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e  ** This function
c760: 20 69 73 20 61 6e 20 66 74 73 33 45 78 70 72 49   is an fts3ExprI
c770: 74 65 72 61 74 65 28 29 20 63 61 6c 6c 62 61 63  terate() callbac
c780: 6b 20 75 73 65 64 20 62 79 20 73 71 6c 69 74 65  k used by sqlite
c790: 33 46 74 73 33 4f 66 66 73 65 74 73 28 29 2e 0a  3Fts3Offsets()..
c7a0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66 74  */.static int ft
c7b0: 73 33 45 78 70 72 54 65 72 6d 4f 66 66 73 65 74  s3ExprTermOffset
c7c0: 49 6e 69 74 28 46 74 73 33 45 78 70 72 20 2a 70  Init(Fts3Expr *p
c7d0: 45 78 70 72 2c 20 69 6e 74 20 69 50 68 72 61 73  Expr, int iPhras
c7e0: 65 2c 20 76 6f 69 64 20 2a 63 74 78 29 7b 0a 20  e, void *ctx){. 
c7f0: 20 54 65 72 6d 4f 66 66 73 65 74 43 74 78 20 2a   TermOffsetCtx *
c800: 70 20 3d 20 28 54 65 72 6d 4f 66 66 73 65 74 43  p = (TermOffsetC
c810: 74 78 20 2a 29 63 74 78 3b 0a 20 20 69 6e 74 20  tx *)ctx;.  int 
c820: 6e 54 65 72 6d 3b 20 20 20 20 20 20 20 20 20 20  nTerm;          
c830: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
c840: 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 20  umber of tokens 
c850: 69 6e 20 70 68 72 61 73 65 20 2a 2f 0a 20 20 69  in phrase */.  i
c860: 6e 74 20 69 54 65 72 6d 3b 20 20 20 20 20 20 20  nt iTerm;       
c870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
c880: 2a 20 46 6f 72 20 6c 6f 6f 70 69 6e 67 20 74 68  * For looping th
c890: 72 6f 75 67 68 20 6e 54 65 72 6d 20 70 68 72 61  rough nTerm phra
c8a0: 73 65 20 74 65 72 6d 73 20 2a 2f 0a 20 20 63 68  se terms */.  ch
c8b0: 61 72 20 2a 70 4c 69 73 74 3b 20 20 20 20 20 20  ar *pList;      
c8c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
c8d0: 20 50 6f 69 6e 74 65 72 20 74 6f 20 70 6f 73 69   Pointer to posi
c8e0: 74 69 6f 6e 20 6c 69 73 74 20 66 6f 72 20 70 68  tion list for ph
c8f0: 72 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20 69 50  rase */.  int iP
c900: 6f 73 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  os = 0;         
c910: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 69 72            /* Fir
c920: 73 74 20 70 6f 73 69 74 69 6f 6e 20 69 6e 20 70  st position in p
c930: 6f 73 69 74 69 6f 6e 2d 6c 69 73 74 20 2a 2f 0a  osition-list */.
c940: 20 20 69 6e 74 20 72 63 3b 0a 0a 20 20 55 4e 55    int rc;..  UNU
c950: 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 69 50  SED_PARAMETER(iP
c960: 68 72 61 73 65 29 3b 0a 20 20 72 63 20 3d 20 73  hrase);.  rc = s
c970: 71 6c 69 74 65 33 46 74 73 33 45 76 61 6c 50 68  qlite3Fts3EvalPh
c980: 72 61 73 65 50 6f 73 6c 69 73 74 28 70 2d 3e 70  rasePoslist(p->p
c990: 43 73 72 2c 20 70 45 78 70 72 2c 20 70 2d 3e 69  Csr, pExpr, p->i
c9a0: 43 6f 6c 2c 20 26 70 4c 69 73 74 29 3b 0a 20 20  Col, &pList);.  
c9b0: 6e 54 65 72 6d 20 3d 20 70 45 78 70 72 2d 3e 70  nTerm = pExpr->p
c9c0: 50 68 72 61 73 65 2d 3e 6e 54 6f 6b 65 6e 3b 0a  Phrase->nToken;.
c9d0: 20 20 69 66 28 20 70 4c 69 73 74 20 29 7b 0a 20    if( pList ){. 
c9e0: 20 20 20 66 74 73 33 47 65 74 44 65 6c 74 61 50     fts3GetDeltaP
c9f0: 6f 73 69 74 69 6f 6e 28 26 70 4c 69 73 74 2c 20  osition(&pList, 
ca00: 26 69 50 6f 73 29 3b 0a 20 20 20 20 61 73 73 65  &iPos);.    asse
ca10: 72 74 28 20 69 50 6f 73 3e 3d 30 20 29 3b 0a 20  rt( iPos>=0 );. 
ca20: 20 7d 0a 0a 20 20 66 6f 72 28 69 54 65 72 6d 3d   }..  for(iTerm=
ca30: 30 3b 20 69 54 65 72 6d 3c 6e 54 65 72 6d 3b 20  0; iTerm<nTerm; 
ca40: 69 54 65 72 6d 2b 2b 29 7b 0a 20 20 20 20 54 65  iTerm++){.    Te
ca50: 72 6d 4f 66 66 73 65 74 20 2a 70 54 20 3d 20 26  rmOffset *pT = &
ca60: 70 2d 3e 61 54 65 72 6d 5b 70 2d 3e 69 54 65 72  p->aTerm[p->iTer
ca70: 6d 2b 2b 5d 3b 0a 20 20 20 20 70 54 2d 3e 69 4f  m++];.    pT->iO
ca80: 66 66 20 3d 20 6e 54 65 72 6d 2d 69 54 65 72 6d  ff = nTerm-iTerm
ca90: 2d 31 3b 0a 20 20 20 20 70 54 2d 3e 70 4c 69 73  -1;.    pT->pLis
caa0: 74 20 3d 20 70 4c 69 73 74 3b 0a 20 20 20 20 70  t = pList;.    p
cab0: 54 2d 3e 69 50 6f 73 20 3d 20 69 50 6f 73 3b 0a  T->iPos = iPos;.
cac0: 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 72 63    }..  return rc
cad0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6d 70 6c 65  ;.}../*.** Imple
cae0: 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20 6f 66 66  mentation of off
caf0: 73 65 74 73 28 29 20 66 75 6e 63 74 69 6f 6e 2e  sets() function.
cb00: 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74 65 33  .*/.void sqlite3
cb10: 46 74 73 33 4f 66 66 73 65 74 73 28 0a 20 20 73  Fts3Offsets(.  s
cb20: 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74 20 2a  qlite3_context *
cb30: 70 43 74 78 2c 20 20 20 20 20 20 20 20 20 20 2f  pCtx,          /
cb40: 2a 20 53 51 4c 69 74 65 20 66 75 6e 63 74 69 6f  * SQLite functio
cb50: 6e 20 63 61 6c 6c 20 63 6f 6e 74 65 78 74 20 2a  n call context *
cb60: 2f 0a 20 20 46 74 73 33 43 75 72 73 6f 72 20 2a  /.  Fts3Cursor *
cb70: 70 43 73 72 20 20 20 20 20 20 20 20 20 20 20 20  pCsr            
cb80: 20 20 20 20 2f 2a 20 43 75 72 73 6f 72 20 6f 62      /* Cursor ob
cb90: 6a 65 63 74 20 2a 2f 0a 29 7b 0a 20 20 46 74 73  ject */.){.  Fts
cba0: 33 54 61 62 6c 65 20 2a 70 54 61 62 20 3d 20 28  3Table *pTab = (
cbb0: 46 74 73 33 54 61 62 6c 65 20 2a 29 70 43 73 72  Fts3Table *)pCsr
cbc0: 2d 3e 62 61 73 65 2e 70 56 74 61 62 3b 0a 20 20  ->base.pVtab;.  
cbd0: 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65  sqlite3_tokenize
cbe0: 72 5f 6d 6f 64 75 6c 65 20 63 6f 6e 73 74 20 2a  r_module const *
cbf0: 70 4d 6f 64 20 3d 20 70 54 61 62 2d 3e 70 54 6f  pMod = pTab->pTo
cc00: 6b 65 6e 69 7a 65 72 2d 3e 70 4d 6f 64 75 6c 65  kenizer->pModule
cc10: 3b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20  ;.  int rc;     
cc20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
cc30: 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 43 6f      /* Return Co
cc40: 64 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 54 6f 6b  de */.  int nTok
cc50: 65 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  en;             
cc60: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
cc70: 72 20 6f 66 20 74 6f 6b 65 6e 73 20 69 6e 20 71  r of tokens in q
cc80: 75 65 72 79 20 2a 2f 0a 20 20 69 6e 74 20 69 43  uery */.  int iC
cc90: 6f 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  ol;             
cca0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6c            /* Col
ccb0: 75 6d 6e 20 63 75 72 72 65 6e 74 6c 79 20 62 65  umn currently be
ccc0: 69 6e 67 20 70 72 6f 63 65 73 73 65 64 20 2a 2f  ing processed */
ccd0: 0a 20 20 53 74 72 42 75 66 66 65 72 20 72 65 73  .  StrBuffer res
cce0: 20 3d 20 7b 30 2c 20 30 2c 20 30 7d 3b 20 20 20   = {0, 0, 0};   
ccf0: 20 20 20 2f 2a 20 52 65 73 75 6c 74 20 73 74 72     /* Result str
cd00: 69 6e 67 20 2a 2f 0a 20 20 54 65 72 6d 4f 66 66  ing */.  TermOff
cd10: 73 65 74 43 74 78 20 73 43 74 78 3b 20 20 20 20  setCtx sCtx;    
cd20: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6e 74           /* Cont
cd30: 65 78 74 20 66 6f 72 20 66 74 73 33 45 78 70 72  ext for fts3Expr
cd40: 54 65 72 6d 4f 66 66 73 65 74 49 6e 69 74 28 29  TermOffsetInit()
cd50: 20 2a 2f 0a 0a 20 20 69 66 28 20 21 70 43 73 72   */..  if( !pCsr
cd60: 2d 3e 70 45 78 70 72 20 29 7b 0a 20 20 20 20 73  ->pExpr ){.    s
cd70: 71 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 74 65  qlite3_result_te
cd80: 78 74 28 70 43 74 78 2c 20 22 22 2c 20 30 2c 20  xt(pCtx, "", 0, 
cd90: 53 51 4c 49 54 45 5f 53 54 41 54 49 43 29 3b 0a  SQLITE_STATIC);.
cda0: 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a      return;.  }.
cdb0: 0a 20 20 6d 65 6d 73 65 74 28 26 73 43 74 78 2c  .  memset(&sCtx,
cdc0: 20 30 2c 20 73 69 7a 65 6f 66 28 73 43 74 78 29   0, sizeof(sCtx)
cdd0: 29 3b 0a 20 20 61 73 73 65 72 74 28 20 70 43 73  );.  assert( pCs
cde0: 72 2d 3e 69 73 52 65 71 75 69 72 65 53 65 65 6b  r->isRequireSeek
cdf0: 3d 3d 30 20 29 3b 0a 0a 20 20 2f 2a 20 43 6f 75  ==0 );..  /* Cou
ce00: 6e 74 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66  nt the number of
ce10: 20 74 65 72 6d 73 20 69 6e 20 74 68 65 20 71 75   terms in the qu
ce20: 65 72 79 20 2a 2f 0a 20 20 72 63 20 3d 20 66 74  ery */.  rc = ft
ce30: 73 33 45 78 70 72 4c 6f 61 64 44 6f 63 6c 69 73  s3ExprLoadDoclis
ce40: 74 73 28 70 43 73 72 2c 20 30 2c 20 26 6e 54 6f  ts(pCsr, 0, &nTo
ce50: 6b 65 6e 29 3b 0a 20 20 69 66 28 20 72 63 21 3d  ken);.  if( rc!=
ce60: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 67 6f 74 6f  SQLITE_OK ) goto
ce70: 20 6f 66 66 73 65 74 73 5f 6f 75 74 3b 0a 0a 20   offsets_out;.. 
ce80: 20 2f 2a 20 41 6c 6c 6f 63 61 74 65 20 74 68 65   /* Allocate the
ce90: 20 61 72 72 61 79 20 6f 66 20 54 65 72 6d 4f 66   array of TermOf
cea0: 66 73 65 74 20 69 74 65 72 61 74 6f 72 73 2e 20  fset iterators. 
ceb0: 2a 2f 0a 20 20 73 43 74 78 2e 61 54 65 72 6d 20  */.  sCtx.aTerm 
cec0: 3d 20 28 54 65 72 6d 4f 66 66 73 65 74 20 2a 29  = (TermOffset *)
ced0: 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 36 34  sqlite3_malloc64
cee0: 28 73 69 7a 65 6f 66 28 54 65 72 6d 4f 66 66 73  (sizeof(TermOffs
cef0: 65 74 29 2a 6e 54 6f 6b 65 6e 29 3b 0a 20 20 69  et)*nToken);.  i
cf00: 66 28 20 30 3d 3d 73 43 74 78 2e 61 54 65 72 6d  f( 0==sCtx.aTerm
cf10: 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 53 51 4c   ){.    rc = SQL
cf20: 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 67  ITE_NOMEM;.    g
cf30: 6f 74 6f 20 6f 66 66 73 65 74 73 5f 6f 75 74 3b  oto offsets_out;
cf40: 0a 20 20 7d 0a 20 20 73 43 74 78 2e 69 44 6f 63  .  }.  sCtx.iDoc
cf50: 69 64 20 3d 20 70 43 73 72 2d 3e 69 50 72 65 76  id = pCsr->iPrev
cf60: 49 64 3b 0a 20 20 73 43 74 78 2e 70 43 73 72 20  Id;.  sCtx.pCsr 
cf70: 3d 20 70 43 73 72 3b 0a 0a 20 20 2f 2a 20 4c 6f  = pCsr;..  /* Lo
cf80: 6f 70 20 74 68 72 6f 75 67 68 20 74 68 65 20 74  op through the t
cf90: 61 62 6c 65 20 63 6f 6c 75 6d 6e 73 2c 20 61 70  able columns, ap
cfa0: 70 65 6e 64 69 6e 67 20 6f 66 66 73 65 74 20 69  pending offset i
cfb0: 6e 66 6f 72 6d 61 74 69 6f 6e 20 74 6f 20 0a 20  nformation to . 
cfc0: 20 2a 2a 20 73 74 72 69 6e 67 2d 62 75 66 66 65   ** string-buffe
cfd0: 72 20 72 65 73 20 66 6f 72 20 65 61 63 68 20 63  r res for each c
cfe0: 6f 6c 75 6d 6e 2e 0a 20 20 2a 2f 0a 20 20 66 6f  olumn..  */.  fo
cff0: 72 28 69 43 6f 6c 3d 30 3b 20 69 43 6f 6c 3c 70  r(iCol=0; iCol<p
d000: 54 61 62 2d 3e 6e 43 6f 6c 75 6d 6e 3b 20 69 43  Tab->nColumn; iC
d010: 6f 6c 2b 2b 29 7b 0a 20 20 20 20 73 71 6c 69 74  ol++){.    sqlit
d020: 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63 75 72  e3_tokenizer_cur
d030: 73 6f 72 20 2a 70 43 3b 20 2f 2a 20 54 6f 6b 65  sor *pC; /* Toke
d040: 6e 69 7a 65 72 20 63 75 72 73 6f 72 20 2a 2f 0a  nizer cursor */.
d050: 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a      const char *
d060: 5a 44 55 4d 4d 59 3b 20 20 20 20 20 20 20 20 20  ZDUMMY;         
d070: 20 20 2f 2a 20 44 75 6d 6d 79 20 61 72 67 75 6d    /* Dummy argum
d080: 65 6e 74 20 75 73 65 64 20 77 69 74 68 20 78 4e  ent used with xN
d090: 65 78 74 28 29 20 2a 2f 0a 20 20 20 20 69 6e 74  ext() */.    int
d0a0: 20 4e 44 55 4d 4d 59 20 3d 20 30 3b 20 20 20 20   NDUMMY = 0;    
d0b0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44 75             /* Du
d0c0: 6d 6d 79 20 61 72 67 75 6d 65 6e 74 20 75 73 65  mmy argument use
d0d0: 64 20 77 69 74 68 20 78 4e 65 78 74 28 29 20 2a  d with xNext() *
d0e0: 2f 0a 20 20 20 20 69 6e 74 20 69 53 74 61 72 74  /.    int iStart
d0f0: 20 3d 20 30 3b 0a 20 20 20 20 69 6e 74 20 69 45   = 0;.    int iE
d100: 6e 64 20 3d 20 30 3b 0a 20 20 20 20 69 6e 74 20  nd = 0;.    int 
d110: 69 43 75 72 72 65 6e 74 20 3d 20 30 3b 0a 20 20  iCurrent = 0;.  
d120: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 44    const char *zD
d130: 6f 63 3b 0a 20 20 20 20 69 6e 74 20 6e 44 6f 63  oc;.    int nDoc
d140: 3b 0a 0a 20 20 20 20 2f 2a 20 49 6e 69 74 69 61  ;..    /* Initia
d150: 6c 69 7a 65 20 74 68 65 20 63 6f 6e 74 65 6e 74  lize the content
d160: 73 20 6f 66 20 73 43 74 78 2e 61 54 65 72 6d 5b  s of sCtx.aTerm[
d170: 5d 20 66 6f 72 20 63 6f 6c 75 6d 6e 20 69 43 6f  ] for column iCo
d180: 6c 2e 20 54 68 65 72 65 20 69 73 20 0a 20 20 20  l. There is .   
d190: 20 2a 2a 20 6e 6f 20 77 61 79 20 74 68 61 74 20   ** no way that 
d1a0: 74 68 69 73 20 6f 70 65 72 61 74 69 6f 6e 20 63  this operation c
d1b0: 61 6e 20 66 61 69 6c 2c 20 73 6f 20 74 68 65 20  an fail, so the 
d1c0: 72 65 74 75 72 6e 20 63 6f 64 65 20 66 72 6f 6d  return code from
d1d0: 0a 20 20 20 20 2a 2a 20 66 74 73 33 45 78 70 72  .    ** fts3Expr
d1e0: 49 74 65 72 61 74 65 28 29 20 63 61 6e 20 62 65  Iterate() can be
d1f0: 20 64 69 73 63 61 72 64 65 64 2e 0a 20 20 20 20   discarded..    
d200: 2a 2f 0a 20 20 20 20 73 43 74 78 2e 69 43 6f 6c  */.    sCtx.iCol
d210: 20 3d 20 69 43 6f 6c 3b 0a 20 20 20 20 73 43 74   = iCol;.    sCt
d220: 78 2e 69 54 65 72 6d 20 3d 20 30 3b 0a 20 20 20  x.iTerm = 0;.   
d230: 20 28 76 6f 69 64 29 66 74 73 33 45 78 70 72 49   (void)fts3ExprI
d240: 74 65 72 61 74 65 28 70 43 73 72 2d 3e 70 45 78  terate(pCsr->pEx
d250: 70 72 2c 20 66 74 73 33 45 78 70 72 54 65 72 6d  pr, fts3ExprTerm
d260: 4f 66 66 73 65 74 49 6e 69 74 2c 20 28 76 6f 69  OffsetInit, (voi
d270: 64 2a 29 26 73 43 74 78 29 3b 0a 0a 20 20 20 20  d*)&sCtx);..    
d280: 2f 2a 20 52 65 74 72 65 69 76 65 20 74 68 65 20  /* Retreive the 
d290: 74 65 78 74 20 73 74 6f 72 65 64 20 69 6e 20 63  text stored in c
d2a0: 6f 6c 75 6d 6e 20 69 43 6f 6c 2e 20 49 66 20 61  olumn iCol. If a
d2b0: 6e 20 53 51 4c 20 4e 55 4c 4c 20 69 73 20 73 74  n SQL NULL is st
d2c0: 6f 72 65 64 20 0a 20 20 20 20 2a 2a 20 69 6e 20  ored .    ** in 
d2d0: 63 6f 6c 75 6d 6e 20 69 43 6f 6c 2c 20 6a 75 6d  column iCol, jum
d2e0: 70 20 69 6d 6d 65 64 69 61 74 65 6c 79 20 74 6f  p immediately to
d2f0: 20 74 68 65 20 6e 65 78 74 20 69 74 65 72 61 74   the next iterat
d300: 69 6f 6e 20 6f 66 20 74 68 65 20 6c 6f 6f 70 2e  ion of the loop.
d310: 0a 20 20 20 20 2a 2a 20 49 66 20 61 6e 20 4f 4f  .    ** If an OO
d320: 4d 20 6f 63 63 75 72 73 20 77 68 69 6c 65 20 72  M occurs while r
d330: 65 74 72 69 65 76 69 6e 67 20 74 68 65 20 64 61  etrieving the da
d340: 74 61 20 28 74 68 69 73 20 63 61 6e 20 68 61 70  ta (this can hap
d350: 70 65 6e 20 69 66 20 53 51 4c 69 74 65 0a 20 20  pen if SQLite.  
d360: 20 20 2a 2a 20 6e 65 65 64 73 20 74 6f 20 74 72    ** needs to tr
d370: 61 6e 73 66 6f 72 6d 20 74 68 65 20 64 61 74 61  ansform the data
d380: 20 66 72 6f 6d 20 75 74 66 2d 31 36 20 74 6f 20   from utf-16 to 
d390: 75 74 66 2d 38 29 2c 20 72 65 74 75 72 6e 20 53  utf-8), return S
d3a0: 51 4c 49 54 45 5f 4e 4f 4d 45 4d 20 0a 20 20 20  QLITE_NOMEM .   
d3b0: 20 2a 2a 20 74 6f 20 74 68 65 20 63 61 6c 6c 65   ** to the calle
d3c0: 72 2e 20 0a 20 20 20 20 2a 2f 0a 20 20 20 20 7a  r. .    */.    z
d3d0: 44 6f 63 20 3d 20 28 63 6f 6e 73 74 20 63 68 61  Doc = (const cha
d3e0: 72 20 2a 29 73 71 6c 69 74 65 33 5f 63 6f 6c 75  r *)sqlite3_colu
d3f0: 6d 6e 5f 74 65 78 74 28 70 43 73 72 2d 3e 70 53  mn_text(pCsr->pS
d400: 74 6d 74 2c 20 69 43 6f 6c 2b 31 29 3b 0a 20 20  tmt, iCol+1);.  
d410: 20 20 6e 44 6f 63 20 3d 20 73 71 6c 69 74 65 33    nDoc = sqlite3
d420: 5f 63 6f 6c 75 6d 6e 5f 62 79 74 65 73 28 70 43  _column_bytes(pC
d430: 73 72 2d 3e 70 53 74 6d 74 2c 20 69 43 6f 6c 2b  sr->pStmt, iCol+
d440: 31 29 3b 0a 20 20 20 20 69 66 28 20 7a 44 6f 63  1);.    if( zDoc
d450: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 69 66 28  ==0 ){.      if(
d460: 20 73 71 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f   sqlite3_column_
d470: 74 79 70 65 28 70 43 73 72 2d 3e 70 53 74 6d 74  type(pCsr->pStmt
d480: 2c 20 69 43 6f 6c 2b 31 29 3d 3d 53 51 4c 49 54  , iCol+1)==SQLIT
d490: 45 5f 4e 55 4c 4c 20 29 7b 0a 20 20 20 20 20 20  E_NULL ){.      
d4a0: 20 20 63 6f 6e 74 69 6e 75 65 3b 0a 20 20 20 20    continue;.    
d4b0: 20 20 7d 0a 20 20 20 20 20 20 72 63 20 3d 20 53    }.      rc = S
d4c0: 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20  QLITE_NOMEM;.   
d4d0: 20 20 20 67 6f 74 6f 20 6f 66 66 73 65 74 73 5f     goto offsets_
d4e0: 6f 75 74 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20  out;.    }..    
d4f0: 2f 2a 20 49 6e 69 74 69 61 6c 69 7a 65 20 61 20  /* Initialize a 
d500: 74 6f 6b 65 6e 69 7a 65 72 20 69 74 65 72 61 74  tokenizer iterat
d510: 6f 72 20 74 6f 20 69 74 65 72 61 74 65 20 74 68  or to iterate th
d520: 72 6f 75 67 68 20 63 6f 6c 75 6d 6e 20 69 43 6f  rough column iCo
d530: 6c 2e 20 2a 2f 0a 20 20 20 20 72 63 20 3d 20 73  l. */.    rc = s
d540: 71 6c 69 74 65 33 46 74 73 33 4f 70 65 6e 54 6f  qlite3Fts3OpenTo
d550: 6b 65 6e 69 7a 65 72 28 70 54 61 62 2d 3e 70 54  kenizer(pTab->pT
d560: 6f 6b 65 6e 69 7a 65 72 2c 20 70 43 73 72 2d 3e  okenizer, pCsr->
d570: 69 4c 61 6e 67 69 64 2c 0a 20 20 20 20 20 20 20  iLangid,.       
d580: 20 7a 44 6f 63 2c 20 6e 44 6f 63 2c 20 26 70 43   zDoc, nDoc, &pC
d590: 0a 20 20 20 20 29 3b 0a 20 20 20 20 69 66 28 20  .    );.    if( 
d5a0: 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20  rc!=SQLITE_OK ) 
d5b0: 67 6f 74 6f 20 6f 66 66 73 65 74 73 5f 6f 75 74  goto offsets_out
d5c0: 3b 0a 0a 20 20 20 20 72 63 20 3d 20 70 4d 6f 64  ;..    rc = pMod
d5d0: 2d 3e 78 4e 65 78 74 28 70 43 2c 20 26 5a 44 55  ->xNext(pC, &ZDU
d5e0: 4d 4d 59 2c 20 26 4e 44 55 4d 4d 59 2c 20 26 69  MMY, &NDUMMY, &i
d5f0: 53 74 61 72 74 2c 20 26 69 45 6e 64 2c 20 26 69  Start, &iEnd, &i
d600: 43 75 72 72 65 6e 74 29 3b 0a 20 20 20 20 77 68  Current);.    wh
d610: 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f  ile( rc==SQLITE_
d620: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 69 6e 74 20  OK ){.      int 
d630: 69 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  i;              
d640: 20 20 20 20 20 20 20 20 2f 2a 20 55 73 65 64 20          /* Used 
d650: 74 6f 20 6c 6f 6f 70 20 74 68 72 6f 75 67 68 20  to loop through 
d660: 74 65 72 6d 73 20 2a 2f 0a 20 20 20 20 20 20 69  terms */.      i
d670: 6e 74 20 69 4d 69 6e 50 6f 73 20 3d 20 30 78 37  nt iMinPos = 0x7
d680: 46 46 46 46 46 46 46 3b 20 20 20 2f 2a 20 50 6f  FFFFFFF;   /* Po
d690: 73 69 74 69 6f 6e 20 6f 66 20 6e 65 78 74 20 74  sition of next t
d6a0: 6f 6b 65 6e 20 2a 2f 0a 20 20 20 20 20 20 54 65  oken */.      Te
d6b0: 72 6d 4f 66 66 73 65 74 20 2a 70 54 65 72 6d 20  rmOffset *pTerm 
d6c0: 3d 20 30 3b 20 20 20 20 20 20 2f 2a 20 54 65 72  = 0;      /* Ter
d6d0: 6d 4f 66 66 73 65 74 20 61 73 73 6f 63 69 61 74  mOffset associat
d6e0: 65 64 20 77 69 74 68 20 6e 65 78 74 20 74 6f 6b  ed with next tok
d6f0: 65 6e 20 2a 2f 0a 0a 20 20 20 20 20 20 66 6f 72  en */..      for
d700: 28 69 3d 30 3b 20 69 3c 6e 54 6f 6b 65 6e 3b 20  (i=0; i<nToken; 
d710: 69 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 54 65  i++){.        Te
d720: 72 6d 4f 66 66 73 65 74 20 2a 70 54 20 3d 20 26  rmOffset *pT = &
d730: 73 43 74 78 2e 61 54 65 72 6d 5b 69 5d 3b 0a 20  sCtx.aTerm[i];. 
d740: 20 20 20 20 20 20 20 69 66 28 20 70 54 2d 3e 70         if( pT->p
d750: 4c 69 73 74 20 26 26 20 28 70 54 2d 3e 69 50 6f  List && (pT->iPo
d760: 73 2d 70 54 2d 3e 69 4f 66 66 29 3c 69 4d 69 6e  s-pT->iOff)<iMin
d770: 50 6f 73 20 29 7b 0a 20 20 20 20 20 20 20 20 20  Pos ){.         
d780: 20 69 4d 69 6e 50 6f 73 20 3d 20 70 54 2d 3e 69   iMinPos = pT->i
d790: 50 6f 73 2d 70 54 2d 3e 69 4f 66 66 3b 0a 20 20  Pos-pT->iOff;.  
d7a0: 20 20 20 20 20 20 20 20 70 54 65 72 6d 20 3d 20          pTerm = 
d7b0: 70 54 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20  pT;.        }.  
d7c0: 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 69 66 28      }..      if(
d7d0: 20 21 70 54 65 72 6d 20 29 7b 0a 20 20 20 20 20   !pTerm ){.     
d7e0: 20 20 20 2f 2a 20 41 6c 6c 20 6f 66 66 73 65 74     /* All offset
d7f0: 73 20 66 6f 72 20 74 68 69 73 20 63 6f 6c 75 6d  s for this colum
d800: 6e 20 68 61 76 65 20 62 65 65 6e 20 67 61 74 68  n have been gath
d810: 65 72 65 64 2e 20 2a 2f 0a 20 20 20 20 20 20 20  ered. */.       
d820: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 44 4f 4e   rc = SQLITE_DON
d830: 45 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a  E;.      }else{.
d840: 20 20 20 20 20 20 20 20 61 73 73 65 72 74 28 20          assert( 
d850: 69 43 75 72 72 65 6e 74 3c 3d 69 4d 69 6e 50 6f  iCurrent<=iMinPo
d860: 73 20 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28  s );.        if(
d870: 20 30 3d 3d 28 30 78 46 45 26 2a 70 54 65 72 6d   0==(0xFE&*pTerm
d880: 2d 3e 70 4c 69 73 74 29 20 29 7b 0a 20 20 20 20  ->pList) ){.    
d890: 20 20 20 20 20 20 70 54 65 72 6d 2d 3e 70 4c 69        pTerm->pLi
d8a0: 73 74 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20  st = 0;.        
d8b0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20  }else{.         
d8c0: 20 66 74 73 33 47 65 74 44 65 6c 74 61 50 6f 73   fts3GetDeltaPos
d8d0: 69 74 69 6f 6e 28 26 70 54 65 72 6d 2d 3e 70 4c  ition(&pTerm->pL
d8e0: 69 73 74 2c 20 26 70 54 65 72 6d 2d 3e 69 50 6f  ist, &pTerm->iPo
d8f0: 73 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20  s);.        }.  
d900: 20 20 20 20 20 20 77 68 69 6c 65 28 20 72 63 3d        while( rc=
d910: 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 69 43  =SQLITE_OK && iC
d920: 75 72 72 65 6e 74 3c 69 4d 69 6e 50 6f 73 20 29  urrent<iMinPos )
d930: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
d940: 20 70 4d 6f 64 2d 3e 78 4e 65 78 74 28 70 43 2c   pMod->xNext(pC,
d950: 20 26 5a 44 55 4d 4d 59 2c 20 26 4e 44 55 4d 4d   &ZDUMMY, &NDUMM
d960: 59 2c 20 26 69 53 74 61 72 74 2c 20 26 69 45 6e  Y, &iStart, &iEn
d970: 64 2c 20 26 69 43 75 72 72 65 6e 74 29 3b 0a 20  d, &iCurrent);. 
d980: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
d990: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
d9a0: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  OK ){.          
d9b0: 63 68 61 72 20 61 42 75 66 66 65 72 5b 36 34 5d  char aBuffer[64]
d9c0: 3b 0a 20 20 20 20 20 20 20 20 20 20 73 71 6c 69  ;.          sqli
d9d0: 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 73 69 7a  te3_snprintf(siz
d9e0: 65 6f 66 28 61 42 75 66 66 65 72 29 2c 20 61 42  eof(aBuffer), aB
d9f0: 75 66 66 65 72 2c 20 0a 20 20 20 20 20 20 20 20  uffer, .        
da00: 20 20 20 20 20 20 22 25 64 20 25 64 20 25 64 20        "%d %d %d 
da10: 25 64 20 22 2c 20 69 43 6f 6c 2c 20 70 54 65 72  %d ", iCol, pTer
da20: 6d 2d 73 43 74 78 2e 61 54 65 72 6d 2c 20 69 53  m-sCtx.aTerm, iS
da30: 74 61 72 74 2c 20 69 45 6e 64 2d 69 53 74 61 72  tart, iEnd-iStar
da40: 74 0a 20 20 20 20 20 20 20 20 20 20 29 3b 0a 20  t.          );. 
da50: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 66 74           rc = ft
da60: 73 33 53 74 72 69 6e 67 41 70 70 65 6e 64 28 26  s3StringAppend(&
da70: 72 65 73 2c 20 61 42 75 66 66 65 72 2c 20 2d 31  res, aBuffer, -1
da80: 29 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65  );.        }else
da90: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
daa0: 44 4f 4e 45 20 26 26 20 70 54 61 62 2d 3e 7a 43  DONE && pTab->zC
dab0: 6f 6e 74 65 6e 74 54 62 6c 3d 3d 30 20 29 7b 0a  ontentTbl==0 ){.
dac0: 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 46            rc = F
dad0: 54 53 5f 43 4f 52 52 55 50 54 5f 56 54 41 42 3b  TS_CORRUPT_VTAB;
dae0: 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20  .        }.     
daf0: 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28   }.    }.    if(
db00: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 44 4f 4e 45   rc==SQLITE_DONE
db10: 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 53   ){.      rc = S
db20: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 7d 0a  QLITE_OK;.    }.
db30: 0a 20 20 20 20 70 4d 6f 64 2d 3e 78 43 6c 6f 73  .    pMod->xClos
db40: 65 28 70 43 29 3b 0a 20 20 20 20 69 66 28 20 72  e(pC);.    if( r
db50: 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 67  c!=SQLITE_OK ) g
db60: 6f 74 6f 20 6f 66 66 73 65 74 73 5f 6f 75 74 3b  oto offsets_out;
db70: 0a 20 20 7d 0a 0a 20 6f 66 66 73 65 74 73 5f 6f  .  }.. offsets_o
db80: 75 74 3a 0a 20 20 73 71 6c 69 74 65 33 5f 66 72  ut:.  sqlite3_fr
db90: 65 65 28 73 43 74 78 2e 61 54 65 72 6d 29 3b 0a  ee(sCtx.aTerm);.
dba0: 20 20 61 73 73 65 72 74 28 20 72 63 21 3d 53 51    assert( rc!=SQ
dbb0: 4c 49 54 45 5f 44 4f 4e 45 20 29 3b 0a 20 20 73  LITE_DONE );.  s
dbc0: 71 6c 69 74 65 33 46 74 73 33 53 65 67 6d 65 6e  qlite3Fts3Segmen
dbd0: 74 73 43 6c 6f 73 65 28 70 54 61 62 29 3b 0a 20  tsClose(pTab);. 
dbe0: 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f   if( rc!=SQLITE_
dbf0: 4f 4b 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65  OK ){.    sqlite
dc00: 33 5f 72 65 73 75 6c 74 5f 65 72 72 6f 72 5f 63  3_result_error_c
dc10: 6f 64 65 28 70 43 74 78 2c 20 20 72 63 29 3b 0a  ode(pCtx,  rc);.
dc20: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65      sqlite3_free
dc30: 28 72 65 73 2e 7a 29 3b 0a 20 20 7d 65 6c 73 65  (res.z);.  }else
dc40: 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 72 65  {.    sqlite3_re
dc50: 73 75 6c 74 5f 74 65 78 74 28 70 43 74 78 2c 20  sult_text(pCtx, 
dc60: 72 65 73 2e 7a 2c 20 72 65 73 2e 6e 2d 31 2c 20  res.z, res.n-1, 
dc70: 73 71 6c 69 74 65 33 5f 66 72 65 65 29 3b 0a 20  sqlite3_free);. 
dc80: 20 7d 0a 20 20 72 65 74 75 72 6e 3b 0a 7d 0a 0a   }.  return;.}..
dc90: 2f 2a 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e 74 61  /*.** Implementa
dca0: 74 69 6f 6e 20 6f 66 20 6d 61 74 63 68 69 6e 66  tion of matchinf
dcb0: 6f 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f  o() function..*/
dcc0: 0a 76 6f 69 64 20 73 71 6c 69 74 65 33 46 74 73  .void sqlite3Fts
dcd0: 33 4d 61 74 63 68 69 6e 66 6f 28 0a 20 20 73 71  3Matchinfo(.  sq
dce0: 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74 20 2a 70  lite3_context *p
dcf0: 43 6f 6e 74 65 78 74 2c 20 20 20 20 20 20 2f 2a  Context,      /*
dd00: 20 46 75 6e 63 74 69 6f 6e 20 63 61 6c 6c 20 63   Function call c
dd10: 6f 6e 74 65 78 74 20 2a 2f 0a 20 20 46 74 73 33  ontext */.  Fts3
dd20: 43 75 72 73 6f 72 20 2a 70 43 73 72 2c 20 20 20  Cursor *pCsr,   
dd30: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46              /* F
dd40: 54 53 33 20 74 61 62 6c 65 20 63 75 72 73 6f 72  TS3 table cursor
dd50: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
dd60: 20 2a 7a 41 72 67 20 20 20 20 20 20 20 20 20 20   *zArg          
dd70: 20 20 20 20 20 20 2f 2a 20 53 65 63 6f 6e 64 20        /* Second 
dd80: 61 72 67 20 74 6f 20 6d 61 74 63 68 69 6e 66 6f  arg to matchinfo
dd90: 28 29 20 66 75 6e 63 74 69 6f 6e 20 2a 2f 0a 29  () function */.)
dda0: 7b 0a 20 20 46 74 73 33 54 61 62 6c 65 20 2a 70  {.  Fts3Table *p
ddb0: 54 61 62 20 3d 20 28 46 74 73 33 54 61 62 6c 65  Tab = (Fts3Table
ddc0: 20 2a 29 70 43 73 72 2d 3e 62 61 73 65 2e 70 56   *)pCsr->base.pV
ddd0: 74 61 62 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61  tab;.  const cha
dde0: 72 20 2a 7a 46 6f 72 6d 61 74 3b 0a 0a 20 20 69  r *zFormat;..  i
ddf0: 66 28 20 7a 41 72 67 20 29 7b 0a 20 20 20 20 7a  f( zArg ){.    z
de00: 46 6f 72 6d 61 74 20 3d 20 7a 41 72 67 3b 0a 20  Format = zArg;. 
de10: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 7a 46 6f 72   }else{.    zFor
de20: 6d 61 74 20 3d 20 46 54 53 33 5f 4d 41 54 43 48  mat = FTS3_MATCH
de30: 49 4e 46 4f 5f 44 45 46 41 55 4c 54 3b 0a 20 20  INFO_DEFAULT;.  
de40: 7d 0a 0a 20 20 69 66 28 20 21 70 43 73 72 2d 3e  }..  if( !pCsr->
de50: 70 45 78 70 72 20 29 7b 0a 20 20 20 20 73 71 6c  pExpr ){.    sql
de60: 69 74 65 33 5f 72 65 73 75 6c 74 5f 62 6c 6f 62  ite3_result_blob
de70: 28 70 43 6f 6e 74 65 78 74 2c 20 22 22 2c 20 30  (pContext, "", 0
de80: 2c 20 53 51 4c 49 54 45 5f 53 54 41 54 49 43 29  , SQLITE_STATIC)
de90: 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20  ;.    return;.  
dea0: 7d 65 6c 73 65 7b 0a 20 20 20 20 2f 2a 20 52 65  }else{.    /* Re
deb0: 74 72 69 65 76 65 20 6d 61 74 63 68 69 6e 66 6f  trieve matchinfo
dec0: 28 29 20 64 61 74 61 2e 20 2a 2f 0a 20 20 20 20  () data. */.    
ded0: 66 74 73 33 47 65 74 4d 61 74 63 68 69 6e 66 6f  fts3GetMatchinfo
dee0: 28 70 43 6f 6e 74 65 78 74 2c 20 70 43 73 72 2c  (pContext, pCsr,
def0: 20 7a 46 6f 72 6d 61 74 29 3b 0a 20 20 20 20 73   zFormat);.    s
df00: 71 6c 69 74 65 33 46 74 73 33 53 65 67 6d 65 6e  qlite3Fts3Segmen
df10: 74 73 43 6c 6f 73 65 28 70 54 61 62 29 3b 0a 20  tsClose(pTab);. 
df20: 20 7d 0a 7d 0a 0a 23 65 6e 64 69 66 0a            }.}..#endif.