[anjuta/sdb-queries: 16/22] symbol-db: Implements initial query interface
- From: Naba Kumar <naba src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta/sdb-queries: 16/22] symbol-db: Implements initial query interface
- Date: Wed, 2 Jun 2010 21:26:04 +0000 (UTC)
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]