[epiphany/history-rewrite: 45/45] ephy-history-service: add the hosts table and plug it
- From: Claudio Saavedra <csaavedra src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/history-rewrite: 45/45] ephy-history-service: add the hosts table and plug it
- Date: Wed, 24 Aug 2011 19:43:05 +0000 (UTC)
commit 6f826c4a20d379ae16f93ef0036efa41318f71fb
Author: Claudio Saavedra <csaavedra igalia com>
Date: Wed Aug 3 18:39:43 2011 +0300
ephy-history-service: add the hosts table and plug it
Add the methods needed to work with hosts and ensure the hosts are
up-to-date upon addition of visits to the history.
One thing that is missing: on removal of urls from the history the
hosts remain in the database. Ideally, we need to remove a host once
all the urls referring to it are gone.
Also, it is probably a bad idea to store the visit count in this
table, since removing urls from the database would make the count
inconsistent. We need to either update it or to just remove it and
make the client-code calculate it on demand through sql.
lib/history/ephy-history-service-hosts-table.c | 318 ++++++++++++++++++++++++
lib/history/ephy-history-service-private.h | 7 +
lib/history/ephy-history-service-urls-table.c | 8 +-
lib/history/ephy-history-service.c | 10 +-
4 files changed, 339 insertions(+), 4 deletions(-)
---
diff --git a/lib/history/ephy-history-service-hosts-table.c b/lib/history/ephy-history-service-hosts-table.c
new file mode 100644
index 0000000..e790796
--- /dev/null
+++ b/lib/history/ephy-history-service-hosts-table.c
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* vim: set sw=2 ts=2 sts=2 et: */
+/*
+ * Copyright  2011 Igalia S.L.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "ephy-history-service.h"
+#include "ephy-history-service-private.h"
+#include "ephy-string.h"
+#include <glib/gi18n.h>
+
+gboolean
+ephy_history_service_initialize_hosts_table (EphyHistoryService *self)
+{
+ EphyHistoryServicePrivate *priv = EPHY_HISTORY_SERVICE (self)->priv;
+ GError *error = NULL;
+
+ if (ephy_sqlite_connection_table_exists (priv->history_database, "hosts")) {
+ return TRUE;
+ }
+ ephy_sqlite_connection_execute (priv->history_database,
+ "CREATE TABLE hosts ("
+ "id INTEGER PRIMARY KEY,"
+ "url LONGVARCAR,"
+ "title LONGVARCAR,"
+ "visit_count INTEGER DEFAULT 0 NOT NULL,"
+ "favicon_id INTEGER DEFAULT 0 NOT NULL)", &error);
+
+ if (error) {
+ g_error("Could not create hosts table: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+ ephy_history_service_schedule_commit (self);
+ return TRUE;
+}
+
+void
+ephy_history_service_add_host_row (EphyHistoryService *self, EphyHistoryHost *host)
+{
+ EphyHistoryServicePrivate *priv = EPHY_HISTORY_SERVICE (self)->priv;
+ EphySQLiteStatement *statement = NULL;
+ GError *error = NULL;
+
+ g_assert (priv->history_thread == g_thread_self ());
+ g_assert (priv->history_database != NULL);
+
+ statement = ephy_sqlite_connection_create_statement (priv->history_database,
+ "INSERT INTO hosts (url, title, visit_count) "
+ "VALUES (?, ?, ?)", &error);
+
+ if (error) {
+ g_error ("Could not build hosts table addition statement: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ if (ephy_sqlite_statement_bind_string (statement, 0, host->url, &error) == FALSE ||
+ ephy_sqlite_statement_bind_string (statement, 1, host->title, &error) == FALSE ||
+ ephy_sqlite_statement_bind_int (statement, 2, host->visit_count, &error) == FALSE) {
+ g_error ("Could not insert host into hosts table: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ ephy_sqlite_statement_step (statement, &error);
+ if (error) {
+ g_error ("Could not insert host into hosts table: %s", error->message);
+ g_error_free (error);
+ return;
+ } else {
+ host->id = ephy_sqlite_connection_get_last_insert_id (priv->history_database);
+ }
+
+ g_object_unref (statement);
+}
+
+void
+ephy_history_service_update_host_row (EphyHistoryService *self, EphyHistoryHost *host)
+{
+ EphyHistoryServicePrivate *priv = EPHY_HISTORY_SERVICE (self)->priv;
+ EphySQLiteStatement *statement;
+ GError *error = NULL;
+
+ g_assert (priv->history_thread == g_thread_self ());
+ g_assert (priv->history_database != NULL);
+
+ statement = ephy_sqlite_connection_create_statement (priv->history_database,
+ "UPDATE hosts SET url=?, title=?, visit_count=?"
+ "WHERE id=?", &error);
+ if (error) {
+ g_error ("Could not build hosts table modification statement: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ if (ephy_sqlite_statement_bind_string (statement, 0, host->url, &error) == FALSE ||
+ ephy_sqlite_statement_bind_string (statement, 1, host->title, &error) == FALSE ||
+ ephy_sqlite_statement_bind_int (statement, 2, host->visit_count, &error) == FALSE ||
+ ephy_sqlite_statement_bind_int (statement, 3, host->id, &error) == FALSE) {
+ g_error ("Could not modify host in hosts table: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ ephy_sqlite_statement_step (statement, &error);
+ if (error) {
+ g_error ("Could not modify URL in urls table: %s", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (statement);
+}
+
+EphyHistoryHost*
+ephy_history_service_get_host_row (EphyHistoryService *self, const gchar *host_string, EphyHistoryHost *host)
+{
+ EphyHistoryServicePrivate *priv = EPHY_HISTORY_SERVICE (self)->priv;
+ EphySQLiteStatement *statement = NULL;
+ GError *error = NULL;
+
+ g_assert (priv->history_thread == g_thread_self ());
+ g_assert (priv->history_database != NULL);
+
+ if (host_string == NULL && host != NULL) {
+ host_string = host->url;
+ }
+ g_assert (host_string || host->id !=-1);
+
+ if (host != NULL && host->id != -1) {
+ statement = ephy_sqlite_connection_create_statement (priv->history_database,
+ "SELECT id, url, title, visit_count FROM hosts "
+ "WHERE id=?", &error);
+ } else {
+ statement = ephy_sqlite_connection_create_statement (priv->history_database,
+ "SELECT id, url, title, visit_count FROM hosts "
+ "WHERE url=?", &error);
+ }
+
+ if (error) {
+ g_error ("Could not build hosts query statement: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ if (host != NULL && host->id != -1) {
+ ephy_sqlite_statement_bind_int (statement, 0, host->id, &error);
+ } else {
+ ephy_sqlite_statement_bind_string (statement, 0, host_string, &error);
+ }
+ if (error) {
+ g_error ("Could not build hosts table query statement: %s", error->message);
+ g_error_free (error);
+ g_object_unref (statement);
+ return NULL;
+ }
+
+ if (ephy_sqlite_statement_step (statement, &error) == FALSE) {
+ g_object_unref (statement);
+ return NULL;
+ }
+
+ if (host == NULL) {
+ host = ephy_history_host_new (NULL, NULL, 0);
+ } else {
+ if (host->url)
+ g_free (host->url);
+ if (host->title)
+ g_free (host->title);
+ }
+
+ host->id = ephy_sqlite_statement_get_column_as_int (statement, 0);
+ host->url = g_strdup (ephy_sqlite_statement_get_column_as_string (statement, 1)),
+ host->title = g_strdup (ephy_sqlite_statement_get_column_as_string (statement, 2)),
+ host->visit_count = ephy_sqlite_statement_get_column_as_int (statement, 3),
+
+ g_object_unref (statement);
+ return host;
+}
+
+static EphyHistoryHost*
+create_host_from_statement (EphySQLiteStatement *statement)
+{
+ EphyHistoryHost *host =
+ ephy_history_host_new (ephy_sqlite_statement_get_column_as_string (statement, 1),
+ ephy_sqlite_statement_get_column_as_string (statement, 2),
+ ephy_sqlite_statement_get_column_as_int (statement, 3));
+ host->id = ephy_sqlite_statement_get_column_as_int (statement, 0);
+
+ return host;
+}
+
+GList*
+ephy_history_service_get_all_hosts (EphyHistoryService *self)
+{
+ EphyHistoryServicePrivate *priv = EPHY_HISTORY_SERVICE (self)->priv;
+ EphySQLiteStatement *statement = NULL;
+ GList *hosts = NULL;
+ GError *error = NULL;
+
+ g_assert (priv->history_thread == g_thread_self ());
+ g_assert (priv->history_database != NULL);
+
+ statement = ephy_sqlite_connection_create_statement (priv->history_database,
+ "SELECT id, url, title, visit_count FROM hosts", &error);
+
+ if (error) {
+ g_error ("Could not build hosts query statement: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ while (ephy_sqlite_statement_step (statement, &error)) {
+ hosts = g_list_prepend (hosts, create_host_from_statement (statement));
+ }
+ hosts = g_list_reverse (hosts);
+
+ if (error) {
+ g_error ("Could not execute hosts table query statement: %s", error->message);
+ g_error_free (error);
+ }
+ g_object_unref (statement);
+
+ return hosts;
+}
+
+/* Inspired from ephy-history.c */
+static GList *
+get_hostname_and_locations (const gchar *url, gchar **hostname)
+{
+ GList *host_locations = NULL;
+ char *scheme = NULL;
+
+ if (url)
+ {
+ scheme = g_uri_parse_scheme (url);
+ *hostname = ephy_string_get_host_name (url);
+ }
+ /* Build an host name */
+ if (scheme == NULL || *hostname == NULL) {
+ *hostname = g_strdup (_("Others"));
+ host_locations = g_list_append (host_locations,
+ g_strdup ("about:blank"));
+ } else if (strcmp (scheme, "file") == 0) {
+ *hostname = g_strdup (_("Local files"));
+ host_locations = g_list_append (host_locations,
+ g_strdup ("file:///"));
+ } else {
+ char *location;
+ char *tmp;
+
+ if (g_str_equal (scheme, "https")) {
+ /* If scheme is https, we still fake http. */
+ location = g_strconcat ("http://", *hostname, "/", NULL);
+ host_locations = g_list_append (host_locations, location);
+ }
+
+ /* We append the real address */
+ location = g_strconcat (scheme,
+ "://", *hostname, "/", NULL);
+ host_locations = g_list_append (host_locations, location);
+
+ /* and also a fake www-modified address if it's http or https. */
+ if (g_str_has_prefix (scheme, "http")) {
+ if (g_str_has_prefix (*hostname, "www.")) {
+ tmp = g_strdup (*hostname + 4);
+ } else {
+ tmp = g_strconcat ("www.", *hostname, NULL);
+ }
+ location = g_strconcat ("http://", tmp, "/", NULL);
+ g_free (tmp);
+ host_locations = g_list_append (host_locations, location);
+ }
+ }
+ return host_locations;
+}
+
+EphyHistoryHost*
+ephy_history_service_get_host_row_from_url (EphyHistoryService *self,
+ const gchar *url)
+{
+ GList *host_locations, *l;
+ char *hostname;
+ EphyHistoryHost *host;
+
+ host_locations = get_hostname_and_locations (url, &hostname);
+
+ for (l = host_locations; l != NULL; l = l->next) {
+ host = ephy_history_service_get_host_row (self, l->data, NULL);
+ if (host != NULL)
+ break;
+ }
+
+ if (host == NULL) {
+ host = ephy_history_host_new (host_locations->data, hostname, 0);
+ ephy_history_service_add_host_row (self, host);
+ }
+
+ g_free (hostname);
+ g_list_free_full (host_locations, (GDestroyNotify) g_free);
+
+ return host;
+}
diff --git a/lib/history/ephy-history-service-private.h b/lib/history/ephy-history-service-private.h
index 94e8d8e..560e7b6 100644
--- a/lib/history/ephy-history-service-private.h
+++ b/lib/history/ephy-history-service-private.h
@@ -43,4 +43,11 @@ gboolean ephy_history_service_initialize_visits_table (EphyHisto
void ephy_history_service_add_visit_row (EphyHistoryService *self, EphyHistoryPageVisit *visit);
GList * ephy_history_service_find_visit_rows (EphyHistoryService *self, EphyHistoryQuery *query);
+gboolean ephy_history_service_initialize_hosts_table (EphyHistoryService *self);
+void ephy_history_service_add_host_row (EphyHistoryService *self, EphyHistoryHost *host);
+void ephy_history_service_update_host_row (EphyHistoryService *self, EphyHistoryHost *host);
+EphyHistoryHost * ephy_history_service_get_host_row (EphyHistoryService *self, const gchar *url_string, EphyHistoryHost *host);
+GList * ephy_history_service_get_all_hosts (EphyHistoryService *self);
+EphyHistoryHost * ephy_history_service_get_host_row_from_url (EphyHistoryService *self, const gchar *url);
+
#endif /* EPHY_HISTORY_SERVICE_PRIVATE_H */
diff --git a/lib/history/ephy-history-service-urls-table.c b/lib/history/ephy-history-service-urls-table.c
index 56eb58c..61e8eb9 100644
--- a/lib/history/ephy-history-service-urls-table.c
+++ b/lib/history/ephy-history-service-urls-table.c
@@ -35,6 +35,7 @@ ephy_history_service_initialize_urls_table (EphyHistoryService *self)
ephy_sqlite_connection_execute (priv->history_database,
"CREATE TABLE urls ("
"id INTEGER PRIMARY KEY,"
+ "host INTEGER NOT NULL REFERENCES hosts(id) ON DELETE CASCADE,"
"url LONGVARCAR,"
"title LONGVARCAR,"
"visit_count INTEGER DEFAULT 0 NOT NULL,"
@@ -131,8 +132,8 @@ ephy_history_service_add_url_row (EphyHistoryService *self, EphyHistoryURL *url)
g_assert (priv->history_database != NULL);
statement = ephy_sqlite_connection_create_statement (priv->history_database,
- "INSERT INTO urls (url, title, visit_count, typed_count, last_visit_time, zoom_level) "
- " VALUES (?, ?, ?, ?, ?, ?)", &error);
+ "INSERT INTO urls (url, title, visit_count, typed_count, last_visit_time, zoom_level, host) "
+ " VALUES (?, ?, ?, ?, ?, ?, ?)", &error);
if (error) {
g_error ("Could not build urls table addition statement: %s", error->message);
g_error_free (error);
@@ -144,7 +145,8 @@ ephy_history_service_add_url_row (EphyHistoryService *self, EphyHistoryURL *url)
ephy_sqlite_statement_bind_int (statement, 2, url->visit_count, &error) == FALSE ||
ephy_sqlite_statement_bind_int (statement, 3, url->typed_count, &error) == FALSE ||
ephy_sqlite_statement_bind_int (statement, 4, url->last_visit_time, &error) == FALSE ||
- ephy_sqlite_statement_bind_double (statement, 5, url->zoom_level, &error) == FALSE) {
+ ephy_sqlite_statement_bind_double (statement, 5, url->zoom_level, &error) == FALSE ||
+ ephy_sqlite_statement_bind_int (statement, 6, url->host->id, &error) == FALSE) {
g_error ("Could not insert URL into urls table: %s", error->message);
g_error_free (error);
return;
diff --git a/lib/history/ephy-history-service.c b/lib/history/ephy-history-service.c
index aa12fa7..9fc9d63 100644
--- a/lib/history/ephy-history-service.c
+++ b/lib/history/ephy-history-service.c
@@ -267,7 +267,8 @@ ephy_history_service_open_database_connections (EphyHistoryService *self)
return FALSE;
}
- if ((ephy_history_service_initialize_urls_table (self) == FALSE) ||
+ if ((ephy_history_service_initialize_hosts_table (self) == FALSE) ||
+ (ephy_history_service_initialize_urls_table (self) == FALSE) ||
(ephy_history_service_initialize_visits_table (self) == FALSE)) {
return FALSE;
}
@@ -413,6 +414,13 @@ ephy_history_service_execute_job_on_history_thread (gpointer data)
static gboolean
ephy_history_service_execute_add_visit_helper (EphyHistoryService *self, EphyHistoryPageVisit *visit)
{
+ if (visit->url->host == NULL) {
+ visit->url->host = ephy_history_service_get_host_row_from_url (self, visit->url->url);
+ }
+
+ visit->url->host->visit_count++;
+ ephy_history_service_update_host_row (self, visit->url->host);
+
/* A NULL return here means that the URL does not yet exist in the database */
if (NULL == ephy_history_service_get_url_row (self, visit->url->url, visit->url)) {
visit->url->last_visit_time = visit->visit_time;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]