Update Chinese (China) translation
[yelp.git] / libyelp / yelp-sqlite-storage.c
blobc872f729800bdec83dc8cc94b577cae3e82d3229
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Copyright (C) 2011 Shaun McCance <shaunm@gnome.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Shaun McCance <shaunm@gnome.org>
21 #include "config.h"
23 #include <glib/gi18n.h>
24 #include <sqlite3.h>
26 #include "yelp-sqlite-storage.h"
28 static void yelp_sqlite_storage_iface_init (YelpStorageInterface *iface);
29 static void yelp_sqlite_storage_finalize (GObject *object);
30 static void yelp_sqlite_storage_get_property (GObject *object,
31 guint prop_id,
32 GValue *value,
33 GParamSpec *pspec);
34 static void yelp_sqlite_storage_set_property (GObject *object,
35 guint prop_id,
36 const GValue *value,
37 GParamSpec *pspec);
39 static void yelp_sqlite_storage_update (YelpStorage *storage,
40 const gchar *doc_uri,
41 const gchar *full_uri,
42 const gchar *title,
43 const gchar *desc,
44 const gchar *icon,
45 const gchar *text);
46 static GVariant * yelp_sqlite_storage_search (YelpStorage *storage,
47 const gchar *doc_uri,
48 const gchar *text);
49 static gchar * yelp_sqlite_storage_get_root_title (YelpStorage *storage,
50 const gchar *doc_uri);
51 static void yelp_sqlite_storage_set_root_title (YelpStorage *storage,
52 const gchar *doc_uri,
53 const gchar *title);
55 typedef struct _YelpSqliteStoragePrivate YelpSqliteStoragePrivate;
56 struct _YelpSqliteStoragePrivate {
57 gchar *filename;
58 sqlite3 *db;
59 GMutex mutex;
62 enum {
63 PROP_0,
64 PROP_FILENAME
67 G_DEFINE_TYPE_WITH_CODE (YelpSqliteStorage, yelp_sqlite_storage, G_TYPE_OBJECT,
68 G_IMPLEMENT_INTERFACE (YELP_TYPE_STORAGE,
69 yelp_sqlite_storage_iface_init))
70 #define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_SQLITE_STORAGE, YelpSqliteStoragePrivate))
72 static void
73 yelp_sqlite_storage_finalize (GObject *object)
75 YelpSqliteStoragePrivate *priv = GET_PRIV (object);
77 if (priv->filename)
78 g_free (priv->filename);
80 if (priv->db)
81 sqlite3_close (priv->db);
83 g_mutex_clear (&priv->mutex);
85 G_OBJECT_CLASS (yelp_sqlite_storage_parent_class)->finalize (object);
88 static void
89 yelp_sqlite_storage_init (YelpSqliteStorage *storage)
91 YelpSqliteStoragePrivate *priv = GET_PRIV (storage);
92 g_mutex_init (&priv->mutex);
95 static void
96 yelp_sqlite_storage_constructed (GObject *object)
98 int status;
99 sqlite3_stmt *stmt = NULL;
100 YelpSqliteStoragePrivate *priv = GET_PRIV (object);
102 if (priv->filename != NULL)
103 status = sqlite3_open (priv->filename, &(priv->db));
104 else
105 status = sqlite3_open (":memory:", &(priv->db));
107 if (status != SQLITE_OK)
108 return;
110 status = sqlite3_prepare_v2 (priv->db,
111 "create virtual table pages using fts4("
112 " doc_uri, lang, full_uri,"
113 " title, desc, icon, body"
114 ");",
115 -1, &stmt, NULL);
116 if (status != SQLITE_OK)
117 return;
118 sqlite3_step (stmt);
119 sqlite3_finalize (stmt);
121 status = sqlite3_prepare_v2 (priv->db,
122 "create table titles (doc_uri text, lang text, title text);",
123 -1, &stmt, NULL);
124 if (status != SQLITE_OK)
125 return;
126 sqlite3_step (stmt);
127 sqlite3_finalize (stmt);
130 static void
131 yelp_sqlite_storage_class_init (YelpSqliteStorageClass *klass)
133 GObjectClass *object_class = G_OBJECT_CLASS (klass);
135 object_class->constructed = yelp_sqlite_storage_constructed;
136 object_class->finalize = yelp_sqlite_storage_finalize;
137 object_class->get_property = yelp_sqlite_storage_get_property;
138 object_class->set_property = yelp_sqlite_storage_set_property;
140 g_type_class_add_private (klass, sizeof (YelpSqliteStoragePrivate));
142 g_object_class_install_property (object_class,
143 PROP_FILENAME,
144 g_param_spec_string ("filename",
145 "Database filename",
146 "The filename of the sqlite database",
147 NULL,
148 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
149 G_PARAM_STATIC_STRINGS));
152 static void
153 yelp_sqlite_storage_iface_init (YelpStorageInterface *iface)
155 iface->update = yelp_sqlite_storage_update;
156 iface->search = yelp_sqlite_storage_search;
157 iface->get_root_title = yelp_sqlite_storage_get_root_title;
158 iface->set_root_title = yelp_sqlite_storage_set_root_title;
161 YelpStorage *
162 yelp_sqlite_storage_new (const gchar *filename)
164 YelpStorage *storage;
166 storage = g_object_new (YELP_TYPE_SQLITE_STORAGE,
167 "filename", filename,
168 NULL);
170 return storage;
173 static void
174 yelp_sqlite_storage_get_property (GObject *object,
175 guint prop_id,
176 GValue *value,
177 GParamSpec *pspec)
179 YelpSqliteStoragePrivate *priv = GET_PRIV (object);
181 switch (prop_id) {
182 case PROP_FILENAME:
183 g_value_set_string (value, priv->filename);
184 break;
185 default:
186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187 break;
191 static void
192 yelp_sqlite_storage_set_property (GObject *object,
193 guint prop_id,
194 const GValue *value,
195 GParamSpec *pspec)
197 YelpSqliteStoragePrivate *priv = GET_PRIV (object);
199 switch (prop_id) {
200 case PROP_FILENAME:
201 priv->filename = g_value_dup_string (value);
202 break;
203 default:
204 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
205 break;
209 /******************************************************************************/
211 static void
212 yelp_sqlite_storage_update (YelpStorage *storage,
213 const gchar *doc_uri,
214 const gchar *full_uri,
215 const gchar *title,
216 const gchar *desc,
217 const gchar *icon,
218 const gchar *text)
220 sqlite3_stmt *stmt = NULL;
221 YelpSqliteStoragePrivate *priv = GET_PRIV (storage);
223 g_mutex_lock (&priv->mutex);
225 sqlite3_prepare_v2 (priv->db,
226 "delete from pages where doc_uri = ? and lang = ? and full_uri = ?;",
227 -1, &stmt, NULL);
228 sqlite3_bind_text (stmt, 1, doc_uri, -1, SQLITE_TRANSIENT);
229 sqlite3_bind_text (stmt, 2, g_get_language_names()[0], -1, SQLITE_STATIC);
230 sqlite3_bind_text (stmt, 3, full_uri, -1, SQLITE_TRANSIENT);
231 sqlite3_step (stmt);
232 sqlite3_finalize (stmt);
234 sqlite3_prepare_v2 (priv->db,
235 "insert into pages (doc_uri, lang, full_uri, title, desc, icon, body)"
236 " values (?, ?, ?, ?, ?, ?, ?);",
237 -1, &stmt, NULL);
238 sqlite3_bind_text (stmt, 1, doc_uri, -1, SQLITE_TRANSIENT);
239 sqlite3_bind_text (stmt, 2, g_get_language_names()[0], -1, SQLITE_STATIC);
240 sqlite3_bind_text (stmt, 3, full_uri, -1, SQLITE_TRANSIENT);
241 sqlite3_bind_text (stmt, 4, title, -1, SQLITE_TRANSIENT);
242 sqlite3_bind_text (stmt, 5, desc, -1, SQLITE_TRANSIENT);
243 sqlite3_bind_text (stmt, 6, icon, -1, SQLITE_TRANSIENT);
244 sqlite3_bind_text (stmt, 7, text, -1, SQLITE_TRANSIENT);
245 sqlite3_step (stmt);
246 sqlite3_finalize (stmt);
248 g_mutex_unlock (&priv->mutex);
251 static GVariant *
252 yelp_sqlite_storage_search (YelpStorage *storage,
253 const gchar *doc_uri,
254 const gchar *text)
256 sqlite3_stmt *stmt = NULL;
257 GVariantBuilder builder;
258 GVariant *ret;
259 YelpSqliteStoragePrivate *priv = GET_PRIV (storage);
261 g_mutex_lock (&priv->mutex);
263 sqlite3_prepare_v2 (priv->db,
264 "select full_uri, title, desc, icon from pages where"
265 " doc_uri = ? and lang = ? and body match ?;",
266 -1, &stmt, NULL);
267 sqlite3_bind_text (stmt, 1, doc_uri, -1, SQLITE_TRANSIENT);
268 sqlite3_bind_text (stmt, 2, g_get_language_names()[0], -1, SQLITE_STATIC);
269 sqlite3_bind_text (stmt, 3, text, -1, SQLITE_TRANSIENT);
271 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ssss)"));
272 while (sqlite3_step (stmt) == SQLITE_ROW) {
273 g_variant_builder_add (&builder, "(ssss)",
274 sqlite3_column_text (stmt, 0),
275 sqlite3_column_text (stmt, 1),
276 sqlite3_column_text (stmt, 2),
277 sqlite3_column_text (stmt, 3));
279 sqlite3_finalize (stmt);
280 ret = g_variant_new ("a(ssss)", &builder);
282 g_mutex_unlock (&priv->mutex);
284 return ret;
287 static gchar *
288 yelp_sqlite_storage_get_root_title (YelpStorage *storage,
289 const gchar *doc_uri)
291 gchar *ret = NULL;
292 sqlite3_stmt *stmt = NULL;
293 YelpSqliteStoragePrivate *priv = GET_PRIV (storage);
295 g_mutex_lock (&priv->mutex);
297 sqlite3_prepare_v2 (priv->db,
298 "select title from titles where doc_uri = ? and lang = ?;",
299 -1, &stmt, NULL);
300 sqlite3_bind_text (stmt, 1, doc_uri, -1, SQLITE_TRANSIENT);
301 sqlite3_bind_text (stmt, 2, g_get_language_names()[0], -1, SQLITE_STATIC);
302 if (sqlite3_step (stmt) == SQLITE_ROW)
303 ret = g_strdup ((const gchar *) sqlite3_column_text (stmt, 0));
304 sqlite3_finalize (stmt);
306 g_mutex_unlock (&priv->mutex);
307 return ret;
310 static void
311 yelp_sqlite_storage_set_root_title (YelpStorage *storage,
312 const gchar *doc_uri,
313 const gchar *title)
315 sqlite3_stmt *stmt = NULL;
316 YelpSqliteStoragePrivate *priv = GET_PRIV (storage);
318 g_mutex_lock (&priv->mutex);
320 sqlite3_prepare_v2 (priv->db,
321 "delete from titles where doc_uri = ? and lang = ?;",
322 -1, &stmt, NULL);
323 sqlite3_bind_text (stmt, 1, doc_uri, -1, SQLITE_TRANSIENT);
324 sqlite3_bind_text (stmt, 2, g_get_language_names()[0], -1, SQLITE_STATIC);
325 sqlite3_step (stmt);
326 sqlite3_finalize (stmt);
328 sqlite3_prepare_v2 (priv->db,
329 "insert into titles (doc_uri, lang, title)"
330 " values (?, ?, ?);",
331 -1, &stmt, NULL);
332 sqlite3_bind_text (stmt, 1, doc_uri, -1, SQLITE_TRANSIENT);
333 sqlite3_bind_text (stmt, 2, g_get_language_names()[0], -1, SQLITE_STATIC);
334 sqlite3_bind_text (stmt, 3, title, -1, SQLITE_TRANSIENT);
335 sqlite3_step (stmt);
336 sqlite3_finalize (stmt);
338 g_mutex_unlock (&priv->mutex);