modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/fts5/test/fts5merge.test (about)

     1  # 2014 Dec 20
     2  #
     3  # The author disclaims copyright to this source code.  In place of
     4  # a legal notice, here is a blessing:
     5  #
     6  #    May you do good and not evil.
     7  #    May you find forgiveness for yourself and forgive others.
     8  #    May you share freely, never taking more than you give.
     9  #
    10  #***********************************************************************
    11  #
    12  # Test that focus on incremental merges of segments.
    13  #
    14  
    15  source [file join [file dirname [info script]] fts5_common.tcl]
    16  set testprefix fts5merge
    17  
    18  # If SQLITE_ENABLE_FTS5 is defined, omit this file.
    19  ifcapable !fts5 {
    20    finish_test
    21    return
    22  }
    23  
    24  db func repeat [list string repeat]
    25  
    26  #-------------------------------------------------------------------------
    27  # Create an fts index so that:
    28  #
    29  #   * the index consists of two top-level segments
    30  #   * each segment contains records related to $nRowPerSeg rows
    31  #   * all rows consist of tokens "x" and "y" only.
    32  #
    33  # Then run ('merge', 1) until everything is completely merged.
    34  #
    35  proc do_merge1_test {testname nRowPerSeg} {
    36    set ::nRowPerSeg [expr $nRowPerSeg]
    37    do_execsql_test $testname.0 {
    38      DROP TABLE IF EXISTS x8;
    39      CREATE VIRTUAL TABLE x8 USING fts5(i);
    40      INSERT INTO x8(x8, rank) VALUES('pgsz', 32);
    41  
    42      WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
    43        INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
    44  
    45      WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
    46        INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
    47  
    48      INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
    49    }
    50  
    51    for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} {
    52      do_execsql_test $testname.$tn {
    53        INSERT INTO x8(x8, rank) VALUES('merge', 1);
    54        INSERT INTO x8(x8) VALUES('integrity-check');
    55      }
    56      if {$tn>5} break
    57    }
    58  
    59    do_test $testname.x [list expr "$tn < 5"] 1
    60  }
    61  
    62  do_merge1_test 1.1   1
    63  do_merge1_test 1.2   2
    64  do_merge1_test 1.3   3
    65  do_merge1_test 1.4   4
    66  do_merge1_test 1.5  10
    67  do_merge1_test 1.6  20
    68  do_merge1_test 1.7 100
    69  
    70  #-------------------------------------------------------------------------
    71  #
    72  proc do_merge2_test {testname nRow} {
    73    db func rnddoc fts5_rnddoc
    74  
    75    do_execsql_test $testname.0 {
    76      DROP TABLE IF EXISTS x8;
    77      CREATE VIRTUAL TABLE x8 USING fts5(i);
    78      INSERT INTO x8(x8, rank) VALUES('pgsz', 32);
    79    }
    80  
    81    set ::nRow $nRow
    82    do_test $testname.1 {
    83      for {set i 0} {$i < $::nRow} {incr i} {
    84        execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) }
    85        while {[not_merged x8]} {
    86          execsql {
    87            INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
    88            INSERT INTO x8(x8, rank) VALUES('merge', 1);
    89            INSERT INTO x8(x8, rank) VALUES('usermerge', 16);
    90            INSERT INTO x8(x8) VALUES('integrity-check');
    91          }
    92        }
    93      }
    94    } {}
    95  }
    96  proc not_merged {tbl} {
    97    set segs [fts5_level_segs $tbl]
    98    foreach s $segs { if {$s>1} { return 1 } }
    99    return 0
   100  }
   101  
   102  do_merge2_test 2.1    5
   103  do_merge2_test 2.2   10
   104  do_merge2_test 2.3   20
   105  
   106  #-------------------------------------------------------------------------
   107  # Test that a merge will complete any merge that has already been
   108  # started, even if the number of input segments is less than the current
   109  # value of the 'usermerge' configuration parameter.
   110  #
   111  db func rnddoc fts5_rnddoc
   112  
   113  do_execsql_test 3.1 {
   114    DROP TABLE IF EXISTS x8;
   115    CREATE VIRTUAL TABLE x8 USING fts5(i);
   116    INSERT INTO x8(x8, rank) VALUES('pgsz', 32);
   117    INSERT INTO x8 VALUES(rnddoc(100));
   118    INSERT INTO x8 VALUES(rnddoc(100));
   119  }
   120  do_test 3.2 {
   121    execsql {
   122      INSERT INTO x8(x8, rank) VALUES('usermerge', 4);
   123      INSERT INTO x8(x8, rank) VALUES('merge', 1);
   124    }
   125    fts5_level_segs x8
   126  } {2}
   127  
   128  do_test 3.3 {
   129    execsql {
   130      INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
   131      INSERT INTO x8(x8, rank) VALUES('merge', 1);
   132    }
   133    fts5_level_segs x8
   134  } {2 1}
   135  
   136  do_test 3.4 {
   137    execsql { INSERT INTO x8(x8, rank) VALUES('usermerge', 4) }
   138    while {[not_merged x8]} {
   139      execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) }
   140    }
   141    fts5_level_segs x8
   142  } {0 1}
   143  
   144  #-------------------------------------------------------------------------
   145  #
   146  proc mydoc {} {
   147    set x [lindex {a b c d e f g h i j} [expr int(rand()*10)]]
   148    return [string repeat "$x " 30]
   149  }
   150  db func mydoc mydoc
   151  
   152  proc mycount {} {
   153    set res [list]
   154    foreach x {a b c d e f g h i j} {
   155      lappend res [db one {SELECT count(*) FROM x8 WHERE x8 MATCH $x}]
   156    }
   157    set res
   158  }
   159  
   160    #1 32
   161  foreach {tn pgsz} {
   162    2 1000
   163  } {
   164    do_execsql_test 4.$tn.1 {
   165      DROP TABLE IF EXISTS x8;
   166      CREATE VIRTUAL TABLE x8 USING fts5(i);
   167      INSERT INTO x8(x8, rank) VALUES('pgsz', $pgsz);
   168    }
   169  
   170    do_execsql_test 4.$tn.2 {
   171      INSERT INTO x8(x8, rank) VALUES('merge', 1);
   172    }
   173  
   174    do_execsql_test 4.$tn.3 {
   175      WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
   176        INSERT INTO x8 SELECT mydoc() FROM ii;
   177      WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
   178        INSERT INTO x8 SELECT mydoc() FROM ii;
   179      INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
   180    }
   181  
   182    set expect [mycount]
   183      for {set i 0} {$i < 20} {incr i} {
   184        do_test 4.$tn.4.$i {
   185          execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1); }
   186          mycount
   187        } $expect
   188        break
   189      }
   190  #  db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r }
   191  }
   192  
   193  #-------------------------------------------------------------------------
   194  # Test that the 'merge' command does not modify the database if there is
   195  # no work to do. 
   196  
   197  do_execsql_test 5.1 {
   198    CREATE VIRTUAL TABLE x9 USING fts5(one, two);
   199    INSERT INTO x9(x9, rank) VALUES('pgsz', 32);
   200    INSERT INTO x9(x9, rank) VALUES('automerge', 2);
   201    INSERT INTO x9(x9, rank) VALUES('usermerge', 2);
   202    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   203    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   204    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   205    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   206    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   207    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   208    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   209    INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
   210  }
   211  
   212  do_test 5.2 {
   213    while 1 {
   214      set nChange [db total_changes]
   215      execsql { INSERT INTO x9(x9, rank) VALUES('merge', 1); }
   216      set nChange [expr [db total_changes] - $nChange]
   217      #puts $nChange
   218      if {$nChange<2} break
   219    }
   220  } {}
   221  
   222  
   223  #--------------------------------------------------------------------------
   224  # Test that running 'merge' on an empty database does not cause a 
   225  # problem.
   226  #
   227  reset_db
   228  do_execsql_test 6.0 {
   229    CREATE VIRTUAL TABLE g1 USING fts5(a, b);
   230  }
   231  do_execsql_test 6.1 {
   232    INSERT INTO g1(g1, rank) VALUES('merge', 10);
   233  }
   234  do_execsql_test 6.2 {
   235    INSERT INTO g1(g1, rank) VALUES('merge', -10);
   236  }
   237  do_execsql_test 6.3 {
   238    INSERT INTO g1(g1) VALUES('integrity-check');
   239  }
   240  
   241  
   242  
   243  finish_test