summaryrefslogtreecommitdiff
path: root/chromium/third_party/sqlite/src/src/test_func.c
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/sqlite/src/src/test_func.c')
-rw-r--r--chromium/third_party/sqlite/src/src/test_func.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/chromium/third_party/sqlite/src/src/test_func.c b/chromium/third_party/sqlite/src/src/test_func.c
index c8d287341d0..30f4a326a5b 100644
--- a/chromium/third_party/sqlite/src/src/test_func.c
+++ b/chromium/third_party/sqlite/src/src/test_func.c
@@ -792,6 +792,123 @@ abuse_err:
/*
+** SQLite user defined function to use with matchinfo() to calculate the
+** relevancy of an FTS match. The value returned is the relevancy score
+** (a real value greater than or equal to zero). A larger value indicates
+** a more relevant document.
+**
+** The overall relevancy returned is the sum of the relevancies of each
+** column value in the FTS table. The relevancy of a column value is the
+** sum of the following for each reportable phrase in the FTS query:
+**
+** (<hit count> / <global hit count>) * <column weight>
+**
+** where <hit count> is the number of instances of the phrase in the
+** column value of the current row and <global hit count> is the number
+** of instances of the phrase in the same column of all rows in the FTS
+** table. The <column weight> is a weighting factor assigned to each
+** column by the caller (see below).
+**
+** The first argument to this function must be the return value of the FTS
+** matchinfo() function. Following this must be one argument for each column
+** of the FTS table containing a numeric weight factor for the corresponding
+** column. Example:
+**
+** CREATE VIRTUAL TABLE documents USING fts3(title, content)
+**
+** The following query returns the docids of documents that match the full-text
+** query <query> sorted from most to least relevant. When calculating
+** relevance, query term instances in the 'title' column are given twice the
+** weighting of those in the 'content' column.
+**
+** SELECT docid FROM documents
+** WHERE documents MATCH <query>
+** ORDER BY rank(matchinfo(documents), 1.0, 0.5) DESC
+*/
+static void rankfunc(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
+ int *aMatchinfo; /* Return value of matchinfo() */
+ int nMatchinfo; /* Number of elements in aMatchinfo[] */
+ int nCol = 0; /* Number of columns in the table */
+ int nPhrase = 0; /* Number of phrases in the query */
+ int iPhrase; /* Current phrase */
+ double score = 0.0; /* Value to return */
+
+ assert( sizeof(int)==4 );
+
+ /* Check that the number of arguments passed to this function is correct.
+ ** If not, jump to wrong_number_args. Set aMatchinfo to point to the array
+ ** of unsigned integer values returned by FTS function matchinfo. Set
+ ** nPhrase to contain the number of reportable phrases in the users full-text
+ ** query, and nCol to the number of columns in the table. Then check that the
+ ** size of the matchinfo blob is as expected. Return an error if it is not.
+ */
+ if( nVal<1 ) goto wrong_number_args;
+ aMatchinfo = (int*)sqlite3_value_blob(apVal[0]);
+ nMatchinfo = sqlite3_value_bytes(apVal[0]) / sizeof(int);
+ if( nMatchinfo>=2 ){
+ nPhrase = aMatchinfo[0];
+ nCol = aMatchinfo[1];
+ }
+ if( nMatchinfo!=(2+3*nCol*nPhrase) ){
+ sqlite3_result_error(pCtx,
+ "invalid matchinfo blob passed to function rank()", -1);
+ return;
+ }
+ if( nVal!=(1+nCol) ) goto wrong_number_args;
+
+ /* Iterate through each phrase in the users query. */
+ for(iPhrase=0; iPhrase<nPhrase; iPhrase++){
+ int iCol; /* Current column */
+
+ /* Now iterate through each column in the users query. For each column,
+ ** increment the relevancy score by:
+ **
+ ** (<hit count> / <global hit count>) * <column weight>
+ **
+ ** aPhraseinfo[] points to the start of the data for phrase iPhrase. So
+ ** the hit count and global hit counts for each column are found in
+ ** aPhraseinfo[iCol*3] and aPhraseinfo[iCol*3+1], respectively.
+ */
+ int *aPhraseinfo = &aMatchinfo[2 + iPhrase*nCol*3];
+ for(iCol=0; iCol<nCol; iCol++){
+ int nHitCount = aPhraseinfo[3*iCol];
+ int nGlobalHitCount = aPhraseinfo[3*iCol+1];
+ double weight = sqlite3_value_double(apVal[iCol+1]);
+ if( nHitCount>0 ){
+ score += ((double)nHitCount / (double)nGlobalHitCount) * weight;
+ }
+ }
+ }
+
+ sqlite3_result_double(pCtx, score);
+ return;
+
+ /* Jump here if the wrong number of arguments are passed to this function */
+wrong_number_args:
+ sqlite3_result_error(pCtx, "wrong number of arguments to function rank()", -1);
+}
+
+static int SQLITE_TCLAPI install_fts3_rank_function(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
+ sqlite3 *db;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ sqlite3_create_function(db, "rank", -1, SQLITE_UTF8, 0, rankfunc, 0, 0);
+ return TCL_OK;
+}
+
+
+/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_func_Init(Tcl_Interp *interp){
@@ -801,6 +918,7 @@ int Sqlitetest_func_Init(Tcl_Interp *interp){
} aObjCmd[] = {
{ "autoinstall_test_functions", autoinstall_test_funcs },
{ "abuse_create_function", abuse_create_function },
+ { "install_fts3_rank_function", install_fts3_rank_function },
};
int i;
extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);