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

📄 fts1.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
  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){    if( sqlite3_column_type(s, i)==SQLITE_NULL ){      values[i] = NULL;    }else{      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);}/* select rowid, doclist from %_term *  where term = [pTerm] and segment = [iSegment] * If found, returns SQLITE_ROW; the caller must free the * returned doclist.  If no rows found, returns SQLITE_DONE. */static int term_select(fulltext_vtab *v, const char *pTerm, int nTerm,                       int iSegment,                       sqlite_int64 *rowid, DocList *out){  sqlite3_stmt *s;  int rc = sql_get_statement(v, TERM_SELECT_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_text(s, 1, pTerm, nTerm, SQLITE_STATIC);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int(s, 2, iSegment);  if( rc!=SQLITE_OK ) return rc;  rc = sql_step_statement(v, TERM_SELECT_STMT, &s);  if( rc!=SQLITE_ROW ) return rc;  *rowid = sqlite3_column_int64(s, 0);  docListInit(out, DL_DEFAULT,              sqlite3_column_blob(s, 1), sqlite3_column_bytes(s, 1));  /* 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);  return rc==SQLITE_DONE ? SQLITE_ROW : rc;}/* Load the segment doclists for term pTerm and merge them in** appropriate order into out.  Returns SQLITE_OK if successful.  If** there are no segments for pTerm, successfully returns an empty** doclist in out.**** Each document consists of 1 or more "columns".  The number of** columns is v->nColumn.  If iColumn==v->nColumn, then return** position information about all columns.  If iColumn<v->nColumn,** then only return position information about the iColumn-th column** (where the first column is 0).*/static int term_select_all(  fulltext_vtab *v,     /* The fulltext index we are querying against */  int iColumn,          /* If <nColumn, only look at the iColumn-th column */  const char *pTerm,    /* The term whose posting lists we want */  int nTerm,            /* Number of bytes in pTerm */  DocList *out          /* Write the resulting doclist here */){  DocList doclist;  sqlite3_stmt *s;  int rc = sql_get_statement(v, TERM_SELECT_ALL_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_text(s, 1, pTerm, nTerm, SQLITE_STATIC);  if( rc!=SQLITE_OK ) return rc;  docListInit(&doclist, DL_DEFAULT, 0, 0);  /* TODO(shess) Handle schema and busy errors. */  while( (rc=sql_step_statement(v, TERM_SELECT_ALL_STMT, &s))==SQLITE_ROW ){    DocList old;    /* TODO(shess) If we processed doclists from oldest to newest, we    ** could skip the malloc() involved with the following call.  For    ** now, I'd rather keep this logic similar to index_insert_term().    ** We could additionally drop elements when we see deletes, but    ** that would require a distinct version of docListAccumulate().    */    docListInit(&old, DL_DEFAULT,                sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0));    if( iColumn<v->nColumn ){   /* querying a single column */      docListRestrictColumn(&old, iColumn);    }    /* doclist contains the newer data, so write it over old.  Then    ** steal accumulated result for doclist.    */    docListAccumulate(&old, &doclist);    docListDestroy(&doclist);    doclist = old;  }  if( rc!=SQLITE_DONE ){    docListDestroy(&doclist);    return rc;  }  docListDiscardEmpty(&doclist);  *out = doclist;  return SQLITE_OK;}/* insert into %_term (rowid, term, segment, doclist)               values ([piRowid], [pTerm], [iSegment], [doclist])** Lets sqlite select rowid if piRowid is NULL, else uses *piRowid.**** NOTE(shess) piRowid is IN, with values of "space of int64" plus** null, it is not used to pass data back to the caller.*/static int term_insert(fulltext_vtab *v, sqlite_int64 *piRowid,                       const char *pTerm, int nTerm,                       int iSegment, DocList *doclist){  sqlite3_stmt *s;  int rc = sql_get_statement(v, TERM_INSERT_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  if( piRowid==NULL ){    rc = sqlite3_bind_null(s, 1);  }else{    rc = sqlite3_bind_int64(s, 1, *piRowid);  }  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_text(s, 2, pTerm, nTerm, SQLITE_STATIC);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int(s, 3, iSegment);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_blob(s, 4, doclist->pData, doclist->nData, SQLITE_STATIC);  if( rc!=SQLITE_OK ) return rc;  return sql_single_step_statement(v, TERM_INSERT_STMT, &s);}/* update %_term set doclist = [doclist] where rowid = [rowid] */static int term_update(fulltext_vtab *v, sqlite_int64 rowid,                       DocList *doclist){  sqlite3_stmt *s;  int rc = sql_get_statement(v, TERM_UPDATE_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_blob(s, 1, doclist->pData, doclist->nData, SQLITE_STATIC);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 2, rowid);  if( rc!=SQLITE_OK ) return rc;  return sql_single_step_statement(v, TERM_UPDATE_STMT, &s);}static int term_delete(fulltext_vtab *v, sqlite_int64 rowid){  sqlite3_stmt *s;  int rc = sql_get_statement(v, TERM_DELETE_STMT, &s);  if( rc!=SQLITE_OK ) return rc;  rc = sqlite3_bind_int64(s, 1, rowid);  if( rc!=SQLITE_OK ) return rc;  return sql_single_step_statement(v, TERM_DELETE_STMT, &s);}/*** Free the memory used to contain a fulltext_vtab structure.*/static void fulltext_vtab_destroy(fulltext_vtab *v){  int iStmt, i;  TRACE(("FTS1 Destroy %p\n", v));  for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){    if( v->pFulltextStatements[iStmt]!=NULL ){      sqlite3_finalize(v->pFulltextStatements[iStmt]);      v->pFulltextStatements[iStmt] = NULL;    }  }  if( v->pTokenizer!=NULL ){    v->pTokenizer->pModule->xDestroy(v->pTokenizer);    v->pTokenizer = NULL;  }    free(v->azColumn);  for(i = 0; i < v->nColumn; ++i) {    sqlite3_free(v->azContentColumn[i]);  }  free(v->azContentColumn);  free(v);}/*** Token types for parsing the arguments to xConnect or xCreate.*/#define TOKEN_EOF         0    /* End of file */#define TOKEN_SPACE       1    /* Any kind of whitespace */#define TOKEN_ID          2    /* An identifier */#define TOKEN_STRING      3    /* A string literal */#define TOKEN_PUNCT       4    /* A single punctuation character *//*** If X is a character that can be used in an identifier then** IdChar(X) will be true.  Otherwise it is false.**** For ASCII, any character with the high-order bit set is** allowed in an identifier.  For 7-bit characters, ** sqlite3IsIdChar[X] must be 1.**** Ticket #1066.  the SQL standard does not allow '$' in the** middle of identfiers.  But many SQL implementations do. ** SQLite will allow '$' in identifiers for compatibility.** But the feature is undocumented.*/static const char isIdChar[] = {/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */    0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */};#define IdChar(C)  (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))/*** Return the length of the token that begins at z[0]. ** Store the token type in *tokenType before returning.*/static int getToken(const char *z, int *tokenType){  int i, c;  switch( *z ){    case 0: {      *tokenType = TOKEN_EOF;      return 0;    }    case ' ': case '\t': case '\n': case '\f': case '\r': {      for(i=1; safe_isspace(z[i]); i++){}      *tokenType = TOKEN_SPACE;      return i;    }    case '`':    case '\'':    case '"': {      int delim = z[0];      for(i=1; (c=z[i])!=0; i++){        if( c==delim ){          if( z[i+1]==delim ){            i++;          }else{            break;          }        }      }      *tokenType = TOKEN_STRING;      return i + (c!=0);    }    case '[': {      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}      *tokenType = TOKEN_ID;      return i;    }    default: {      if( !IdChar(*z) ){        break;      }      for(i=1; IdChar(z[i]); i++){}      *tokenType = TOKEN_ID;      return i;    }  }  *tokenType = TOKEN_PUNCT;  return 1;}/*** A token extracted from a string is an instance of the following** structure.*/typedef struct Token {  const char *z;       /* Pointer to token text.  Not '\000' terminated */  short int n;         /* Length of the token text in bytes. */} Token;/*** Given a input string (which is really one of the argv[] parameters** passed into xConnect or xCreate) split the string up into tokens.** Return an array of pointers to '\000' terminated strings, one string** for each non-whitespace token.**** The returned array is terminated by a single NULL pointer.**** Space to hold the returned array is obtained from a single** malloc and should be freed by passing the return value to free().** The individual strings within the token list are all a part of** the single memory allocation and will all be freed at once.*/static char **tokenizeString(const char *z, int *pnToken){  int nToken = 0;  Token *aToken = malloc( strlen(z) * sizeof(aToken[0]) );  int n = 1;  int e, i;  int totalSize = 0;  char **azToken;  char *zCopy;  while( n>0 ){    n = getToken(z, &e);    if( e!=TOKEN_SPACE ){      aToken[nToken].z = z;      aToken[nToken].n = n;      nToken++;      totalSize += n+1;    }    z += n;  }  azToken = (char**)malloc( nToken*sizeof(char*) + totalSize );  zCopy = (char*)&azToken[nToken];  nToken--;  for(i=0; i<nToken; i++){    azToken[i] = zCopy;    n = aToken[i].n;    memcpy(zCopy, aToken[i].z, n);    zCopy[n] = 0;    zCopy += n+1;  }  azToken[nToken] = 0;  free(aToken);  *pnToken = nToken;  return azToken;}/*** Convert an SQL-style quoted string into a normal string by removing** the quote characters.  The conversion is done in-place.  If the** input does not begin with a quote character, then this routine** is a no-op.**** Examples:****     "abc"   becomes   abc**     'xyz'   becomes   xyz**     [pqr]   becomes   pqr**     `mno`   becomes   mno*/static void dequoteString(char *z){  int quote;  int i, j;  if( z==0 ) return;  quote = z[0];  switch( quote ){    case '\'':  break;    case '"':   break;    case '`':   break;                /* For MySQL compatibility */    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */    default:    return;  }  for(i=1, j=0; z[i]; i++){    if( z[i]==quote ){      if( z[i+1]==quote ){        z[j++] = quote;        i++;      }else{        z[j++] = 0;        break;      }    }else{      z[j++] = z[i];    }  }}/*** The input azIn is a NULL-terminated list of tokens.  Remove the first** token and all punctuation tokens.  Remove the quotes from** around string literal tokens.**** Example:****     input:      tokenize chinese ( 'simplifed' , 'mixed' )**     output:     chinese simplifed mixed**** Another example:****     input:      delimiters ( '[' , ']' , '...' )**     output:     [ ] ...*/static void tokenListToIdList(char **azIn){  int i, j;  if( azIn ){    for(i=0, j=-1; azIn[i]; i++){      if( safe_isalnum(azIn[i][0]) || azIn[i][1] ){        dequoteString(azIn[i]);        if( j>=0 ){          azIn[j] = azIn[i];        }        j++;      }    }    azIn[j] = 0;  }}/*** Find the first alphanumeric token in the string zIn.  Null-terminate** this token.  Remove any quotation marks.  And return a pointer to** the result.

⌨️ 快捷键说明

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