/ Check-in [dee1a0fd]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Modify handling of SQLITE_SCHEMA in fts2 code. An SQLITE_SCHEMA error may cause SQLite to reload the internal schema, deleting and recreating v-table objects. So the sqlite3_vtab structure can be deleted out from under a v-table implementation. (CVS 4151)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: dee1a0fd28e8341af6523ab0c5628b671d7d2811
User & Date: danielk1977 2007-07-02 10:16:50
Context
2007-07-02
19:31
Fix a comment typo reported on the mailing list. (CVS 4152) check-in: 25e6df9c user: drh tags: trunk
10:16
Modify handling of SQLITE_SCHEMA in fts2 code. An SQLITE_SCHEMA error may cause SQLite to reload the internal schema, deleting and recreating v-table objects. So the sqlite3_vtab structure can be deleted out from under a v-table implementation. (CVS 4151) check-in: dee1a0fd user: danielk1977 tags: trunk
2007-07-01
21:18
Remove an unnecessary temporary variable for clarity of presentation in a loop that GCC 4.2.0 is miscompiling. Ticket #2469. GCC 4.2.0 miscompiles this loop regardless of whether or not the temporary variable is used, but by removing the variable, we hope to make it easier to explain the problem to GCC maintainers. The error only appears if -ftree-vrp is used (which is turned on by -O2). (CVS 4150) check-in: 35ae398b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts2/fts2.c.

1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
....
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023




2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034

2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046

  while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
    sqlite3_stmt *pNewStmt;

    if( rc==SQLITE_BUSY ) continue;
    if( rc!=SQLITE_ERROR ) return rc;

    rc = sqlite3_reset(s);
    if( rc!=SQLITE_SCHEMA ) return SQLITE_ERROR;

    v->pFulltextStatements[iStmt] = NULL;   /* Still in s */
    rc = sql_get_statement(v, iStmt, &pNewStmt);
    if( rc!=SQLITE_OK ) goto err;
    *ppStmt = pNewStmt;

    rc = sqlite3_transfer_bindings(s, pNewStmt);
    if( rc!=SQLITE_OK ) goto err;

    rc = sqlite3_finalize(s);
    if( rc!=SQLITE_OK ) return rc;
    s = pNewStmt;
  }
  return rc;

 err:
  sqlite3_finalize(s);
  return rc;
}
................................................................................

  while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
    sqlite3_stmt *pNewStmt;

    if( rc==SQLITE_BUSY ) continue;
    if( rc!=SQLITE_ERROR ) return rc;

    rc = sqlite3_reset(s);
    if( rc!=SQLITE_SCHEMA ) return SQLITE_ERROR;





    v->pLeafSelectStmts[idx] = NULL;   /* Still in s */
    rc = sql_get_leaf_statement(v, idx, &pNewStmt);
    if( rc!=SQLITE_OK ) goto err;
    *ppStmt = pNewStmt;

    rc = sqlite3_transfer_bindings(s, pNewStmt);
    if( rc!=SQLITE_OK ) goto err;

    rc = sqlite3_finalize(s);
    if( rc!=SQLITE_OK ) return rc;
    s = pNewStmt;

  }
  return rc;

 err:
  sqlite3_finalize(s);
  return rc;
}

/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */
static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
                          sqlite3_value **pValues){
  sqlite3_stmt *s;







|
|
|
|
|
|
|
|
|
<
<
<
<
<







 







|
|
<
>
>
>
>
|
<
<
<
<
<
<
<

<
<
>

<

<
<







1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958





1959
1960
1961
1962
1963
1964
1965
....
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018
2019
2020
2021
2022







2023


2024
2025

2026


2027
2028
2029
2030
2031
2032
2033

  while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
    sqlite3_stmt *pNewStmt;

    if( rc==SQLITE_BUSY ) continue;
    if( rc!=SQLITE_ERROR ) return rc;

    /* If an SQLITE_SCHEMA error has occured, then finalizing this
     * statement is going to delete the fulltext_vtab structure. If
     * the statement just executed is in the pFulltextStatements[]
     * array, it will be finalized twice. So remove it before
     * calling sqlite3_finalize().
     */
    v->pFulltextStatements[iStmt] = NULL;
    rc = sqlite3_finalize(s);
    break;





  }
  return rc;

 err:
  sqlite3_finalize(s);
  return rc;
}
................................................................................

  while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){
    sqlite3_stmt *pNewStmt;

    if( rc==SQLITE_BUSY ) continue;
    if( rc!=SQLITE_ERROR ) return rc;

    /* If an SQLITE_SCHEMA error has occured, then finalizing this
     * statement is going to delete the fulltext_vtab structure. If

     * the statement just executed is in the pLeafSelectStmts[]
     * array, it will be finalized twice. So remove it before
     * calling sqlite3_finalize().
     */
    v->pLeafSelectStmts[idx] = NULL;







    rc = sqlite3_finalize(s);


    break;
  }




  return rc;
}

/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */
static int content_insert(fulltext_vtab *v, sqlite3_value *rowid,
                          sqlite3_value **pValues){
  sqlite3_stmt *s;

Changes to test/fts2o.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
96
97
98
99
100
101
102



103
104



105



























































#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the FTS2 module.
#
# $Id: fts2o.test,v 1.3 2007/06/27 17:09:25 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS2 is not defined, omit this file.
ifcapable !fts2 {
................................................................................
do_test fts2o-2.11 {
  execsql { SELECT tbl_name FROM sqlite_master WHERE type = 'table'}
} {fts_t1 fts_t1_content fts_t1_segments fts_t1_segdir t1_segdir}
do_test fts2o-2.12 {
  execsql COMMIT
  execsql {SELECT a FROM fts_t1}
} {{one three four} {one two three}}




finish_test






































































|







 







>
>
>

<
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the FTS2 module.
#
# $Id: fts2o.test,v 1.4 2007/07/02 10:16:50 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS2 is not defined, omit this file.
ifcapable !fts2 {
................................................................................
do_test fts2o-2.11 {
  execsql { SELECT tbl_name FROM sqlite_master WHERE type = 'table'}
} {fts_t1 fts_t1_content fts_t1_segments fts_t1_segdir t1_segdir}
do_test fts2o-2.12 {
  execsql COMMIT
  execsql {SELECT a FROM fts_t1}
} {{one three four} {one two three}}
do_test fts2o-2.12 {
  execsql { SELECT a, b, c FROM fts_t1 WHERE c MATCH 'four'; }
} {{one three four} {one four} {one four two}}


#-------------------------------------------------------------------
# Close, delete and reopen the database. The following test should 
# be run on an initially empty db.
#
db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test fts2o-3.1 {
  execsql {
    CREATE VIRTUAL TABLE t1 USING fts2(a, b, c);
    INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one two');
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';
  }
} {{one three four} {one four} {one two}}

# This test was crashing at one point.
#
do_test fts2o-3.2 {
  execsql {
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';
    CREATE TABLE t3(a, b, c);
    SELECT a, b, c FROM t1 WHERE  c  MATCH 'two';
  }
} {{one three four} {one four} {one two} {one three four} {one four} {one two}}

#---------------------------------------------------------------------
# Test that it is possible to rename an fts2 table in an attached 
# database.
#
file delete -force test2.db test2.db-journal

do_test fts2o-3.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
    CREATE VIRTUAL TABLE aux.t1 USING fts2(a, b, c);
    INSERT INTO aux.t1(a, b, c) VALUES(
      'neung song sahm', 'neung see', 'neung see song'
    );
  }
} {}

do_test fts2o-3.2 {
  execsql { SELECT a, b, c FROM aux.t1 WHERE a MATCH 'song'; }
} {{neung song sahm} {neung see} {neung see song}}

do_test fts2o-3.3 {
  execsql { SELECT a, b, c FROM t1 WHERE c MATCH 'two'; }
} {{one three four} {one four} {one two}}

do_test fts2o-3.4 {
  execsql { ALTER TABLE aux.t1 RENAME TO t2 }
} {}

do_test fts2o-3.2 {
  execsql { SELECT a, b, c FROM t2 WHERE a MATCH 'song'; }
} {{neung song sahm} {neung see} {neung see song}}

do_test fts2o-3.3 {
  execsql { SELECT a, b, c FROM t1 WHERE c MATCH 'two'; }
} {{one three four} {one four} {one two}}

finish_test