⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fts2.c

📁 轻量级数据库软件,嵌入式设计可以考虑考虑,性能不错
💻 C
📖 第 1 页 / 共 5 页
字号:
  StringBuffer sb;  int i;  initStringBuffer(&sb);  append(&sb, "insert into %_content (rowid, ");  appendList(&sb, v->nColumn, v->azContentColumn);  append(&sb, ") values (?");  for(i=0; i<v->nColumn; ++i)    append(&sb, ", ?");  append(&sb, ")");  return stringBufferData(&sb);}/* Return a dynamically generated statement of the form *   update %_content set [col_0] = ?, [col_1] = ?, ... *                    where rowid = ? */static const char *contentUpdateStatement(fulltext_vtab *v){  StringBuffer sb;  int i;  initStringBuffer(&sb);  append(&sb, "update %_content set ");  for(i=0; i<v->nColumn; ++i) {    if( i>0 ){      append(&sb, ", ");    }    append(&sb, v->azContentColumn[i]);    append(&sb, " = ?");  }  append(&sb, " where rowid = ?");  return stringBufferData(&sb);}/* Puts a freshly-prepared statement determined by iStmt in *ppStmt.** If the indicated statement has never been prepared, it is prepared** and cached, otherwise the cached version is reset.*/static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt,                             sqlite3_stmt **ppStmt){  assert( iStmt<MAX_STMT );  if( v->pFulltextStatements[iStmt]==NULL ){    const char *zStmt;    int rc;    switch( iStmt ){      case CONTENT_INSERT_STMT:        zStmt = contentInsertStatement(v); break;      case CONTENT_UPDATE_STMT:        zStmt = contentUpdateStatement(v); break;      default:        zStmt = fulltext_zStatement[iStmt];    }    rc = sql_prepare(v->db, v->zName, &v->pFulltextStatements[iStmt],                         zStmt);    if( zStmt != fulltext_zStatement[iStmt]) free((void *) zStmt);    if( rc!=SQLITE_OK ) return rc;  } else {    int rc = sqlite3_reset(v->pFulltextStatements[iStmt]);    if( rc!=SQLITE_OK ) return rc;  }  *ppStmt = v->pFulltextStatements[iStmt];  return SQLITE_OK;}/* Step the indicated statement, handling errors SQLITE_BUSY (by** retrying) and SQLITE_SCHEMA (by re-preparing and transferring** bindings to the new statement).** TODO(adam): We should extend this function so that it can work with** statements declared locally, not only globally cached statements.*/static int sql_step_statement(fulltext_vtab *v, fulltext_statement iStmt,                              sqlite3_stmt **ppStmt){  int rc;  sqlite3_stmt *s = *ppStmt;  assert( iStmt<MAX_STMT );  assert( s==v->pFulltextStatements[iStmt] );  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;}/* Like sql_step_statement(), but convert SQLITE_DONE to SQLITE_OK.** Useful for statements like UPDATE, where we expect no results.*/static int sql_single_step_statement(fulltext_vtab *v,                                     fulltext_statement iStmt,                                     sqlite3_stmt **ppStmt){  int rc = sql_step_statement(v, iStmt, ppStmt);  return (rc==SQLITE_DONE) ? SQLITE_OK : rc;}/* Like sql_get_statement(), but for special replicated LEAF_SELECT** statements.*//* TODO(shess) Write version for generic statements and then share** that between the cached-statement functions.*/static int sql_get_leaf_statement(fulltext_vtab *v, int idx,                                  sqlite3_stmt **ppStmt){  assert( idx>=0 && idx<MERGE_COUNT );  if( v->pLeafSelectStmts[idx]==NULL ){    int rc = sql_prepare(v->db, v->zName, &v->pLeafSelectStmts[idx],                         LEAF_SELECT);    if( rc!=SQLITE_OK ) return rc;  }else{    int rc = sqlite3_reset(v->pLeafSelectStmts[idx]);    if( rc!=SQLITE_OK ) return rc;  }  *ppStmt = v->pLeafSelectStmts[idx];  return SQLITE_OK;}/* Like sql_step_statement(), but for special replicated LEAF_SELECT** statements.*//* TODO(shess) Write version for generic statements and then share** that between the cached-statement functions.*/static int sql_step_leaf_statement(fulltext_vtab *v, int idx,                                   sqlite3_stmt **ppStmt){  int rc;  sqlite3_stmt *s = *ppStmt;  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;  int i;  int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_value(s, 1, rowid);  if( rc!=SQLITE_OK ) return rc;  for(i=0; i<v->nColumn; ++i){    rc = sqlite3_bind_value(s, 2+i, pValues[i]);    if( rc!=SQLITE_OK ) return rc;  }  return sql_single_step_statement(v, CONTENT_INSERT_STMT, &s);}/* update %_content set col0 = pValues[0], col1 = pValues[1], ... *                  where rowid = [iRowid] */static int content_update(fulltext_vtab *v, sqlite3_value **pValues,                          sqlite_int64 iRowid){  sqlite3_stmt *s;  int i;  int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  for(i=0; i<v->nColumn; ++i){    rc = sqlite3_bind_value(s, 1+i, pValues[i]);    if( rc!=SQLITE_OK ) return rc;  }  rc = sqlite3_bind_int64(s, 1+v->nColumn, iRowid);  if( rc!=SQLITE_OK ) return rc;  return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s);}static void freeStringArray(int nString, const char **pString){  int i;  for (i=0 ; i < nString ; ++i) {    free((void *) pString[i]);  }  free((void *) pString);}/* select * from %_content where rowid = [iRow] * The caller must delete the returned array and all strings in it. * * TODO: Perhaps we should return pointer/length strings here for consistency * with other code which uses pointer/length. */static int content_select(fulltext_vtab *v, sqlite_int64 iRow,                          const char ***pValues){  sqlite3_stmt *s;  const char **values;  int i;  int rc;  *pValues = NULL;  rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 1, iRow);  if( rc!=SQLITE_OK ) return rc;  rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s);  if( rc!=SQLITE_ROW ) return rc;  values = (const char **) malloc(v->nColumn * sizeof(const char *));  for(i=0; i<v->nColumn; ++i){    values[i] = string_dup((char*)sqlite3_column_text(s, i));  }  /* We expect only one row.  We must execute another sqlite3_step()   * to complete the iteration; otherwise the table will remain locked. */  rc = sqlite3_step(s);  if( rc==SQLITE_DONE ){    *pValues = values;    return SQLITE_OK;  }  freeStringArray(v->nColumn, values);  return rc;}/* delete from %_content where rowid = [iRow ] */static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){  sqlite3_stmt *s;  int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 1, iRow);  if( rc!=SQLITE_OK ) return rc;  return sql_single_step_statement(v, CONTENT_DELETE_STMT, &s);}/* insert into %_segments values ([pData])**   returns assigned rowid in *piBlockid*/static int block_insert(fulltext_vtab *v, const char *pData, int nData,                        sqlite_int64 *piBlockid){  sqlite3_stmt *s;  int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC);  if( rc!=SQLITE_OK ) return rc;  rc = sql_step_statement(v, BLOCK_INSERT_STMT, &s);  if( rc==SQLITE_ROW ) return SQLITE_ERROR;  if( rc!=SQLITE_DONE ) return rc;  *piBlockid = sqlite3_last_insert_rowid(v->db);  return SQLITE_OK;}/* delete from %_segments**   where rowid between [iStartBlockid] and [iEndBlockid]**** Deletes the range of blocks, inclusive, used to delete the blocks** which form a segment.*/static int block_delete(fulltext_vtab *v,                        sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){  sqlite3_stmt *s;  int rc = sql_get_statement(v, BLOCK_DELETE_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 1, iStartBlockid);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 2, iEndBlockid);  if( rc!=SQLITE_OK ) return rc;  return sql_single_step_statement(v, BLOCK_DELETE_STMT, &s);}/* Returns SQLITE_ROW with *pidx set to the maximum segment idx found** at iLevel.  Returns SQLITE_DONE if there are no segments at** iLevel.  Otherwise returns an error.*/static int segdir_max_index(fulltext_vtab *v, int iLevel, int *pidx){  sqlite3_stmt *s;  int rc = sql_get_statement(v, SEGDIR_MAX_INDEX_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int(s, 1, iLevel);  if( rc!=SQLITE_OK ) return rc;  rc = sql_step_statement(v, SEGDIR_MAX_INDEX_STMT, &s);  /* Should always get at least one row due to how max() works. */  if( rc==SQLITE_DONE ) return SQLITE_DONE;  if( rc!=SQLITE_ROW ) return rc;  /* NULL means that there were no inputs to max(). */  if( SQLITE_NULL==sqlite3_column_type(s, 0) ){    rc = sqlite3_step(s);    if( rc==SQLITE_ROW ) return SQLITE_ERROR;    return rc;  }  *pidx = sqlite3_column_int(s, 0);  /* We expect only one row.  We must execute another sqlite3_step()   * to complete the iteration; otherwise the table will remain locked. */  rc = sqlite3_step(s);  if( rc==SQLITE_ROW ) return SQLITE_ERROR;  if( rc!=SQLITE_DONE ) return rc;  return SQLITE_ROW;}/* insert into %_segdir values (**   [iLevel], [idx],**   [iStartBlockid], [iLeavesEndBlockid], [iEndBlockid],**   [pRootData]** )*/static int segdir_set(fulltext_vtab *v, int iLevel, int idx,                      sqlite_int64 iStartBlockid,                      sqlite_int64 iLeavesEndBlockid,                      sqlite_int64 iEndBlockid,                      const char *pRootData, int nRootData){  sqlite3_stmt *s;  int rc = sql_get_statement(v, SEGDIR_SET_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int(s, 1, iLevel);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int(s, 2, idx);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 3, iStartBlockid);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 4, iLeavesEndBlockid);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 5, iEndBlockid);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_blob(s, 6, pRootData, nRootData, SQLITE_STATIC);  if( rc!=SQLITE_OK ) return rc;  return sql_single_step_statement(v, SEGDIR_SET_STMT, &s);}/* Queries %_segdir for the block span of the segments in level** iLevel.  Returns SQLITE_DONE if there are no blocks for iLevel,** SQLITE_ROW if there are blocks, else an error.*/static int segdir_span(fulltext_vtab *v, int iLevel,                       sqlite_int64 *piStartBlockid,                       sqlite_int64 *piEndBlockid){  sqlite3_stmt *s;  int rc = sql_get_statement(v, SEGDIR_SPAN_STMT, &s);  if( rc!=SQLITE_OK ) return r

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -