Location | Tool | Test ID | Function | Issue |
---|---|---|---|---|
tracker-fts.c:95:10 | gcc | function_offsets | assignment discards 'const' qualifier from pointer target type [enabled by default] | |
tracker-fts.c:140:3 | clang-analyzer | Value stored to 'rc' is never read | ||
tracker-fts.c:182:3 | clang-analyzer | Value stored to 'rc' is never read | ||
tracker-fts.c:195:10 | gcc | pointer-sign | function_property_names | pointer targets in assignment differ in signedness |
tracker-fts.c:315:2 | clang-analyzer | Value stored to 'rc' is never read |
1 /*
2 * Copyright (C) 2011 Nokia <ivan.frade@nokia.com>
3 *
4 * Author: Carlos Garnacho <carlos@lanedo.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 */
21
22 #include "config.h"
23 #include <sqlite3.h>
24 #include "tracker-fts-tokenizer.h"
25 #include "tracker-fts.h"
26
27 #ifndef HAVE_BUILTIN_FTS
28 # include "fts3.h"
29 #endif
30
31 gboolean
32 tracker_fts_init (void) {
33 #ifdef HAVE_BUILTIN_FTS
34 /* SQLite has all needed FTS4 features compiled in */
35 return TRUE;
36 #else
37 static gsize module_initialized = 0;
38 int rc = SQLITE_OK;
39
40 if (g_once_init_enter (&module_initialized)) {
41 rc = sqlite3_auto_extension ((void (*) (void)) fts4_extension_init);
42 g_once_init_leave (&module_initialized, (rc == SQLITE_OK));
43 }
44
45 return (module_initialized != 0);
46 #endif
47 }
48
49 static void
50 function_rank (sqlite3_context *context,
51 int argc,
52 sqlite3_value *argv[])
53 {
54 guint *matchinfo, *weights;
55 gdouble rank = 0;
56 gint i, n_columns;
57
58 if (argc != 2) {
59 sqlite3_result_error(context,
60 "wrong number of arguments to function rank()",
61 -1);
62 return;
63 }
64
65 matchinfo = (unsigned int *) sqlite3_value_blob (argv[0]);
66 weights = (unsigned int *) sqlite3_value_blob (argv[1]);
67 n_columns = matchinfo[0];
68
69 for (i = 0; i < n_columns; i++) {
70 if (matchinfo[i + 1] != 0) {
71 rank += (gdouble) weights[i];
72 }
73 }
74
75 sqlite3_result_double(context, rank);
76 }
77
78 static void
79 function_offsets (sqlite3_context *context,
80 int argc,
81 sqlite3_value *argv[])
82 {
83 gchar *offsets, **names;
84 gint offset_values[4];
85 GString *result = NULL;
86 gint i = 0;
87
88 if (argc != 2) {
89 sqlite3_result_error(context,
90 "wrong number of arguments to function tracker_offsets()",
91 -1);
92 return;
93 }
94
95 offsets = sqlite3_value_text (argv[0]);
(emitted by gcc) 96 names = (unsigned int *) sqlite3_value_blob (argv[1]);
97
98 while (offsets && *offsets) {
99 offset_values[i] = g_strtod (offsets, &offsets);
100
101 /* All 4 values from the quartet have been gathered */
102 if (i == 3) {
103 if (!result) {
104 result = g_string_new ("");
105 } else {
106 g_string_append_c (result, ',');
107 }
108
109 g_string_append_printf (result,
110 "%s,%d",
111 names[offset_values[0]],
112 offset_values[2]);
113
114 }
115
116 i = (i + 1) % 4;
117 }
118
119 sqlite3_result_text (context,
120 (result) ? g_string_free (result, FALSE) : NULL,
121 -1, g_free);
122 }
123
124 static void
125 function_weights (sqlite3_context *context,
126 int argc,
127 sqlite3_value *argv[])
128 {
129 static guint *weights = NULL;
130 static gsize weights_initialized = 0;
131
132 if (g_once_init_enter (&weights_initialized)) {
133 GArray *weight_array;
134 sqlite3_stmt *stmt;
135 sqlite3 *db;
136 int rc;
137
138 weight_array = g_array_new (FALSE, FALSE, sizeof (guint));
139 db = sqlite3_context_db_handle (context);
140 rc = sqlite3_prepare_v2 (db,
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
141 "SELECT \"rdf:Property\".\"tracker:weight\" "
142 "FROM \"rdf:Property\" "
143 "WHERE \"rdf:Property\".\"tracker:fulltextIndexed\" = 1 "
144 "ORDER BY \"rdf:Property\".ID ",
145 -1, &stmt, NULL);
146
147 while ((rc = sqlite3_step (stmt)) != SQLITE_DONE) {
148 if (rc == SQLITE_ROW) {
149 guint weight;
150 weight = sqlite3_column_int (stmt, 0);
151 g_array_append_val (weight_array, weight);
152 }
153 }
154
155 if (rc == SQLITE_DONE) {
156 rc = sqlite3_finalize (stmt);
157 }
158
159 weights = (guint *) g_array_free (weight_array, FALSE);
160 g_once_init_leave (&weights_initialized, (rc == SQLITE_OK));
161 }
162
163 sqlite3_result_blob (context, weights, sizeof (weights), NULL);
164 }
165
166 static void
167 function_property_names (sqlite3_context *context,
168 int argc,
169 sqlite3_value *argv[])
170 {
171 static gchar **names = NULL;
172 static gsize names_initialized = 0;
173
174 if (g_once_init_enter (&names_initialized)) {
175 GPtrArray *names_array;
176 sqlite3_stmt *stmt;
177 sqlite3 *db;
178 int rc;
179
180 names_array = g_ptr_array_new ();
181 db = sqlite3_context_db_handle (context);
182 rc = sqlite3_prepare_v2 (db,
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
183 "SELECT Uri "
184 "FROM Resource "
185 "JOIN \"rdf:Property\" "
186 "ON Resource.ID = \"rdf:Property\".ID "
187 "WHERE \"rdf:Property\".\"tracker:fulltextIndexed\" = 1 "
188 "ORDER BY \"rdf:Property\".ID ",
189 -1, &stmt, NULL);
190
191 while ((rc = sqlite3_step (stmt)) != SQLITE_DONE) {
192 if (rc == SQLITE_ROW) {
193 const gchar *name;
194
195 name = sqlite3_column_text (stmt, 0);
(emitted by gcc) 196 g_ptr_array_add (names_array, g_strdup (name));
197 }
198 }
199
200 if (rc == SQLITE_DONE) {
201 rc = sqlite3_finalize (stmt);
202 }
203
204 names = (gchar **) g_ptr_array_free (names_array, FALSE);
205 g_once_init_leave (&names_initialized, (rc == SQLITE_OK));
206 }
207
208 sqlite3_result_blob (context, names, sizeof (names), NULL);
209 }
210
211 static void
212 tracker_fts_register_functions (sqlite3 *db)
213 {
214 sqlite3_create_function (db, "tracker_rank", 2, SQLITE_ANY,
215 NULL, &function_rank,
216 NULL, NULL);
217 sqlite3_create_function (db, "tracker_offsets", 2, SQLITE_ANY,
218 NULL, &function_offsets,
219 NULL, NULL);
220 sqlite3_create_function (db, "fts_column_weights", 0, SQLITE_ANY,
221 NULL, &function_weights,
222 NULL, NULL);
223 sqlite3_create_function (db, "fts_property_names", 0, SQLITE_ANY,
224 NULL, &function_property_names,
225 NULL, NULL);
226 }
227
228 gboolean
229 tracker_fts_init_db (sqlite3 *db) {
230 if (!tracker_tokenizer_initialize (db)) {
231 return FALSE;
232 }
233
234 tracker_fts_register_functions (db);
235 return TRUE;
236 }
237
238 gboolean
239 tracker_fts_create_table (sqlite3 *db,
240 gchar *table_name,
241 GHashTable *tables,
242 GHashTable *grouped_columns)
243 {
244 GString *str, *from, *fts;
245 GHashTableIter iter;
246 gchar *index_table;
247 GList *columns;
248 gint rc;
249
250 /* Create view on tables/columns marked as FTS-indexed */
251 g_hash_table_iter_init (&iter, tables);
252 str = g_string_new ("CREATE VIEW fts_view AS SELECT Resource.ID as rowid ");
253 from = g_string_new ("FROM Resource ");
254
255 fts = g_string_new ("CREATE VIRTUAL TABLE ");
256 g_string_append_printf (fts, "%s USING fts4(content=\"fts_view\", ",
257 table_name);
258
259 while (g_hash_table_iter_next (&iter, (gpointer *) &index_table,
260 (gpointer *) &columns)) {
261 while (columns) {
262 if (grouped_columns &&
263 g_hash_table_lookup (grouped_columns, columns->data)) {
264 g_string_append_printf (str, ", group_concat(\"%s\".\"%s\")",
265 index_table,
266 (gchar *) columns->data);
267 } else {
268 g_string_append_printf (str, ", \"%s\".\"%s\"",
269 index_table,
270 (gchar *) columns->data);
271 }
272
273 g_string_append_printf (str, " AS \"%s\" ",
274 (gchar *) columns->data);
275 g_string_append_printf (fts, "\"%s\", ",
276 (gchar *) columns->data);
277
278 columns = columns->next;
279 }
280
281 g_string_append_printf (from, "LEFT OUTER JOIN \"%s\" ON "
282 " Resource.ID = \"%s\".ID ",
283 index_table, index_table);
284 }
285
286 g_string_append (str, from->str);
287 g_string_free (from, TRUE);
288
289 rc = sqlite3_exec(db, str->str, NULL, 0, NULL);
290 g_string_free (str, TRUE);
291
292 if (rc != SQLITE_OK) {
293 return FALSE;
294 }
295
296 g_string_append (fts, "tokenize=TrackerTokenizer)");
297 rc = sqlite3_exec(db, fts->str, NULL, 0, NULL);
298 g_string_free (fts, TRUE);
299
300 return (rc == SQLITE_OK);
301 }
302
303 gboolean
304 tracker_fts_alter_table (sqlite3 *db,
305 gchar *table_name,
306 GHashTable *tables,
307 GHashTable *grouped_columns)
308 {
309 gchar *query, *tmp_name;
310 int rc;
311
312 tmp_name = g_strdup_printf ("%s_TMP", table_name);
313
314 query = g_strdup_printf ("DROP VIEW fts_view");
315 rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
316
317 if (!tracker_fts_create_table (db, tmp_name, tables, grouped_columns)) {
318 g_free (tmp_name);
319 g_free (query);
320 return FALSE;
321 }
322
323 query = g_strdup_printf ("INSERT INTO %s (docid) SELECT docid FROM %s",
324 tmp_name, table_name);
325 rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
326 g_free (query);
327
328 if (rc != SQLITE_OK) {
329 g_free (tmp_name);
330 return FALSE;
331 }
332
333 query = g_strdup_printf ("INSERT INTO %s(%s) VALUES('rebuild')",
334 tmp_name, tmp_name);
335 rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
336 g_free (query);
337
338 if (rc != SQLITE_OK) {
339 g_free (tmp_name);
340 return FALSE;
341 }
342
343 query = g_strdup_printf ("ALTER TABLE %s RENAME TO %s",
344 tmp_name, table_name);
345 rc = sqlite3_prepare_v2 (db, query, -1, NULL, NULL);
346 g_free (query);
347 g_free (tmp_name);
348
349
350 if (rc != SQLITE_OK) {
351 g_free (tmp_name);
352 return FALSE;
353 }
354
355 return TRUE;
356 }