/ Check-in [89f2f482]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Modify fts3rnd.test to run tests for both "ORDER BY docid ASC" and "ORDER BY docid DESC" with both order=ASC and order=DESC FTS tables. Fixes for some bugs found.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fts3-prefix-search
Files: files | file ages | folders
SHA1: 89f2f482e077241ac29a58eadf44a72a9c01f98c
User & Date: dan 2011-06-06 14:51:50
Context
2011-06-06
18:14
Merge the latest trunk changes into the fts3-prefix-search branch. check-in: 567dd843 user: drh tags: fts3-prefix-search
14:51
Modify fts3rnd.test to run tests for both "ORDER BY docid ASC" and "ORDER BY docid DESC" with both order=ASC and order=DESC FTS tables. Fixes for some bugs found. check-in: 89f2f482 user: dan tags: fts3-prefix-search
06:55
Clean up the code for processing FTS4 options a bit. check-in: 0425138a user: dan tags: fts3-prefix-search
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to ext/fts3/fts3.c.

  1140   1140     if( rc!=SQLITE_OK ){
  1141   1141       if( p ){
  1142   1142         fts3DisconnectMethod((sqlite3_vtab *)p);
  1143   1143       }else if( pTokenizer ){
  1144   1144         pTokenizer->pModule->xDestroy(pTokenizer);
  1145   1145       }
  1146   1146     }else{
         1147  +    assert( p->pSegments==0 );
  1147   1148       *ppVTab = &p->base;
  1148   1149     }
  1149   1150     return rc;
  1150   1151   }
  1151   1152   
  1152   1153   /*
  1153   1154   ** The xConnect() and xCreate() methods for the virtual table. All the
................................................................................
  1241   1242         }else{
  1242   1243           pInfo->idxStr = "ASC";
  1243   1244         }
  1244   1245         pInfo->orderByConsumed = 1;
  1245   1246       }
  1246   1247     }
  1247   1248   
         1249  +  assert( p->pSegments==0 );
  1248   1250     return SQLITE_OK;
  1249   1251   }
  1250   1252   
  1251   1253   /*
  1252   1254   ** Implementation of xOpen method.
  1253   1255   */
  1254   1256   static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
................................................................................
  1276   1278     Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
  1277   1279     assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  1278   1280     sqlite3_finalize(pCsr->pStmt);
  1279   1281     sqlite3Fts3ExprFree(pCsr->pExpr);
  1280   1282     sqlite3Fts3FreeDeferredTokens(pCsr);
  1281   1283     sqlite3_free(pCsr->aDoclist);
  1282   1284     sqlite3_free(pCsr->aMatchinfo);
         1285  +  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  1283   1286     sqlite3_free(pCsr);
  1284   1287     return SQLITE_OK;
  1285   1288   }
  1286   1289   
  1287   1290   /*
  1288   1291   ** Position the pCsr->pStmt statement so that it is on the row
  1289   1292   ** of the %_content table that contains the last match.  Return
................................................................................
  2560   2563       }else{
  2561   2564         pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
  2562   2565         rc = SQLITE_OK;
  2563   2566       }
  2564   2567     }else{
  2565   2568       rc = sqlite3Fts3EvalNext((Fts3Cursor *)pCursor);
  2566   2569     }
         2570  +  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  2567   2571     return rc;
  2568   2572   }
  2569   2573   
  2570   2574   /*
  2571   2575   ** This is the xFilter interface for the virtual table.  See
  2572   2576   ** the virtual table xFilter method documentation for additional
  2573   2577   ** information.
................................................................................
  2697   2701   ** the row that the supplied cursor currently points to.
  2698   2702   */
  2699   2703   static int fts3ColumnMethod(
  2700   2704     sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
  2701   2705     sqlite3_context *pContext,      /* Context for sqlite3_result_xxx() calls */
  2702   2706     int iCol                        /* Index of column to read value from */
  2703   2707   ){
  2704         -  int rc;                         /* Return Code */
         2708  +  int rc = SQLITE_OK;             /* Return Code */
  2705   2709     Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
  2706   2710     Fts3Table *p = (Fts3Table *)pCursor->pVtab;
  2707   2711   
  2708   2712     /* The column value supplied by SQLite must be in range. */
  2709   2713     assert( iCol>=0 && iCol<=p->nColumn+1 );
  2710   2714   
  2711   2715     if( iCol==p->nColumn+1 ){
  2712   2716       /* This call is a request for the "docid" column. Since "docid" is an 
  2713   2717       ** alias for "rowid", use the xRowid() method to obtain the value.
  2714   2718       */
  2715         -    sqlite3_int64 iRowid;
  2716         -    rc = fts3RowidMethod(pCursor, &iRowid);
  2717         -    sqlite3_result_int64(pContext, iRowid);
         2719  +    sqlite3_result_int64(pContext, pCsr->iPrevId);
  2718   2720     }else if( iCol==p->nColumn ){
  2719   2721       /* The extra column whose name is the same as the table.
  2720   2722       ** Return a blob which is a pointer to the cursor.
  2721   2723       */
  2722   2724       sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
  2723         -    rc = SQLITE_OK;
  2724   2725     }else{
  2725   2726       rc = fts3CursorSeek(0, pCsr);
  2726   2727       if( rc==SQLITE_OK ){
  2727   2728         sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
  2728   2729       }
  2729   2730     }
         2731  +
         2732  +  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  2730   2733     return rc;
  2731   2734   }
  2732   2735   
  2733   2736   /* 
  2734   2737   ** This function is the implementation of the xUpdate callback used by 
  2735   2738   ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
  2736   2739   ** inserted, updated or deleted.
................................................................................
  2756   2759   
  2757   2760   /*
  2758   2761   ** Implementation of xBegin() method. This is a no-op.
  2759   2762   */
  2760   2763   static int fts3BeginMethod(sqlite3_vtab *pVtab){
  2761   2764     UNUSED_PARAMETER(pVtab);
  2762   2765     TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
         2766  +  assert( p->pSegments==0 );
  2763   2767     assert( p->nPendingData==0 );
  2764   2768     assert( p->inTransaction!=1 );
  2765   2769     TESTONLY( p->inTransaction = 1 );
  2766   2770     TESTONLY( p->mxSavepoint = -1; );
  2767   2771     return SQLITE_OK;
  2768   2772   }
  2769   2773   
................................................................................
  2773   2777   ** by fts3SyncMethod().
  2774   2778   */
  2775   2779   static int fts3CommitMethod(sqlite3_vtab *pVtab){
  2776   2780     UNUSED_PARAMETER(pVtab);
  2777   2781     TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  2778   2782     assert( p->nPendingData==0 );
  2779   2783     assert( p->inTransaction!=0 );
         2784  +  assert( p->pSegments==0 );
  2780   2785     TESTONLY( p->inTransaction = 0 );
  2781   2786     TESTONLY( p->mxSavepoint = -1; );
  2782   2787     return SQLITE_OK;
  2783   2788   }
  2784   2789   
  2785   2790   /*
  2786   2791   ** Implementation of xRollback(). Discard the contents of the pending-terms
................................................................................
  3043   3048   }
  3044   3049   
  3045   3050   static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
  3046   3051     Fts3Table *p = (Fts3Table*)pVtab;
  3047   3052     assert( p->inTransaction );
  3048   3053     assert( p->mxSavepoint < iSavepoint );
  3049   3054     TESTONLY( p->mxSavepoint = iSavepoint );
  3050         -  return sqlite3Fts3PendingTermsFlush(p);
         3055  +  return fts3SyncMethod(pVtab);
  3051   3056   }
  3052   3057   static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  3053   3058     TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  3054   3059     assert( p->inTransaction );
  3055   3060     assert( p->mxSavepoint >= iSavepoint );
  3056   3061     TESTONLY( p->mxSavepoint = iSavepoint-1 );
  3057   3062     return SQLITE_OK;
................................................................................
  3455   3460       p->bIncr = 0;
  3456   3461     }
  3457   3462   
  3458   3463     assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr );
  3459   3464     return rc;
  3460   3465   }
  3461   3466   
         3467  +/*
         3468  +** This function is used to iterate backwards (from the end to start) 
         3469  +** through doclists.
         3470  +*/
  3462   3471   void sqlite3Fts3DoclistPrev(
  3463   3472     int bDescIdx,                   /* True if the doclist is desc */
  3464   3473     char *aDoclist,                 /* Pointer to entire doclist */
  3465   3474     int nDoclist,                   /* Length of aDoclist in bytes */
  3466   3475     char **ppIter,                  /* IN/OUT: Iterator pointer */
  3467   3476     sqlite3_int64 *piDocid,         /* IN/OUT: Docid pointer */
  3468   3477     int *pnList,                    /* IN/OUT: List length pointer */
  3469   3478     u8 *pbEof                       /* OUT: End-of-file flag */
  3470   3479   ){
  3471   3480     char *p = *ppIter;
  3472   3481     int iMul = (bDescIdx ? -1 : 1);
  3473   3482   
         3483  +  assert( nDoclist>0 );
  3474   3484     assert( *pbEof==0 );
  3475   3485     assert( p || *piDocid==0 );
  3476   3486     assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
  3477   3487   
  3478   3488     if( p==0 ){
  3479   3489       sqlite3_int64 iDocid = 0;
  3480   3490       char *pNext = 0;
................................................................................
  3533   3543       assert( p->nToken==1 );
  3534   3544       rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, 
  3535   3545           &pDL->iDocid, &pDL->pList, &pDL->nList
  3536   3546       );
  3537   3547       if( rc==SQLITE_OK && !pDL->pList ){
  3538   3548         *pbEof = 1;
  3539   3549       }
  3540         -  }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->aAll ){
         3550  +  }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
  3541   3551       sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, 
  3542   3552           &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
  3543   3553       );
  3544   3554       pDL->pList = pDL->pNextDocid;
  3545   3555     }else{
  3546   3556       char *pIter;
  3547   3557       if( pDL->pNextDocid ){
................................................................................
  3875   3885   
  3876   3886   static void fts3EvalNext(
  3877   3887     Fts3Cursor *pCsr, 
  3878   3888     Fts3Expr *pExpr, 
  3879   3889     int *pRc
  3880   3890   ){
  3881   3891     if( *pRc==SQLITE_OK ){
         3892  +    assert( pExpr->bEof==0 );
  3882   3893       pExpr->bStart = 1;
  3883   3894   
  3884   3895       switch( pExpr->eType ){
  3885   3896         case FTSQUERY_NEAR:
  3886   3897         case FTSQUERY_AND: {
  3887   3898           Fts3Expr *pLeft = pExpr->pLeft;
  3888   3899           Fts3Expr *pRight = pExpr->pRight;
................................................................................
  3897   3908             pExpr->iDocid = pLeft->iDocid;
  3898   3909             pExpr->bEof = pLeft->bEof;
  3899   3910           }else{
  3900   3911             fts3EvalNext(pCsr, pLeft, pRc);
  3901   3912             fts3EvalNext(pCsr, pRight, pRc);
  3902   3913   
  3903   3914             while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){
  3904         -            int iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
         3915  +            sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
  3905   3916               if( iDiff==0 ) break;
  3906   3917               if( iDiff<0 ){
  3907   3918                 fts3EvalNext(pCsr, pLeft, pRc);
  3908   3919               }else{
  3909   3920                 fts3EvalNext(pCsr, pRight, pRc);
  3910   3921               }
  3911   3922             }
................................................................................
  3915   3926           }
  3916   3927           break;
  3917   3928         }
  3918   3929     
  3919   3930         case FTSQUERY_OR: {
  3920   3931           Fts3Expr *pLeft = pExpr->pLeft;
  3921   3932           Fts3Expr *pRight = pExpr->pRight;
  3922         -        int iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
         3933  +        sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
  3923   3934   
  3924   3935           assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
  3925   3936           assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
  3926   3937   
  3927         -        if( iCmp==0 ){
         3938  +        if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
  3928   3939             fts3EvalNext(pCsr, pLeft, pRc);
         3940  +        }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
  3929   3941             fts3EvalNext(pCsr, pRight, pRc);
  3930         -        }else if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
  3931         -          fts3EvalNext(pCsr, pLeft, pRc);
  3932   3942           }else{
         3943  +          fts3EvalNext(pCsr, pLeft, pRc);
  3933   3944             fts3EvalNext(pCsr, pRight, pRc);
  3934   3945           }
  3935   3946     
  3936   3947           pExpr->bEof = (pLeft->bEof && pRight->bEof);
  3937   3948           iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
  3938   3949           if( pRight->bEof || (pLeft->bEof==0 &&  iCmp<0) ){
  3939   3950             pExpr->iDocid = pLeft->iDocid;
................................................................................
  3968   3979         }
  3969   3980   
  3970   3981         default: {
  3971   3982           Fts3Phrase *pPhrase = pExpr->pPhrase;
  3972   3983           fts3EvalFreeDeferredDoclist(pPhrase);
  3973   3984           *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof);
  3974   3985           pExpr->iDocid = pPhrase->doclist.iDocid;
         3986  +#if 0
         3987  +        printf("token \"%.*s\" docid=%lld\n", 
         3988  +            pPhrase->aToken[0].n, pPhrase->aToken[0].z, pExpr->iDocid
         3989  +        );
         3990  +#endif
         3991  +        
  3975   3992           break;
  3976   3993         }
  3977   3994       }
  3978   3995     }
  3979   3996   }
  3980   3997   
  3981   3998   static int fts3EvalDeferredTest(Fts3Cursor *pCsr, Fts3Expr *pExpr, int *pRc){
................................................................................
  4119   4136   
  4120   4137       rc = sqlite3Fts3EvalStart(pCsr, pExpr, 0);
  4121   4138       assert( pExpr->bEof==bEof );
  4122   4139       assert( pExpr->bStart==bStart );
  4123   4140       assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
  4124   4141       if( pExpr->bStart && !pExpr->bEof ){
  4125   4142         pExpr->bStart = 0;
  4126         -      while( rc==SQLITE_OK && pExpr->bEof==0 && pExpr->iDocid!=iDocid ){
         4143  +      while( rc==SQLITE_OK && (pExpr->bStart==0 || pExpr->iDocid!=iDocid) ){
  4127   4144           fts3EvalNext(pCsr, pExpr, &rc);
         4145  +        assert( !pExpr->bEof );
  4128   4146         }
  4129   4147       }
  4130   4148     }
  4131   4149   
  4132   4150     *pnList = pPhrase->doclist.nAll;
  4133   4151     *ppList = pPhrase->doclist.aAll;
  4134   4152     return rc;

Changes to ext/fts3/fts3_write.c.

  3155   3155     sqlite3_value **apVal,          /* Array of arguments */
  3156   3156     sqlite_int64 *pRowid            /* OUT: The affected (or effected) rowid */
  3157   3157   ){
  3158   3158     Fts3Table *p = (Fts3Table *)pVtab;
  3159   3159     int rc = SQLITE_OK;             /* Return Code */
  3160   3160     int isRemove = 0;               /* True for an UPDATE or DELETE */
  3161   3161     sqlite3_int64 iRemove = 0;      /* Rowid removed by UPDATE or DELETE */
  3162         -  u32 *aSzIns;                    /* Sizes of inserted documents */
         3162  +  u32 *aSzIns = 0;                /* Sizes of inserted documents */
  3163   3163     u32 *aSzDel;                    /* Sizes of deleted documents */
  3164   3164     int nChng = 0;                  /* Net change in number of documents */
  3165   3165     int bInsertDone = 0;
  3166   3166   
  3167   3167     assert( p->pSegments==0 );
  3168   3168   
  3169   3169     /* Check for a "special" INSERT operation. One of the form:
................................................................................
  3170   3170     **
  3171   3171     **   INSERT INTO xyz(xyz) VALUES('command');
  3172   3172     */
  3173   3173     if( nArg>1 
  3174   3174      && sqlite3_value_type(apVal[0])==SQLITE_NULL 
  3175   3175      && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL 
  3176   3176     ){
  3177         -    return fts3SpecialInsert(p, apVal[p->nColumn+2]);
         3177  +    rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
         3178  +    goto update_out;
  3178   3179     }
  3179   3180   
  3180   3181     /* Allocate space to hold the change in document sizes */
  3181   3182     aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
  3182         -  if( aSzIns==0 ) return SQLITE_NOMEM;
         3183  +  if( aSzIns==0 ){
         3184  +    rc = SQLITE_NOMEM;
         3185  +    goto update_out;
         3186  +  }
  3183   3187     aSzDel = &aSzIns[p->nColumn+1];
  3184   3188     memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
  3185   3189   
  3186   3190     /* If this is an INSERT operation, or an UPDATE that modifies the rowid
  3187   3191     ** value, then this operation requires constraint handling.
  3188   3192     **
  3189   3193     ** If the on-conflict mode is REPLACE, this means that the existing row
................................................................................
  3225   3229         }else{
  3226   3230           rc = fts3InsertData(p, apVal, pRowid);
  3227   3231           bInsertDone = 1;
  3228   3232         }
  3229   3233       }
  3230   3234     }
  3231   3235     if( rc!=SQLITE_OK ){
  3232         -    sqlite3_free(aSzIns);
  3233         -    return rc;
         3236  +    goto update_out;
  3234   3237     }
  3235   3238   
  3236   3239     /* If this is a DELETE or UPDATE operation, remove the old record. */
  3237   3240     if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
  3238   3241       assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
  3239   3242       rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
  3240   3243       isRemove = 1;
................................................................................
  3259   3262       nChng++;
  3260   3263     }
  3261   3264   
  3262   3265     if( p->bHasStat ){
  3263   3266       fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng);
  3264   3267     }
  3265   3268   
         3269  + update_out:
  3266   3270     sqlite3_free(aSzIns);
  3267   3271     sqlite3Fts3SegmentsClose(p);
  3268   3272     return rc;
  3269   3273   }
  3270   3274   
  3271   3275   /* 
  3272   3276   ** Flush any data in the pending-terms hash table to disk. If successful,

Changes to test/fts3rnd.test.

   158    158   
   159    159     #lsort -uniq -integer $ret
   160    160     set ret
   161    161   }
   162    162   
   163    163   # This [proc] is used to test the FTS3 matchinfo() function.
   164    164   # 
   165         -proc simple_token_matchinfo {zToken} {
          165  +proc simple_token_matchinfo {zToken bDesc} {
   166    166   
   167    167     set nDoc(0) 0
   168    168     set nDoc(1) 0
   169    169     set nDoc(2) 0
   170    170     set nHit(0) 0
   171    171     set nHit(1) 0
   172    172     set nHit(2) 0
   173    173   
          174  +  set dir -inc
          175  +  if {$bDesc} { set dir -dec }
   174    176   
   175    177     foreach key [array names ::t1] {
   176    178       set value $::t1($key)
   177    179       set a($key) [list]
   178    180       foreach i {0 1 2} col $value {
   179    181         set hit [llength [lsearch -all $col $zToken]]
   180    182         lappend a($key) $hit
   181    183         incr nHit($i) $hit
   182    184         if {$hit>0} { incr nDoc($i) }
   183    185       }
   184    186     }
   185    187   
   186    188     set ret [list]
   187         -  foreach docid [lsort -integer [array names a]] {
          189  +  foreach docid [lsort -integer $dir [array names a]] {
   188    190       if { [lindex [lsort -integer $a($docid)] end] } {
   189    191         set matchinfo [list 1 3]
   190    192         foreach i {0 1 2} hit $a($docid) {
   191    193           lappend matchinfo $hit $nHit($i) $nDoc($i)
   192    194         }
   193    195         lappend ret $docid $matchinfo
   194    196       }
................................................................................
   258    260   proc mit {blob} {
   259    261     set scan(littleEndian) i*
   260    262     set scan(bigEndian) I*
   261    263     binary scan $blob $scan($::tcl_platform(byteOrder)) r
   262    264     return $r
   263    265   }
   264    266   db func mit mit
   265         -
   266    267   set sqlite_fts3_enable_parentheses 1
   267    268   
   268         -foreach nodesize {50 500 1000 2000} {
          269  +proc do_orderbydocid_test {tn sql res} {
          270  +  uplevel [list do_select_test $tn.asc "$sql ORDER BY docid ASC" $res]
          271  +  uplevel [list do_select_test $tn.desc "$sql ORDER BY docid DESC" \
          272  +    [lsort -int -dec $res]
          273  +  ]
          274  +}
          275  +
          276  +foreach {nodesize order} {
          277  +  50    DESC
          278  +  50    ASC
          279  +  500   ASC
          280  +  1000  DESC
          281  +  2000  ASC
          282  +} {
   269    283     catch { array unset ::t1 }
          284  +  set testname "$nodesize/$order"
   270    285   
   271    286     # Create the FTS3 table. Populate it (and the Tcl array) with 100 rows.
   272    287     #
   273    288     db transaction {
   274    289       catchsql { DROP TABLE t1 }
   275         -    execsql "CREATE VIRTUAL TABLE t1 USING fts3(a, b, c)"
          290  +    execsql "CREATE VIRTUAL TABLE t1 USING fts4(a, b, c, order=$order)"
   276    291       execsql "INSERT INTO t1(t1) VALUES('nodesize=$nodesize')"
   277    292       for {set i 0} {$i < 100} {incr i} { insert_row $i }
   278    293     }
   279    294     
   280    295     for {set iTest 1} {$iTest <= 100} {incr iTest} {
   281    296       catchsql COMMIT
   282    297   
   283    298       set DO_MALLOC_TEST 0
   284    299       set nRep 10
   285    300       if {$iTest==100 && $nodesize==50} { 
   286    301         set DO_MALLOC_TEST 1 
   287    302         set nRep 2
   288    303       }
          304  +
          305  +    set ::testprefix fts3rnd-1.$testname.$iTest
   289    306     
   290    307       # Delete one row, update one row and insert one row.
   291    308       #
   292    309       set rows [array names ::t1]
   293    310       set nRow [llength $rows]
   294    311       set iUpdate [lindex $rows [expr {int(rand()*$nRow)}]]
   295    312       set iDelete $iUpdate
................................................................................
   303    320       execsql BEGIN
   304    321         insert_row $iInsert
   305    322         update_row $iUpdate
   306    323         delete_row $iDelete
   307    324       if {0==($iTest%2)} { execsql COMMIT }
   308    325   
   309    326       if {0==($iTest%2)} { 
   310         -      do_test fts3rnd-1.$nodesize.$iTest.0 { fts3_integrity_check t1 } ok 
          327  +      #do_test 0 { fts3_integrity_check t1 } ok 
   311    328       }
   312    329   
   313    330       # Pick 10 terms from the vocabulary. Check that the results of querying
   314    331       # the database for the set of documents containing each of these terms
   315    332       # is the same as the result obtained by scanning the contents of the Tcl 
   316    333       # array for each term.
   317    334       #
   318    335       for {set i 0} {$i < 10} {incr i} {
   319    336         set term [random_term]
   320         -      do_select_test fts3rnd-1.$nodesize.$iTest.1.$i {
          337  +      do_select_test 1.$i {
          338  +        SELECT docid, mit(matchinfo(t1)) FROM t1 WHERE t1 MATCH $term
          339  +        ORDER BY docid ASC
          340  +      } [simple_token_matchinfo $term 0]
          341  +      do_select_test 1.$i {
   321    342           SELECT docid, mit(matchinfo(t1)) FROM t1 WHERE t1 MATCH $term
   322         -      } [simple_token_matchinfo $term]
          343  +        ORDER BY docid DESC
          344  +      } [simple_token_matchinfo $term 1]
   323    345       }
   324    346   
   325    347       # This time, use the first two characters of each term as a term prefix
   326    348       # to query for. Test that querying the Tcl array produces the same results
   327    349       # as querying the FTS3 table for the prefix.
   328    350       #
   329    351       for {set i 0} {$i < $nRep} {incr i} {
   330    352         set prefix [string range [random_term] 0 end-1]
   331    353         set match "${prefix}*"
   332         -      do_select_test fts3rnd-1.$nodesize.$iTest.2.$i {
          354  +      do_orderbydocid_test 2.$i {
   333    355           SELECT docid FROM t1 WHERE t1 MATCH $match
   334    356         } [simple_phrase $match]
   335    357       }
   336    358   
   337    359       # Similar to the above, except for phrase queries.
   338    360       #
   339    361       for {set i 0} {$i < $nRep} {incr i} {
   340    362         set term [list [random_term] [random_term]]
   341    363         set match "\"$term\""
   342         -      do_select_test fts3rnd-1.$nodesize.$iTest.3.$i {
          364  +      do_orderbydocid_test 3.$i {
   343    365           SELECT docid FROM t1 WHERE t1 MATCH $match
   344    366         } [simple_phrase $term]
   345    367       }
   346    368   
   347    369       # Three word phrases.
   348    370       #
   349    371       for {set i 0} {$i < $nRep} {incr i} {
   350    372         set term [list [random_term] [random_term] [random_term]]
   351    373         set match "\"$term\""
   352         -      do_select_test fts3rnd-1.$nodesize.$iTest.4.$i {
          374  +      do_orderbydocid_test 4.$i {
   353    375           SELECT docid FROM t1 WHERE t1 MATCH $match
   354    376         } [simple_phrase $term]
   355    377       }
   356    378   
   357    379       # Three word phrases made up of term-prefixes.
   358    380       #
   359    381       for {set i 0} {$i < $nRep} {incr i} {
   360    382         set    query "[string range [random_term] 0 end-1]* "
   361    383         append query "[string range [random_term] 0 end-1]* "
   362    384         append query "[string range [random_term] 0 end-1]*"
   363    385   
   364    386         set match "\"$query\""
   365         -      do_select_test fts3rnd-1.$nodesize.$iTest.5.$i {
          387  +      do_orderbydocid_test 5.$i {
   366    388           SELECT docid FROM t1 WHERE t1 MATCH $match
   367    389         } [simple_phrase $query]
   368    390       }
   369    391   
   370         -    # A NEAR query with terms as the arguments.
          392  +    # A NEAR query with terms as the arguments:
          393  +    #
          394  +    #     ... MATCH '$term1 NEAR $term2' ...
   371    395       #
   372    396       for {set i 0} {$i < $nRep} {incr i} {
   373    397         set terms [list [random_term] [random_term]]
   374    398         set match [join $terms " NEAR "]
   375         -      do_select_test fts3rnd-1.$nodesize.$iTest.6.$i {
          399  +      do_orderbydocid_test 6.$i {
   376    400           SELECT docid FROM t1 WHERE t1 MATCH $match 
   377    401         } [simple_near $terms 10]
   378    402       }
   379    403   
   380    404       # A 3-way NEAR query with terms as the arguments.
   381    405       #
   382    406       for {set i 0} {$i < $nRep} {incr i} {
   383    407         set terms [list [random_term] [random_term] [random_term]]
   384    408         set nNear 11
   385    409         set match [join $terms " NEAR/$nNear "]
   386         -      do_select_test fts3rnd-1.$nodesize.$iTest.7.$i {
          410  +      do_orderbydocid_test 7.$i {
   387    411           SELECT docid FROM t1 WHERE t1 MATCH $match
   388    412         } [simple_near $terms $nNear]
   389    413       }
   390    414       
   391    415       # Set operations on simple term queries.
   392    416       #
   393    417       foreach {tn op proc} {
................................................................................
   395    419         9  NOT setop_not
   396    420         10 AND setop_and
   397    421       } {
   398    422         for {set i 0} {$i < $nRep} {incr i} {
   399    423           set term1 [random_term]
   400    424           set term2 [random_term]
   401    425           set match "$term1 $op $term2"
   402         -        do_select_test fts3rnd-1.$nodesize.$iTest.$tn.$i {
          426  +        do_orderbydocid_test $tn.$i {
   403    427             SELECT docid FROM t1 WHERE t1 MATCH $match
   404    428           } [$proc [simple_phrase $term1] [simple_phrase $term2]]
   405    429         }
   406    430       }
   407    431    
   408    432       # Set operations on NEAR queries.
   409    433       #
................................................................................
   414    438       } {
   415    439         for {set i 0} {$i < $nRep} {incr i} {
   416    440           set term1 [random_term]
   417    441           set term2 [random_term]
   418    442           set term3 [random_term]
   419    443           set term4 [random_term]
   420    444           set match "$term1 NEAR $term2 $op $term3 NEAR $term4"
   421         -        do_select_test fts3rnd-1.$nodesize.$iTest.$tn.$i {
          445  +        do_orderbydocid_test $tn.$i {
   422    446             SELECT docid FROM t1 WHERE t1 MATCH $match
   423    447           } [$proc                                  \
   424    448               [simple_near [list $term1 $term2] 10] \
   425    449               [simple_near [list $term3 $term4] 10]
   426    450             ]
   427    451         }
   428    452       }
   429    453   
   430    454       catchsql COMMIT
   431    455     }
   432    456   }
   433    457   
   434    458   finish_test