/ Check-in [69c21ee4]
Login

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

Overview
Comment:Modify [2ad1461f25] to avoid leaving a prepared statement in "active" state following an OOM error in FTS3.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 69c21ee46aeeb624fd8638b17ff7259a3e5f9a46
User & Date: dan 2009-12-04 14:11:34
Context
2009-12-04
14:25
In the OSTRACE debugging macros in os_unix.c, identify the VFS currently in use. check-in: 082b8da0 user: drh tags: trunk
14:11
Modify [2ad1461f25] to avoid leaving a prepared statement in "active" state following an OOM error in FTS3. check-in: 69c21ee4 user: dan tags: trunk
13:43
Fix an FTS3 problem where an OOM error was not being propagated back out to the top-level interface. check-in: 2ad1461f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

1553
1554
1555
1556
1557
1558
1559

1560
1561
1562
1563
1564
1565








1566
1567

1568
1569
1570
1571
1572
1573
1574
    if( sqlite3_column_int64(pStmt, 1)==0 ){
      /* The entire segment is stored on the root node (which must be a
      ** leaf). Do not bother inspecting any data in this case, just
      ** create a Fts3SegReader to scan the single leaf. 
      */
      rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew);
    }else{

      sqlite3_int64 i1;
      rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1);
      if( rc==SQLITE_OK ){
        sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2);
        rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew);
      }








      if( rc==SQLITE_OK ){
        rc = sqlite3Fts3ReadBlock(p, 0, 0, 0);

      }
    }
    iAge++;

    /* If a new Fts3SegReader was allocated, add it to the apSegment array. */
    assert( pNew!=0 || rc!=SQLITE_OK );
    if( pNew ){







>
|





>
>
>
>
>
>
>
>

<
>







1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1583
    if( sqlite3_column_int64(pStmt, 1)==0 ){
      /* The entire segment is stored on the root node (which must be a
      ** leaf). Do not bother inspecting any data in this case, just
      ** create a Fts3SegReader to scan the single leaf. 
      */
      rc = sqlite3Fts3SegReaderNew(p, iAge, 0, 0, 0, zRoot, nRoot, &pNew);
    }else{
      int rc2;                    /* Return value of sqlite3Fts3ReadBlock() */
      sqlite3_int64 i1;           /* Blockid of leaf that may contain zTerm */
      rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &i1);
      if( rc==SQLITE_OK ){
        sqlite3_int64 i2 = sqlite3_column_int64(pStmt, 2);
        rc = sqlite3Fts3SegReaderNew(p, iAge, i1, i2, 0, 0, 0, &pNew);
      }

      /* The following call to ReadBlock() serves to reset the SQL statement
      ** used to retrieve blocks of data from the %_segments table. If it is
      ** not reset here, then it may remain classified as an active statement 
      ** by SQLite, which may lead to "DROP TABLE" or "DETACH" commands 
      ** failing.
      */ 
      rc2 = sqlite3Fts3ReadBlock(p, 0, 0, 0);
      if( rc==SQLITE_OK ){

        rc = rc2;
      }
    }
    iAge++;

    /* If a new Fts3SegReader was allocated, add it to the apSegment array. */
    assert( pNew!=0 || rc!=SQLITE_OK );
    if( pNew ){

Changes to test/fts3rnd.test.

74
75
76
77
78
79
80














81
82
83
84
85
86
87
...
112
113
114
115
116
117
118
119
120
121
122
123
124












125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144












145
146
147
148
proc simple_term {zTerm} {
  set ret [list]
  foreach {key value} [array get ::t1] {
    if {[string first $zTerm $value]>=0} { lappend ret $key }
  }
  lsort -integer $ret
}















foreach nodesize {50 500 1000 2000} {
  catch { array unset ::t1 }

  # Create the FTS3 table. Populate it (and the Tcl array) with 100 rows.
  #
  db transaction {
................................................................................
    }
  
    # Pick 10 terms from the vocabulary. Check that the results of querying
    # the database for the set of documents containing each of these terms
    # is the same as the result obtained by scanning the contents of the Tcl 
    # array for each term.
    #
    set n [expr {$iTest % ([llength $::lVocab]-10)}]
    foreach term [lrange $::lVocab $n [expr $n+10]] {
      do_test fts3rnd-1.$nodesize.$iTest.$term {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $term }
      } [simple_term $term]
    }













    # Similar to the above, except for phrase queries.
    #
    for {set i 0} {$i < 10} {incr i} {
      set term [list [random_term] [random_term]]
      set match "\"$term\""
      do_test fts3rnd-1.$nodesize.$iTest.$match {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
      } [simple_term $term]
    }
    
    # Three word phrases.
    #
    for {set i 0} {$i < 10} {incr i} {
      set term [list [random_term] [random_term] [random_term]]
      set match "\"$term\""
      do_test fts3rnd-1.$nodesize.$iTest.$match {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
      } [simple_term $term]
    }












  }
}

finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
|



>
>
>
>
>
>
>
>
>
>
>
>






|









|



>
>
>
>
>
>
>
>
>
>
>
>




74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
proc simple_term {zTerm} {
  set ret [list]
  foreach {key value} [array get ::t1] {
    if {[string first $zTerm $value]>=0} { lappend ret $key }
  }
  lsort -integer $ret
}

proc simple_prefix {zPrefix} {
  set ret [list]
  set pattern [format "*%s%s*" $zPrefix [
    string repeat {[a-z]} [expr {3-[string length $zPrefix]}]
  ]]
  foreach {key value} [array get ::t1] {
    if {[string match $pattern $value]} { lappend ret $key }
  }
  lsort -integer $ret
}

proc simple_near {termlist nNear} {
}

foreach nodesize {50 500 1000 2000} {
  catch { array unset ::t1 }

  # Create the FTS3 table. Populate it (and the Tcl array) with 100 rows.
  #
  db transaction {
................................................................................
    }
  
    # Pick 10 terms from the vocabulary. Check that the results of querying
    # the database for the set of documents containing each of these terms
    # is the same as the result obtained by scanning the contents of the Tcl 
    # array for each term.
    #
    for {set i 0} {$i < 10} {incr i} {
      set term [random_term]
      do_test fts3rnd-1.$nodesize.$iTest.1.$i {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $term }
      } [simple_term $term]
    }

    # This time, use the first two characters of each term as a term prefix
    # to query for. Test that querying the Tcl array produces the same results
    # as querying the FTS3 table for the prefix.
    #
    for {set i 0} {$i < 10} {incr i} {
      set prefix [string range [random_term] 0 1]
      set match "${prefix}*"
      do_test fts3rnd-1.$nodesize.$iTest.2.$i {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
      } [simple_prefix $prefix]
    }

    # Similar to the above, except for phrase queries.
    #
    for {set i 0} {$i < 10} {incr i} {
      set term [list [random_term] [random_term]]
      set match "\"$term\""
      do_test fts3rnd-1.$nodesize.$iTest.3.$i {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
      } [simple_term $term]
    }
    
    # Three word phrases.
    #
    for {set i 0} {$i < 10} {incr i} {
      set term [list [random_term] [random_term] [random_term]]
      set match "\"$term\""
      do_test fts3rnd-1.$nodesize.$iTest.4.$i {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
      } [simple_term $term]
    }

    # A NEAR query with terms as the arguments.
    #
if 0 {
    for {set i 0} {$i < 10} {incr i} {
      set terms [list [random_term] [random_term]]
      set match [join $terms " NEAR "]
      do_test fts3rnd-1.$nodesize.$iTest.5.$i {
        execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
      } [simple_near $terms 10]
    }
}
  }
}

finish_test