/ Hex Artifact Content
Login

Artifact 24fa13f330db011500acb95590da9eee24951894:


0000: 2f 2a 0a 2a 2a 20 32 30 31 31 20 4a 75 6e 20 31  /*.** 2011 Jun 1
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 2a 0a 2a 2a 20 54 68 69 73  *****.**.** This
0180: 20 66 69 6c 65 20 69 73 20 6e 6f 74 20 70 61 72   file is not par
0190: 74 20 6f 66 20 74 68 65 20 70 72 6f 64 75 63 74  t of the product
01a0: 69 6f 6e 20 46 54 53 20 63 6f 64 65 2e 20 49 74  ion FTS code. It
01b0: 20 69 73 20 6f 6e 6c 79 20 75 73 65 64 20 66 6f   is only used fo
01c0: 72 0a 2a 2a 20 74 65 73 74 69 6e 67 2e 20 49 74  r.** testing. It
01d0: 20 63 6f 6e 74 61 69 6e 73 20 61 20 54 63 6c 20   contains a Tcl 
01e0: 63 6f 6d 6d 61 6e 64 20 74 68 61 74 20 63 61 6e  command that can
01f0: 20 62 65 20 75 73 65 64 20 74 6f 20 74 65 73 74   be used to test
0200: 20 69 66 20 61 20 64 6f 63 75 6d 65 6e 74 0a 2a   if a document.*
0210: 2a 20 6d 61 74 63 68 65 73 20 61 6e 20 46 54 53  * matches an FTS
0220: 20 4e 45 41 52 20 65 78 70 72 65 73 73 69 6f 6e   NEAR expression
0230: 2e 0a 2a 2f 0a 0a 23 69 6e 63 6c 75 64 65 20 3c  ..*/..#include <
0240: 74 63 6c 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20  tcl.h>.#include 
0250: 3c 73 74 72 69 6e 67 2e 68 3e 0a 23 69 6e 63 6c  <string.h>.#incl
0260: 75 64 65 20 3c 61 73 73 65 72 74 2e 68 3e 0a 0a  ude <assert.h>..
0270: 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f 54 45  #ifdef SQLITE_TE
0280: 53 54 0a 0a 2f 2a 20 52 65 71 75 69 72 65 64 20  ST../* Required 
0290: 73 6f 20 74 68 61 74 20 74 68 65 20 22 69 66 64  so that the "ifd
02a0: 65 66 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45  ef SQLITE_ENABLE
02b0: 5f 46 54 53 33 22 20 62 65 6c 6f 77 20 77 6f 72  _FTS3" below wor
02c0: 6b 73 20 2a 2f 0a 23 69 6e 63 6c 75 64 65 20 22  ks */.#include "
02d0: 66 74 73 33 49 6e 74 2e 68 22 0a 0a 23 64 65 66  fts3Int.h"..#def
02e0: 69 6e 65 20 4e 4d 5f 4d 41 58 5f 54 4f 4b 45 4e  ine NM_MAX_TOKEN
02f0: 20 31 32 0a 0a 74 79 70 65 64 65 66 20 73 74 72   12..typedef str
0300: 75 63 74 20 4e 65 61 72 50 68 72 61 73 65 20 4e  uct NearPhrase N
0310: 65 61 72 50 68 72 61 73 65 3b 0a 74 79 70 65 64  earPhrase;.typed
0320: 65 66 20 73 74 72 75 63 74 20 4e 65 61 72 44 6f  ef struct NearDo
0330: 63 75 6d 65 6e 74 20 4e 65 61 72 44 6f 63 75 6d  cument NearDocum
0340: 65 6e 74 3b 0a 74 79 70 65 64 65 66 20 73 74 72  ent;.typedef str
0350: 75 63 74 20 4e 65 61 72 54 6f 6b 65 6e 20 4e 65  uct NearToken Ne
0360: 61 72 54 6f 6b 65 6e 3b 0a 0a 73 74 72 75 63 74  arToken;..struct
0370: 20 4e 65 61 72 44 6f 63 75 6d 65 6e 74 20 7b 0a   NearDocument {.
0380: 20 20 69 6e 74 20 6e 54 6f 6b 65 6e 3b 20 20 20    int nToken;   
0390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
03a0: 20 20 2f 2a 20 4c 65 6e 67 74 68 20 6f 66 20 74    /* Length of t
03b0: 6f 6b 65 6e 20 69 6e 20 62 79 74 65 73 20 2a 2f  oken in bytes */
03c0: 0a 20 20 4e 65 61 72 54 6f 6b 65 6e 20 2a 61 54  .  NearToken *aT
03d0: 6f 6b 65 6e 3b 20 20 20 20 20 20 20 20 20 20 20  oken;           
03e0: 20 20 20 2f 2a 20 54 6f 6b 65 6e 20 61 72 72 61     /* Token arra
03f0: 79 20 2a 2f 0a 7d 3b 0a 0a 73 74 72 75 63 74 20  y */.};..struct 
0400: 4e 65 61 72 54 6f 6b 65 6e 20 7b 0a 20 20 69 6e  NearToken {.  in
0410: 74 20 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20  t n;            
0420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
0430: 20 4c 65 6e 67 74 68 20 6f 66 20 74 6f 6b 65 6e   Length of token
0440: 20 69 6e 20 62 79 74 65 73 20 2a 2f 0a 20 20 63   in bytes */.  c
0450: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 3b 20 20 20  onst char *z;   
0460: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0470: 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20 74 6f 6b  * Pointer to tok
0480: 65 6e 20 73 74 72 69 6e 67 20 2a 2f 0a 7d 3b 0a  en string */.};.
0490: 0a 73 74 72 75 63 74 20 4e 65 61 72 50 68 72 61  .struct NearPhra
04a0: 73 65 20 7b 0a 20 20 69 6e 74 20 6e 4e 65 61 72  se {.  int nNear
04b0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
04c0: 20 20 20 20 20 20 20 2f 2a 20 50 72 65 63 65 64         /* Preced
04d0: 69 6e 67 20 4e 45 41 52 20 76 61 6c 75 65 20 2a  ing NEAR value *
04e0: 2f 0a 20 20 69 6e 74 20 6e 54 6f 6b 65 6e 3b 20  /.  int nToken; 
04f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0500: 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66      /* Number of
0510: 20 74 6f 6b 65 6e 73 20 69 6e 20 74 68 69 73 20   tokens in this 
0520: 70 68 72 61 73 65 20 2a 2f 0a 20 20 4e 65 61 72  phrase */.  Near
0530: 54 6f 6b 65 6e 20 61 54 6f 6b 65 6e 5b 4e 4d 5f  Token aToken[NM_
0540: 4d 41 58 5f 54 4f 4b 45 4e 5d 3b 20 2f 2a 20 41  MAX_TOKEN]; /* A
0550: 72 72 61 79 20 6f 66 20 74 6f 6b 65 6e 73 20 69  rray of tokens i
0560: 6e 20 74 68 69 73 20 70 68 72 61 73 65 20 2a 2f  n this phrase */
0570: 0a 7d 3b 0a 0a 73 74 61 74 69 63 20 69 6e 74 20  .};..static int 
0580: 6e 6d 5f 70 68 72 61 73 65 5f 6d 61 74 63 68 28  nm_phrase_match(
0590: 0a 20 20 4e 65 61 72 50 68 72 61 73 65 20 2a 70  .  NearPhrase *p
05a0: 2c 0a 20 20 4e 65 61 72 54 6f 6b 65 6e 20 2a 61  ,.  NearToken *a
05b0: 54 6f 6b 65 6e 0a 29 7b 0a 20 20 69 6e 74 20 69  Token.){.  int i
05c0: 69 3b 0a 0a 20 20 66 6f 72 28 69 69 3d 30 3b 20  i;..  for(ii=0; 
05d0: 69 69 3c 70 2d 3e 6e 54 6f 6b 65 6e 3b 20 69 69  ii<p->nToken; ii
05e0: 2b 2b 29 7b 0a 20 20 20 20 4e 65 61 72 54 6f 6b  ++){.    NearTok
05f0: 65 6e 20 2a 70 54 6f 6b 65 6e 20 3d 20 26 70 2d  en *pToken = &p-
0600: 3e 61 54 6f 6b 65 6e 5b 69 69 5d 3b 0a 20 20 20  >aToken[ii];.   
0610: 20 69 66 28 20 70 54 6f 6b 65 6e 2d 3e 6e 3e 30   if( pToken->n>0
0620: 20 26 26 20 70 54 6f 6b 65 6e 2d 3e 7a 5b 70 54   && pToken->z[pT
0630: 6f 6b 65 6e 2d 3e 6e 2d 31 5d 3d 3d 27 2a 27 20  oken->n-1]=='*' 
0640: 29 7b 0a 20 20 20 20 20 20 69 66 28 20 61 54 6f  ){.      if( aTo
0650: 6b 65 6e 5b 69 69 5d 2e 6e 3c 28 70 54 6f 6b 65  ken[ii].n<(pToke
0660: 6e 2d 3e 6e 2d 31 29 20 29 20 72 65 74 75 72 6e  n->n-1) ) return
0670: 20 30 3b 0a 20 20 20 20 20 20 69 66 28 20 6d 65   0;.      if( me
0680: 6d 63 6d 70 28 61 54 6f 6b 65 6e 5b 69 69 5d 2e  mcmp(aToken[ii].
0690: 7a 2c 20 70 54 6f 6b 65 6e 2d 3e 7a 2c 20 70 54  z, pToken->z, pT
06a0: 6f 6b 65 6e 2d 3e 6e 2d 31 29 20 29 20 72 65 74  oken->n-1) ) ret
06b0: 75 72 6e 20 30 3b 0a 20 20 20 20 7d 65 6c 73 65  urn 0;.    }else
06c0: 7b 0a 20 20 20 20 20 20 69 66 28 20 61 54 6f 6b  {.      if( aTok
06d0: 65 6e 5b 69 69 5d 2e 6e 21 3d 70 54 6f 6b 65 6e  en[ii].n!=pToken
06e0: 2d 3e 6e 20 29 20 72 65 74 75 72 6e 20 30 3b 0a  ->n ) return 0;.
06f0: 20 20 20 20 20 20 69 66 28 20 6d 65 6d 63 6d 70        if( memcmp
0700: 28 61 54 6f 6b 65 6e 5b 69 69 5d 2e 7a 2c 20 70  (aToken[ii].z, p
0710: 54 6f 6b 65 6e 2d 3e 7a 2c 20 70 54 6f 6b 65 6e  Token->z, pToken
0720: 2d 3e 6e 29 20 29 20 72 65 74 75 72 6e 20 30 3b  ->n) ) return 0;
0730: 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65  .    }.  }..  re
0740: 74 75 72 6e 20 31 3b 0a 7d 0a 0a 73 74 61 74 69  turn 1;.}..stati
0750: 63 20 69 6e 74 20 6e 6d 5f 6e 65 61 72 5f 63 68  c int nm_near_ch
0760: 61 69 6e 28 0a 20 20 69 6e 74 20 69 44 69 72 2c  ain(.  int iDir,
0770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0780: 20 20 20 20 20 20 20 2f 2a 20 44 69 72 65 63 74         /* Direct
0790: 69 6f 6e 20 74 6f 20 69 74 65 72 61 74 65 20 74  ion to iterate t
07a0: 68 72 6f 75 67 68 20 61 50 68 72 61 73 65 5b 5d  hrough aPhrase[]
07b0: 20 2a 2f 0a 20 20 4e 65 61 72 44 6f 63 75 6d 65   */.  NearDocume
07c0: 6e 74 20 2a 70 44 6f 63 2c 20 20 20 20 20 20 20  nt *pDoc,       
07d0: 20 20 20 20 20 20 2f 2a 20 44 6f 63 75 6d 65 6e        /* Documen
07e0: 74 20 74 6f 20 6d 61 74 63 68 20 61 67 61 69 6e  t to match again
07f0: 73 74 20 2a 2f 0a 20 20 69 6e 74 20 69 50 6f 73  st */.  int iPos
0800: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
0810: 20 20 20 20 20 20 20 20 2f 2a 20 50 6f 73 69 74          /* Posit
0820: 69 6f 6e 20 61 74 20 77 68 69 63 68 20 69 50 68  ion at which iPh
0830: 72 61 73 65 20 77 61 73 20 66 6f 75 6e 64 20 2a  rase was found *
0840: 2f 0a 20 20 69 6e 74 20 6e 50 68 72 61 73 65 2c  /.  int nPhrase,
0850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0860: 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20 70      /* Size of p
0870: 68 72 61 73 65 20 61 72 72 61 79 20 2a 2f 0a 20  hrase array */. 
0880: 20 4e 65 61 72 50 68 72 61 73 65 20 2a 61 50 68   NearPhrase *aPh
0890: 72 61 73 65 2c 20 20 20 20 20 20 20 20 20 20 20  rase,           
08a0: 20 2f 2a 20 50 68 72 61 73 65 20 61 72 72 61 79   /* Phrase array
08b0: 20 2a 2f 0a 20 20 69 6e 74 20 69 50 68 72 61 73   */.  int iPhras
08c0: 65 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e               
08d0: 20 20 20 20 20 20 2f 2a 20 49 6e 64 65 78 20 6f        /* Index o
08e0: 66 20 70 68 72 61 73 65 20 66 6f 75 6e 64 20 2a  f phrase found *
08f0: 2f 0a 29 7b 0a 20 20 69 6e 74 20 69 53 74 61 72  /.){.  int iStar
0900: 74 3b 0a 20 20 69 6e 74 20 69 53 74 6f 70 3b 0a  t;.  int iStop;.
0910: 20 20 69 6e 74 20 69 69 3b 0a 20 20 69 6e 74 20    int ii;.  int 
0920: 6e 4e 65 61 72 3b 0a 20 20 69 6e 74 20 69 50 68  nNear;.  int iPh
0930: 72 61 73 65 32 3b 0a 20 20 4e 65 61 72 50 68 72  rase2;.  NearPhr
0940: 61 73 65 20 2a 70 3b 0a 20 20 4e 65 61 72 50 68  ase *p;.  NearPh
0950: 72 61 73 65 20 2a 70 50 72 65 76 3b 0a 0a 20 20  rase *pPrev;..  
0960: 61 73 73 65 72 74 28 20 69 44 69 72 3d 3d 31 20  assert( iDir==1 
0970: 7c 7c 20 69 44 69 72 3d 3d 2d 31 20 29 3b 0a 0a  || iDir==-1 );..
0980: 20 20 69 66 28 20 69 44 69 72 3d 3d 31 20 29 7b    if( iDir==1 ){
0990: 0a 20 20 20 20 69 66 28 20 28 69 50 68 72 61 73  .    if( (iPhras
09a0: 65 2b 31 29 3d 3d 6e 50 68 72 61 73 65 20 29 20  e+1)==nPhrase ) 
09b0: 72 65 74 75 72 6e 20 31 3b 0a 20 20 20 20 6e 4e  return 1;.    nN
09c0: 65 61 72 20 3d 20 61 50 68 72 61 73 65 5b 69 50  ear = aPhrase[iP
09d0: 68 72 61 73 65 2b 31 5d 2e 6e 4e 65 61 72 3b 0a  hrase+1].nNear;.
09e0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 69 66 28    }else{.    if(
09f0: 20 69 50 68 72 61 73 65 3d 3d 30 20 29 20 72 65   iPhrase==0 ) re
0a00: 74 75 72 6e 20 31 3b 0a 20 20 20 20 6e 4e 65 61  turn 1;.    nNea
0a10: 72 20 3d 20 61 50 68 72 61 73 65 5b 69 50 68 72  r = aPhrase[iPhr
0a20: 61 73 65 5d 2e 6e 4e 65 61 72 3b 0a 20 20 7d 0a  ase].nNear;.  }.
0a30: 20 20 70 50 72 65 76 20 3d 20 26 61 50 68 72 61    pPrev = &aPhra
0a40: 73 65 5b 69 50 68 72 61 73 65 5d 3b 0a 20 20 69  se[iPhrase];.  i
0a50: 50 68 72 61 73 65 32 20 3d 20 69 50 68 72 61 73  Phrase2 = iPhras
0a60: 65 2b 69 44 69 72 3b 0a 20 20 70 20 3d 20 26 61  e+iDir;.  p = &a
0a70: 50 68 72 61 73 65 5b 69 50 68 72 61 73 65 32 5d  Phrase[iPhrase2]
0a80: 3b 0a 0a 20 20 69 53 74 61 72 74 20 3d 20 69 50  ;..  iStart = iP
0a90: 6f 73 20 2d 20 6e 4e 65 61 72 20 2d 20 70 2d 3e  os - nNear - p->
0aa0: 6e 54 6f 6b 65 6e 3b 0a 20 20 69 53 74 6f 70 20  nToken;.  iStop 
0ab0: 3d 20 69 50 6f 73 20 2b 20 6e 4e 65 61 72 20 2b  = iPos + nNear +
0ac0: 20 70 50 72 65 76 2d 3e 6e 54 6f 6b 65 6e 3b 0a   pPrev->nToken;.
0ad0: 0a 20 20 69 66 28 20 69 53 74 61 72 74 3c 30 20  .  if( iStart<0 
0ae0: 29 20 69 53 74 61 72 74 20 3d 20 30 3b 0a 20 20  ) iStart = 0;.  
0af0: 69 66 28 20 69 53 74 6f 70 20 3e 20 70 44 6f 63  if( iStop > pDoc
0b00: 2d 3e 6e 54 6f 6b 65 6e 20 2d 20 70 2d 3e 6e 54  ->nToken - p->nT
0b10: 6f 6b 65 6e 20 29 20 69 53 74 6f 70 20 3d 20 70  oken ) iStop = p
0b20: 44 6f 63 2d 3e 6e 54 6f 6b 65 6e 20 2d 20 70 2d  Doc->nToken - p-
0b30: 3e 6e 54 6f 6b 65 6e 3b 0a 0a 20 20 66 6f 72 28  >nToken;..  for(
0b40: 69 69 3d 69 53 74 61 72 74 3b 20 69 69 3c 3d 69  ii=iStart; ii<=i
0b50: 53 74 6f 70 3b 20 69 69 2b 2b 29 7b 0a 20 20 20  Stop; ii++){.   
0b60: 20 69 66 28 20 6e 6d 5f 70 68 72 61 73 65 5f 6d   if( nm_phrase_m
0b70: 61 74 63 68 28 70 2c 20 26 70 44 6f 63 2d 3e 61  atch(p, &pDoc->a
0b80: 54 6f 6b 65 6e 5b 69 69 5d 29 20 29 7b 0a 20 20  Token[ii]) ){.  
0b90: 20 20 20 20 69 66 28 20 6e 6d 5f 6e 65 61 72 5f      if( nm_near_
0ba0: 63 68 61 69 6e 28 69 44 69 72 2c 20 70 44 6f 63  chain(iDir, pDoc
0bb0: 2c 20 69 69 2c 20 6e 50 68 72 61 73 65 2c 20 61  , ii, nPhrase, a
0bc0: 50 68 72 61 73 65 2c 20 69 50 68 72 61 73 65 32  Phrase, iPhrase2
0bd0: 29 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20 20  ) ) return 1;.  
0be0: 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72    }.  }..  retur
0bf0: 6e 20 30 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69  n 0;.}..static i
0c00: 6e 74 20 6e 6d 5f 6d 61 74 63 68 5f 63 6f 75 6e  nt nm_match_coun
0c10: 74 28 0a 20 20 4e 65 61 72 44 6f 63 75 6d 65 6e  t(.  NearDocumen
0c20: 74 20 2a 70 44 6f 63 2c 20 20 20 20 20 20 20 20  t *pDoc,        
0c30: 20 20 20 20 20 2f 2a 20 44 6f 63 75 6d 65 6e 74       /* Document
0c40: 20 74 6f 20 6d 61 74 63 68 20 61 67 61 69 6e 73   to match agains
0c50: 74 20 2a 2f 0a 20 20 69 6e 74 20 6e 50 68 72 61  t */.  int nPhra
0c60: 73 65 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  se,             
0c70: 20 20 20 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f         /* Size o
0c80: 66 20 70 68 72 61 73 65 20 61 72 72 61 79 20 2a  f phrase array *
0c90: 2f 0a 20 20 4e 65 61 72 50 68 72 61 73 65 20 2a  /.  NearPhrase *
0ca0: 61 50 68 72 61 73 65 2c 20 20 20 20 20 20 20 20  aPhrase,        
0cb0: 20 20 20 20 2f 2a 20 50 68 72 61 73 65 20 61 72      /* Phrase ar
0cc0: 72 61 79 20 2a 2f 0a 20 20 69 6e 74 20 69 50 68  ray */.  int iPh
0cd0: 72 61 73 65 20 20 20 20 20 20 20 20 20 20 20 20  rase            
0ce0: 20 20 20 20 20 20 20 20 20 2f 2a 20 49 6e 64 65           /* Inde
0cf0: 78 20 6f 66 20 70 68 72 61 73 65 20 74 6f 20 63  x of phrase to c
0d00: 6f 75 6e 74 20 6d 61 74 63 68 65 73 20 66 6f 72  ount matches for
0d10: 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 6e 4f 63   */.){.  int nOc
0d20: 63 20 3d 20 30 3b 0a 20 20 69 6e 74 20 69 69 3b  c = 0;.  int ii;
0d30: 0a 20 20 4e 65 61 72 50 68 72 61 73 65 20 2a 70  .  NearPhrase *p
0d40: 20 3d 20 26 61 50 68 72 61 73 65 5b 69 50 68 72   = &aPhrase[iPhr
0d50: 61 73 65 5d 3b 0a 0a 20 20 66 6f 72 28 69 69 3d  ase];..  for(ii=
0d60: 30 3b 20 69 69 3c 28 70 44 6f 63 2d 3e 6e 54 6f  0; ii<(pDoc->nTo
0d70: 6b 65 6e 20 2b 20 31 20 2d 20 70 2d 3e 6e 54 6f  ken + 1 - p->nTo
0d80: 6b 65 6e 29 3b 20 69 69 2b 2b 29 7b 0a 20 20 20  ken); ii++){.   
0d90: 20 69 66 28 20 6e 6d 5f 70 68 72 61 73 65 5f 6d   if( nm_phrase_m
0da0: 61 74 63 68 28 70 2c 20 26 70 44 6f 63 2d 3e 61  atch(p, &pDoc->a
0db0: 54 6f 6b 65 6e 5b 69 69 5d 29 20 29 7b 0a 20 20  Token[ii]) ){.  
0dc0: 20 20 20 20 2f 2a 20 54 65 73 74 20 66 6f 72 77      /* Test forw
0dd0: 61 72 64 20 4e 45 41 52 20 63 68 61 69 6e 20 28  ard NEAR chain (
0de0: 69 3e 69 50 68 72 61 73 65 29 20 2a 2f 0a 20 20  i>iPhrase) */.  
0df0: 20 20 20 20 69 66 28 20 30 3d 3d 6e 6d 5f 6e 65      if( 0==nm_ne
0e00: 61 72 5f 63 68 61 69 6e 28 31 2c 20 70 44 6f 63  ar_chain(1, pDoc
0e10: 2c 20 69 69 2c 20 6e 50 68 72 61 73 65 2c 20 61  , ii, nPhrase, a
0e20: 50 68 72 61 73 65 2c 20 69 50 68 72 61 73 65 29  Phrase, iPhrase)
0e30: 20 29 20 63 6f 6e 74 69 6e 75 65 3b 0a 0a 20 20   ) continue;..  
0e40: 20 20 20 20 2f 2a 20 54 65 73 74 20 72 65 76 65      /* Test reve
0e50: 72 73 65 20 4e 45 41 52 20 63 68 61 69 6e 20 28  rse NEAR chain (
0e60: 69 3c 69 50 68 72 61 73 65 29 20 2a 2f 0a 20 20  i<iPhrase) */.  
0e70: 20 20 20 20 69 66 28 20 30 3d 3d 6e 6d 5f 6e 65      if( 0==nm_ne
0e80: 61 72 5f 63 68 61 69 6e 28 2d 31 2c 20 70 44 6f  ar_chain(-1, pDo
0e90: 63 2c 20 69 69 2c 20 6e 50 68 72 61 73 65 2c 20  c, ii, nPhrase, 
0ea0: 61 50 68 72 61 73 65 2c 20 69 50 68 72 61 73 65  aPhrase, iPhrase
0eb0: 29 20 29 20 63 6f 6e 74 69 6e 75 65 3b 0a 0a 20  ) ) continue;.. 
0ec0: 20 20 20 20 20 2f 2a 20 54 68 69 73 20 69 73 20       /* This is 
0ed0: 61 20 72 65 61 6c 20 6d 61 74 63 68 2e 20 49 6e  a real match. In
0ee0: 63 72 65 6d 65 6e 74 20 74 68 65 20 63 6f 75 6e  crement the coun
0ef0: 74 65 72 2e 20 2a 2f 0a 20 20 20 20 20 20 6e 4f  ter. */.      nO
0f00: 63 63 2b 2b 3b 0a 20 20 20 20 7d 0a 20 20 7d 20  cc++;.    }.  } 
0f10: 0a 0a 20 20 72 65 74 75 72 6e 20 6e 4f 63 63 3b  ..  return nOcc;
0f20: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63 6c 63 6d 64  .}../*.** Tclcmd
0f30: 3a 20 66 74 73 33 5f 6e 65 61 72 5f 6d 61 74 63  : fts3_near_matc
0f40: 68 20 44 4f 43 55 4d 45 4e 54 20 45 58 50 52 20  h DOCUMENT EXPR 
0f50: 3f 4f 50 54 49 4f 4e 53 3f 0a 2a 2f 0a 73 74 61  ?OPTIONS?.*/.sta
0f60: 74 69 63 20 69 6e 74 20 66 74 73 33 5f 6e 65 61  tic int fts3_nea
0f70: 72 5f 6d 61 74 63 68 5f 63 6d 64 28 0a 20 20 43  r_match_cmd(.  C
0f80: 6c 69 65 6e 74 44 61 74 61 20 63 6c 69 65 6e 74  lientData client
0f90: 44 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65  Data,.  Tcl_Inte
0fa0: 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e  rp *interp,.  in
0fb0: 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62  t objc,.  Tcl_Ob
0fc0: 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a  j *CONST objv[].
0fd0: 29 7b 0a 20 20 69 6e 74 20 6e 54 6f 74 61 6c 20  ){.  int nTotal 
0fe0: 3d 20 30 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20  = 0;.  int rc;. 
0ff0: 20 69 6e 74 20 69 69 3b 0a 20 20 69 6e 74 20 6e   int ii;.  int n
1000: 50 68 72 61 73 65 3b 0a 20 20 4e 65 61 72 50 68  Phrase;.  NearPh
1010: 72 61 73 65 20 2a 61 50 68 72 61 73 65 20 3d 20  rase *aPhrase = 
1020: 30 3b 0a 20 20 4e 65 61 72 44 6f 63 75 6d 65 6e  0;.  NearDocumen
1030: 74 20 64 6f 63 20 3d 20 7b 30 2c 20 30 7d 3b 0a  t doc = {0, 0};.
1040: 20 20 54 63 6c 5f 4f 62 6a 20 2a 2a 61 70 44 6f    Tcl_Obj **apDo
1050: 63 54 6f 6b 65 6e 3b 0a 20 20 54 63 6c 5f 4f 62  cToken;.  Tcl_Ob
1060: 6a 20 2a 70 52 65 74 3b 0a 20 20 54 63 6c 5f 4f  j *pRet;.  Tcl_O
1070: 62 6a 20 2a 70 50 68 72 61 73 65 63 6f 75 6e 74  bj *pPhrasecount
1080: 20 3d 20 30 3b 0a 20 20 0a 20 20 54 63 6c 5f 4f   = 0;.  .  Tcl_O
1090: 62 6a 20 2a 2a 61 70 45 78 70 72 54 6f 6b 65 6e  bj **apExprToken
10a0: 3b 0a 20 20 69 6e 74 20 6e 45 78 70 72 54 6f 6b  ;.  int nExprTok
10b0: 65 6e 3b 0a 0a 20 20 2f 2a 20 4d 75 73 74 20 68  en;..  /* Must h
10c0: 61 76 65 20 33 20 6f 72 20 6d 6f 72 65 20 61 72  ave 3 or more ar
10d0: 67 75 6d 65 6e 74 73 2e 20 2a 2f 0a 20 20 69 66  guments. */.  if
10e0: 28 20 6f 62 6a 63 3c 33 20 7c 7c 20 28 6f 62 6a  ( objc<3 || (obj
10f0: 63 25 32 29 3d 3d 30 20 29 7b 0a 20 20 20 20 54  c%2)==0 ){.    T
1100: 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41 72 67 73 28  cl_WrongNumArgs(
1110: 69 6e 74 65 72 70 2c 20 31 2c 20 6f 62 6a 76 2c  interp, 1, objv,
1120: 20 22 44 4f 43 55 4d 45 4e 54 20 45 58 50 52 20   "DOCUMENT EXPR 
1130: 3f 4f 50 54 49 4f 4e 20 56 41 4c 55 45 3f 2e 2e  ?OPTION VALUE?..
1140: 2e 22 29 3b 0a 20 20 20 20 72 63 20 3d 20 54 43  .");.    rc = TC
1150: 4c 5f 45 52 52 4f 52 3b 0a 20 20 20 20 67 6f 74  L_ERROR;.    got
1160: 6f 20 6e 65 61 72 5f 6d 61 74 63 68 5f 6f 75 74  o near_match_out
1170: 3b 0a 20 20 7d 0a 0a 20 20 66 6f 72 28 69 69 3d  ;.  }..  for(ii=
1180: 33 3b 20 69 69 3c 6f 62 6a 63 3b 20 69 69 2b 3d  3; ii<objc; ii+=
1190: 32 29 7b 0a 20 20 20 20 65 6e 75 6d 20 4e 4d 5f  2){.    enum NM_
11a0: 65 6e 75 6d 20 7b 20 4e 4d 5f 50 48 52 41 53 45  enum { NM_PHRASE
11b0: 43 4f 55 4e 54 53 20 7d 3b 0a 20 20 20 20 73 74  COUNTS };.    st
11c0: 72 75 63 74 20 54 65 73 74 6e 6d 53 75 62 63 6d  ruct TestnmSubcm
11d0: 64 20 7b 0a 20 20 20 20 20 20 63 68 61 72 20 2a  d {.      char *
11e0: 7a 4e 61 6d 65 3b 0a 20 20 20 20 20 20 65 6e 75  zName;.      enu
11f0: 6d 20 4e 4d 5f 65 6e 75 6d 20 65 4f 70 74 3b 0a  m NM_enum eOpt;.
1200: 20 20 20 20 7d 20 61 4f 70 74 5b 5d 20 3d 20 7b      } aOpt[] = {
1210: 0a 20 20 20 20 20 20 7b 20 22 2d 70 68 72 61 73  .      { "-phras
1220: 65 63 6f 75 6e 74 76 61 72 22 2c 20 4e 4d 5f 50  ecountvar", NM_P
1230: 48 52 41 53 45 43 4f 55 4e 54 53 20 7d 2c 0a 20  HRASECOUNTS },. 
1240: 20 20 20 20 20 7b 20 30 2c 20 30 20 7d 0a 20 20       { 0, 0 }.  
1250: 20 20 7d 3b 0a 20 20 20 20 69 6e 74 20 69 4f 70    };.    int iOp
1260: 74 3b 0a 20 20 20 20 69 66 28 20 54 63 6c 5f 47  t;.    if( Tcl_G
1270: 65 74 49 6e 64 65 78 46 72 6f 6d 4f 62 6a 53 74  etIndexFromObjSt
1280: 72 75 63 74 28 0a 20 20 20 20 20 20 20 20 69 6e  ruct(.        in
1290: 74 65 72 70 2c 20 6f 62 6a 76 5b 69 69 5d 2c 20  terp, objv[ii], 
12a0: 61 4f 70 74 2c 20 73 69 7a 65 6f 66 28 61 4f 70  aOpt, sizeof(aOp
12b0: 74 5b 30 5d 29 2c 20 22 6f 70 74 69 6f 6e 22 2c  t[0]), "option",
12c0: 20 30 2c 20 26 69 4f 70 74 29 20 0a 20 20 20 20   0, &iOpt) .    
12d0: 29 7b 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20  ){.      return 
12e0: 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 20 20 7d  TCL_ERROR;.    }
12f0: 0a 0a 20 20 20 20 73 77 69 74 63 68 28 20 61 4f  ..    switch( aO
1300: 70 74 5b 69 4f 70 74 5d 2e 65 4f 70 74 20 29 7b  pt[iOpt].eOpt ){
1310: 0a 20 20 20 20 20 20 63 61 73 65 20 4e 4d 5f 50  .      case NM_P
1320: 48 52 41 53 45 43 4f 55 4e 54 53 3a 0a 20 20 20  HRASECOUNTS:.   
1330: 20 20 20 20 20 70 50 68 72 61 73 65 63 6f 75 6e       pPhrasecoun
1340: 74 20 3d 20 6f 62 6a 76 5b 69 69 2b 31 5d 3b 0a  t = objv[ii+1];.
1350: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
1360: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 63 20 3d     }.  }..  rc =
1370: 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 47 65 74 45   Tcl_ListObjGetE
1380: 6c 65 6d 65 6e 74 73 28 69 6e 74 65 72 70 2c 20  lements(interp, 
1390: 6f 62 6a 76 5b 31 5d 2c 20 26 64 6f 63 2e 6e 54  objv[1], &doc.nT
13a0: 6f 6b 65 6e 2c 20 26 61 70 44 6f 63 54 6f 6b 65  oken, &apDocToke
13b0: 6e 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 54 43  n);.  if( rc!=TC
13c0: 4c 5f 4f 4b 20 29 20 67 6f 74 6f 20 6e 65 61 72  L_OK ) goto near
13d0: 5f 6d 61 74 63 68 5f 6f 75 74 3b 0a 20 20 64 6f  _match_out;.  do
13e0: 63 2e 61 54 6f 6b 65 6e 20 3d 20 28 4e 65 61 72  c.aToken = (Near
13f0: 54 6f 6b 65 6e 20 2a 29 63 6b 61 6c 6c 6f 63 28  Token *)ckalloc(
1400: 64 6f 63 2e 6e 54 6f 6b 65 6e 2a 73 69 7a 65 6f  doc.nToken*sizeo
1410: 66 28 4e 65 61 72 54 6f 6b 65 6e 29 29 3b 0a 20  f(NearToken));. 
1420: 20 66 6f 72 28 69 69 3d 30 3b 20 69 69 3c 64 6f   for(ii=0; ii<do
1430: 63 2e 6e 54 6f 6b 65 6e 3b 20 69 69 2b 2b 29 7b  c.nToken; ii++){
1440: 0a 20 20 20 20 64 6f 63 2e 61 54 6f 6b 65 6e 5b  .    doc.aToken[
1450: 69 69 5d 2e 7a 20 3d 20 54 63 6c 5f 47 65 74 53  ii].z = Tcl_GetS
1460: 74 72 69 6e 67 46 72 6f 6d 4f 62 6a 28 61 70 44  tringFromObj(apD
1470: 6f 63 54 6f 6b 65 6e 5b 69 69 5d 2c 20 26 64 6f  ocToken[ii], &do
1480: 63 2e 61 54 6f 6b 65 6e 5b 69 69 5d 2e 6e 29 3b  c.aToken[ii].n);
1490: 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20 54 63 6c  .  }..  rc = Tcl
14a0: 5f 4c 69 73 74 4f 62 6a 47 65 74 45 6c 65 6d 65  _ListObjGetEleme
14b0: 6e 74 73 28 69 6e 74 65 72 70 2c 20 6f 62 6a 76  nts(interp, objv
14c0: 5b 32 5d 2c 20 26 6e 45 78 70 72 54 6f 6b 65 6e  [2], &nExprToken
14d0: 2c 20 26 61 70 45 78 70 72 54 6f 6b 65 6e 29 3b  , &apExprToken);
14e0: 0a 20 20 69 66 28 20 72 63 21 3d 54 43 4c 5f 4f  .  if( rc!=TCL_O
14f0: 4b 20 29 20 67 6f 74 6f 20 6e 65 61 72 5f 6d 61  K ) goto near_ma
1500: 74 63 68 5f 6f 75 74 3b 0a 0a 20 20 6e 50 68 72  tch_out;..  nPhr
1510: 61 73 65 20 3d 20 28 6e 45 78 70 72 54 6f 6b 65  ase = (nExprToke
1520: 6e 20 2b 20 31 29 20 2f 20 32 3b 0a 20 20 61 50  n + 1) / 2;.  aP
1530: 68 72 61 73 65 20 3d 20 28 4e 65 61 72 50 68 72  hrase = (NearPhr
1540: 61 73 65 20 2a 29 63 6b 61 6c 6c 6f 63 28 6e 50  ase *)ckalloc(nP
1550: 68 72 61 73 65 20 2a 20 73 69 7a 65 6f 66 28 4e  hrase * sizeof(N
1560: 65 61 72 50 68 72 61 73 65 29 29 3b 0a 20 20 6d  earPhrase));.  m
1570: 65 6d 73 65 74 28 61 50 68 72 61 73 65 2c 20 30  emset(aPhrase, 0
1580: 2c 20 6e 50 68 72 61 73 65 20 2a 20 73 69 7a 65  , nPhrase * size
1590: 6f 66 28 4e 65 61 72 50 68 72 61 73 65 29 29 3b  of(NearPhrase));
15a0: 0a 20 20 66 6f 72 28 69 69 3d 30 3b 20 69 69 3c  .  for(ii=0; ii<
15b0: 6e 50 68 72 61 73 65 3b 20 69 69 2b 2b 29 7b 0a  nPhrase; ii++){.
15c0: 20 20 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 50 68      Tcl_Obj *pPh
15d0: 72 61 73 65 20 3d 20 61 70 45 78 70 72 54 6f 6b  rase = apExprTok
15e0: 65 6e 5b 69 69 2a 32 5d 3b 0a 20 20 20 20 54 63  en[ii*2];.    Tc
15f0: 6c 5f 4f 62 6a 20 2a 2a 61 70 54 6f 6b 65 6e 3b  l_Obj **apToken;
1600: 0a 20 20 20 20 69 6e 74 20 6e 54 6f 6b 65 6e 3b  .    int nToken;
1610: 0a 20 20 20 20 69 6e 74 20 6a 6a 3b 0a 0a 20 20  .    int jj;..  
1620: 20 20 72 63 20 3d 20 54 63 6c 5f 4c 69 73 74 4f    rc = Tcl_ListO
1630: 62 6a 47 65 74 45 6c 65 6d 65 6e 74 73 28 69 6e  bjGetElements(in
1640: 74 65 72 70 2c 20 70 50 68 72 61 73 65 2c 20 26  terp, pPhrase, &
1650: 6e 54 6f 6b 65 6e 2c 20 26 61 70 54 6f 6b 65 6e  nToken, &apToken
1660: 29 3b 0a 20 20 20 20 69 66 28 20 72 63 21 3d 54  );.    if( rc!=T
1670: 43 4c 5f 4f 4b 20 29 20 67 6f 74 6f 20 6e 65 61  CL_OK ) goto nea
1680: 72 5f 6d 61 74 63 68 5f 6f 75 74 3b 0a 20 20 20  r_match_out;.   
1690: 20 69 66 28 20 6e 54 6f 6b 65 6e 3e 4e 4d 5f 4d   if( nToken>NM_M
16a0: 41 58 5f 54 4f 4b 45 4e 20 29 7b 0a 20 20 20 20  AX_TOKEN ){.    
16b0: 20 20 54 63 6c 5f 41 70 70 65 6e 64 52 65 73 75    Tcl_AppendResu
16c0: 6c 74 28 69 6e 74 65 72 70 2c 20 22 54 6f 6f 20  lt(interp, "Too 
16d0: 6d 61 6e 79 20 74 6f 6b 65 6e 73 20 69 6e 20 70  many tokens in p
16e0: 68 72 61 73 65 22 2c 20 30 29 3b 0a 20 20 20 20  hrase", 0);.    
16f0: 20 20 72 63 20 3d 20 54 43 4c 5f 45 52 52 4f 52    rc = TCL_ERROR
1700: 3b 0a 20 20 20 20 20 20 67 6f 74 6f 20 6e 65 61  ;.      goto nea
1710: 72 5f 6d 61 74 63 68 5f 6f 75 74 3b 0a 20 20 20  r_match_out;.   
1720: 20 7d 0a 20 20 20 20 66 6f 72 28 6a 6a 3d 30 3b   }.    for(jj=0;
1730: 20 6a 6a 3c 6e 54 6f 6b 65 6e 3b 20 6a 6a 2b 2b   jj<nToken; jj++
1740: 29 7b 0a 20 20 20 20 20 20 4e 65 61 72 54 6f 6b  ){.      NearTok
1750: 65 6e 20 2a 70 54 20 3d 20 26 61 50 68 72 61 73  en *pT = &aPhras
1760: 65 5b 69 69 5d 2e 61 54 6f 6b 65 6e 5b 6a 6a 5d  e[ii].aToken[jj]
1770: 3b 0a 20 20 20 20 20 20 70 54 2d 3e 7a 20 3d 20  ;.      pT->z = 
1780: 54 63 6c 5f 47 65 74 53 74 72 69 6e 67 46 72 6f  Tcl_GetStringFro
1790: 6d 4f 62 6a 28 61 70 54 6f 6b 65 6e 5b 6a 6a 5d  mObj(apToken[jj]
17a0: 2c 20 26 70 54 2d 3e 6e 29 3b 0a 20 20 20 20 7d  , &pT->n);.    }
17b0: 0a 20 20 20 20 61 50 68 72 61 73 65 5b 69 69 5d  .    aPhrase[ii]
17c0: 2e 6e 54 6f 6b 65 6e 20 3d 20 6e 54 6f 6b 65 6e  .nToken = nToken
17d0: 3b 0a 20 20 7d 0a 20 20 66 6f 72 28 69 69 3d 31  ;.  }.  for(ii=1
17e0: 3b 20 69 69 3c 6e 50 68 72 61 73 65 3b 20 69 69  ; ii<nPhrase; ii
17f0: 2b 2b 29 7b 0a 20 20 20 20 54 63 6c 5f 4f 62 6a  ++){.    Tcl_Obj
1800: 20 2a 70 4e 65 61 72 20 3d 20 61 70 45 78 70 72   *pNear = apExpr
1810: 54 6f 6b 65 6e 5b 32 2a 69 69 2d 31 5d 3b 0a 20  Token[2*ii-1];. 
1820: 20 20 20 69 6e 74 20 6e 4e 65 61 72 3b 0a 20 20     int nNear;.  
1830: 20 20 72 63 20 3d 20 54 63 6c 5f 47 65 74 49 6e    rc = Tcl_GetIn
1840: 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c  tFromObj(interp,
1850: 20 70 4e 65 61 72 2c 20 26 6e 4e 65 61 72 29 3b   pNear, &nNear);
1860: 0a 20 20 20 20 69 66 28 20 72 63 21 3d 54 43 4c  .    if( rc!=TCL
1870: 5f 4f 4b 20 29 20 67 6f 74 6f 20 6e 65 61 72 5f  _OK ) goto near_
1880: 6d 61 74 63 68 5f 6f 75 74 3b 0a 20 20 20 20 61  match_out;.    a
1890: 50 68 72 61 73 65 5b 69 69 5d 2e 6e 4e 65 61 72  Phrase[ii].nNear
18a0: 20 3d 20 6e 4e 65 61 72 3b 0a 20 20 7d 0a 0a 20   = nNear;.  }.. 
18b0: 20 70 52 65 74 20 3d 20 54 63 6c 5f 4e 65 77 4f   pRet = Tcl_NewO
18c0: 62 6a 28 29 3b 0a 20 20 54 63 6c 5f 49 6e 63 72  bj();.  Tcl_Incr
18d0: 52 65 66 43 6f 75 6e 74 28 70 52 65 74 29 3b 0a  RefCount(pRet);.
18e0: 20 20 66 6f 72 28 69 69 3d 30 3b 20 69 69 3c 6e    for(ii=0; ii<n
18f0: 50 68 72 61 73 65 3b 20 69 69 2b 2b 29 7b 0a 20  Phrase; ii++){. 
1900: 20 20 20 69 6e 74 20 6e 4f 63 63 20 3d 20 6e 6d     int nOcc = nm
1910: 5f 6d 61 74 63 68 5f 63 6f 75 6e 74 28 26 64 6f  _match_count(&do
1920: 63 2c 20 6e 50 68 72 61 73 65 2c 20 61 50 68 72  c, nPhrase, aPhr
1930: 61 73 65 2c 20 69 69 29 3b 0a 20 20 20 20 54 63  ase, ii);.    Tc
1940: 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45  l_ListObjAppendE
1950: 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70  lement(interp, p
1960: 52 65 74 2c 20 54 63 6c 5f 4e 65 77 49 6e 74 4f  Ret, Tcl_NewIntO
1970: 62 6a 28 6e 4f 63 63 29 29 3b 0a 20 20 20 20 6e  bj(nOcc));.    n
1980: 54 6f 74 61 6c 20 2b 3d 20 6e 4f 63 63 3b 0a 20  Total += nOcc;. 
1990: 20 7d 0a 20 20 69 66 28 20 70 50 68 72 61 73 65   }.  if( pPhrase
19a0: 63 6f 75 6e 74 20 29 7b 0a 20 20 20 20 54 63 6c  count ){.    Tcl
19b0: 5f 4f 62 6a 53 65 74 56 61 72 32 28 69 6e 74 65  _ObjSetVar2(inte
19c0: 72 70 2c 20 70 50 68 72 61 73 65 63 6f 75 6e 74  rp, pPhrasecount
19d0: 2c 20 30 2c 20 70 52 65 74 2c 20 30 29 3b 0a 20  , 0, pRet, 0);. 
19e0: 20 7d 0a 20 20 54 63 6c 5f 44 65 63 72 52 65 66   }.  Tcl_DecrRef
19f0: 43 6f 75 6e 74 28 70 52 65 74 29 3b 0a 20 20 54  Count(pRet);.  T
1a00: 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c 74 28  cl_SetObjResult(
1a10: 69 6e 74 65 72 70 2c 20 54 63 6c 5f 4e 65 77 42  interp, Tcl_NewB
1a20: 6f 6f 6c 65 61 6e 4f 62 6a 28 6e 54 6f 74 61 6c  ooleanObj(nTotal
1a30: 3e 30 29 29 3b 0a 0a 20 6e 65 61 72 5f 6d 61 74  >0));.. near_mat
1a40: 63 68 5f 6f 75 74 3a 20 0a 20 20 63 6b 66 72 65  ch_out: .  ckfre
1a50: 65 28 28 63 68 61 72 20 2a 29 61 50 68 72 61 73  e((char *)aPhras
1a60: 65 29 3b 0a 20 20 63 6b 66 72 65 65 28 28 63 68  e);.  ckfree((ch
1a70: 61 72 20 2a 29 64 6f 63 2e 61 54 6f 6b 65 6e 29  ar *)doc.aToken)
1a80: 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  ;.  return rc;.}
1a90: 0a 0a 2f 2a 0a 2a 2a 20 20 20 54 63 6c 63 6d 64  ../*.**   Tclcmd
1aa0: 3a 20 66 74 73 33 5f 63 6f 6e 66 69 67 75 72 65  : fts3_configure
1ab0: 5f 69 6e 63 72 5f 6c 6f 61 64 20 3f 43 48 55 4e  _incr_load ?CHUN
1ac0: 4b 53 49 5a 45 20 54 48 52 45 53 48 4f 4c 44 3f  KSIZE THRESHOLD?
1ad0: 0a 2a 2a 0a 2a 2a 20 4e 6f 72 6d 61 6c 6c 79 2c  .**.** Normally,
1ae0: 20 46 54 53 20 75 73 65 73 20 68 61 72 64 2d 63   FTS uses hard-c
1af0: 6f 64 65 64 20 76 61 6c 75 65 73 20 74 6f 20 64  oded values to d
1b00: 65 74 65 72 6d 69 6e 65 20 74 68 65 20 6d 69 6e  etermine the min
1b10: 69 6d 75 6d 20 64 6f 63 6c 69 73 74 0a 2a 2a 20  imum doclist.** 
1b20: 73 69 7a 65 20 65 6c 69 67 69 62 6c 65 20 66 6f  size eligible fo
1b30: 72 20 69 6e 63 72 65 6d 65 6e 74 61 6c 20 6c 6f  r incremental lo
1b40: 61 64 69 6e 67 2c 20 61 6e 64 20 74 68 65 20 73  ading, and the s
1b50: 69 7a 65 20 6f 66 20 74 68 65 20 63 68 75 6e 6b  ize of the chunk
1b60: 73 20 6c 6f 61 64 65 64 0a 2a 2a 20 77 68 65 6e  s loaded.** when
1b70: 20 61 20 64 6f 63 6c 69 73 74 20 69 73 20 69 6e   a doclist is in
1b80: 63 72 65 6d 65 6e 74 61 6c 6c 79 20 6c 6f 61 64  crementally load
1b90: 65 64 2e 20 54 68 69 73 20 63 6f 6d 6d 61 6e 64  ed. This command
1ba0: 20 61 6c 6c 6f 77 73 20 74 68 65 20 62 75 69 6c   allows the buil
1bb0: 74 2d 69 6e 0a 2a 2a 20 76 61 6c 75 65 73 20 74  t-in.** values t
1bc0: 6f 20 62 65 20 6f 76 65 72 72 69 64 64 65 6e 20  o be overridden 
1bd0: 66 6f 72 20 74 65 73 74 69 6e 67 20 70 75 72 70  for testing purp
1be0: 6f 73 65 73 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 70  oses..**.** If p
1bf0: 72 65 73 65 6e 74 2c 20 74 68 65 20 66 69 72 73  resent, the firs
1c00: 74 20 61 72 67 75 6d 65 6e 74 20 69 73 20 74 68  t argument is th
1c10: 65 20 63 68 75 6e 6b 73 69 7a 65 20 69 6e 20 62  e chunksize in b
1c20: 79 74 65 73 20 74 6f 20 6c 6f 61 64 20 64 6f 63  ytes to load doc
1c30: 6c 69 73 74 73 0a 2a 2a 20 69 6e 2e 20 54 68 65  lists.** in. The
1c40: 20 73 65 63 6f 6e 64 20 61 72 67 75 6d 65 6e 74   second argument
1c50: 20 69 73 20 74 68 65 20 6d 69 6e 69 6d 75 6d 20   is the minimum 
1c60: 64 6f 63 6c 69 73 74 20 73 69 7a 65 20 69 6e 20  doclist size in 
1c70: 62 79 74 65 73 20 74 6f 20 75 73 65 0a 2a 2a 20  bytes to use.** 
1c80: 69 6e 63 72 65 6d 65 6e 74 61 6c 20 6c 6f 61 64  incremental load
1c90: 69 6e 67 20 77 69 74 68 2e 0a 2a 2a 0a 2a 2a 20  ing with..**.** 
1ca0: 57 68 65 74 68 65 72 20 6f 72 20 6e 6f 74 20 74  Whether or not t
1cb0: 68 65 20 61 72 67 75 6d 65 6e 74 73 20 61 72 65  he arguments are
1cc0: 20 70 72 65 73 65 6e 74 2c 20 74 68 69 73 20 63   present, this c
1cd0: 6f 6d 6d 61 6e 64 20 72 65 74 75 72 6e 73 20 61  ommand returns a
1ce0: 20 6c 69 73 74 20 6f 66 0a 2a 2a 20 74 77 6f 20   list of.** two 
1cf0: 69 6e 74 65 67 65 72 73 20 2d 20 74 68 65 20 69  integers - the i
1d00: 6e 69 74 69 61 6c 20 63 68 75 6e 6b 73 69 7a 65  nitial chunksize
1d10: 20 61 6e 64 20 74 68 72 65 73 68 6f 6c 64 20 77   and threshold w
1d20: 68 65 6e 20 74 68 65 20 63 6f 6d 6d 61 6e 64 20  hen the command 
1d30: 69 73 0a 2a 2a 20 69 6e 76 6f 6b 65 64 2e 20 54  is.** invoked. T
1d40: 68 69 73 20 63 61 6e 20 62 65 20 75 73 65 64 20  his can be used 
1d50: 74 6f 20 72 65 73 74 6f 72 65 20 74 68 65 20 64  to restore the d
1d60: 65 66 61 75 6c 74 20 62 65 68 61 76 69 6f 75 72  efault behaviour
1d70: 20 61 66 74 65 72 20 72 75 6e 6e 69 6e 67 0a 2a   after running.*
1d80: 2a 20 74 65 73 74 73 2e 20 46 6f 72 20 65 78 61  * tests. For exa
1d90: 6d 70 6c 65 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 23  mple:.**.**    #
1da0: 20 4f 76 65 72 72 69 64 65 20 69 6e 63 72 2d 6c   Override incr-l
1db0: 6f 61 64 20 73 65 74 74 69 6e 67 73 20 66 6f 72  oad settings for
1dc0: 20 74 65 73 74 69 6e 67 3a 0a 2a 2a 20 20 20 20   testing:.**    
1dd0: 73 65 74 20 63 66 67 20 5b 66 74 73 33 5f 63 6f  set cfg [fts3_co
1de0: 6e 66 69 67 75 72 65 5f 69 6e 63 72 5f 6c 6f 61  nfigure_incr_loa
1df0: 64 20 24 6e 65 77 5f 63 68 75 6e 6b 73 69 7a 65  d $new_chunksize
1e00: 20 24 6e 65 77 5f 74 68 72 65 73 68 6f 6c 64 5d   $new_threshold]
1e10: 0a 2a 2a 0a 2a 2a 20 20 20 20 2e 2e 2e 2e 20 72  .**.**    .... r
1e20: 75 6e 20 74 65 73 74 73 20 2e 2e 2e 2e 0a 2a 2a  un tests .....**
1e30: 0a 2a 2a 20 20 20 20 23 20 52 65 73 74 6f 72 65  .**    # Restore
1e40: 20 69 6e 69 74 69 61 6c 20 69 6e 63 72 2d 6c 6f   initial incr-lo
1e50: 61 64 20 73 65 74 74 69 6e 67 73 3a 0a 2a 2a 20  ad settings:.** 
1e60: 20 20 20 65 76 61 6c 20 66 74 73 33 5f 63 6f 6e     eval fts3_con
1e70: 66 69 67 75 72 65 5f 69 6e 63 72 5f 6c 6f 61 64  figure_incr_load
1e80: 20 24 63 66 67 0a 2a 2f 0a 73 74 61 74 69 63 20   $cfg.*/.static 
1e90: 69 6e 74 20 66 74 73 33 5f 63 6f 6e 66 69 67 75  int fts3_configu
1ea0: 72 65 5f 69 6e 63 72 5f 6c 6f 61 64 5f 63 6d 64  re_incr_load_cmd
1eb0: 28 0a 20 20 43 6c 69 65 6e 74 44 61 74 61 20 63  (.  ClientData c
1ec0: 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c  lientData,.  Tcl
1ed0: 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c  _Interp *interp,
1ee0: 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54  .  int objc,.  T
1ef0: 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62  cl_Obj *CONST ob
1f00: 6a 76 5b 5d 0a 29 7b 0a 23 69 66 64 65 66 20 53  jv[].){.#ifdef S
1f10: 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 46 54 53  QLITE_ENABLE_FTS
1f20: 33 0a 20 20 65 78 74 65 72 6e 20 69 6e 74 20 74  3.  extern int t
1f30: 65 73 74 5f 66 74 73 33 5f 6e 6f 64 65 5f 63 68  est_fts3_node_ch
1f40: 75 6e 6b 73 69 7a 65 3b 0a 20 20 65 78 74 65 72  unksize;.  exter
1f50: 6e 20 69 6e 74 20 74 65 73 74 5f 66 74 73 33 5f  n int test_fts3_
1f60: 6e 6f 64 65 5f 63 68 75 6e 6b 5f 74 68 72 65 73  node_chunk_thres
1f70: 68 6f 6c 64 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20  hold;.  Tcl_Obj 
1f80: 2a 70 52 65 74 3b 0a 0a 20 20 69 66 28 20 6f 62  *pRet;..  if( ob
1f90: 6a 63 21 3d 31 20 26 26 20 6f 62 6a 63 21 3d 33  jc!=1 && objc!=3
1fa0: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e   ){.    Tcl_Wron
1fb0: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
1fc0: 20 31 2c 20 6f 62 6a 76 2c 20 22 3f 43 48 55 4e   1, objv, "?CHUN
1fd0: 4b 53 49 5a 45 20 54 48 52 45 53 48 4f 4c 44 3f  KSIZE THRESHOLD?
1fe0: 22 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54  ");.    return T
1ff0: 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20  CL_ERROR;.  }.. 
2000: 20 70 52 65 74 20 3d 20 54 63 6c 5f 4e 65 77 4f   pRet = Tcl_NewO
2010: 62 6a 28 29 3b 0a 20 20 54 63 6c 5f 49 6e 63 72  bj();.  Tcl_Incr
2020: 52 65 66 43 6f 75 6e 74 28 70 52 65 74 29 3b 0a  RefCount(pRet);.
2030: 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70    Tcl_ListObjApp
2040: 65 6e 64 45 6c 65 6d 65 6e 74 28 0a 20 20 20 20  endElement(.    
2050: 20 20 69 6e 74 65 72 70 2c 20 70 52 65 74 2c 20    interp, pRet, 
2060: 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 74 65  Tcl_NewIntObj(te
2070: 73 74 5f 66 74 73 33 5f 6e 6f 64 65 5f 63 68 75  st_fts3_node_chu
2080: 6e 6b 73 69 7a 65 29 29 3b 0a 20 20 54 63 6c 5f  nksize));.  Tcl_
2090: 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65  ListObjAppendEle
20a0: 6d 65 6e 74 28 0a 20 20 20 20 20 20 69 6e 74 65  ment(.      inte
20b0: 72 70 2c 20 70 52 65 74 2c 20 54 63 6c 5f 4e 65  rp, pRet, Tcl_Ne
20c0: 77 49 6e 74 4f 62 6a 28 74 65 73 74 5f 66 74 73  wIntObj(test_fts
20d0: 33 5f 6e 6f 64 65 5f 63 68 75 6e 6b 5f 74 68 72  3_node_chunk_thr
20e0: 65 73 68 6f 6c 64 29 29 3b 0a 0a 20 20 69 66 28  eshold));..  if(
20f0: 20 6f 62 6a 63 3d 3d 33 20 29 7b 0a 20 20 20 20   objc==3 ){.    
2100: 69 6e 74 20 69 41 72 67 31 3b 0a 20 20 20 20 69  int iArg1;.    i
2110: 6e 74 20 69 41 72 67 32 3b 0a 20 20 20 20 69 66  nt iArg2;.    if
2120: 28 20 54 63 6c 5f 47 65 74 49 6e 74 46 72 6f 6d  ( Tcl_GetIntFrom
2130: 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f 62 6a 76  Obj(interp, objv
2140: 5b 31 5d 2c 20 26 69 41 72 67 31 29 0a 20 20 20  [1], &iArg1).   
2150: 20 20 7c 7c 20 54 63 6c 5f 47 65 74 49 6e 74 46    || Tcl_GetIntF
2160: 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f  romObj(interp, o
2170: 62 6a 76 5b 32 5d 2c 20 26 69 41 72 67 32 29 0a  bjv[2], &iArg2).
2180: 20 20 20 20 29 7b 0a 20 20 20 20 20 20 54 63 6c      ){.      Tcl
2190: 5f 44 65 63 72 52 65 66 43 6f 75 6e 74 28 70 52  _DecrRefCount(pR
21a0: 65 74 29 3b 0a 20 20 20 20 20 20 72 65 74 75 72  et);.      retur
21b0: 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 20  n TCL_ERROR;.   
21c0: 20 7d 0a 20 20 20 20 74 65 73 74 5f 66 74 73 33   }.    test_fts3
21d0: 5f 6e 6f 64 65 5f 63 68 75 6e 6b 73 69 7a 65 20  _node_chunksize 
21e0: 3d 20 69 41 72 67 31 3b 0a 20 20 20 20 74 65 73  = iArg1;.    tes
21f0: 74 5f 66 74 73 33 5f 6e 6f 64 65 5f 63 68 75 6e  t_fts3_node_chun
2200: 6b 5f 74 68 72 65 73 68 6f 6c 64 20 3d 20 69 41  k_threshold = iA
2210: 72 67 32 3b 0a 20 20 7d 0a 0a 20 20 54 63 6c 5f  rg2;.  }..  Tcl_
2220: 53 65 74 4f 62 6a 52 65 73 75 6c 74 28 69 6e 74  SetObjResult(int
2230: 65 72 70 2c 20 70 52 65 74 29 3b 0a 20 20 54 63  erp, pRet);.  Tc
2240: 6c 5f 44 65 63 72 52 65 66 43 6f 75 6e 74 28 70  l_DecrRefCount(p
2250: 52 65 74 29 3b 0a 23 65 6e 64 69 66 0a 20 20 72  Ret);.#endif.  r
2260: 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a  eturn TCL_OK;.}.
2270: 0a 69 6e 74 20 53 71 6c 69 74 65 74 65 73 74 66  .int Sqlitetestf
2280: 74 73 33 5f 49 6e 69 74 28 54 63 6c 5f 49 6e 74  ts3_Init(Tcl_Int
2290: 65 72 70 20 2a 69 6e 74 65 72 70 29 7b 0a 20 20  erp *interp){.  
22a0: 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43 6f 6d  Tcl_CreateObjCom
22b0: 6d 61 6e 64 28 69 6e 74 65 72 70 2c 20 22 66 74  mand(interp, "ft
22c0: 73 33 5f 6e 65 61 72 5f 6d 61 74 63 68 22 2c 20  s3_near_match", 
22d0: 66 74 73 33 5f 6e 65 61 72 5f 6d 61 74 63 68 5f  fts3_near_match_
22e0: 63 6d 64 2c 20 30 2c 20 30 29 3b 0a 20 20 54 63  cmd, 0, 0);.  Tc
22f0: 6c 5f 43 72 65 61 74 65 4f 62 6a 43 6f 6d 6d 61  l_CreateObjComma
2300: 6e 64 28 69 6e 74 65 72 70 2c 20 0a 20 20 20 20  nd(interp, .    
2310: 20 20 22 66 74 73 33 5f 63 6f 6e 66 69 67 75 72    "fts3_configur
2320: 65 5f 69 6e 63 72 5f 6c 6f 61 64 22 2c 20 66 74  e_incr_load", ft
2330: 73 33 5f 63 6f 6e 66 69 67 75 72 65 5f 69 6e 63  s3_configure_inc
2340: 72 5f 6c 6f 61 64 5f 63 6d 64 2c 20 30 2c 20 30  r_load_cmd, 0, 0
2350: 0a 20 20 29 3b 0a 20 20 72 65 74 75 72 6e 20 54  .  );.  return T
2360: 43 4c 5f 4f 4b 3b 0a 7d 0a 23 65 6e 64 69 66 20  CL_OK;.}.#endif 
2370: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2380: 20 2f 2a 20 69 66 64 65 66 20 53 51 4c 49 54 45   /* ifdef SQLITE
2390: 5f 54 45 53 54 20 2a 2f 0a                       _TEST */.