/ Check-in [61efff41]
Login

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

Overview
Comment:Fix an OOM related problem in the snippet() and offsets() functions of fts3.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:61efff414254f209f1c69728ae2da3b3888b7290
User & Date: dan 2009-12-10 18:20:32
Context
2009-12-10
18:29
Fix handling of "WHERE col MATCH ? AND docid = ?" clauses in fts3. check-in: 6cbbae84 user: dan tags: trunk
18:20
Fix an OOM related problem in the snippet() and offsets() functions of fts3. check-in: 61efff41 user: dan tags: trunk
16:04
Changes to fts3 to avoid flushing data to disk within a SELECT statement. check-in: 48c0db0e user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
...
889
890
891
892
893
894
895



896
897
898
899
900
901
902
....
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
....
2119
2120
2121
2122
2123
2124
2125
2126



2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138

2139
2140
2141
2142
2143
2144

2145

2146
2147
2148
2149
2150
2151
2152
  sqlite3_finalize(pCsr->pStmt);
  sqlite3Fts3ExprFree(pCsr->pExpr);
  sqlite3_free(pCsr->aDoclist);
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

static int fts3CursorSeek(Fts3Cursor *pCsr){
  if( pCsr->isRequireSeek ){
    pCsr->isRequireSeek = 0;
    sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
    if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
      return SQLITE_OK;
    }else{
      int rc = sqlite3_reset(pCsr->pStmt);
................................................................................
        /* If no row was found and no error has occured, then the %_content
        ** table is missing a row that is present in the full-text index.
        ** The data structures are corrupt.
        */
        rc = SQLITE_CORRUPT;
      }
      pCsr->isEof = 1;



      return rc;
    }
  }else{
    return SQLITE_OK;
  }
}

................................................................................
  }else if( iCol==p->nColumn ){
    /* The extra column whose name is the same as the table.
    ** Return a blob which is a pointer to the cursor.
    */
    sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
    rc = SQLITE_OK;
  }else{
    rc = fts3CursorSeek(pCsr);
    if( rc==SQLITE_OK ){
      sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
    }
  }
  return rc;
}

................................................................................
  if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;

  switch( nVal ){
    case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
    case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
    case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
  }




  sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis);

}

/*
** Implementation of the offsets() function for FTS3
*/
static void fts3OffsetsFunc(
  sqlite3_context *pContext,      /* SQLite function call context */
  int nVal,                       /* Size of argument array */
  sqlite3_value **apVal           /* Array of arguments */
){
  Fts3Cursor *pCsr;               /* Cursor handle passed through apVal[0] */


  UNUSED_PARAMETER(nVal);

  assert( nVal==1 );
  if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return;
  assert( pCsr );

  sqlite3Fts3Offsets(pContext, pCsr);

}

/* 
** Implementation of the special optimize() function for FTS3. This 
** function merges all segments in the database to a single segment.
** Example usage is:
**







|







 







>
>
>







 







|







 







<
>
>
>
|
>











>






>
|
>







873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
...
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
....
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
....
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
  sqlite3_finalize(pCsr->pStmt);
  sqlite3Fts3ExprFree(pCsr->pExpr);
  sqlite3_free(pCsr->aDoclist);
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
  if( pCsr->isRequireSeek ){
    pCsr->isRequireSeek = 0;
    sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
    if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
      return SQLITE_OK;
    }else{
      int rc = sqlite3_reset(pCsr->pStmt);
................................................................................
        /* If no row was found and no error has occured, then the %_content
        ** table is missing a row that is present in the full-text index.
        ** The data structures are corrupt.
        */
        rc = SQLITE_CORRUPT;
      }
      pCsr->isEof = 1;
      if( pContext && rc!=SQLITE_OK ){
        sqlite3_result_error_code(pContext, rc);
      }
      return rc;
    }
  }else{
    return SQLITE_OK;
  }
}

................................................................................
  }else if( iCol==p->nColumn ){
    /* The extra column whose name is the same as the table.
    ** Return a blob which is a pointer to the cursor.
    */
    sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
    rc = SQLITE_OK;
  }else{
    rc = fts3CursorSeek(0, pCsr);
    if( rc==SQLITE_OK ){
      sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1));
    }
  }
  return rc;
}

................................................................................
  if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;

  switch( nVal ){
    case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
    case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
    case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
  }

  if( !zStart || !zEnd || !zEllipsis ){
    sqlite3_result_error_nomem(pContext);
  }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
    sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis);
  }
}

/*
** Implementation of the offsets() function for FTS3
*/
static void fts3OffsetsFunc(
  sqlite3_context *pContext,      /* SQLite function call context */
  int nVal,                       /* Size of argument array */
  sqlite3_value **apVal           /* Array of arguments */
){
  Fts3Cursor *pCsr;               /* Cursor handle passed through apVal[0] */
  int rc;

  UNUSED_PARAMETER(nVal);

  assert( nVal==1 );
  if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return;
  assert( pCsr );
  if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
    sqlite3Fts3Offsets(pContext, pCsr);
  }
}

/* 
** Implementation of the special optimize() function for FTS3. This 
** function merges all segments in the database to a single segment.
** Example usage is:
**

Changes to test/fts3_common.tcl.

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  } else {
    set answers [list $catchres]
    set modes [list 0 ""]
  }
  set str [join $answers " OR "]

  foreach {nRepeat zName} $modes {
    for {set iFail 48} 1 {incr iFail} {
      if {$::DO_MALLOC_TEST} {sqlite3_memdebug_fail $iFail -repeat $nRepeat}

      set res [uplevel [list catchsql $sql]]
      if {[lsearch -exact $answers $res]>=0} {
        set res $str
      }
      set testname "$name.$zName.$iFail"







|







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  } else {
    set answers [list $catchres]
    set modes [list 0 ""]
  }
  set str [join $answers " OR "]

  foreach {nRepeat zName} $modes {
    for {set iFail 1} 1 {incr iFail} {
      if {$::DO_MALLOC_TEST} {sqlite3_memdebug_fail $iFail -repeat $nRepeat}

      set res [uplevel [list catchsql $sql]]
      if {[lsearch -exact $answers $res]>=0} {
        set res $str
      }
      set testname "$name.$zName.$iFail"