[tracker/wip/fts4: 5/21] libtracker-fts: Add the tracker_rank() sqlite function



commit 6f3102851a888b2a2422d5f3431c24f0fdd9a7f6
Author: Carlos Garnacho <carlos lanedo com>
Date:   Fri Nov 4 12:49:34 2011 +0100

    libtracker-fts: Add the tracker_rank() sqlite function
    
    This is now used in FTS searches to provide the rank based on
    the matched columns and their respective property weight.

 src/libtracker-data/tracker-sparql-pattern.vala |    3 +-
 src/libtracker-fts/tracker-fts.c                |   84 +++++++++++++++++++++++
 2 files changed, 86 insertions(+), 1 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-pattern.vala b/src/libtracker-data/tracker-sparql-pattern.vala
index 8e5bba3..a12dc3e 100644
--- a/src/libtracker-data/tracker-sparql-pattern.vala
+++ b/src/libtracker-data/tracker-sparql-pattern.vala
@@ -1470,7 +1470,8 @@ class Tracker.Sparql.Pattern : Object {
 				binding.sql_db_column_name = "fts";
 				triple_context.bindings.append (binding);
 
-				sql.append_printf ("rank(\"%s\".\"fts\") AS \"%s_u_rank\", ",
+				sql.append_printf ("tracker_rank(matchinfo(\"%s\".\"fts\", 'cl'),fts_column_weights()) " +
+                                                   "AS \"%s_u_rank\", ",
 					binding.table.sql_query_tablename,
 					context.get_variable (current_subject).name);
 				sql.append_printf ("offsets(\"%s\".\"fts\") AS \"%s_u_offsets\", ",
diff --git a/src/libtracker-fts/tracker-fts.c b/src/libtracker-fts/tracker-fts.c
index 23c6f46..8909687 100644
--- a/src/libtracker-fts/tracker-fts.c
+++ b/src/libtracker-fts/tracker-fts.c
@@ -37,12 +37,96 @@ tracker_fts_init (void) {
 	return (module_initialized != 0);
 }
 
+static void
+function_rank (sqlite3_context *context,
+               int              argc,
+               sqlite3_value   *argv[])
+{
+	guint *matchinfo, *weights;
+	gdouble rank = 0;
+	gint i, n_columns;
+
+	if (argc != 2) {
+		sqlite3_result_error(context,
+		                     "wrong number of arguments to function rank()",
+		                     -1);
+		return;
+	}
+
+	matchinfo = (unsigned int *) sqlite3_value_blob (argv[0]);
+	weights = (unsigned int *) sqlite3_value_blob (argv[1]);
+	n_columns = matchinfo[0];
+
+	for (i = 0; i < n_columns; i++) {
+		if (matchinfo[i + 1] != 0) {
+			rank += (gdouble) weights[i];
+		}
+	}
+
+	sqlite3_result_double(context, rank);
+}
+
+static void
+function_weights (sqlite3_context *context,
+                  int              argc,
+                  sqlite3_value   *argv[])
+{
+	static guint *weights = NULL;
+	static gsize weights_initialized = 0;
+
+	if (g_once_init_enter (&weights_initialized)) {
+		GArray *weight_array;
+		sqlite3_stmt *stmt;
+		sqlite3 *db;
+		int rc;
+
+		weight_array = g_array_new (FALSE, FALSE, sizeof (guint));
+		db = sqlite3_context_db_handle (context);
+		rc = sqlite3_prepare_v2 (db,
+		                         "SELECT \"rdf:Property\".\"tracker:weight\" "
+		                         "FROM \"rdf:Property\" "
+		                         "WHERE \"rdf:Property\".\"tracker:fulltextIndexed\" = 1 "
+		                         "ORDER BY \"rdf:Property\".ID ",
+		                         -1, &stmt, NULL);
+
+		while ((rc = sqlite3_step (stmt)) != SQLITE_DONE) {
+			if (rc == SQLITE_ROW) {
+				guint weight;
+				weight = sqlite3_column_int (stmt, 0);
+				g_array_append_val (weight_array, weight);
+			}
+		}
+
+		if (rc == SQLITE_DONE) {
+			rc = sqlite3_finalize (stmt);
+		}
+
+		weights = g_array_free (weight_array, FALSE);
+		g_once_init_leave (&weights_initialized, (rc == SQLITE_OK));
+	}
+
+	sqlite3_result_blob (context, weights, sizeof (weights), NULL);
+}
+
+
+static void
+tracker_fts_register_functions (sqlite3 *db)
+{
+	sqlite3_create_function (db, "tracker_rank", 2, SQLITE_ANY,
+	                         NULL, &function_rank,
+	                         NULL, NULL);
+	sqlite3_create_function (db, "fts_column_weights", 0, SQLITE_ANY,
+	                         NULL, &function_weights,
+	                         NULL, NULL);
+}
+
 gboolean
 tracker_fts_init_db (sqlite3 *db) {
 	if (!tracker_tokenizer_initialize (db)) {
 		return FALSE;
 	}
 
+	tracker_fts_register_functions (db);
 	return TRUE;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]