Improve comments and other things in fts3_write.c.

FossilOrigin-Name: 1cf0e3cc14bad22867e740736c2886dc1c4a48dc
This commit is contained in:
dan 2009-11-20 05:05:19 +00:00
parent d313865550
commit d1414c58e5
3 changed files with 128 additions and 73 deletions

View File

@ -147,11 +147,22 @@ struct SegmentNode {
#define SQL_CONTENT_INSERT 16
#define SQL_GET_BLOCK 17
/*
** This function is used to obtain an SQLite prepared statement handle
** for the statement identified by the second argument. If successful,
** *pp is set to the requested statement handle and SQLITE_OK returned.
** Otherwise, an SQLite error code is returned and *pp is set to 0.
**
** If argument apVal is not NULL, then it must point to an array with
** at least as many entries as the requested statement has bound
** parameters. The values are bound to the statements parameters before
** returning.
*/
static int fts3SqlStmt(
Fts3Table *p,
int eStmt,
sqlite3_stmt **pp,
sqlite3_value **apVal
Fts3Table *p, /* Virtual table handle */
int eStmt, /* One of the SQL_XXX constants above */
sqlite3_stmt **pp, /* OUT: Statement handle */
sqlite3_value **apVal /* Values to bind to statement */
){
const char *azSql[] = {
/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?",
@ -176,9 +187,8 @@ static int fts3SqlStmt(
/* 14 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?",
/* 15 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?",
/* 16 */ 0, /* CONTENT_INSERT - generated elsewhere */
/* 16 */ "INSERT INTO %Q.'%q_content' VALUES(%z)",
/* 17 */ "SELECT block FROM %Q.'%q_segments' WHERE blockid = ?",
};
int rc = SQLITE_OK;
sqlite3_stmt *pStmt;
@ -188,7 +198,25 @@ static int fts3SqlStmt(
pStmt = p->aStmt[eStmt];
if( !pStmt ){
char *zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
char *zSql;
if( eStmt==SQL_CONTENT_INSERT ){
int i; /* Iterator variable */
char *zVarlist; /* The "?, ?, ..." string */
zVarlist = (char *)sqlite3_malloc(2*p->nColumn+2);
if( !zVarlist ){
*pp = 0;
return SQLITE_NOMEM;
}
zVarlist[0] = '?';
zVarlist[p->nColumn*2+1] = '\0';
for(i=1; i<=p->nColumn; i++){
zVarlist[i*2-1] = ',';
zVarlist[i*2] = '?';
}
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, zVarlist);
}else{
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
}
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
@ -209,6 +237,25 @@ static int fts3SqlStmt(
return rc;
}
/*
** Similar to fts3SqlStmt(). Except, after binding the parameters in
** array apVal[] to the SQL statement identified by eStmt, the statement
** is executed.
**
** Returns SQLITE_OK if the statement is successfully executed, or an
** SQLite error code otherwise.
*/
static int fts3SqlExec(Fts3Table *p, int eStmt, sqlite3_value **apVal){
sqlite3_stmt *pStmt;
int rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
}
return rc;
}
/*
** Read a single block from the %_segments table. If the specified block
** does not exist, return SQLITE_CORRUPT. If some other error (malloc, IO
@ -268,16 +315,18 @@ int sqlite3Fts3AllSegdirs(Fts3Table *p, sqlite3_stmt **ppStmt){
}
static int fts3SqlExec(Fts3Table *p, int eStmt, sqlite3_value **apVal){
sqlite3_stmt *pStmt;
int rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
}
return rc;
}
/*
** Append a single varint to a PendingList buffer. SQLITE_OK is returned
** if successful, or an SQLite error code otherwise.
**
** This function also serves to allocate the PendingList structure itself.
** For example, to create a new PendingList structure containing two
** varints:
**
** PendingList *p = 0;
** fts3PendingListAppendVarint(&p, 1);
** fts3PendingListAppendVarint(&p, 2);
*/
static int fts3PendingListAppendVarint(
PendingList **pp, /* IN/OUT: Pointer to PendingList struct */
sqlite3_int64 i /* Value to append to data */
@ -313,12 +362,21 @@ static int fts3PendingListAppendVarint(
return SQLITE_OK;
}
/*
** Add a docid/column/position entry to a PendingList structure. Non-zero
** is returned if the structure is sqlite3_realloced as part of adding
** the entry. Otherwise, zero.
**
** If an OOM error occurs, *pRc is set to SQLITE_NOMEM before returning.
** Zero is always returned in this case. Otherwise, if no OOM error occurs,
** it is set to SQLITE_OK.
*/
static int fts3PendingListAppend(
PendingList **pp,
sqlite3_int64 iDocid,
sqlite3_int64 iCol,
sqlite3_int64 iPos,
int *pRc
PendingList **pp, /* IN/OUT: PendingList structure */
sqlite3_int64 iDocid, /* Docid for entry to add */
sqlite3_int64 iCol, /* Column for entry to add */
sqlite3_int64 iPos, /* Position of term for entry to add */
int *pRc /* OUT: Return code */
){
PendingList *p = *pp;
int rc = SQLITE_OK;
@ -363,6 +421,13 @@ static int fts3PendingListAppend(
return 0;
}
/*
** Tokenize the nul-terminated string zText and add all tokens to the
** pending-terms hash-table. The docid used is that currently stored in
** p->iPrevDocid, and the column is specified by argument iCol.
**
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
*/
static int fts3PendingTermsAdd(Fts3Table *p, const char *zText, int iCol){
int rc;
int iStart;
@ -497,47 +562,19 @@ static int fts3InsertData(
sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */
/* Locate the statement handle used to insert data into the %_content
** table. If no such statement has been prepared, prepare a new one.
** The SQL for this statement is:
** table. The SQL for this statement is:
**
** INSERT INTO %_content VALUES(?, ?, ?, ...)
**
** The statement features N '?' variables, where N is the number of user
** defined columns in the FTS3 table, plus one for the docid field.
*/
pContentInsert = p->aStmt[SQL_CONTENT_INSERT];
if( !pContentInsert ){
char *zVarlist; /* The "?, ?, ..." string */
char *zSql; /* The text of the INSERT statement */
/* Construct the SQL statement text. */
zVarlist = (char *)sqlite3_malloc(2*p->nColumn+2);
if( !zVarlist ){
return SQLITE_NOMEM;
}
zVarlist[0] = '?';
for(i=1; i<=p->nColumn; i++){
zVarlist[i*2-1] = ',';
zVarlist[i*2] = '?';
}
zVarlist[p->nColumn*2+1] = '\0';
zSql = sqlite3_mprintf("INSERT INTO %Q.'%q_content' VALUES(%z)",
p->zDb, p->zName, zVarlist
);
if( !zSql ) return SQLITE_NOMEM;
/* Prepare the SQL statement. */
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pContentInsert, NULL);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ){
return rc;
}
p->aStmt[SQL_CONTENT_INSERT] = pContentInsert;
rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
if( rc!=SQLITE_OK ){
return rc;
}
/* Bind values to the prepared statement.
**
** There is a quirk here. The users INSERT statement may have specified
/* There is a quirk here. The users INSERT statement may have specified
** a value for the "rowid" field, for the "docid" field, or for both.
** Which is a problem, since "rowid" and "docid" are aliases for the
** same value. For example:
@ -547,10 +584,6 @@ static int fts3InsertData(
** In FTS3, if a non-NULL docid value is specified, it is the value
** inserted. Otherwise, the rowid value is used.
*/
for(i=0; i<=p->nColumn; i++){
rc = sqlite3_bind_value(pContentInsert, i+1, apVal[i+1]);
if( rc!=SQLITE_OK ) return rc;
}
if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){
rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]);
if( rc!=SQLITE_OK ) return rc;
@ -616,6 +649,10 @@ static int fts3DeleteTerms(Fts3Table *p, sqlite3_value **apVal){
return sqlite3_reset(pSelect);
}
/*
** Forward declaration to account for the circular dependency between
** functions fts3SegmentMerge() and fts3AllocateSegdirIdx().
*/
static int fts3SegmentMerge(Fts3Table *, int);
/*
@ -719,6 +756,10 @@ static int fts3SegReaderNext(Fts3SegReader *pReader){
return SQLITE_OK;
}
/*
** Set the SegReader to point to the first docid in the doclist associated
** with the current term.
*/
static void fts3SegReaderFirstDocid(Fts3SegReader *pReader){
int n;
assert( pReader->aDoclist );
@ -728,15 +769,14 @@ static void fts3SegReaderFirstDocid(Fts3SegReader *pReader){
}
/*
**
** Advance the SegReader to point to the next docid in the doclist
** associated with the current term.
**
** If arguments ppOffsetList and pnOffsetList are not NULL, then
** *ppOffsetList is set to point to the first column-offset list
** in the doclist entry (i.e. immediately past the docid varint).
** *pnOffsetList is set to the length of the set of column-offset
** lists, not including the nul-terminator byte. For example:
**
** TODO: example.
**
*/
static void fts3SegReaderNextDocid(
Fts3SegReader *pReader,
@ -776,12 +816,15 @@ static void fts3SegReaderNextDocid(
}
/*
** Free all allocations associated with the iterator passed as the first
** argument.
** Free all allocations associated with the iterator passed as the
** second argument.
*/
void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){
if( pReader ){
if( pReader->pStmt ){
/* Move the leaf-range SELECT statement to the aLeavesStmt[] array,
** so that it can be reused when required by another query.
*/
assert( p->nLeavesStmt<p->nLeavesTotal );
sqlite3_reset(pReader->pStmt);
p->aLeavesStmt[p->nLeavesStmt++] = pReader->pStmt;
@ -825,6 +868,11 @@ int sqlite3Fts3SegReaderNew(
memcpy(pReader->aNode, zRoot, nRoot);
}else{
sqlite3_stmt *pStmt;
/* If the text of the SQL statement to iterate through a contiguous
** set of entries in the %_segments table has not yet been composed,
** compose it now.
*/
if( !p->zSelectLeaves ){
p->zSelectLeaves = sqlite3_mprintf(
"SELECT block FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ? "
@ -835,6 +883,11 @@ int sqlite3Fts3SegReaderNew(
goto finished;
}
}
/* If there are no free statements in the aLeavesStmt[] array, prepare
** a new statement now. Otherwise, reuse a prepared statement from
** aLeavesStmt[].
*/
if( p->nLeavesStmt==0 ){
if( p->nLeavesTotal==p->nLeavesAlloc ){
int nNew = p->nLeavesAlloc + 16;
@ -856,6 +909,8 @@ int sqlite3Fts3SegReaderNew(
}else{
pReader->pStmt = p->aLeavesStmt[--p->nLeavesStmt];
}
/* Bind the start and end leaf blockids to the prepared SQL statement. */
sqlite3_bind_int64(pReader->pStmt, 1, iStartLeaf);
sqlite3_bind_int64(pReader->pStmt, 2, iEndLeaf);
}
@ -1645,7 +1700,7 @@ int sqlite3Fts3SegReaderIterate(
int nDoclist = 0; /* Size of doclist */
sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */
/* The current term of the first nMerge entries in the linked list
/* The current term of the first nMerge entries in the array
** of Fts3SegReader objects is the same. The doclists must be merged
** and a single term added to the new segment.
*/

View File

@ -1,5 +1,5 @@
C Minor\soptimizations\sto\sfts3\scode.
D 2009-11-20T02:24:15
C Improve\scomments\sand\sother\sthings\sin\sfts3_write.c.
D 2009-11-20T05:05:19
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 7f6c6aa7feeeb5e26e01b344161d9aa1b5d64177
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -68,7 +68,7 @@ F ext/fts3/fts3_snippet.c 082f2906deaaa2656f19b88834e89d099352af6e
F ext/fts3/fts3_tokenizer.c 36f78d1a43a29b0feaec1ced6da9e56b9c653d1f
F ext/fts3/fts3_tokenizer.h 7ff73caa3327589bf6550f60d93ebdd1f6a0fb5c
F ext/fts3/fts3_tokenizer1.c 0a5bcc579f35de5d24a9345d7908dc25ae403ee7
F ext/fts3/fts3_write.c 3c8a5d912af939232480b3f4064ac49621816250
F ext/fts3/fts3_write.c 6b9b4fd998fc2cbc05859b79af559b32792023ab
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
@ -772,7 +772,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 4115c0c286052e32cb81f77a644d530c1766206f
R d93aed1e18b2651263389c52f5a6aa80
P b456eacbbb16513d1b27e90015ea58a6dc92cc3b
R 70a25367badaa9e85b170e396db9833f
U dan
Z 234100290840447274601364a421931c
Z 5ffc5a8c993fa4958f562d1dcf7d0c6b

View File

@ -1 +1 @@
b456eacbbb16513d1b27e90015ea58a6dc92cc3b
1cf0e3cc14bad22867e740736c2886dc1c4a48dc