[anjuta/sdb-queries: 16/22] symbol-db: Implements initial query interface



commit c6298b8453167c3185e63dd226e5f25aebe7fd75
Author: Naba Kumar <naba gnome org>
Date:   Tue May 18 23:28:06 2010 +0300

    symbol-db: Implements initial query interface

 libanjuta/interfaces/libanjuta.idl  |   39 ++--
 plugins/symbol-db/symbol-db-query.c |  416 ++++++++++++++++++++++++++++++++---
 plugins/symbol-db/symbol-db-query.h |    2 -
 3 files changed, 408 insertions(+), 49 deletions(-)
---
diff --git a/libanjuta/interfaces/libanjuta.idl b/libanjuta/interfaces/libanjuta.idl
index e5a3cd8..36b0412 100644
--- a/libanjuta/interfaces/libanjuta.idl
+++ b/libanjuta/interfaces/libanjuta.idl
@@ -5277,11 +5277,6 @@ interface IAnjutaSymbol
 		FIELD_KIND = 16,
 		FIELD_TYPE = 32,
 		FIELD_TYPE_NAME = 64,
-		FIELD_LANGUAGE = 128,
-		FIELD_FILE_IGNORE = 256,
-		FIELD_FILE_INCLUDE = 512,
-		FIELD_PROJECT_NAME = 1024,
-		FIELD_WORKSPACE_NAME = 2048
 	}
 	
 	/**
@@ -5404,26 +5399,36 @@ interface IAnjutaSymbol
 	const GdkPixbuf *get_icon ();	
 }
 
-interface IAnjutaSymbolQuery {
+interface IAnjutaSymbolQuery
+{
+	#include "ianjuta-iterable.h"
+	#include "ianjuta-symbol.h"
 
-	enum IAnjutaSymbolQueryKind {
-		SEARCH,
+	enum Name
+	{
 		SEARCH_SYSTEM,
 		SEARCH_PROJECT,
 		SEARCH_FILE
-	};
+	}
 
-	/**
-    * IAnjutaSymbolQueryAsyncResult:
-    * @result: #IAnjutaIterable iterator object that contains the database query result.
-    * @user_data: User data
-    *
-    * Callback called for an async query to the database.
-	*/
+	enum FileScope
+	{
+		SEARCH_FS_IGNORE = -1,
+		SEARCH_FS_PUBLIC = 1,
+		SEARCH_FS_PRIVATE = 0		
+	}
+	
 	typedef void (*AsyncResult) (IAnjutaIterable* result, gpointer user_data);
-	void set_async (gboolean asyn_mode);
+	void set_async (gboolean async_mode);
+	void set_fields (IAnjutaSymbolField info_fields);
+	void set_filter (IAnjutaSymbolType filters, gboolean includes_types);
+	void set_file_scope (IAnjutaSymbolQueryFileScope filescope_search);
 	void set_offset (gint offset);
 	void set_limit (gint limit);
+	
+	IAnjutaIterable* search_system (const gchar *pattern);
+	IAnjutaIterable* search_project (const gchar *pattern);
+	IAnjutaIterable* search_file (const gchar *pattern, const GFile *file);
 }
 
 /**
diff --git a/plugins/symbol-db/symbol-db-query.c b/plugins/symbol-db/symbol-db-query.c
index 3084fbb..6b0a26f 100644
--- a/plugins/symbol-db/symbol-db-query.c
+++ b/plugins/symbol-db/symbol-db-query.c
@@ -19,6 +19,7 @@
 
 #include <limits.h>
 #include <libgda/gda-statement.h>
+#include <libanjuta/interfaces/ianjuta-symbol-query.h>
 #include "symbol-db-query.h"
 #include "symbol-db-engine.h"
 
@@ -32,22 +33,266 @@ enum
 	PROP_STATEMENT,
 	PROP_LIMIT,
 	PROP_OFFSET,
-	PROP_DB_ENGINE
+	PROP_DB_ENGINE_SYSTEM,
+	PROP_DB_ENGINE_PROJECT,
+	PROP_DB_ENGINE_SELECTED
 };
 
 struct _SymbolDBQueryPriv {
 	GdaStatement *stmt;
-	gint limit;
-	gint offset;
-	SymbolDBEngine *dbe;
+	gboolean prepared;
+	
+	IAnjutaSymbolQueryName name;
+	IAnjutaSymbolField fields;
+	IAnjutaSymbolType filters;
+	IAnjutaSymbolQueryFileScope scope;
+
+	gboolean async;
+	SymbolDBEngine *dbe_system;
+	SymbolDBEngine *dbe_project;
+	SymbolDBEngine *dbe_selected;
+	
+	/* Param holders */
+	GdaSet *params;
+	GdaHolder *param_pattern, *param_file_path, *param_limit, *param_offset;
+};
+
+typedef struct
+{
+	IAnjutaSymbolType fields;
+	gchar *columns;
+	gchar *join;
+} SymbolDBQueryFieldSpec;
+
+SymbolDBQueryFieldSpec field_specs[] = {
+	{
+		IANJUTA_SYMBOL_FIELD_SIMPLE,
+		"symbol.symbol_id "
+		"symbol.name "
+		"symbol.file_position "
+		"symbol.scope_definition_id "
+		"symbol.signature "
+		"symbol.returntype "
+		"symbol.is_file_scope ",
+		NULL},
+	{
+		IANJUTA_SYMBOL_FIELD_FILE_PATH,
+		"file.file_path",
+		"LEFT JOIN file ON symbol.file_defined_id = file.file_id"
+	},
+	{
+		IANJUTA_SYMBOL_FIELD_IMPLEMENTATION,
+		"sym_implementation.implementation_name",
+		"LEFT JOIN sym_implementation ON symbol.implementation_kind_id = sym_implementation.sym_impl_id"
+	},
+	{
+		IANJUTA_SYMBOL_FIELD_ACCESS,
+		"sym_access.access_name",
+		"LEFT JOIN sym_access ON symbol.access_kind_id = sym_access.access_kind_id"
+	},
+	{
+		IANJUTA_SYMBOL_FIELD_TYPE | IANJUTA_SYMBOL_FIELD_TYPE_NAME,
+		"sym_type.type_type "
+		"sym_type.type_name",
+		"LEFT JOIN sym_type ON symbol.type_id = sym_type.type_id"
+	},
+	{
+		IANJUTA_SYMBOL_FIELD_KIND,
+		"sym_kind.kind_name "
+		"sym_kind.is_container",
+		"LEFT JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id"
+	}
+};
+
+/* FIXME: This maps to the bit position of IAnjutaSymbolType enum. This can
+ * easily get out of hand if IAnjutaSymbolType enum value and this is not
+ * associated more concretely through DB.
+ */
+static gchar* kind_names[] =
+{
+	"undef",
+	"class",
+	"enum",
+	"enumerator",
+	"field",
+	"function",
+	"interface",
+	"member",
+	"method",
+	"namespace",
+	"package",
+	"prototype",
+	"struct",
+	"typedef",
+	"union",
+	"variable",
+	"externvar",
+	"macro",
+	"macro_with_arg",
+	"file",
+	"other"
 };
 
-G_DEFINE_TYPE (SymbolDBQuery, sdb_query, G_TYPE_OBJECT);
+static void ianjuta_symbol_query_iface_init (IAnjutaSymbolQueryIface *iface);
 
+G_DEFINE_TYPE_WITH_CODE (SymbolDBQuery, sdb_query, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_SYMBOL_QUERY,
+                                                ianjuta_symbol_query_iface_init));
+/**
+ * This creates SQL header like "SELECT ... FROM symbol LEFT JOIN ... WHERE "
+ */
 static void
-sdb_query_init (SymbolDBQuery *object)
+sdb_query_build_sql_head (SymbolDBQuery *query, GString *sql)
+{
+	GString *sql_joins;
+	gint specs_len, i;
+	SymbolDBQueryPriv *priv;
+
+	g_return_if_fail (SYMBOL_DB_IS_QUERY (query));
+	g_return_if_fail (sql != NULL);
+
+	priv = SYMBOL_DB_QUERY (query)->priv;
+	g_return_if_fail (priv->fields != 0);
+
+	g_string_assign (sql, "SELECT ");
+	sql_joins = g_string_new_len ("", 512);
+	specs_len = sizeof (field_specs) / sizeof (SymbolDBQueryFieldSpec);
+	for (i = 0; i < specs_len; i++)
+	{
+		if (field_specs[i].fields & priv->fields)
+		{
+			g_string_append (sql, field_specs[i].columns);
+			g_string_append (sql, " ");
+			g_string_append (sql_joins, field_specs[i].join);
+			g_string_append (sql_joins, " ");
+		}
+	}
+	g_string_append (sql, "FROM symbol ");
+	g_string_append (sql, sql_joins->str);
+	g_string_append (sql, "WHERE ");
+	g_string_free (sql_joins, TRUE);
+}
+
+static gboolean
+sdb_query_build_sql_kind_filter (SymbolDBQuery *query, GString *sql)
 {
-	object->priv = SYMBOL_DB_QUERY_GET_PRIVATE(object);
+	gboolean first = TRUE;
+	gint bit_count = 0;
+	IAnjutaSymbolType filters;
+	SymbolDBQueryPriv *priv;
+
+	g_return_val_if_fail (SYMBOL_DB_IS_QUERY (query), TRUE);
+	g_return_val_if_fail (sql != NULL, TRUE);
+
+	priv = SYMBOL_DB_QUERY (query)->priv;
+
+	filters = priv->filters;
+	if (filters)
+	{
+		g_string_append (sql, "(symbol.kind_id IN (SELECT kind_id FROM sym_kind WHERE kind_name IN (");
+		while (filters)
+		{
+			if (filters & 1)
+			{
+				if (first) first = FALSE;
+				else g_string_append (sql, ", ");
+				g_string_append (sql, "'");
+				g_string_append (sql, kind_names[bit_count]);
+				g_string_append (sql, "'");
+			}
+			filters >>= 1;
+		}
+		g_string_append (sql, ")) ");
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+sdb_query_update (SymbolDBQuery *query)
+{
+	const gchar *condition;
+	GString *sql;
+	SymbolDBQueryPriv *priv;
+
+	g_return_if_fail (SYMBOL_DB_IS_QUERY (query));
+	priv = SYMBOL_DB_QUERY (query)->priv;
+
+	/* Prepare select conditions */
+	switch (priv->name)
+	{
+		case IANJUTA_SYMBOL_QUERY_SEARCH_PROJECT:
+			condition = " (symbol.name LIKE ## /* name:'pattern' type:gchararray */) ";
+			priv->dbe_selected = priv->dbe_project;
+			break;
+		case IANJUTA_SYMBOL_QUERY_SEARCH_SYSTEM:
+			condition = " (symbol.name LIKE ## /* name:'pattern' type:gchararray */) ";
+			priv->dbe_selected = priv->dbe_system;
+			break;
+		case IANJUTA_SYMBOL_QUERY_SEARCH_FILE:
+			condition = " \
+				(symbol.name LIKE ## /* name:'pattern' type:gchararray */) AND \
+				(symbol.file_defined_id IN \
+					( \
+						SELECT file_id \
+						FROM file \
+						WHERE file_path = ## /* name:'filepath' type:gchararray */ \
+					) \
+				) ";
+			priv->filters &= IANJUTA_SYMBOL_FIELD_FILE_PATH;
+			break;
+		default:
+			g_warning ("Invalid query kind");
+			g_warn_if_reached ();
+			return;
+	}
+
+	/* Build SQL statement */
+	sql = g_string_new_len ("", 1024);
+
+	/* Add head of the SQL statement */
+	sdb_query_build_sql_head (query, sql);
+
+	/* Add symbol type filters of the SQL statement */
+	if (sdb_query_build_sql_kind_filter (query, sql))
+		g_string_append (sql, "AND ");
+
+	/* Add condition of the SQL statement */
+	g_string_append (sql, condition);
+	
+	/* Add tail of the SQL statement */
+	g_string_append (sql, "LIMIT ## /* name:'limit' type:gint */ ");
+	g_string_append (sql, "OFFSET ## /* name:'offset' type:gint */ ");
+
+	/* Prepare statement */
+	priv->stmt = symbol_db_engine_get_statement (priv->dbe_selected, sql->str);
+	g_string_free (sql, TRUE);
+}
+
+static void
+sdb_query_init (SymbolDBQuery *query)
+{
+	SymbolDBQueryPriv *priv;
+	GdaHolder *param;
+	GSList *param_holders = NULL;
+	
+	priv = query->priv = SYMBOL_DB_QUERY_GET_PRIVATE(query);
+
+	/* Prepare sql parameter holders */
+	param = priv->param_pattern = gda_holder_new_string ("pattern", "");
+	param_holders = g_slist_prepend (param_holders, param);
+	
+	param = priv->param_file_path = gda_holder_new_string ("filepath", "");
+	param_holders = g_slist_prepend (param_holders, param);
+
+	param = priv->param_limit = gda_holder_new_int ("limit", INT_MAX);
+	param_holders = g_slist_prepend (param_holders, param);
+
+	param = priv->param_limit = gda_holder_new_int ("offset", 0);
+	param_holders = g_slist_prepend (param_holders, param);
+
+	priv->params = gda_set_new (param_holders);
+	g_slist_free (param_holders);
 }
 
 static void
@@ -67,13 +312,19 @@ sdb_query_set_property (GObject *object, guint prop_id, const GValue *value, GPa
 	switch (prop_id)
 	{
 	case PROP_LIMIT:
-		priv->limit = g_value_get_int (value);
+		gda_holder_set_value (priv->param_limit, value, NULL);
 		break;
 	case PROP_OFFSET:
-		priv->offset = g_value_get_int (value);
+		gda_holder_set_value (priv->param_offset, value, NULL);
 		break;
-	case PROP_DB_ENGINE:
-		priv->dbe = g_value_get_object (value);
+	case PROP_DB_ENGINE_SYSTEM:
+		priv->dbe_system = g_value_get_object (value);
+		break;
+	case PROP_DB_ENGINE_PROJECT:
+		priv->dbe_project = g_value_get_object (value);
+		break;
+	case PROP_DB_ENGINE_SELECTED:
+		priv->dbe_selected = g_value_get_object (value);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -95,13 +346,16 @@ sdb_query_get_property (GObject *object, guint prop_id, GValue *value, GParamSpe
 		g_value_set_object (value, priv->stmt);
 		break;
 	case PROP_LIMIT:
-		g_value_set_int (value, priv->limit);
+		g_value_copy (gda_holder_get_value (priv->param_limit), value);
 		break;
 	case PROP_OFFSET:
-		g_value_set_int (value, priv->offset);
+		g_value_copy (gda_holder_get_value (priv->param_offset), value);
+		break;
+	case PROP_DB_ENGINE_SYSTEM:
+		g_value_set_object (value, priv->dbe_system);
 		break;
-	case PROP_DB_ENGINE:
-		g_value_set_object (value, priv->dbe);
+	case PROP_DB_ENGINE_PROJECT:
+		g_value_set_object (value, priv->dbe_project);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -124,8 +378,10 @@ sdb_query_class_init (SymbolDBQueryClass *klass)
 	                                 g_param_spec_enum ("query-kind",
 	                                                    "Query kind",
 	                                                    "The query kind",
-	                                                    SymbolDBQueryType,
-	                                                    G_PARAM_READABLE | G_PARAM_CONSTRUCT));
+	                                                    IANJUTA_TYPE_SYMBOL_QUERY_NAME,
+	                                                    IANJUTA_SYMBOL_QUERY_SEARCH_PROJECT,
+	                                                    G_PARAM_READABLE |
+	                                                    G_PARAM_CONSTRUCT));
 	g_object_class_install_property (object_class,
 	                                 PROP_STATEMENT,
 	                                 g_param_spec_object ("statement",
@@ -140,7 +396,8 @@ sdb_query_class_init (SymbolDBQueryClass *klass)
 	                                                   "Query Limit",
 	                                                   "Limit to resultset",
 	                                                   0, INT_MAX, INT_MAX,
-	                                                   G_PARAM_READABLE | G_PARAM_WRITABLE));
+	                                                   G_PARAM_READABLE |
+	                                                   G_PARAM_WRITABLE));
 	
 	g_object_class_install_property (object_class,
 	                                 PROP_OFFSET,
@@ -148,25 +405,124 @@ sdb_query_class_init (SymbolDBQueryClass *klass)
 	                                                   "Query offset",
 	                                                   "Offset of begining of resultset",
 	                                                   0, INT_MAX, 0,
-	                                                   G_PARAM_READABLE | G_PARAM_WRITABLE));
+	                                                   G_PARAM_READABLE |
+	                                                   G_PARAM_WRITABLE));
 	
 	g_object_class_install_property (object_class,
-	                                 PROP_DB_ENGINE,
-	                                 g_param_spec_object ("db-engine",
-	                                                      "DB Engine",
-	                                                      "The SymbolDBEngine",
+	                                 PROP_DB_ENGINE_SYSTEM,
+	                                 g_param_spec_object ("db-engine-system",
+	                                                      "System DB Engine",
+	                                                      "The System SymbolDBEngine",
+	                                                      SYMBOL_TYPE_DB_ENGINE,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));
+	g_object_class_install_property (object_class,
+	                                 PROP_DB_ENGINE_PROJECT,
+	                                 g_param_spec_object ("db-engine-project",
+	                                                      "Project DB Engine",
+	                                                      "The Project SymbolDBEngine",
+	                                                      SYMBOL_TYPE_DB_ENGINE,
+	                                                      G_PARAM_READABLE |
+	                                                      G_PARAM_WRITABLE |
+	                                                      G_PARAM_CONSTRUCT));
+	g_object_class_install_property (object_class,
+	                                 PROP_DB_ENGINE_SELECTED,
+	                                 g_param_spec_object ("db-engine-selected",
+	                                                      "Selected DB Engine",
+	                                                      "The selected SymbolDBEngine",
 	                                                      SYMBOL_TYPE_DB_ENGINE,
-	                                                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+	                                                      G_PARAM_READABLE));
 }
 
-IAnjutaIterable*
-sdb_query_search (gchar *search_string)
+static IAnjutaIterable*
+sdb_query_execute (SymbolDBQuery *query)
 {
-	/* TODO: Add public function implementation here */
+	SymbolDBEngineIterator *iter;
+	GdaDataModel *data_model;
+	SymbolDBQueryPriv *priv = query->priv;
+	
+	if (!priv->prepared)
+	{
+		sdb_query_update (query);
+		priv->prepared = TRUE;
+	}
+	data_model = symbol_db_engine_execute_select (priv->dbe_selected,
+	                                              priv->stmt,
+	                                              priv->params);
+	iter = symbol_db_engine_iterator_new (data_model, 
+	                                      symbol_db_engine_get_type_conversion_hash (priv->dbe_selected),
+	                                      symbol_db_engine_get_project_directory (priv->dbe_selected));
+	return IANJUTA_ITERABLE (iter);
 }
 
-IAnjutaIterable*
-sdb_query_search_prefix (gchar *search_string)
+static IAnjutaIterable*
+sdb_query_search_system (IAnjutaSymbolQuery *query,
+                         const gchar *search_string, GError **error)
+{
+	GValue sv = {0};
+	SymbolDBQueryPriv *priv;
+
+	g_return_val_if_fail (SYMBOL_DB_IS_QUERY (query), NULL);
+
+	priv = SYMBOL_DB_QUERY (query)->priv;
+	g_return_val_if_fail (priv->name == IANJUTA_SYMBOL_QUERY_SEARCH_SYSTEM, NULL);
+
+	g_value_init (&sv, G_TYPE_STRING);
+	g_value_set_static_string (&sv, search_string);
+	gda_holder_set_value (priv->param_pattern, &sv, NULL);
+	return sdb_query_execute (SYMBOL_DB_QUERY (query));
+}
+
+static IAnjutaIterable*
+sdb_query_search_project (IAnjutaSymbolQuery *query,
+                          const gchar *search_string, GError **error)
+{
+	GValue sv = {0};
+	SymbolDBQueryPriv *priv;
+
+	g_return_val_if_fail (SYMBOL_DB_IS_QUERY (query), NULL);
+
+	priv = SYMBOL_DB_QUERY (query)->priv;
+	g_return_val_if_fail (priv->name == IANJUTA_SYMBOL_QUERY_SEARCH_PROJECT, NULL);
+
+	g_value_init (&sv, G_TYPE_STRING);
+	g_value_set_static_string (&sv, search_string);
+	gda_holder_set_value (priv->param_pattern, &sv, NULL);
+	return sdb_query_execute (SYMBOL_DB_QUERY (query));
+}
+
+static IAnjutaIterable*
+sdb_query_search_file (IAnjutaSymbolQuery *query, const gchar *search_string,
+                       const GFile *file, GError **error)
+{
+	gchar *rel_file_path, *abs_file_path;
+	GValue sv = {0};
+	SymbolDBQueryPriv *priv;
+
+	g_return_val_if_fail (SYMBOL_DB_IS_QUERY (query), NULL);
+
+	priv = SYMBOL_DB_QUERY (query)->priv;
+	g_return_val_if_fail (priv->name == IANJUTA_SYMBOL_QUERY_SEARCH_SYSTEM, NULL);
+
+	g_value_init (&sv, G_TYPE_STRING);
+	g_value_set_static_string (&sv, search_string);
+	gda_holder_set_value (priv->param_pattern, &sv, NULL);
+
+	abs_file_path = g_file_get_path (file);
+	rel_file_path = symbol_db_util_get_file_db_path (priv->dbe_selected, abs_file_path);
+	g_value_take_string (&sv, rel_file_path);
+	gda_holder_set_value (priv->param_file_path, &sv, NULL);
+	g_free (abs_file_path);
+	g_value_reset (&sv);
+	
+	return sdb_query_execute (SYMBOL_DB_QUERY (query));
+}
+
+static void
+ianjuta_symbol_query_iface_init (IAnjutaSymbolQueryIface *iface)
 {
-	/* TODO: Add public function implementation here */
+	iface->search_system = sdb_query_search_system;
+	iface->search_project = sdb_query_search_project;
+	iface->search_file = sdb_query_search_file;
 }
diff --git a/plugins/symbol-db/symbol-db-query.h b/plugins/symbol-db/symbol-db-query.h
index 1b51c02..6ef092c 100644
--- a/plugins/symbol-db/symbol-db-query.h
+++ b/plugins/symbol-db/symbol-db-query.h
@@ -48,8 +48,6 @@ struct _SymbolDBQuery
 };
 
 GType sdb_query_get_type (void) G_GNUC_CONST;
-IAnjutaIterable* sdb_query_search (gchar *search_string);
-IAnjutaIterable* sdb_query_search_prefix (gchar *search_string);
 
 G_END_DECLS
 



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