SQLite

Check-in [018e82c775]
Login

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

Overview
Comment:Have all FTS3 queries obtain a read or write table-lock at the shared-cache level before doing anything else.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 018e82c775d0fb8c0d90cddf7a87c20c8c8172a9
User & Date: dan 2010-09-17 15:28:42.000
Context
2010-09-17
16:01
Add new test file fts3shared.test to test the previous change. (check-in: a207f74408 user: dan tags: trunk)
15:28
Have all FTS3 queries obtain a read or write table-lock at the shared-cache level before doing anything else. (check-in: 018e82c775 user: dan tags: trunk)
01:07
Completely remove all trace of ctype.h from FTS2. (check-in: 876845661a user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/fts3/fts3.c.
2199
2200
2201
2202
2203
2204
2205



2206
2207
2208
2209
2210
2211
2212
      if( rc==SQLITE_ERROR ){
        p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]",
                                          zQuery);
      }
      return rc;
    }




    rc = evalFts3Expr(p, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
    pCsr->pNextId = pCsr->aDoclist;
    pCsr->iPrevId = 0;
  }

  if( rc!=SQLITE_OK ) return rc;
  return fts3NextMethod(pCursor);







>
>
>







2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
      if( rc==SQLITE_ERROR ){
        p->base.zErrMsg = sqlite3_mprintf("malformed MATCH expression: [%s]",
                                          zQuery);
      }
      return rc;
    }

    rc = sqlite3Fts3ReadLock(p);
    if( rc!=SQLITE_OK ) return rc;

    rc = evalFts3Expr(p, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
    pCsr->pNextId = pCsr->aDoclist;
    pCsr->iPrevId = 0;
  }

  if( rc!=SQLITE_OK ) return rc;
  return fts3NextMethod(pCursor);
Changes to ext/fts3/fts3Int.h.
269
270
271
272
273
274
275

276
277
278
279
280
281
282
  Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *,
  int (*)(Fts3Table *, void *, char *, int, char *, int),  void *
);
int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*);
int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **);
int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*);
int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*);


/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
#define FTS3_SEGMENT_REQUIRE_POS   0x00000001
#define FTS3_SEGMENT_IGNORE_EMPTY  0x00000002
#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
#define FTS3_SEGMENT_PREFIX        0x00000008








>







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *,
  int (*)(Fts3Table *, void *, char *, int, char *, int),  void *
);
int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*);
int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **);
int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*);
int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*);
int sqlite3Fts3ReadLock(Fts3Table *);

/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
#define FTS3_SEGMENT_REQUIRE_POS   0x00000001
#define FTS3_SEGMENT_IGNORE_EMPTY  0x00000002
#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
#define FTS3_SEGMENT_PREFIX        0x00000008

Changes to ext/fts3/fts3_write.c.
317
318
319
320
321
322
323






























324
325
326
327
328
329
330
    *pzBlock = (char *)sqlite3_column_blob(pStmt, 0);
    if( sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
      return SQLITE_CORRUPT;
    }
  }
  return SQLITE_OK;
}































/*
** Set *ppStmt to a statement handle that may be used to iterate through
** all rows in the %_segdir table, from oldest to newest. If successful,
** return SQLITE_OK. If an error occurs while preparing the statement, 
** return an SQLite error code.
**







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







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
    *pzBlock = (char *)sqlite3_column_blob(pStmt, 0);
    if( sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
      return SQLITE_CORRUPT;
    }
  }
  return SQLITE_OK;
}

/*
** This function ensures that the caller has obtained a shared-cache
** table-lock on the %_content table. This is required before reading
** data from the fts3 table. If this lock is not acquired first, then
** the caller may end up holding read-locks on the %_segments and %_segdir
** tables, but no read-lock on the %_content table. If this happens 
** a second connection will be able to write to the fts3 table, but
** attempting to commit those writes might return SQLITE_LOCKED or
** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain 
** write-locks on the %_segments and %_segdir ** tables). 
**
** We try to avoid this because if FTS3 returns any error when committing
** a transaction, the whole transaction will be rolled back. And this is
** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can
** still happen if the user reads data directly from the %_segments or
** %_segdir tables instead of going through FTS3 though.
*/
int sqlite3Fts3ReadLock(Fts3Table *p){
  int rc;                         /* Return code */
  sqlite3_stmt *pStmt;            /* Statement used to obtain lock */

  rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
  if( rc==SQLITE_OK ){
    sqlite3_bind_null(pStmt, 1);
    sqlite3_step(pStmt);
    rc = sqlite3_reset(pStmt);
  }
  return rc;
}

/*
** Set *ppStmt to a statement handle that may be used to iterate through
** all rows in the %_segdir table, from oldest to newest. If successful,
** return SQLITE_OK. If an error occurs while preparing the statement, 
** return an SQLite error code.
**