[anjuta] symbol-db: added queries to get the scope chain of a symbol
- From: Massimo Cora' <mcora src gnome org>
- To: svn-commits-list gnome org
- Subject: [anjuta] symbol-db: added queries to get the scope chain of a symbol
- Date: Tue, 21 Jul 2009 22:02:43 +0000 (UTC)
commit 76db8a131d661dbdd7e89d9ce371742a909882da
Author: Massimo Corà <mcora src gnome org>
Date: Tue Jul 21 23:50:43 2009 +0200
symbol-db: added queries to get the scope chain of a symbol
I needed to implement a particular GdaDataModelConcat object that'll accept multiple
data models. This because it's not possible to get the scope chain in one go with a sql query.
plugins/symbol-db/Makefile.am | 4 +-
.../symbol-db/libgda-extra/gda-data-model-concat.c | 366 ++++++++++++++++++++
.../symbol-db/libgda-extra/gda-data-model-concat.h | 62 ++++
plugins/symbol-db/symbol-db-engine-iterator.c | 4 +-
plugins/symbol-db/symbol-db-engine-queries.c | 262 ++++++++++-----
plugins/symbol-db/symbol-db-engine-queries.h | 23 ++
plugins/symbol-db/test/Makefile.am | 6 +-
plugins/symbol-db/test/benchmark.c | 2 -
8 files changed, 641 insertions(+), 88 deletions(-)
---
diff --git a/plugins/symbol-db/Makefile.am b/plugins/symbol-db/Makefile.am
index 404080d..fc7ea7b 100644
--- a/plugins/symbol-db/Makefile.am
+++ b/plugins/symbol-db/Makefile.am
@@ -67,7 +67,9 @@ libanjuta_symbol_db_la_SOURCES = plugin.c plugin.h \
symbol-db-engine-core.c symbol-db-engine-core.h \
symbol-db-engine.h symbol-db-iface.c \
symbol-db-iface.h symbol-db-search-command.h \
- symbol-db-search-command.c
+ symbol-db-search-command.c \
+ libgda-extra/gda-data-model-concat.c \
+ libgda-extra/gda-data-model-concat.h
libanjuta_symbol_db_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
diff --git a/plugins/symbol-db/libgda-extra/gda-data-model-concat.c b/plugins/symbol-db/libgda-extra/gda-data-model-concat.c
new file mode 100644
index 0000000..8d2faed
--- /dev/null
+++ b/plugins/symbol-db/libgda-extra/gda-data-model-concat.c
@@ -0,0 +1,366 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2009 <maxcvs email it>
+ *
+ * anjuta 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * anjuta 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gda-data-model-concat.h"
+
+/**
+ *
+ * An external user won't recognize that the GdaDataModel is composed
+ * by more than a GdaDataModel with the same structure (n_rows, n_cols etc)
+ *
+ * |------------------- GdaDataModel -------------------| (external vision)
+ * |<----- ModelSlice 1 -----><----- ModelSlice 2 ----->| (internal vision)
+ */
+
+/*
+ * I would rather present it as the following because each data model concatenated
+ * need to have the same number an types of columns, but can have any number of rows.
+ *
+ * col0 | col1 | ...
+ * -----+-------+---------
+ * ...
+ * Rows from Slice 0
+ * ...
+ * -----+-------+---------
+ * ...
+ * Rows from Slice 1
+ * ...
+ * -----+-------+---------
+ * ...
+ * Rows from Slice N
+ * ...
+ *
+ */
+typedef struct _ModelSlice {
+ GdaDataModel *model;
+
+ /* In a general way these number represents the boundaries
+ * mapped on the GdaDataModel as seen from an external user. See ascii above.
+ */
+ gint lower_bound;
+ gint upper_bound;
+
+} ModelSlice;
+
+struct _GdaDataModelConcatPrivate {
+
+ /* a list of ModelSlice(s) */
+ GList *slices;
+ ModelSlice *curr_model_slice;
+
+ /* num of records which is the total of the different models appended */
+ gint tot_items;
+};
+
+
+static GObjectClass *parent_class = NULL;
+
+
+static void
+gdm_concat_iface_impl_init (GdaDataModelIface *iface);
+
+static void
+gdm_concat_model_slice_destroy (ModelSlice *slice)
+{
+ g_object_unref (slice->model);
+ g_free (slice);
+}
+
+static void
+gdm_concat_init (GdaDataModelConcat *mconcat)
+{
+ g_return_if_fail (GDA_IS_DATA_MODEL_CONCAT (mconcat));
+ mconcat->priv = g_new0 (GdaDataModelConcatPrivate, 1);
+ mconcat->priv->slices = NULL;
+ mconcat->priv->curr_model_slice = NULL;
+ mconcat->priv->tot_items = 0;
+}
+
+static void
+gdm_concat_dispose (GObject *object)
+{
+ GdaDataModelConcat *mconcat = GDA_DATA_MODEL_CONCAT (object);
+ GdaDataModelConcatPrivate *priv;
+
+ priv = mconcat->priv;
+
+ /* we'll just point curr_moodel_slice to NULL because it's already
+ * in the slices list
+ */
+ priv->curr_model_slice = NULL;
+
+ GList *node = priv->slices;
+ while (node != NULL)
+ {
+ gdm_concat_model_slice_destroy ((ModelSlice*) node->data);
+
+ node = node->next;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gdm_concat_finalize (GObject *object)
+{
+ GdaDataModelConcat *mconcat = (GdaDataModelConcat *) object;
+
+ /* free memory */
+ if (mconcat->priv)
+ {
+ g_free (mconcat->priv);
+ mconcat->priv = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gdm_concat_class_init (GdaDataModelConcatClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = gdm_concat_dispose;
+ object_class->finalize = gdm_concat_finalize;
+}
+
+/**
+ * gdm_concat_get_type
+ *
+ * Returns: the #GType of GdaDataModelConcat.
+ */
+GType
+gdm_concat_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+ static const GTypeInfo info = {
+ sizeof (GdaDataModelConcatClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gdm_concat_class_init,
+ NULL,
+ NULL,
+ sizeof (GdaDataModelConcat),
+ 0,
+ (GInstanceInitFunc) gdm_concat_init
+ };
+
+ static const GInterfaceInfo data_model_info = {
+ (GInterfaceInitFunc) gdm_concat_iface_impl_init,
+ NULL,
+ NULL
+ };
+
+ g_static_mutex_lock (®istering);
+ if (type == 0) {
+ type = g_type_register_static (G_TYPE_OBJECT, "GdaDataModelConcat", &info, 0);
+ g_type_add_interface_static (type, GDA_TYPE_DATA_MODEL, &data_model_info);
+ }
+ g_static_mutex_unlock (®istering);
+ }
+ return type;
+}
+
+static gint
+gdm_concat_get_n_rows (GdaDataModel *model)
+{
+ GdaDataModelConcat *mconcat = GDA_DATA_MODEL_CONCAT (model);
+ GdaDataModelConcatPrivate *priv;
+
+ g_return_val_if_fail (model != NULL, -1);
+
+ priv = mconcat->priv;
+
+ return priv->tot_items;
+}
+
+static gint
+gdm_concat_get_n_columns (GdaDataModel *model)
+{
+ GdaDataModelConcat *mconcat = GDA_DATA_MODEL_CONCAT (model);
+ GdaDataModelConcatPrivate *priv;
+
+ g_return_val_if_fail (model != NULL, -1);
+
+ priv = mconcat->priv;
+
+ if (priv->curr_model_slice == NULL)
+ {
+ g_warning ("No model has been appended yet");
+ return -1;
+ }
+
+ return gda_data_model_get_n_columns (priv->curr_model_slice->model);
+}
+
+static GdaColumn *
+gdm_concat_describe_column (GdaDataModel *model, gint col)
+{
+ GdaDataModelConcat *mconcat = GDA_DATA_MODEL_CONCAT (model);
+ GdaDataModelConcatPrivate *priv;
+
+ g_return_val_if_fail (model != NULL, NULL);
+
+ priv = mconcat->priv;
+
+ if (priv->curr_model_slice == NULL)
+ {
+ g_warning ("No model has been appended yet");
+ return NULL;
+ }
+
+ return gda_data_model_describe_column (priv->curr_model_slice->model, col);
+}
+
+
+static gint
+gdm_concat_set_curr_slice_by_row_num (GdaDataModelConcat *mconcat, gint row)
+{
+ GdaDataModelConcatPrivate *priv;
+ ModelSlice *found_slice = NULL;
+
+ priv = mconcat->priv;
+
+ /* iterate and search for the correct slice (e.g. the one that suits the bounds) */
+ GList *node = priv->slices;
+
+ while (node)
+ {
+ ModelSlice *curr_slice = node->data;
+
+ if (curr_slice && row >= curr_slice->lower_bound &&
+ row <= curr_slice->upper_bound)
+ {
+ found_slice = curr_slice;
+ break;
+ }
+ node = g_list_next (node);
+ }
+
+ /* if not found it'll be set to NULL */
+ priv->curr_model_slice = found_slice;
+
+ /* if NULL return -1, otherwise return the relative row value */
+ return priv->curr_model_slice == NULL ? -1 :
+ row - priv->curr_model_slice->lower_bound;
+}
+
+static const GValue *
+gdm_concat_get_value_at (GdaDataModel *model, gint col, gint row,
+ GError **error)
+{
+ GdaDataModelConcat *mconcat = GDA_DATA_MODEL_CONCAT (model);
+ GdaDataModelConcatPrivate *priv;
+ gint relative_row;
+
+ g_return_val_if_fail (model != NULL, NULL);
+
+ priv = mconcat->priv;
+
+ if ( (relative_row = gdm_concat_set_curr_slice_by_row_num (mconcat, row)) < 0)
+ {
+ /* maybe an array out of bound error occurred */
+ return NULL;
+ }
+
+ return gda_data_model_get_value_at (priv->curr_model_slice->model, col, relative_row,
+ error);
+}
+
+static GdaDataModelAccessFlags
+gda_concat_get_access_flags (GdaDataModel *model)
+{
+ return GDA_DATA_MODEL_ACCESS_RANDOM;
+}
+
+static void
+gdm_concat_iface_impl_init (GdaDataModelIface *iface)
+{
+ iface->i_get_n_rows = gdm_concat_get_n_rows;
+ iface->i_get_n_columns = gdm_concat_get_n_columns;
+ iface->i_create_iter = NULL;
+
+ iface->i_get_value_at = gdm_concat_get_value_at;
+ iface->i_iter_at_row = NULL;
+ iface->i_iter_next = NULL;
+ iface->i_iter_prev = NULL;
+
+ iface->i_get_attributes_at = NULL;
+ iface->i_get_access_flags = gda_concat_get_access_flags;
+ iface->i_describe_column = gdm_concat_describe_column;
+
+ iface->i_set_value_at = NULL;
+ iface->i_iter_set_value = NULL;
+ iface->i_set_values = NULL;
+ iface->i_append_values = NULL;
+ iface->i_append_row = NULL;
+ iface->i_remove_row = NULL;
+ iface->i_find_row = NULL;
+
+ iface->i_set_notify = NULL;
+ iface->i_get_notify = NULL;
+ iface->i_send_hint = NULL;
+}
+
+GdaDataModel *
+gda_data_model_concat_new (void)
+{
+ GdaDataModelConcat *mconcat;
+
+ mconcat = g_object_new (GDA_TYPE_DATA_MODEL_CONCAT, NULL);
+
+ return GDA_DATA_MODEL (mconcat);
+}
+
+void
+gda_data_model_concat_append_model (GdaDataModelConcat *mconcat, GdaDataModel *model)
+{
+ GdaDataModelConcatPrivate *priv;
+ gint new_model_rows;
+
+ g_return_if_fail (GDA_IS_DATA_MODEL_CONCAT (mconcat));
+ g_return_if_fail (GDA_IS_DATA_MODEL (model));
+
+ /* we want random access data models */
+ g_return_if_fail (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM);
+
+ priv = mconcat->priv;
+
+ /* get the n rows of the new model to be attached */
+ new_model_rows = gda_data_model_get_n_rows (model);
+
+ ModelSlice *slice = g_new0 (ModelSlice, 1);
+ slice->model = g_object_ref (model);
+
+ slice->lower_bound = priv->tot_items;
+ slice->upper_bound = priv->tot_items + new_model_rows -1;
+
+ /* append the new object to the list */
+ priv->slices = g_list_append (priv->slices, slice);
+
+ priv->tot_items += new_model_rows;
+
+ if (priv->curr_model_slice == NULL)
+ priv->curr_model_slice = slice;
+}
+
diff --git a/plugins/symbol-db/libgda-extra/gda-data-model-concat.h b/plugins/symbol-db/libgda-extra/gda-data-model-concat.h
new file mode 100644
index 0000000..45183db
--- /dev/null
+++ b/plugins/symbol-db/libgda-extra/gda-data-model-concat.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2009 <maxcvs email it>
+ *
+ * anjuta 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * anjuta 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _GDA_DATA_MODEL_CONCAT_H_
+#define _GDA_DATA_MODEL_CONCAT_H_
+
+#include <libgda/gda-data-model.h>
+#include <libgda/gda-data-select.h>
+#include <libgda/gda-data-model-iter.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_DATA_MODEL_CONCAT (gdm_concat_get_type ())
+#define GDA_DATA_MODEL_CONCAT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDA_TYPE_DATA_MODEL_CONCAT, GdaDataModelConcat))
+#define GDA_DATA_MODEL_CONCAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDA_TYPE_DATA_MODEL_CONCAT, GdaDataModelConcatClass))
+#define GDA_IS_DATA_MODEL_CONCAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDA_TYPE_DATA_MODEL_CONCAT))
+#define GDA_IS_DATA_MODEL_CONCAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDA_TYPE_DATA_MODEL_CONCAT))
+#define GDA_DATA_MODEL_CONCAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDA_TYPE_DATA_MODEL_CONCAT, GdaDataModelConcatClass))
+
+typedef struct _GdaDataModelConcat GdaDataModelConcat;
+typedef struct _GdaDataModelConcatClass GdaDataModelConcatClass;
+typedef struct _GdaDataModelConcatPrivate GdaDataModelConcatPrivate;
+
+struct _GdaDataModelConcat
+{
+ GObject parent_instance;
+ GdaDataModelConcatPrivate *priv;
+};
+
+struct _GdaDataModelConcatClass
+{
+ GObjectClass parent_class;
+};
+
+
+GType gdm_concat_get_type (void) G_GNUC_CONST;
+
+GdaDataModel *gda_data_model_concat_new (void);
+
+void gda_data_model_concat_append_model (GdaDataModelConcat *mconcat,
+ GdaDataModel *model);
+
+G_END_DECLS
+
+#endif /* _GDA_DATA_MODEL_CONCAT_H_ */
diff --git a/plugins/symbol-db/symbol-db-engine-iterator.c b/plugins/symbol-db/symbol-db-engine-iterator.c
index 5b4374b..b41154a 100644
--- a/plugins/symbol-db/symbol-db-engine-iterator.c
+++ b/plugins/symbol-db/symbol-db-engine-iterator.c
@@ -91,9 +91,9 @@ symbol_db_engine_iterator_new (GdaDataModel *model,
dbi = g_object_new (SYMBOL_TYPE_DB_ENGINE_ITERATOR, NULL);
priv = dbi->priv;
- priv->data_model = model;
+ priv->data_model = model;
priv->data_iter = gda_data_model_create_iter (model);
-
+
/* because gda_data_model_get_n_rows () could be cpu-intensive, we'll
* proxy this value, e.g. it's calculated if it is really needed */
priv->total_rows = -1;
diff --git a/plugins/symbol-db/symbol-db-engine-queries.c b/plugins/symbol-db/symbol-db-engine-queries.c
index e125026..bca3e9d 100644
--- a/plugins/symbol-db/symbol-db-engine-queries.c
+++ b/plugins/symbol-db/symbol-db-engine-queries.c
@@ -26,7 +26,7 @@
#include "symbol-db-engine-queries.h"
#include "symbol-db-engine-priv.h"
-
+#include "libgda-extra/gda-data-model-concat.h"
/*
* extern declarations
@@ -1570,87 +1570,6 @@ symbol_db_engine_get_file_symbols (SymbolDBEngine *dbe,
priv->project_directory);
}
-SymbolDBEngineIterator *
-symbol_db_engine_get_symbol_info_by_id (SymbolDBEngine *dbe,
- gint sym_id, SymExtraInfo sym_info)
-{
- SymbolDBEnginePriv *priv;
- gchar *query_str;
- GdaDataModel *data;
- GString *info_data;
- GString *join_data;
- GdaHolder *param;
- const DynChildQueryNode *dyn_node;
- GValue *ret_value;
- gboolean ret_bool;
-
-
- g_return_val_if_fail (dbe != NULL, NULL);
- priv = dbe->priv;
-
- SDB_LOCK(priv);
-
- if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe,
- DYN_PREP_QUERY_GET_SYMBOL_INFO_BY_ID, sym_info, 0)) == NULL)
- {
- /* info_data contains the stuff after SELECT and befor FROM */
- info_data = g_string_new ("");
-
- /* join_data contains the optionals joins to do to retrieve new data on other
- * tables.
- */
- join_data = g_string_new ("");
-
- /* fill info_data and join data with optional sql */
- sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
-
- query_str = g_strdup_printf ("SELECT symbol.symbol_id AS symbol_id, "
- "symbol.name AS name, symbol.file_position AS file_position, "
- "symbol.is_file_scope AS is_file_scope, symbol.signature AS signature, "
- "symbol.returntype AS returntype "
- "%s FROM symbol "
- "%s WHERE symbol.symbol_id = ## /* name:'symid' type:gint */",
- info_data->str, join_data->str);
-
- dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe,
- DYN_PREP_QUERY_GET_SYMBOL_INFO_BY_ID,
- sym_info, 0,
- query_str);
-
- g_free (query_str);
- g_string_free (info_data, TRUE);
- g_string_free (join_data, TRUE);
- }
-
- if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "symid")) == NULL)
- {
- SDB_UNLOCK(priv);
- return NULL;
- }
-
- MP_SET_HOLDER_BATCH_INT(priv, param, sym_id, ret_bool, ret_value);
-
- /* execute the query with parametes just set */
- data = gda_connection_statement_execute_select (priv->db_connection,
- (GdaStatement*)dyn_node->stmt,
- (GdaSet*)dyn_node->plist, NULL);
-
- if (!GDA_IS_DATA_MODEL (data) ||
- gda_data_model_get_n_rows (data) <= 0)
- {
- if (data != NULL)
- g_object_unref (data);
-
- SDB_UNLOCK(priv);
- return NULL;
- }
-
- SDB_UNLOCK(priv);
- return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data,
- priv->sym_type_conversion_hash,
- priv->project_directory);
-}
-
#define DYN_FIND_SYMBOL_NAME_BY_PATTERN_EXTRA_PAR_EXACT_MATCH_YES 0x010000
#define DYN_FIND_SYMBOL_NAME_BY_PATTERN_EXTRA_PAR_EXACT_MATCH_NO 0x020000
@@ -2028,6 +1947,185 @@ select * from symbol where scope_definition_id = (
return res;
}
+/**
+ * On some queries we need to know the GdaDataModel instead of the iterator.
+ */
+static GdaDataModel *
+sdb_engine_get_symbol_info_by_id_1 (SymbolDBEngine *dbe,
+ gint sym_id, SymExtraInfo sym_info)
+{
+ SymbolDBEnginePriv *priv;
+ gchar *query_str;
+ GdaDataModel *data;
+ GString *info_data;
+ GString *join_data;
+ GdaHolder *param;
+ const DynChildQueryNode *dyn_node;
+ GValue *ret_value;
+ gboolean ret_bool;
+
+
+ priv = dbe->priv;
+
+ SDB_LOCK(priv);
+
+ if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe,
+ DYN_PREP_QUERY_GET_SYMBOL_INFO_BY_ID, sym_info, 0)) == NULL)
+ {
+ /* info_data contains the stuff after SELECT and befor FROM */
+ info_data = g_string_new ("");
+
+ /* join_data contains the optionals joins to do to retrieve new data on other
+ * tables.
+ */
+ join_data = g_string_new ("");
+
+ /* fill info_data and join data with optional sql */
+ sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
+
+ query_str = g_strdup_printf ("SELECT symbol.symbol_id AS symbol_id, "
+ "symbol.name AS name, symbol.file_position AS file_position, "
+ "symbol.is_file_scope AS is_file_scope, symbol.signature AS signature, "
+ "symbol.returntype AS returntype "
+ "%s FROM symbol "
+ "%s WHERE symbol.symbol_id = ## /* name:'symid' type:gint */",
+ info_data->str, join_data->str);
+
+ dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe,
+ DYN_PREP_QUERY_GET_SYMBOL_INFO_BY_ID,
+ sym_info, 0,
+ query_str);
+
+ g_free (query_str);
+ g_string_free (info_data, TRUE);
+ g_string_free (join_data, TRUE);
+ }
+
+ if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "symid")) == NULL)
+ {
+ SDB_UNLOCK(priv);
+ return NULL;
+ }
+
+ MP_SET_HOLDER_BATCH_INT(priv, param, sym_id, ret_bool, ret_value);
+
+ /* execute the query with parameters just set */
+ data = gda_connection_statement_execute_select (priv->db_connection,
+ (GdaStatement*)dyn_node->stmt,
+ (GdaSet*)dyn_node->plist, NULL);
+
+ if (!GDA_IS_DATA_MODEL (data) ||
+ gda_data_model_get_n_rows (data) <= 0)
+ {
+ if (data != NULL)
+ g_object_unref (data);
+
+ SDB_UNLOCK(priv);
+ return NULL;
+ }
+
+ SDB_UNLOCK(priv);
+ return data;
+}
+
+SymbolDBEngineIterator *
+symbol_db_engine_get_symbol_info_by_id (SymbolDBEngine *dbe,
+ gint sym_id, SymExtraInfo sym_info)
+{
+ SymbolDBEnginePriv *priv;
+ GdaDataModel *data;
+
+ g_return_val_if_fail (dbe != NULL, NULL);
+ priv = dbe->priv;
+
+ data = sdb_engine_get_symbol_info_by_id_1 (dbe, sym_id, sym_info);
+ return data == NULL ? NULL :
+ (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data,
+ priv->sym_type_conversion_hash,
+ priv->project_directory);
+}
+
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_chain (SymbolDBEngine *dbe,
+ gint scoped_symbol_id,
+ const gchar* db_file,
+ SymExtraInfo sym_info)
+{
+ SymbolDBEnginePriv *priv;
+ GdaDataModel *tmp_res_data = NULL;
+ GdaDataModel *final_data;
+ gint parent_sym_id;
+ gint i;
+
+ g_return_val_if_fail (dbe != NULL, NULL);
+ priv = dbe->priv;
+
+ /* use an hacked GdaDataModel that can receive multiple datamodels in sequence.
+ * This is necessary because unfortunately there's no way to retrieve the
+ * scopes in one go: the returned query would always order them by id and there's no way
+ * to keep the results unsorted.
+ */
+ final_data = gda_data_model_concat_new ();
+
+ tmp_res_data = sdb_engine_get_symbol_info_by_id_1 (dbe, scoped_symbol_id, sym_info);
+ gda_data_model_concat_append_model (GDA_DATA_MODEL_CONCAT (final_data),
+ tmp_res_data);
+
+ /* no need to get a lock */
+ /* first item is considered separately */
+ parent_sym_id = symbol_db_engine_get_parent_scope_id_by_symbol_id (dbe,
+ scoped_symbol_id, db_file);
+
+ if (parent_sym_id <= 0)
+ {
+ return NULL;
+ }
+
+ tmp_res_data = sdb_engine_get_symbol_info_by_id_1 (dbe, parent_sym_id, sym_info);
+
+ /* did something go wrong? */
+ if (!GDA_IS_DATA_MODEL (tmp_res_data) ||
+ gda_data_model_get_n_rows (GDA_DATA_MODEL (tmp_res_data)) <= 0 )
+ {
+ return NULL;
+ }
+
+ gda_data_model_concat_append_model (GDA_DATA_MODEL_CONCAT (final_data),
+ tmp_res_data);
+
+ /* a ref will be taken into the GdaDataModelConcat object so it's safe to
+ * unref here
+ */
+ g_object_unref (tmp_res_data);
+
+ /* we're ready for the big loop. The 100 is an infinite-loop protection. */
+ for (i = 0; i < 100; i++)
+ {
+ /* get the parent scope */
+ parent_sym_id = symbol_db_engine_get_parent_scope_id_by_symbol_id (dbe,
+ parent_sym_id, db_file);
+ /* DEBUG_PRINT ("got parent symbol_id %d", parent_sym_id); */
+ if (parent_sym_id <= 0)
+ {
+ break;
+ }
+ else
+ {
+ tmp_res_data = sdb_engine_get_symbol_info_by_id_1 (dbe, parent_sym_id,
+ sym_info);
+
+ /* merge into the result data */
+ gda_data_model_concat_append_model (GDA_DATA_MODEL_CONCAT (final_data),
+ tmp_res_data);
+ g_object_unref (tmp_res_data);
+ }
+ }
+
+ return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (final_data,
+ priv->sym_type_conversion_hash,
+ priv->project_directory);
+}
+
#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILE_EXTRA_PAR_INCLUDE_KINDS_YES 0x010000
#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILE_EXTRA_PAR_INCLUDE_KINDS_NO 0x020000
#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILE_EXTRA_PAR_LIMIT 0x040000
diff --git a/plugins/symbol-db/symbol-db-engine-queries.h b/plugins/symbol-db/symbol-db-engine-queries.h
index fdfa55d..b5e0c0b 100644
--- a/plugins/symbol-db/symbol-db-engine-queries.h
+++ b/plugins/symbol-db/symbol-db-engine-queries.h
@@ -153,6 +153,29 @@ symbol_db_engine_get_parent_scope_id_by_symbol_id (SymbolDBEngine *dbe,
gint scoped_symbol_id,
const gchar* db_file);
+/**
+ * Walk the path up to the root scope given a scoped_symbol_id parameter.
+ * The returned iterator will be populated with SymbolDBEngineIteratorNode(s)
+ * so that it could be easily browsed by a client app.
+ *
+ * e.g.
+ * namespace FooBase {
+ * class FooKlass {
+ *
+ * }
+ *
+ * void FooKlass::foo_func () { <-------------- this is the scoped symbol
+ *
+ * }
+ *
+ * the returned iterator'll contain symbols in this order: foo_func, FooKlass, FooBase.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_chain (SymbolDBEngine *dbe,
+ gint scoped_symbol_id,
+ const gchar* db_file,
+ SymExtraInfo sym_info);
+
/**
* scope_path cannot be NULL.
* scope_path will be something like "scope1_kind", "scope1_name", "scope2_kind",
diff --git a/plugins/symbol-db/test/Makefile.am b/plugins/symbol-db/test/Makefile.am
index dd56cae..29b1444 100644
--- a/plugins/symbol-db/test/Makefile.am
+++ b/plugins/symbol-db/test/Makefile.am
@@ -26,7 +26,11 @@ benchmark_SOURCES = \
../symbol-db-engine-iterator-node.c \
../symbol-db-engine-iterator-node.h \
../symbol-db-view.h \
- ../symbol-db-view.c
+ ../symbol-db-view.c \
+ ../symbol-db-engine-iterator.h \
+ ../symbol-db-engine-queries.h \
+ ../libgda-extra/gda-data-model-concat.c \
+ ../libgda-extra/gda-data-model-concat.h
benchmark_LDFLAGS = \
diff --git a/plugins/symbol-db/test/benchmark.c b/plugins/symbol-db/test/benchmark.c
index efd3860..af2a771 100644
--- a/plugins/symbol-db/test/benchmark.c
+++ b/plugins/symbol-db/test/benchmark.c
@@ -13,8 +13,6 @@ static void on_single_file_scan_end (SymbolDBEngine* engine, GPtrArray* files)
static GPtrArray* get_files (const gchar* dir)
{
- GList* list = NULL;
- GList* node;
GPtrArray* files = g_ptr_array_new();
GFile *file;
GFileEnumerator *enumerator;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]