[tracker/cursor] Added a TrackerDBCursor API



commit 764db61ba8bde2e548e01c743298285a375571c3
Author: Philip Van Hoof <philip codeminded be>
Date:   Wed Aug 26 16:13:36 2009 +0200

    Added a TrackerDBCursor API

 src/libtracker-db/tracker-db-interface-sqlite.c |  211 +++++++++++++++++++++++
 src/libtracker-db/tracker-db-interface.c        |   63 +++++++
 src/libtracker-db/tracker-db-interface.h        |   41 +++++
 3 files changed, 315 insertions(+), 0 deletions(-)
---
diff --git a/src/libtracker-db/tracker-db-interface-sqlite.c b/src/libtracker-db/tracker-db-interface-sqlite.c
index 50a5dc7..97e44d4 100644
--- a/src/libtracker-db/tracker-db-interface-sqlite.c
+++ b/src/libtracker-db/tracker-db-interface-sqlite.c
@@ -30,14 +30,36 @@
 
 #include "tracker-db-interface-sqlite.h"
 
+#define TRACKER_TYPE_DB_CURSOR_SQLITE         (tracker_db_cursor_sqlite_get_type ())
+#define TRACKER_DB_CURSOR_SQLITE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_DB_CURSOR_SQLITE, TrackerDBCursorSqlite))
+#define TRACKER_DB_CURSOR_SQLITE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_DB_CURSOR_SQLITE, TrackerDBCursorSqliteClass))
+#define TRACKER_IS_DB_CURSOR_SQLITE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_DB_CURSOR_SQLITE))
+#define TRACKER_IS_DB_CURSOR_SQLITE_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((o),    TRACKER_TYPE_DB_CURSOR_SQLITE))
+#define TRACKER_DB_CURSOR_SQLITE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_DB_CURSOR_SQLITE, TrackerDBCursorSqliteClass))
+
+
 #define TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_DB_INTERFACE_SQLITE, TrackerDBInterfaceSqlitePrivate))
 
 #define TRACKER_DB_STATEMENT_SQLITE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_DB_STATEMENT_SQLITE, TrackerDBStatementSqlitePrivate))
 
+#define TRACKER_DB_CURSOR_SQLITE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_DB_CURSOR_SQLITE, TrackerDBCursorSqlitePrivate))
+
 typedef struct TrackerDBInterfaceSqlitePrivate TrackerDBInterfaceSqlitePrivate;
 typedef struct TrackerDBStatementSqlitePrivate TrackerDBStatementSqlitePrivate;
+typedef struct TrackerDBCursorSqlitePrivate TrackerDBCursorSqlitePrivate;
 typedef struct SqliteFunctionData SqliteFunctionData;
 typedef struct SqliteAggregateData SqliteAggregateData;
+typedef struct TrackerDBCursorSqlite TrackerDBCursorSqlite;
+typedef struct TrackerDBCursorSqliteClass TrackerDBCursorSqliteClass;
+
+
+struct TrackerDBCursorSqlite {
+	GObject parent_instance;
+};
+
+struct TrackerDBCursorSqliteClass {
+	GObjectClass parent_class;
+};
 
 struct TrackerDBInterfaceSqlitePrivate {
 	gchar *filename;
@@ -58,6 +80,12 @@ struct TrackerDBStatementSqlitePrivate {
 	sqlite3_stmt *stmt;
 };
 
+struct TrackerDBCursorSqlitePrivate {
+	TrackerDBInterfaceSqlite *db_interface;
+	sqlite3_stmt *stmt;
+	gboolean finished, owns_stmt;
+};
+
 struct SqliteFunctionData {
 	TrackerDBInterface *interface;
 	TrackerDBFunc func;
@@ -71,13 +99,19 @@ struct SqliteAggregateData {
 	
 };
 
+GType tracker_db_cursor_sqlite_get_type (void);
+
 static void tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface);
 static void tracker_db_statement_sqlite_iface_init (TrackerDBStatementIface *iface);
+static void tracker_db_cursor_sqlite_iface_init (TrackerDBCursorIface *iface);
 static void tracker_db_interface_sqlite_disconnect (TrackerDBInterface *db_interface);
 static void tracker_db_interface_sqlite_reconnect  (TrackerDBInterface *db_interface);
 
 static TrackerDBStatementSqlite * tracker_db_statement_sqlite_new (TrackerDBInterfaceSqlite	*db_interface,
 								   sqlite3_stmt			*sqlite_stmt);
+static TrackerDBCursor          * tracker_db_cursor_sqlite_new    (TrackerDBInterfaceSqlite	*db_interface,
+								   sqlite3_stmt			*sqlite_stmt,
+								   gboolean			 owns_stmt);
 static void tracker_db_statement_sqlite_reset (TrackerDBStatementSqlite *stmt);
 
 enum {
@@ -95,6 +129,10 @@ G_DEFINE_TYPE_WITH_CODE (TrackerDBStatementSqlite, tracker_db_statement_sqlite,
 			 G_IMPLEMENT_INTERFACE (TRACKER_TYPE_DB_STATEMENT,
 						tracker_db_statement_sqlite_iface_init))
 
+G_DEFINE_TYPE_WITH_CODE (TrackerDBCursorSqlite, tracker_db_cursor_sqlite, G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (TRACKER_TYPE_DB_CURSOR,
+						tracker_db_cursor_sqlite_iface_init))
+
 void 
 tracker_db_interface_sqlite_enable_shared_cache (void) 
 {
@@ -649,6 +687,7 @@ create_result_set_from_stmt (TrackerDBInterfaceSqlite  *interface,
 	return result_set;
 }
 
+
 static TrackerDBResultSet *
 tracker_db_interface_sqlite_execute_query (TrackerDBInterface  *db_interface,
 					   GError	      **error,
@@ -687,6 +726,38 @@ tracker_db_interface_sqlite_execute_query (TrackerDBInterface  *db_interface,
 	return result_set;
 }
 
+
+static TrackerDBCursor *
+tracker_db_interface_sqlite_start_cursor (TrackerDBInterface  *db_interface,
+					  GError	      **error,
+					  const gchar	       *query)
+{
+	TrackerDBInterfaceSqlitePrivate *priv;
+	TrackerDBCursor *cursor;
+	sqlite3_stmt *stmt;
+	int retval;
+
+	priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (db_interface);
+
+	retval = sqlite3_prepare_v2 (priv->db, query, -1, &stmt, NULL);
+
+	if (retval != SQLITE_OK) {
+		g_set_error (error, TRACKER_DB_INTERFACE_ERROR,
+		             TRACKER_DB_QUERY_ERROR, "%s", 
+		             sqlite3_errmsg (priv->db));
+		return NULL;
+	} else if (stmt == NULL) {
+		g_set_error (error, TRACKER_DB_INTERFACE_ERROR,
+		             TRACKER_DB_QUERY_ERROR,
+		             "Could not prepare SQL statement:'%s'", query);
+		return NULL;
+	}
+
+	cursor = tracker_db_cursor_sqlite_new (TRACKER_DB_INTERFACE_SQLITE (db_interface), stmt, TRUE);
+
+	return cursor;
+}
+
 static void
 tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface)
 {
@@ -694,6 +765,7 @@ tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface)
 	iface->execute_query = tracker_db_interface_sqlite_execute_query;
 	iface->disconnect  = tracker_db_interface_sqlite_disconnect;
 	iface->reconnect  = tracker_db_interface_sqlite_reconnect;
+	iface->start_cursor = tracker_db_interface_sqlite_start_cursor;
 }
 
 TrackerDBInterface *
@@ -843,6 +915,49 @@ tracker_db_statement_sqlite_new (TrackerDBInterfaceSqlite	*db_interface,
 }
 
 static void
+tracker_db_cursor_sqlite_finalize (GObject *object)
+{
+	TrackerDBCursorSqlitePrivate *priv;
+
+	priv = TRACKER_DB_CURSOR_SQLITE_GET_PRIVATE (object);
+
+	sqlite3_finalize (priv->stmt);
+
+	G_OBJECT_CLASS (tracker_db_cursor_sqlite_parent_class)->finalize (object);
+}
+
+static void
+tracker_db_cursor_sqlite_class_init (TrackerDBCursorSqliteClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+	object_class->finalize = tracker_db_cursor_sqlite_finalize;
+
+	g_type_class_add_private (object_class,
+				  sizeof (TrackerDBCursorSqlitePrivate));
+}
+
+static TrackerDBCursor *
+tracker_db_cursor_sqlite_new (TrackerDBInterfaceSqlite	*db_interface,
+			      sqlite3_stmt		*sqlite_stmt,
+			      gboolean			 owns_stmt)
+{
+	TrackerDBCursor *cursor;
+	TrackerDBCursorSqlitePrivate *priv;
+
+	cursor = g_object_new (TRACKER_TYPE_DB_CURSOR_SQLITE, NULL);
+
+	priv = TRACKER_DB_CURSOR_SQLITE_GET_PRIVATE (cursor);
+
+	priv->db_interface = db_interface;
+	priv->stmt = sqlite_stmt;
+	priv->finished = FALSE;
+	priv->owns_stmt = owns_stmt;
+
+	return cursor;
+}
+
+static void
 tracker_db_statement_sqlite_bind_double (TrackerDBStatement	 *stmt,
 					 int			  index,
 					 double			  value)
@@ -893,6 +1008,74 @@ tracker_db_statement_sqlite_bind_text (TrackerDBStatement	 *stmt,
 }
 
 static void
+tracker_db_cursor_sqlite_set_rewind (TrackerDBCursor *cursor)
+{
+	TrackerDBCursorSqlitePrivate *priv;
+
+	priv = TRACKER_DB_CURSOR_SQLITE_GET_PRIVATE (cursor);
+
+	sqlite3_reset (priv->stmt);
+}
+
+static gboolean
+tracker_db_cursor_sqlite_set_iter_next (TrackerDBCursor *cursor)
+{
+	TrackerDBCursorSqlitePrivate *priv;
+	priv = TRACKER_DB_CURSOR_SQLITE_GET_PRIVATE (cursor);
+
+	if (!priv->finished) {
+		guint result;
+
+		result = sqlite3_step (priv->stmt);
+		priv->finished = (result != SQLITE_OK || result != SQLITE_ROW);
+	}
+
+	return (!priv->finished);
+}
+
+static guint
+tracker_db_cursor_sqlite_get_n_columns (TrackerDBCursor *cursor)
+{
+	TrackerDBCursorSqlitePrivate *priv;
+
+	priv = TRACKER_DB_CURSOR_SQLITE_GET_PRIVATE (cursor);
+
+	return sqlite3_column_count (priv->stmt);
+}
+
+static void
+tracker_db_cursor_sqlite_get_value (TrackerDBCursor *cursor,  guint column, GValue *value)
+{
+	TrackerDBCursorSqlitePrivate *priv;
+	gint col_type;
+
+	priv = TRACKER_DB_CURSOR_SQLITE_GET_PRIVATE (cursor);
+
+	col_type = sqlite3_column_type (priv->stmt, column);
+
+	switch (col_type) {
+	case SQLITE_TEXT:
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, (gchar *) sqlite3_column_text (priv->stmt, column));
+		break;
+	case SQLITE_INTEGER:
+		g_value_init (value, G_TYPE_INT);
+		g_value_set_int (value, sqlite3_column_int (priv->stmt, column));
+		break;
+	case SQLITE_FLOAT:
+		g_value_init (value, G_TYPE_DOUBLE);
+		g_value_set_double (value, sqlite3_column_double (priv->stmt, column));
+		break;
+	case SQLITE_NULL:
+		/* just ignore NULLs */
+		break;
+	default:
+		g_critical ("Unknown sqlite3 database column type:%d", col_type);
+	}
+
+}
+
+static void
 tracker_db_interface_sqlite_disconnect (TrackerDBInterface *db_interface)
 {
 	TrackerDBInterfaceSqlitePrivate *priv;
@@ -924,6 +1107,18 @@ tracker_db_statement_sqlite_execute (TrackerDBStatement		 *stmt,
 	return create_result_set_from_stmt (priv->db_interface, priv->stmt, error);
 }
 
+static TrackerDBCursor *
+tracker_db_statement_sqlite_start_cursor (TrackerDBStatement		 *stmt,
+					  GError			**error)
+{
+	TrackerDBStatementSqlitePrivate *priv;
+
+	priv = TRACKER_DB_STATEMENT_SQLITE_GET_PRIVATE (stmt);
+
+	return tracker_db_cursor_sqlite_new (priv->db_interface, priv->stmt, FALSE);
+}
+
+
 static void
 tracker_db_statement_sqlite_iface_init (TrackerDBStatementIface *iface)
 {
@@ -932,6 +1127,17 @@ tracker_db_statement_sqlite_iface_init (TrackerDBStatementIface *iface)
 	iface->bind_int64 = tracker_db_statement_sqlite_bind_int64;
 	iface->bind_text = tracker_db_statement_sqlite_bind_text;
 	iface->execute = tracker_db_statement_sqlite_execute;
+	iface->start_cursor = tracker_db_statement_sqlite_start_cursor;
+}
+
+
+static void
+tracker_db_cursor_sqlite_iface_init (TrackerDBCursorIface *iface)
+{
+	iface->set_rewind = tracker_db_cursor_sqlite_set_rewind;
+	iface->set_iter_next = tracker_db_cursor_sqlite_set_iter_next;
+	iface->get_n_columns = tracker_db_cursor_sqlite_get_n_columns;
+	iface->get_value = tracker_db_cursor_sqlite_get_value;
 }
 
 static void
@@ -940,6 +1146,11 @@ tracker_db_statement_sqlite_init (TrackerDBStatementSqlite *stmt)
 }
 
 static void
+tracker_db_cursor_sqlite_init (TrackerDBCursorSqlite *cursor)
+{
+}
+
+static void
 tracker_db_statement_sqlite_reset (TrackerDBStatementSqlite *stmt)
 {
 	TrackerDBStatementSqlitePrivate *priv;
diff --git a/src/libtracker-db/tracker-db-interface.c b/src/libtracker-db/tracker-db-interface.c
index c7123b2..5f0e022 100644
--- a/src/libtracker-db/tracker-db-interface.c
+++ b/src/libtracker-db/tracker-db-interface.c
@@ -95,6 +95,25 @@ tracker_db_statement_get_type (void)
 	return type;
 }
 
+GType
+tracker_db_cursor_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		type = g_type_register_static_simple (G_TYPE_INTERFACE,
+						      "TrackerDBCursor",
+						      sizeof (TrackerDBCursorIface),
+						      NULL,
+						      0, NULL, 0);
+
+		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+	}
+
+	return type;
+}
+
+
 /* Boxed type for blobs */
 static gpointer
 blob_copy (gpointer boxed)
@@ -442,6 +461,50 @@ tracker_db_statement_execute (TrackerDBStatement	 *stmt,
 	return ensure_result_set_state (result_set);
 }
 
+TrackerDBCursor *
+tracker_db_statement_start_cursor (TrackerDBStatement	 *stmt,
+				   GError		**error)
+{
+	g_return_val_if_fail (TRACKER_IS_DB_STATEMENT (stmt), NULL);
+
+	return TRACKER_DB_STATEMENT_GET_IFACE (stmt)->start_cursor (stmt, error);
+}
+
+/* TrackerDBCursor API */
+
+void
+tracker_cursor_set_rewind (TrackerDBCursor *cursor)
+{
+	g_return_if_fail (TRACKER_IS_DB_CURSOR (cursor));
+
+	TRACKER_DB_CURSOR_GET_IFACE (cursor)->set_rewind (cursor);
+}
+
+gboolean
+tracker_cursor_set_iter_next (TrackerDBCursor *cursor)
+{
+	g_return_val_if_fail (TRACKER_IS_DB_CURSOR (cursor), FALSE);
+
+	return TRACKER_DB_CURSOR_GET_IFACE (cursor)->set_iter_next (cursor);
+}
+
+guint
+tracker_db_cursor_get_n_columns (TrackerDBCursor *cursor)
+{
+	g_return_val_if_fail (TRACKER_IS_DB_CURSOR (cursor), 0);
+
+	return TRACKER_DB_CURSOR_GET_IFACE (cursor)->get_n_columns (cursor);
+}
+
+void
+tracker_db_cursor_get_value (TrackerDBCursor *cursor,  guint column, GValue *value)
+{
+	g_return_if_fail (TRACKER_IS_DB_CURSOR (cursor));
+
+	TRACKER_DB_CURSOR_GET_IFACE (cursor)->get_value (cursor, column, value);
+}
+
+
 /* TrackerDBResultSet semiprivate API */
 TrackerDBResultSet *
 _tracker_db_result_set_new (guint columns)
diff --git a/src/libtracker-db/tracker-db-interface.h b/src/libtracker-db/tracker-db-interface.h
index 3d2cde4..1a1f672 100644
--- a/src/libtracker-db/tracker-db-interface.h
+++ b/src/libtracker-db/tracker-db-interface.h
@@ -35,6 +35,11 @@ G_BEGIN_DECLS
 #define TRACKER_IS_DB_STATEMENT(obj)	    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_DB_STATEMENT))
 #define TRACKER_DB_STATEMENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TRACKER_TYPE_DB_STATEMENT, TrackerDBStatementIface))
 
+#define TRACKER_TYPE_DB_CURSOR		    (tracker_db_cursor_get_type ())
+#define TRACKER_DB_CURSOR(obj)		    (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_DB_CURSOR, TrackerDBCursor))
+#define TRACKER_IS_DB_CURSOR(obj)	    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_DB_CURSOR))
+#define TRACKER_DB_CURSOR_GET_IFACE(obj)    (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TRACKER_TYPE_DB_CURSOR, TrackerDBCursorIface))
+
 #define TRACKER_TYPE_DB_RESULT_SET	    (tracker_db_result_set_get_type ())
 #define TRACKER_DB_RESULT_SET(o)	    (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_DB_RESULT_SET, TrackerDbResultSet))
 #define TRACKER_DB_RESULT_SET_CLASS(c)	    (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_DB_RESULT_SET, TrackerDbResultSetClass))
@@ -57,6 +62,8 @@ typedef struct TrackerDBStatement TrackerDBStatement;
 typedef struct TrackerDBStatementIface TrackerDBStatementIface;
 typedef struct TrackerDBResultSet TrackerDBResultSet;
 typedef struct TrackerDBResultSetClass TrackerDBResultSetClass;
+typedef struct TrackerDBCursor TrackerDBCursor;
+typedef struct TrackerDBCursorIface TrackerDBCursorIface;
 
 struct TrackerDBInterfaceIface {
 	GTypeInterface iface;
@@ -66,6 +73,9 @@ struct TrackerDBInterfaceIface {
 	TrackerDBResultSet * (* execute_query)	       (TrackerDBInterface  *interface,
 							GError		   **error,
 							const gchar	    *query);
+	TrackerDBCursor    * (* start_cursor)	       (TrackerDBInterface  *interface,
+							GError		   **error,
+							const gchar	    *query);
 	void		     (* disconnect)	       (TrackerDBInterface  *interface);
 	void		     (* reconnect)	       (TrackerDBInterface  *interface);
 
@@ -88,6 +98,8 @@ struct TrackerDBStatementIface {
 	void		     (* bind_int64)	(TrackerDBStatement	 *stmt,
 						 int			  index,
 						 gint64			  value);
+	TrackerDBCursor    * (* start_cursor)	(TrackerDBStatement	 *stmt,
+						 GError			**error);
 };
 
 struct TrackerDBResultSet {
@@ -103,6 +115,7 @@ GQuark tracker_db_interface_error_quark (void);
 
 GType tracker_db_interface_get_type (void);
 GType tracker_db_statement_get_type (void);
+GType tracker_db_cursor_get_type (void);
 GType tracker_db_result_set_get_type (void);
 GType tracker_db_blob_get_type (void);
 
@@ -120,6 +133,11 @@ TrackerDBResultSet *	tracker_db_interface_execute_query	 (TrackerDBInterface   *
 								  const gchar	       *query,
 								  ...) G_GNUC_PRINTF (3, 4);
 
+TrackerDBCursor *	tracker_db_interface_start_cursor	 (TrackerDBInterface   *interface,
+								  GError	     **error,
+								  const gchar	       *query,
+								  ...) G_GNUC_PRINTF (3, 4);
+
 gboolean		tracker_db_interface_start_transaction	    (TrackerDBInterface   *interface);
 gboolean		tracker_db_interface_end_transaction	    (TrackerDBInterface   *interface);
 void			tracker_db_interface_disconnect		    (TrackerDBInterface  *interface);
@@ -140,6 +158,9 @@ void			tracker_db_statement_bind_text		(TrackerDBStatement	 *stmt,
 TrackerDBResultSet *	tracker_db_statement_execute		(TrackerDBStatement	 *stmt,
 								 GError			**error);
 
+TrackerDBCursor *	tracker_db_statement_start_cursor	(TrackerDBStatement	 *stmt,
+								 GError			**error);
+
 /* Semi private TrackerDBResultSet functions */
 TrackerDBResultSet *	  _tracker_db_result_set_new	       (guint		    cols);
 void			  _tracker_db_result_set_append        (TrackerDBResultSet *result_set);
@@ -159,6 +180,26 @@ guint			  tracker_db_result_set_get_n_columns  (TrackerDBResultSet *result_set);
 guint			  tracker_db_result_set_get_n_rows     (TrackerDBResultSet *result_set);
 
 
+struct TrackerDBCursorIface {
+	GTypeInterface iface;
+
+	void     (*set_rewind)      (TrackerDBCursor *cursor);
+	gboolean (*set_iter_next)   (TrackerDBCursor *cursor);
+	guint    (*get_n_columns)   (TrackerDBCursor *cursor);
+	void     (*get_value)       (TrackerDBCursor *cursor, 
+	                             guint            column,
+	                             GValue          *value);
+};
+
+/* Functions to deal with a cursor */
+void			  tracker_cursor_set_rewind         (TrackerDBCursor *cursor);
+gboolean		  tracker_cursor_set_iter_next      (TrackerDBCursor *cursor);
+guint			  tracker_db_cursor_get_n_columns   (TrackerDBCursor *cursor);
+void 			  tracker_db_cursor_get_value       (TrackerDBCursor *cursor, 
+			                                     guint            column, 
+			                                     GValue          *value);
+
+
 G_END_DECLS
 
 #endif /* __TRACKER_DB_INTERFACE_H__ */



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