anjuta r4474 - in trunk: . plugins/symbol-db



Author: mcora
Date: Sat Dec 20 17:44:46 2008
New Revision: 4474
URL: http://svn.gnome.org/viewvc/anjuta?rev=4474&view=rev

Log:
	* plugins/symbol-db/Makefile.am:
	* plugins/symbol-db/plugin.c (symbol_db_activate),
	(on_prefs_package_remove):
	* plugins/symbol-db/plugin.h:
	* plugins/symbol-db/symbol-db-engine-core.c
	(sdb_engine_cache_lookup), (sdb_engine_insert_cache),
	(sdb_engine_clear_caches), (sdb_engine_init_caches),
	(sdb_engine_execute_unknown_sql), (sdb_engine_execute_select_sql),
	(sdb_engine_execute_non_select_sql),
	(sdb_engine_get_statement_by_query_id),
	(sdb_engine_get_dyn_query_node_by_id),
	(sdb_engine_dyn_child_query_node_destroy),
	(sdb_engine_insert_dyn_query_node_by_id),
	(sdb_engine_get_query_parameters_list),
	(sdb_engine_free_cached_queries),
	(sdb_engine_free_cached_dynamic_queries),
	(sdb_engine_disconnect_from_db),
	(sdb_engine_get_tuple_id_by_unique_name),
	(sdb_engine_get_tuple_id_by_unique_name2),
	(sdb_engine_get_tuple_id_by_unique_name3),
	(sdb_engine_get_tuple_id_by_unique_name4),
	(sdb_engine_get_file_defined_id),
	(sdb_engine_udpated_scope_gtree_populate),
	(sdb_engine_populate_db_by_tags), (sdb_engine_ctags_output_thread),
	(sdb_engine_timeout_trigger_signals), (sdb_engine_thread_monitor),
	(sdb_engine_ctags_output_callback_1), (on_scan_files_end_1),
	(sdb_engine_ctags_launcher_create), (sdb_engine_scan_files_1),
	(sdb_engine_init), (sdb_engine_unlink_shared_files),
	(sdb_engine_unref_removed_launchers),
	(sdb_engine_terminate_threads), (sdb_engine_finalize),
	(sdb_engine_class_init), (sdb_engine_get_type),
	(symbol_db_engine_set_ctags_path), (symbol_db_engine_new),
	(sdb_engine_set_defaults_db_parameters),
	(sdb_engine_connect_to_db), (sdb_engine_create_db_tables),
	(symbol_db_engine_db_exists), (symbol_db_engine_file_exists),
	(symbol_db_engine_close_db), (symbol_db_engine_open_db),
	(symbol_db_engine_add_new_workspace),
	(symbol_db_engine_project_exists),
	(symbol_db_engine_add_new_project), (sdb_engine_add_new_language),
	(sdb_engine_add_new_file), (sdb_engine_get_unique_scan_id),
	(symbol_db_engine_add_new_files), (sdb_engine_add_new_sym_type),
	(sdb_engine_add_new_sym_kind), (sdb_engine_add_new_sym_access),
	(sdb_engine_add_new_sym_implementation),
	(sdb_engine_add_new_heritage),
	(sdb_engine_add_new_scope_definition),
	(sdb_engine_add_new_tmp_heritage_scope),
	(sdb_engine_second_pass_update_scope_1),
	(sdb_engine_second_pass_update_scope),
	(sdb_engine_second_pass_update_heritage),
	(sdb_engine_second_pass_do), (sdb_engine_add_new_symbol),
	(sdb_engine_detects_removed_ids), (sdb_engine_update_file),
	(on_scan_update_files_symbols_end),
	(symbol_db_engine_get_sym_type_conversion_hash),
	(symbol_db_engine_fill_type_array),
	(symbol_db_engine_update_files_symbols),
	(symbol_db_engine_update_project_symbols),
	(symbol_db_engine_remove_file), (symbol_db_engine_remove_files),
	(on_scan_update_buffer_end),
	(symbol_db_engine_update_buffer_symbols):
	* plugins/symbol-db/symbol-db-engine-core.h:
	* plugins/symbol-db/symbol-db-engine-queries.c
	(sdb_engine_walk_down_scope_path),
	(sdb_engine_prepare_file_info_sql),
	(sdb_engine_prepare_symbol_info_sql),
	(symbol_db_engine_get_class_parents_by_symbol_id),
	(symbol_db_engine_get_class_parents),
	(symbol_db_engine_get_global_members_filtered),
	(symbol_db_engine_get_scope_members_by_symbol_id_filtered),
	(symbol_db_engine_get_scope_members_by_symbol_id),
	(symbol_db_engine_get_scope_members),
	(symbol_db_engine_get_current_scope),
	(symbol_db_engine_get_file_symbols),
	(symbol_db_engine_get_symbol_info_by_id),
	(symbol_db_engine_find_symbol_by_name_pattern),
	(symbol_db_engine_get_parent_scope_id_by_symbol_id),
	(symbol_db_engine_find_symbol_by_name_pattern_filtered),
	(symbol_db_engine_get_files_for_project):
	* plugins/symbol-db/symbol-db-engine-queries.h:
	* plugins/symbol-db/symbol-db-engine-utils.c
	(symbol_db_glist_compare_func), (symbol_db_gtree_compare_func),
	(symbol_db_engine_is_locked),
	(symbol_db_engine_get_full_local_path),
	(symbol_db_engine_get_file_db_path),
	(symbol_db_engine_get_files_with_zero_symbols):
	* plugins/symbol-db/symbol-db-engine-utils.h:
	* plugins/symbol-db/symbol-db-engine.c:
	* plugins/symbol-db/symbol-db-engine.h:
	* plugins/symbol-db/symbol-db-view-locals.c
	(symbol_db_view_locals_update_list):
	* plugins/symbol-db/symbol-db-view-search.c:
	* plugins/symbol-db/symbol-db-view-search.h:
	* plugins/symbol-db/symbol-db-view.c (on_scan_end),
	(sdb_view_init), (symbol_db_view_open):
	symbol-db-engine refactoring. Fixed #564048 - Split symbol-db-engine into 
	several files.

Added:
   trunk/plugins/symbol-db/symbol-db-engine-core.c
   trunk/plugins/symbol-db/symbol-db-engine-core.h
   trunk/plugins/symbol-db/symbol-db-engine-queries.c
   trunk/plugins/symbol-db/symbol-db-engine-queries.h
   trunk/plugins/symbol-db/symbol-db-engine-utils.c
   trunk/plugins/symbol-db/symbol-db-engine-utils.h
Removed:
   trunk/plugins/symbol-db/symbol-db-engine.c
Modified:
   trunk/ChangeLog
   trunk/plugins/symbol-db/Makefile.am
   trunk/plugins/symbol-db/plugin.c
   trunk/plugins/symbol-db/plugin.h
   trunk/plugins/symbol-db/symbol-db-engine.h
   trunk/plugins/symbol-db/symbol-db-view-locals.c
   trunk/plugins/symbol-db/symbol-db-view-search.c
   trunk/plugins/symbol-db/symbol-db-view-search.h
   trunk/plugins/symbol-db/symbol-db-view.c

Modified: trunk/plugins/symbol-db/Makefile.am
==============================================================================
--- trunk/plugins/symbol-db/Makefile.am	(original)
+++ trunk/plugins/symbol-db/Makefile.am	Sat Dec 20 17:44:46 2008
@@ -48,8 +48,7 @@
 	readtags.c readtags.h \
 	symbol-db-engine-iterator.c \
 	symbol-db-engine-iterator.h \
-	symbol-db-engine.c \
-	symbol-db-engine.h symbol-db-view.h \
+	symbol-db-view.h \
 	symbol-db-view.c \
 	symbol-db-view-locals.c \
 	symbol-db-view-locals.h \
@@ -59,7 +58,11 @@
 	symbol-db-engine-iterator-node.c \
 	symbol-db-system.h \
 	symbol-db-system.c  symbol-db-prefs.h \
-	symbol-db-prefs.c 
+	symbol-db-prefs.c  symbol-db-engine-queries.c \
+	symbol-db-engine-queries.h  symbol-db-engine-utils.c \
+	symbol-db-engine-utils.h  symbol-db-engine-priv.h \
+	symbol-db-engine-core.c  symbol-db-engine-core.h \
+	symbol-db-engine.h
 
 libanjuta_symbol_db_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
 

Modified: trunk/plugins/symbol-db/plugin.c
==============================================================================
--- trunk/plugins/symbol-db/plugin.c	(original)
+++ trunk/plugins/symbol-db/plugin.c	Sat Dec 20 17:44:46 2008
@@ -45,7 +45,6 @@
 #include "symbol-db-view-locals.h"
 #include "symbol-db-view-search.h"
 #include "symbol-db-engine.h"
-#include "symbol-db-engine-iterator.h"
 #include "symbol-db-prefs.h"
 
 #define ICON_FILE "anjuta-symbol-db-plugin-48.png"
@@ -79,18 +78,6 @@
 
 static unsigned int signals[LAST_SIGNAL] = { 0 };
 
-static gint 
-g_list_compare (gconstpointer a, gconstpointer b)
-{
-	return strcmp ((const gchar*)a, (const gchar*)b);
-}
-
-static gint
-gtree_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
-{
-	return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b);
-}
-
 static void
 register_stock_icons (AnjutaPlugin *plugin)
 {
@@ -1859,7 +1846,7 @@
 	/* beign necessary to listen to many scan-end signals, we'll build up a method
 	 * to manage them with just one signal connection
 	 */
-	symbol_db->proc_id_tree = g_tree_new_full ((GCompareDataFunc)&gtree_compare_func, 
+	symbol_db->proc_id_tree = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
 										 NULL,
 										 NULL,
 										 NULL);
@@ -2466,7 +2453,7 @@
 	GList *item;
 	DEBUG_PRINT ("%s", "on_prefs_package_remove");	
 	if ((item = g_list_find_custom (sdb_plugin->session_packages, package, 
-							g_list_compare)) != NULL)
+							symbol_db_glist_compare_func)) != NULL)
 	{
 		sdb_plugin->session_packages = g_list_remove_link (sdb_plugin->session_packages,
 														   item);

Modified: trunk/plugins/symbol-db/plugin.h
==============================================================================
--- trunk/plugins/symbol-db/plugin.h	(original)
+++ trunk/plugins/symbol-db/plugin.h	Sat Dec 20 17:44:46 2008
@@ -28,7 +28,6 @@
 #include <libanjuta/anjuta-plugin.h>
 #include <libanjuta/anjuta-launcher.h>
 #include "symbol-db-engine.h"
-#include "symbol-db-engine-iterator.h"
 
 
 G_BEGIN_DECLS

Added: trunk/plugins/symbol-db/symbol-db-engine-core.c
==============================================================================
--- (empty file)
+++ trunk/plugins/symbol-db/symbol-db-engine-core.c	Sat Dec 20 17:44:46 2008
@@ -0,0 +1,5750 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2007-2008 <maxcvs email it>
+ * 
+ * anjuta is free software.
+ * 
+ * You may 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 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 anjuta.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+/*
+
+interesting queries:
+
+------------------------
+* get all namespaces.
+select symbol.name from symbol join sym_kind on symbol.kind_id = 
+	sym_kind.sym_kind_id where sym_kind.kind_name = "namespace";
+
+------------------------
+* get all symbols_id which scope is under all namespaces' ones
+select * from symbol where scope_id in (select symbol.scope_definition_id 
+	from symbol join sym_kind on symbol.kind_id = sym_kind.sym_kind_id where 
+	sym_kind.kind_name = "namespace");
+
+------------------------
+* get all symbols which have a scope_id of symbol X. X is a symbol of kind namespace,
+class, struct etc. Symbol X can be retrieved by something like
+select * from symbol join sym_type on symbol.type_id = sym_type.type_id where 
+symbol.name = "First" and sym_type.type_type = "namespace";
+our query is:
+select * from symbol where scope_id = ;
+at the end we have:
+
+select * from symbol where scope_id = (select scope_definition_id from symbol join 
+	sym_type on symbol.type_id = sym_type.type_id where symbol.name = 
+	"First" and sym_type.type_type = "namespace");
+
+
+------------------------
+* get a symbol by its name and type. In this case we want to search for the
+  class Fourth_2_class
+select * from symbol join sym_type on symbol.type_id = sym_type.type_id where 
+	symbol.name = "Fourth_2_class" and sym_type.type = "class";
+
+sqlite> select * from symbol join sym_kind on symbol.kind_id = sym_kind.sym_kind_id  
+			join scope on scope.scope_id = symbol.scope_id 
+			join sym_type on sym_type.type_id = scope.type_id 
+		where symbol.name = "Fourth_2_class" 
+			and sym_kind.kind_name = "class" 
+			and scope = "Fourth" 
+			and sym_type.type = "namespace";
+
+183|13|Fourth_2_class|52|0||140|137|175|8|-1|-1|0|8|class|137|Fourth|172|172|namespace|Fourth
+
+* OR * 
+		
+= get the *derived symbol*
+select * from symbol 
+	join sym_kind on symbol.kind_id = sym_kind.sym_kind_id 
+	where symbol.name = "Fourth_2_class" 
+		and sym_kind.kind_name = "class" 
+		and symbol.scope_id in (select scope.scope_id from scope 
+									join sym_type on scope.type_id = sym_type.type_id 
+									where sym_type.type = 'namespace' 
+										and sym_type.type_name = 'Fourth');
+
+query that get the symbol's parent classes
+
+select symbol_id_base, symbol.name from heritage 
+	join symbol on heritage.symbol_id_base = symbol.symbol_id 
+	where symbol_id_derived = (
+		select symbol_id from symbol 
+			join sym_kind on symbol.kind_id = sym_kind.sym_kind_id 
+			where symbol.name = "Fourth_2_class" 
+				and sym_kind.kind_name = "class" 
+				and symbol.scope_id in (
+					select scope.scope_id from scope 
+						join sym_type on scope.type_id = sym_type.type_id 
+						where sym_type.type = 'namespace' 
+							and sym_type.type_name = 'Fourth'
+					)
+		);
+
+
+182|Fourth_1_class
+
+*/
+
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <fcntl.h>           /* For O_* constants */
+#include <string.h>
+
+#include <gio/gio.h>
+#include <libanjuta/interfaces/ianjuta-symbol.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-launcher.h>
+#include <libanjuta/anjuta-utils.h>
+#include <libgda/libgda.h>
+#include <sql-parser/gda-sql-parser.h>
+#include "readtags.h"
+#include "symbol-db-engine-priv.h"
+#include "symbol-db-engine-core.h"
+#include "symbol-db-engine-iterator.h"
+#include "symbol-db-engine-utils.h"
+
+
+
+enum {
+	DO_UPDATE_SYMS = 1,
+	DO_UPDATE_SYMS_AND_EXIT,
+	DONT_UPDATE_SYMS,
+	DONT_UPDATE_SYMS_AND_EXIT,
+	DONT_FAKE_UPDATE_SYMS,
+	END_UPDATE_GROUP_SYMS
+};
+
+
+#define STATIC_QUERY_POPULATE_INIT_NODE(query_list_ptr, query_type, gda_stmt) { \
+	static_query_node *q = g_new0 (static_query_node, 1); \
+	q->query_id = query_type; \
+	q->query_str = gda_stmt; \
+	q->stmt = NULL; \
+	q->plist = NULL; \
+	query_list_ptr [query_type] = q; \
+}
+
+#define DYN_QUERY_POPULATE_INIT_NODE(dquery_list_ptr, dquery_type, gtree_child) { \
+	dyn_query_node *dq = g_new0 (dyn_query_node, 1); \
+	dq->dyn_query_id = dquery_type; \
+	dq->sym_extra_info_gtree = NULL; \
+	dq->has_gtree_child = gtree_child; \
+	dquery_list_ptr [dquery_type] = dq; \
+}
+
+
+typedef void (SymbolDBEngineCallback) (SymbolDBEngine * dbe,
+									   gpointer user_data);
+
+/* signals */
+enum
+{
+	SINGLE_FILE_SCAN_END,
+	SCAN_END,
+	SYMBOL_INSERTED,
+	SYMBOL_UPDATED,
+	SYMBOL_SCOPE_UPDATED,
+	SYMBOL_REMOVED,
+	LAST_SIGNAL
+};
+
+static unsigned int signals[LAST_SIGNAL] = { 0 };
+
+
+typedef struct _ThreadDataOutput {
+	gchar * chars;
+	gpointer user_data;
+	
+} ThreadDataOutput;
+
+typedef struct _UpdateFileSymbolsData {	
+	gchar *project;
+	gboolean update_prj_analyse_time;
+	GPtrArray * files_path;
+	
+} UpdateFileSymbolsData;
+
+
+
+static GObjectClass *parent_class = NULL;
+
+/*
+ * some forward declarations 
+ */
+static void 
+sdb_engine_second_pass_do (SymbolDBEngine * dbe);
+
+static gint
+sdb_engine_add_new_symbol (SymbolDBEngine * dbe, const tagEntry * tag_entry,
+						   int file_defined_id, gboolean sym_update);
+
+inline const GdaStatement *
+sdb_engine_get_statement_by_query_id (SymbolDBEngine * dbe, static_query_type query_id);
+
+inline const GdaSet *
+sdb_engine_get_query_parameters_list (SymbolDBEngine *dbe, static_query_type query_id);
+
+inline const DynChildQueryNode *
+sdb_engine_get_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 SymExtraInfo sym_info, gsize other_parameters);
+
+inline const DynChildQueryNode *
+sdb_engine_insert_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 	SymExtraInfo sym_info, gsize other_parameters,
+										const gchar *sql);
+
+/*
+ * implementation starts here 
+ */
+static inline gint
+sdb_engine_cache_lookup (GHashTable* hash_table, const gchar* lookup)
+{
+	gpointer orig_key = NULL;
+	gpointer value = NULL;
+	
+	/* avoiding lazy initialization may gain some cpu cycles. Just lookup here. */	
+	if (g_hash_table_lookup_extended (hash_table, 
+									  lookup,
+									  &orig_key,
+									  &value))
+	{
+		gint table_id = GPOINTER_TO_INT (value);
+		return table_id;
+	}
+	return -1;
+}
+
+static inline void
+sdb_engine_insert_cache (GHashTable* hash_table, const gchar* key,
+						 gint value)
+{
+	g_hash_table_insert (hash_table, g_strdup (key), 
+						 GINT_TO_POINTER (value));
+}
+
+static void
+sdb_engine_clear_caches (SymbolDBEngine* dbe)
+{
+	SymbolDBEnginePriv *priv = dbe->priv;
+	if (priv->kind_cache)
+		g_hash_table_destroy (priv->kind_cache);
+	if (priv->access_cache)
+		g_hash_table_destroy (priv->access_cache);	
+	if (priv->implementation_cache)
+		g_hash_table_destroy (priv->implementation_cache);
+	
+	priv->kind_cache = NULL;
+	priv->access_cache = NULL;
+	priv->implementation_cache = NULL;
+}
+
+static void
+sdb_engine_init_caches (SymbolDBEngine* dbe)
+{	
+	SymbolDBEnginePriv *priv = dbe->priv;
+	priv->kind_cache = g_hash_table_new_full (g_str_hash,
+											g_str_equal,
+											g_free,
+											NULL);
+	
+	priv->access_cache = g_hash_table_new_full (g_str_hash,
+											g_str_equal,
+											g_free,
+											NULL);
+	
+	priv->implementation_cache = g_hash_table_new_full (g_str_hash,
+											g_str_equal,
+											g_free,
+											NULL);	
+}
+
+static gboolean 
+sdb_engine_execute_unknown_sql (SymbolDBEngine *dbe, const gchar *sql)
+{
+	GdaStatement *stmt;
+	GObject *res;
+	SymbolDBEnginePriv *priv;
+	
+	priv = dbe->priv;	
+	
+	stmt = gda_sql_parser_parse_string (priv->sql_parser, sql, NULL, NULL);	
+
+	if (stmt == NULL)
+		return FALSE;
+	
+    if ((res = gda_connection_statement_execute (priv->db_connection, 
+												   (GdaStatement*)stmt, 
+												 	NULL,
+													GDA_STATEMENT_MODEL_RANDOM_ACCESS, 
+													NULL, NULL)) == NULL)
+	{
+		g_object_unref (stmt);
+		return FALSE;
+	}
+	else 
+	{
+		g_object_unref (res);
+		g_object_unref (stmt);
+		return TRUE;		
+	}
+}
+
+#if 0
+static GdaDataModel *
+sdb_engine_execute_select_sql (SymbolDBEngine * dbe, const gchar *sql)
+{
+	GdaStatement *stmt;
+	GdaDataModel *res;
+	SymbolDBEnginePriv *priv;
+	const gchar *remain;
+	
+	priv = dbe->priv;	
+	
+	stmt = gda_sql_parser_parse_string (priv->sql_parser, sql, &remain, NULL);	
+
+	if (stmt == NULL)
+		return NULL;
+	
+    res = gda_connection_statement_execute_select (priv->db_connection, 
+												   (GdaStatement*)stmt, NULL, NULL);
+	if (!res) 
+		DEBUG_PRINT ("Could not execute query: %s\n", sql);
+	
+	if (remain != NULL)
+	{
+		/* this shouldn't never happen */		
+		sdb_engine_execute_select_sql (dbe, remain);
+	}	
+	
+    g_object_unref (stmt);
+	
+	return res;
+}
+#endif
+
+static gint
+sdb_engine_execute_non_select_sql (SymbolDBEngine * dbe, const gchar *sql)
+{
+	GdaStatement *stmt;
+    gint nrows;
+	SymbolDBEnginePriv *priv;
+	const gchar *remain;	
+	
+	priv = dbe->priv;
+	stmt = gda_sql_parser_parse_string (priv->sql_parser, 
+										sql, &remain, NULL);
+
+	if (stmt == NULL)
+		return -1;
+	
+	nrows = gda_connection_statement_execute_non_select (priv->db_connection, stmt, 
+														 NULL, NULL, NULL);
+	if (remain != NULL) {
+		/* may happen for example when sql is a file-content */
+		sdb_engine_execute_non_select_sql (dbe, remain);
+	}
+	
+	g_object_unref (stmt);
+	return nrows;
+}
+
+/**
+ * Use a proxy to return an already present or a fresh new prepared query 
+ * from static 'query_list'. We should perform actions in the fastest way, because
+ * these queries are time-critical.
+ * A GdaSet will also be populated once, avoiding so to create again later on.
+ */
+inline const GdaStatement *
+sdb_engine_get_statement_by_query_id (SymbolDBEngine * dbe, static_query_type query_id)
+{
+	static_query_node *node;
+	SymbolDBEnginePriv *priv;
+
+	priv = dbe->priv;
+
+	/* no way: if connection is NULL we will break here. There must be
+	 * a connection established to db before using this function */
+	/*g_return_val_if_fail (priv->db_connection != NULL, NULL);*/
+	
+	if ((node = priv->static_query_list[query_id]) == NULL)
+		return NULL;
+
+	if (node->stmt == NULL)
+	{
+		/*DEBUG_PRINT ("generating new statement.. %d", query_id);*/
+		/* create a new GdaStatement */
+		node->stmt =
+			gda_sql_parser_parse_string (priv->sql_parser, node->query_str, NULL, 
+										 NULL);
+
+		if (gda_statement_get_parameters ((GdaStatement*)node->stmt, 
+										  &node->plist, NULL) == FALSE)
+		{
+			g_warning ("Error on getting parameters for %d", query_id);
+		}
+	}
+
+	return node->stmt;
+}
+
+
+/**
+ *
+ */
+inline const DynChildQueryNode *
+sdb_engine_get_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 SymExtraInfo sym_info, gsize other_parameters)
+{
+	dyn_query_node *node;
+	SymbolDBEnginePriv *priv;
+
+	priv = dbe->priv;
+
+	node = priv->dyn_query_list[query_id];
+
+	if (node == NULL || node->sym_extra_info_gtree == NULL) 
+	{
+		/* we didn't find any extra info symbol, nor it has been added before */
+		return NULL;
+	}
+	
+	if (node->has_gtree_child == FALSE) 
+	{
+		/* use only sym_info as key, ignore other_parameters */
+		return g_tree_lookup (node->sym_extra_info_gtree, GINT_TO_POINTER (sym_info));
+	}
+	else {
+		GTree *child_gtree;
+		DynChildQueryNode *result;
+		
+		child_gtree = g_tree_lookup (node->sym_extra_info_gtree, GINT_TO_POINTER (sym_info));
+		if (child_gtree == NULL) 
+		{			
+			return NULL;
+		}
+		
+		result = g_tree_lookup (child_gtree, GINT_TO_POINTER (other_parameters));
+		return result;
+	}
+}
+
+static void
+sdb_engine_dyn_child_query_node_destroy (gpointer data)
+{
+	DynChildQueryNode *node_to_destroy;
+
+	node_to_destroy = (DynChildQueryNode *)data;
+
+	g_free (node_to_destroy->query_str);
+	g_object_unref (node_to_destroy->stmt);
+	g_object_unref (node_to_destroy->plist);
+	g_free (node_to_destroy);
+}
+
+/**
+ * WARNING: We suppose that before calling this function we already checked with
+ * sdb_engine_get_dyn_query_node_by_id () that the node we're going to add 
+ * isn't yet inserted.
+ */
+inline const DynChildQueryNode *
+sdb_engine_insert_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 	SymExtraInfo sym_info, gsize other_parameters,
+										const gchar *sql)
+{
+	dyn_query_node *node;
+	SymbolDBEnginePriv *priv;
+	priv = dbe->priv;
+	
+	/* no way: if connection is NULL we will break here. There must be
+	 * a connection established to db before using this function */
+	g_return_val_if_fail (priv->db_connection != NULL, NULL);
+
+	node = priv->dyn_query_list[query_id];
+	
+	g_return_val_if_fail (node != NULL, NULL);
+	
+	if (node->sym_extra_info_gtree == NULL) 
+	{
+		/* lazy initialization */
+		if (node->has_gtree_child == FALSE)
+		{
+			node->sym_extra_info_gtree = 
+					g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
+										 NULL,
+										 NULL,
+										 sdb_engine_dyn_child_query_node_destroy);
+		}
+		else
+		{
+			node->sym_extra_info_gtree = 
+					g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
+										 NULL,
+										 NULL,
+										 (GDestroyNotify)g_tree_destroy);
+		}
+	}
+
+	if (node->has_gtree_child == FALSE) 
+	{
+		/* main GTree has direct DynChildQueryNode* as its leaves, other parameters
+		 * will be ignored
+		 */
+		DynChildQueryNode *dyn_node;
+				
+		dyn_node = g_new0 (DynChildQueryNode, 1);
+		
+		/* create a new GdaStatement */
+		dyn_node->stmt =
+			gda_sql_parser_parse_string (priv->sql_parser, sql, NULL, 
+										 NULL);
+
+		if (gda_statement_get_parameters ((GdaStatement*)dyn_node->stmt, 
+										  &dyn_node->plist, NULL) == FALSE)
+		{
+			g_warning ("Error on getting parameters for dyn %d", query_id);
+		}
+		
+		dyn_node->query_str = g_strdup (sql);
+				
+		/* insert it into gtree, thanks */
+		g_tree_insert (node->sym_extra_info_gtree, GINT_TO_POINTER (sym_info), dyn_node);
+		
+		/* return it */
+		return dyn_node;
+	}
+	else 
+	{
+		/* ok, this is a slightly more complex case */
+		GTree *child_gtree;
+		DynChildQueryNode *dyn_node;
+
+		child_gtree = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func,
+									 NULL,
+									 NULL, 
+									 sdb_engine_dyn_child_query_node_destroy); 
+				
+		dyn_node = g_new0 (DynChildQueryNode, 1);
+		
+		/* create a new GdaStatement */
+		dyn_node->stmt =
+			gda_sql_parser_parse_string (priv->sql_parser, sql, NULL, 
+										 NULL);
+
+		if (gda_statement_get_parameters ((GdaStatement*)dyn_node->stmt, 
+										  &dyn_node->plist, NULL) == FALSE)
+		{
+			g_warning ("Error on getting parameters for dyn %d", query_id);
+		}
+		
+		dyn_node->query_str = g_strdup (sql);
+		
+/*		
+		DEBUG_PRINT ("inserting child into main_gtree's gtree child, "
+					 "other_parameters %d, sym_info %d, dyn_node %p", 
+					 other_parameters, sym_info, dyn_node);
+*/		
+		/* insert the dyn_node into child_gtree, then child_gtree into main_gtree */
+		g_tree_insert (child_gtree, GINT_TO_POINTER (other_parameters), dyn_node);
+		
+		g_tree_insert (node->sym_extra_info_gtree, GINT_TO_POINTER (sym_info), child_gtree);
+		
+		/* return it */
+		return dyn_node;		
+	}	
+}
+
+/**
+ * Return a GdaSet of parameters calculated from the statement. It does not check
+ * if it's null. You *must* be sure to have called sdb_engine_get_statement_by_query_id () first.
+ */
+inline const GdaSet *
+sdb_engine_get_query_parameters_list (SymbolDBEngine *dbe, static_query_type query_id)
+{
+	SymbolDBEnginePriv *priv;
+	
+	priv = dbe->priv;
+	
+	static_query_node *node;
+	node = priv->static_query_list[query_id];
+	return node->plist;
+}
+
+/**
+ * Clear the static cached queries data. You should call this function when closing/
+ * destroying SymbolDBEngine object.
+ */
+static void
+sdb_engine_free_cached_queries (SymbolDBEngine *dbe)
+{
+	SymbolDBEnginePriv *priv;
+	gint i;
+	static_query_node *node;
+	
+	priv = dbe->priv;
+
+	for (i = 0; i < PREP_QUERY_COUNT; i++)
+	{
+/*DEBUG_PRINT ("sdb_engine_free_cached_queries START %d", i);*/
+		node = priv->static_query_list[i];
+
+		if (node != NULL && node->stmt != NULL)
+		{
+			/*DEBUG_PRINT ("sdb_engine_free_cached_queries stmt %d", i);*/
+			g_object_unref (node->stmt);
+			node->stmt = NULL;
+		}
+		
+		if (node != NULL && node->plist != NULL)
+		{
+			/*DEBUG_PRINT ("sdb_engine_free_cached_queries plist %d", i);*/
+			g_object_unref (node->plist);
+			node->plist = NULL;
+		}
+		
+		/* last but not the least free the node itself */
+		g_free (node);
+		priv->static_query_list[i] = NULL;
+/*DEBUG_PRINT ("sdb_engine_free_cached_queries END %d", i);		*/
+	}
+}
+
+static void
+sdb_engine_free_cached_dynamic_queries (SymbolDBEngine *dbe)
+{
+	SymbolDBEnginePriv *priv;
+	gint i;
+	dyn_query_node *node;
+
+	priv = dbe->priv;
+	
+	for (i = 0; i < DYN_PREP_QUERY_COUNT; i++)
+	{
+		node = priv->dyn_query_list[i];
+		
+		if (node != NULL && node->sym_extra_info_gtree != NULL)
+		{	
+			g_tree_destroy (node->sym_extra_info_gtree);			
+			node->sym_extra_info_gtree = NULL;
+		}		
+		
+		/* last but not the least free the node itself */
+		g_free (node);
+		priv->dyn_query_list[i] = NULL;		
+	}
+}
+
+static gboolean
+sdb_engine_disconnect_from_db (SymbolDBEngine * dbe)
+{
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	priv = dbe->priv;
+
+	if (priv->db_connection != NULL)
+		gda_connection_close (priv->db_connection);
+	priv->db_connection = NULL;
+
+	if (priv->sql_parser != NULL)
+		g_object_unref (priv->sql_parser);
+	priv->sql_parser = NULL;
+	
+	g_free (priv->db_directory);
+	priv->db_directory = NULL;
+	
+	g_free (priv->project_directory);
+	priv->project_directory = NULL;
+	
+	return TRUE;
+}
+
+/**
+ * @return -1 on error. Otherwise the id of tuple.
+ */
+static inline gint
+sdb_engine_get_tuple_id_by_unique_name (SymbolDBEngine * dbe, static_query_type qtype,
+										gchar * param_key,
+										const GValue * param_value)
+{
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaDataModel *data_model;
+	const GValue *num;
+	gint table_id;
+	SymbolDBEnginePriv *priv;
+	
+	priv = dbe->priv;
+
+	/* get prepared query */
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, qtype)) == NULL)
+	{
+		g_warning ("Query is null");
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, qtype);
+	
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name: param is NULL "
+				   "from pquery!\n");
+		return -1;
+	}
+	gda_holder_set_value (param, param_value, NULL);
+	
+	/* execute the query with parametes just set */
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  (GdaSet*)plist, NULL);
+		
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model)) <= 0)
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		return -1;
+	}
+
+	/* get and parse the results. */
+	num = gda_data_model_get_value_at (GDA_DATA_MODEL (data_model), 0, 0, NULL);
+
+	table_id = g_value_get_int (num);
+	g_object_unref (data_model);
+	return table_id;
+}
+
+/**
+ * This is the same as sdb_engine_get_tuple_id_by_unique_name () but for two
+ * unique parameters. This should be the quickest way. Surely quicker than
+ * use g_strdup_printf () with a va_list for example.
+ * @return -1 on error. Otherwise the id of table
+ *
+ */
+static inline gint
+sdb_engine_get_tuple_id_by_unique_name2 (SymbolDBEngine * dbe, 
+										 static_query_type qtype,
+										 gchar * param_key1,
+										 const GValue * value1,
+										 gchar * param_key2,
+										 const GValue * value2)
+{
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaDataModel *data_model;
+	const GValue *num;
+	gint table_id;
+	SymbolDBEnginePriv *priv;
+	
+	priv = dbe->priv;
+
+	/* get prepared query */
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, qtype)) == NULL)
+	{
+		g_warning ("Query is null");
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, qtype);
+	
+	/* look for and set the first parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key1)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name2: "
+				   "param is NULL from pquery! [par1: %s] [par2: %s]\n",
+				   param_key1, param_key2);
+		return -1;
+	}
+	gda_holder_set_value (param, value1, NULL);
+	
+	/* ...and the second one */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key2)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name2: "
+				   "param is NULL from pquery! [par1: %s] [par2: %s]\n",
+				   param_key1, param_key2);
+		return -1;
+	}
+	gda_holder_set_value (param, value2, NULL);
+
+	/* execute the query with parametes just set */
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  (GdaSet*)plist, NULL);
+		
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model)) <= 0)
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		return -1;
+	}
+
+	/* get and parse the results. */
+	num = gda_data_model_get_value_at (GDA_DATA_MODEL (data_model), 0, 0, NULL);
+
+	table_id = g_value_get_int (num);
+	g_object_unref (data_model);
+	
+	return table_id;
+}
+
+static inline gint
+sdb_engine_get_tuple_id_by_unique_name3 (SymbolDBEngine * dbe, 
+										 static_query_type qtype,
+										 gchar * param_key1,
+										 const GValue * value1,
+										 gchar * param_key2,
+										 const GValue * value2,
+										 gchar * param_key3,
+										 const GValue * value3)
+{
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaDataModel *data_model;
+	const GValue *num;
+	gint table_id;
+	SymbolDBEnginePriv *priv;
+	
+	priv = dbe->priv;
+
+	/* get prepared query */
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, qtype)) == NULL)
+	{
+		g_warning ("Query is null");
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, qtype);
+	
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key1)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name: param is NULL "
+				   "from pquery!\n");
+		return -1;
+	}
+	gda_holder_set_value (param, value1, NULL);
+	
+
+	/* ...and the second one */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key2)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name2: "
+				   "param is NULL from pquery! [par1: %s] [par2: %s]\n",
+				   param_key1, param_key2);
+		return -1;
+	}
+	gda_holder_set_value (param, value2, NULL);
+
+	/* ...and the third one */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key3)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name2: "
+				   "param is NULL from pquery! [par1: %s] [par2: %s]\n",
+				   param_key1, param_key3);
+		return -1;
+	}
+	gda_holder_set_value (param, value3, NULL);
+		
+	/* execute the query with parametes just set */
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  (GdaSet*)plist, NULL);
+		
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model)) <= 0)
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		return -1;
+	}
+
+	/* get and parse the results. */
+	num = gda_data_model_get_value_at (GDA_DATA_MODEL (data_model), 0, 0, NULL);
+
+	table_id = g_value_get_int (num);
+	g_object_unref (data_model);
+	return table_id;
+}
+
+static inline gint
+sdb_engine_get_tuple_id_by_unique_name4 (SymbolDBEngine * dbe, 
+										 static_query_type qtype,
+										 gchar * param_key1,
+										 const GValue * value1,
+										 gchar * param_key2,
+										 const GValue * value2,
+										 gchar * param_key3,
+										 const GValue * value3,
+										 gchar * param_key4,
+										 const GValue * value4)
+{
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaDataModel *data_model;
+	const GValue *num;
+	gint table_id;
+	SymbolDBEnginePriv *priv;
+	
+	priv = dbe->priv;
+
+	/* get prepared query */
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, qtype)) == NULL)
+	{
+		g_warning ("Query is null");
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, qtype);
+	
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key1)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name: param is NULL "
+				   "from pquery!\n");
+		return -1;
+	}
+	gda_holder_set_value (param, value1, NULL);
+	
+
+	/* ...and the second one */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key2)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name2: "
+				   "param is NULL from pquery!");
+		return -1;
+	}
+	gda_holder_set_value (param, value2, NULL);
+
+	/* ...and the third one */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key3)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name2: "
+				   "param is NULL from pquery!");
+		return -1;
+	}
+	gda_holder_set_value (param, value3, NULL);
+		
+	/* ...and the fourth one */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, param_key4)) == NULL)
+	{
+		g_warning ("sdb_engine_get_tuple_id_by_unique_name2: "
+				   "param is NULL from pquery!");
+		return -1;
+	}
+	gda_holder_set_value (param, value4, NULL);
+			
+	/* execute the query with parametes just set */
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  (GdaSet*)plist, NULL);
+		
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model)) <= 0)
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		return -1;
+	}
+
+	/* get and parse the results. */
+	num = gda_data_model_get_value_at (GDA_DATA_MODEL (data_model), 0, 0, NULL);
+
+	table_id = g_value_get_int (num);
+	g_object_unref (data_model);
+	return table_id;
+}
+
+static int
+sdb_engine_get_file_defined_id (SymbolDBEngine* dbe,
+								const gchar* base_prj_path,
+								const gchar* fake_file_on_db,
+								tagEntry* tag_entry)
+{
+	SymbolDBEnginePriv *priv;
+	GValue* value;
+	
+	priv = dbe->priv;	
+
+	MP_LEND_OBJ_STR(priv, value);
+	
+	gint file_defined_id = 0;
+	if (base_prj_path != NULL && g_str_has_prefix (tag_entry->file, base_prj_path))
+	{
+		/* in this case fake_file will be ignored. */
+		
+		/* we expect here an absolute path */
+		g_value_set_static_string (value,
+							tag_entry->file + strlen (base_prj_path) );
+	}
+	else
+	{
+		/* check whether the fake_file can substitute the tag_entry->file one */
+		if (fake_file_on_db == NULL)
+			g_value_set_static_string (value, tag_entry->file);
+		else
+			g_value_set_static_string (value, fake_file_on_db);
+	}
+	
+	if ((file_defined_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+													PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
+													"filepath",
+													value)) < 0)
+	{	
+		/* if we arrive here there should be some sync problems between the filenames
+		 * in database and the ones in the ctags files. We trust in db's ones,
+		 * so we'll just return here.
+		 */
+		g_warning ("sync problems between db and ctags filenames entries. "
+				   "File was %s (base_path: %s, fake_file: %s, tag_file: %s)", 
+				   g_value_get_string (value), base_prj_path, fake_file_on_db, 
+				   tag_entry->file);
+		MP_RETURN_OBJ_STR (priv, value);
+		return -1;
+	}
+	MP_RETURN_OBJ_STR (priv, value);
+	return file_defined_id;
+}
+
+static
+gboolean sdb_engine_udpated_scope_gtree_populate (gpointer key,
+                                                  gpointer value,
+                                                  gpointer data)
+{
+	SymbolDBEnginePriv *priv;
+	SymbolDBEngine * dbe = data;
+	priv = dbe->priv;
+
+	GList *list;
+	list = value;
+	if (g_list_length  (list) > 1)
+	{
+		GList *item = list;
+		while (item != NULL)
+		{
+			g_async_queue_push (priv->updated_scope_symbols_id, 
+								(gpointer) item->data);
+			item = item->next;
+		}
+	}
+	
+	/* proceed with a freeing of the values */
+	g_list_free (list);
+	return FALSE;
+}
+
+static GTimer *sym_timer_DEBUG  = NULL;
+
+/**
+ * If fake_file is != NULL we claim and assert that tags contents which are
+ * scanned belong to the fake_file in the project.
+ * More: the fake_file refers to just one single file and cannot be used
+ * for multiple fake_files.
+ */
+static void
+sdb_engine_populate_db_by_tags (SymbolDBEngine * dbe, FILE* fd,
+								gchar * fake_file_on_db,
+								gboolean force_sym_update)
+{
+	tagFile *tag_file;
+	tagFileInfo tag_file_info;
+	tagEntry tag_entry;
+	gint file_defined_id_cache = 0;
+	gchar* tag_entry_file_cache = NULL;
+	
+	SymbolDBEnginePriv *priv = dbe->priv;
+
+	gchar* base_prj_path = fake_file_on_db == NULL ?
+		priv->project_directory : NULL;
+	
+	g_return_if_fail (dbe != NULL);
+
+	g_return_if_fail (priv->db_connection != NULL);
+	g_return_if_fail (fd != NULL);
+	
+	if ((tag_file = tagsOpen_1 (fd, &tag_file_info)) == NULL)
+	{
+		g_warning ("error in opening ctags file");
+	}
+
+	if (sym_timer_DEBUG == NULL)
+		sym_timer_DEBUG = g_timer_new ();
+	else
+		g_timer_reset (sym_timer_DEBUG);
+	gint tags_total_DEBUG = 0;
+	tag_entry.file = NULL;
+
+	while (tagsNext (tag_file, &tag_entry) != TagFailure)
+	{
+		gint file_defined_id = 0;
+		if (tag_entry.file == NULL)
+		{
+			continue;
+		}
+		if (file_defined_id_cache > 0)
+		{
+			if (g_str_equal (tag_entry.file, tag_entry_file_cache))
+			{
+				file_defined_id = file_defined_id_cache;
+			}
+		}
+		if (file_defined_id == 0)
+		{
+			file_defined_id = sdb_engine_get_file_defined_id (dbe,
+															  base_prj_path,
+															  fake_file_on_db,
+															  &tag_entry);
+			file_defined_id_cache = file_defined_id;
+			g_free (tag_entry_file_cache);
+			tag_entry_file_cache = g_strdup (tag_entry.file);
+		}
+		/* insert or update a symbol */
+		sdb_engine_add_new_symbol (dbe, &tag_entry, file_defined_id,
+								   force_sym_update);
+		
+		tags_total_DEBUG ++;
+		tag_entry.file = NULL;
+	}
+	g_free (tag_entry_file_cache);
+
+	if (force_sym_update == TRUE)
+	{
+	
+		/* any scope_updated symbols to the releative queue */
+		g_tree_foreach (priv->file_symbols_cache, 
+					sdb_engine_udpated_scope_gtree_populate, dbe);
+		/* destroying the tree and recreating it should be faster than removing each
+		 * balanced item inside it */
+		g_tree_destroy (priv->file_symbols_cache);
+		priv->file_symbols_cache = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
+										 NULL,
+										 NULL,
+										 NULL);
+	}
+
+	gdouble elapsed_DEBUG = g_timer_elapsed (sym_timer_DEBUG, NULL);
+	DEBUG_PRINT ("elapsed: %f for (%d) [%f per symbol]", elapsed_DEBUG,
+				 tags_total_DEBUG, elapsed_DEBUG / tags_total_DEBUG);
+
+	/* notify listeners that another file has been scanned */
+	g_async_queue_push (priv->signals_queue, GINT_TO_POINTER (SINGLE_FILE_SCAN_END +1));
+	
+	/* we've done with tag_file but we don't need to tagsClose (tag_file); */
+}
+
+static gpointer
+sdb_engine_ctags_output_thread (gpointer data)
+{
+	ThreadDataOutput *output;
+	gint len_chars;
+	gchar *chars, *chars_ptr;
+	gint remaining_chars;
+	gint len_marker;
+	SymbolDBEnginePriv *priv;
+	SymbolDBEngine *dbe;
+	
+	output = (ThreadDataOutput *)data;
+	dbe = output->user_data;
+	chars = chars_ptr = output->chars;	
+	
+	g_return_val_if_fail (dbe != NULL, GINT_TO_POINTER (-1));	
+	g_return_val_if_fail (chars_ptr != NULL, GINT_TO_POINTER (-1));
+
+	priv = dbe->priv;
+
+	/* lock */
+	if (priv->mutex)
+		g_mutex_lock (priv->mutex);
+	priv->thread_status = TRUE;
+	
+	remaining_chars = len_chars = strlen (chars_ptr);
+	len_marker = strlen (CTAGS_MARKER);	
+
+	if ( len_chars >= len_marker ) 
+	{
+		gchar *marker_ptr = NULL;
+		gint tmp_str_length = 0;
+
+		/* is it an end file marker? */
+		marker_ptr = strstr (chars_ptr, CTAGS_MARKER);
+
+		do  
+		{
+			if (marker_ptr != NULL) 
+			{
+				int scan_flag;
+				gchar *real_file;
+		
+				/* set the length of the string parsed */
+				tmp_str_length = marker_ptr - chars_ptr;
+	
+				/*DEBUG_PRINT ("program output [new version]: ==>%s<==", chars_ptr);*/
+				/* write to shm_file all the chars_ptr received without the marker ones */
+				fwrite (chars_ptr, sizeof(gchar), tmp_str_length, priv->shared_mem_file);
+
+				chars_ptr = marker_ptr + len_marker;
+				remaining_chars -= (tmp_str_length + len_marker);
+				fflush (priv->shared_mem_file);
+				
+				/* get the scan flag from the queue. We need it to know whether
+				 * an update of symbols must be done or not */
+				scan_flag = GPOINTER_TO_INT(g_async_queue_try_pop (priv->scan_queue));
+				real_file = g_async_queue_try_pop (priv->scan_queue);
+				
+				/* and now call the populating function */
+				if (scan_flag == DO_UPDATE_SYMS ||
+					scan_flag == DO_UPDATE_SYMS_AND_EXIT)
+				{
+					sdb_engine_populate_db_by_tags (dbe, priv->shared_mem_file,
+								(gsize)real_file == DONT_FAKE_UPDATE_SYMS ? NULL : real_file, 
+								TRUE);
+				}
+				else 
+				{
+					sdb_engine_populate_db_by_tags (dbe, priv->shared_mem_file,
+								(gsize)real_file == DONT_FAKE_UPDATE_SYMS ? NULL : real_file, 
+								FALSE);					
+				}
+				
+				/* don't forget to free the real_file, if it's a char */
+				if ((gsize)real_file != DONT_FAKE_UPDATE_SYMS)
+					g_free (real_file);
+				
+				/* check also if, together with an end file marker, we have an 
+				 * end group-of-files end marker.
+				 */
+				if (scan_flag == DO_UPDATE_SYMS_AND_EXIT || 
+					 scan_flag == DONT_UPDATE_SYMS_AND_EXIT )
+				{
+					gint tmp_inserted;
+					gint tmp_updated;
+
+					/* proceed with second passes */
+					DEBUG_PRINT ("%s", "FOUND end-of-group-files marker."
+								 "go on with sdb_engine_second_pass_do ()");
+					
+					chars_ptr += len_marker;
+					remaining_chars -= len_marker;
+					
+					/* will emit symbol_scope_updated */
+					sdb_engine_second_pass_do (dbe);					
+					
+					/* Here we are. It's the right time to notify the listeners
+					 * about out fresh new inserted/updated symbols...
+					 * Go on by emitting them.
+					 */
+					while ((tmp_inserted = GPOINTER_TO_INT(
+							g_async_queue_try_pop (priv->inserted_symbols_id))) > 0)
+					{
+						/* we must be sure to insert both signals at once */
+						g_async_queue_lock (priv->signals_queue);
+						
+						/* the +1 is because asyn_queue doesn't want NULL values */
+						g_async_queue_push_unlocked (priv->signals_queue, 
+													 GINT_TO_POINTER(SYMBOL_INSERTED + 1));
+						g_async_queue_push_unlocked (priv->signals_queue, 
+													 GINT_TO_POINTER(tmp_inserted));
+						g_async_queue_unlock (priv->signals_queue);
+					}
+					
+					while ((tmp_updated = GPOINTER_TO_INT(
+							g_async_queue_try_pop (priv->updated_symbols_id))) > 0)
+					{
+						g_async_queue_lock (priv->signals_queue);
+						g_async_queue_push_unlocked (priv->signals_queue, GINT_TO_POINTER
+													 (SYMBOL_UPDATED + 1));
+						g_async_queue_push_unlocked (priv->signals_queue, 
+													 GINT_TO_POINTER(tmp_updated));
+						g_async_queue_unlock (priv->signals_queue);
+					}
+
+					while ((tmp_updated = GPOINTER_TO_INT(
+							g_async_queue_try_pop (priv->updated_scope_symbols_id))) > 0)
+					{
+						g_async_queue_lock (priv->signals_queue);
+						g_async_queue_push_unlocked (priv->signals_queue, GINT_TO_POINTER (
+													 SYMBOL_SCOPE_UPDATED + 1));
+						g_async_queue_push_unlocked (priv->signals_queue, 
+													GINT_TO_POINTER(tmp_updated));
+						g_async_queue_unlock (priv->signals_queue);
+					}
+					
+					
+					/* emit signal. The end of files-group can be cannot be
+					 * determined by the caller. This is the only way.
+					 */
+					DEBUG_PRINT ("%s", "EMITTING scan-end");
+					g_async_queue_push (priv->signals_queue, GINT_TO_POINTER(SCAN_END + 1));
+				}
+				
+				/* truncate the file to 0 length */
+				ftruncate (priv->shared_mem_fd, 0);				
+			}
+			else
+			{ 
+				/* marker_ptr is NULL here. We should then exit the loop. */
+				/* write to shm_file all the chars received */
+				fwrite (chars_ptr, sizeof(gchar), remaining_chars, 
+						priv->shared_mem_file);
+
+				fflush (priv->shared_mem_file);
+				break;
+			}
+
+			/* found out a new marker */ 
+			marker_ptr = strstr (marker_ptr + len_marker, CTAGS_MARKER);
+		} while (remaining_chars + len_marker < len_chars || marker_ptr != NULL);
+	}
+	else 
+	{
+		DEBUG_PRINT ("%s", "no len_chars > len_marker");
+	}
+
+	priv->thread_status = FALSE;
+	priv->concurrent_threads--;	
+	
+	/* unlock */
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+
+	/* notify waiters that we've finished another thread */
+	g_cond_signal (priv->shutting_cond);
+	
+	g_free (chars);
+	g_free (output);
+	
+	return 0;
+}
+
+
+/**
+ * This function runs on the main glib thread, so that it can safely spread signals 
+ */
+static gboolean
+sdb_engine_timeout_trigger_signals (gpointer user_data)
+{
+	SymbolDBEngine *dbe = (SymbolDBEngine *) user_data;
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (user_data != NULL, FALSE);	
+	priv = dbe->priv;		
+
+	if (g_async_queue_length (priv->signals_queue) > 0)
+	{
+		gpointer tmp;
+		gpointer sign = NULL;
+		gsize real_signal;
+	
+		while ((sign = g_async_queue_try_pop (priv->signals_queue)) != NULL)  
+		{
+			if (sign == NULL) 
+			{
+				return g_async_queue_length (priv->signals_queue) > 0 ? TRUE : FALSE;
+			}
+	
+			real_signal = (gsize)sign -1;
+	
+			switch (real_signal) 
+			{
+				case SINGLE_FILE_SCAN_END:
+					g_signal_emit (dbe, signals[SINGLE_FILE_SCAN_END], 0);
+					break;
+		
+				case SCAN_END:
+				{
+					/* get the process id from the queue */
+					gint int_tmp = GPOINTER_TO_INT(g_async_queue_pop (priv->scan_process_id_queue));
+					g_signal_emit (dbe, signals[SCAN_END], 0, int_tmp);
+				}
+					break;
+	
+				case SYMBOL_INSERTED:
+					tmp = g_async_queue_try_pop (priv->signals_queue);
+					g_signal_emit (dbe, signals[SYMBOL_INSERTED], 0, tmp);
+					break;
+	
+				case SYMBOL_UPDATED:
+					tmp = g_async_queue_try_pop (priv->signals_queue);
+					g_signal_emit (dbe, signals[SYMBOL_UPDATED], 0, tmp);
+					break;
+	
+				case SYMBOL_SCOPE_UPDATED:
+					tmp = g_async_queue_try_pop (priv->signals_queue);
+					g_signal_emit (dbe, signals[SYMBOL_SCOPE_UPDATED], 0, tmp);
+					break;
+	
+				case SYMBOL_REMOVED:
+					tmp = g_async_queue_try_pop (priv->signals_queue);
+					g_signal_emit (dbe, signals[SYMBOL_REMOVED], 0, tmp);
+					break;
+			}
+		}		
+		/* reset to 0 the retries */
+		priv->trigger_closure_retries = 0;
+	}
+	else {
+		priv->trigger_closure_retries++;
+	}
+	
+	if (priv->thread_status == FALSE &&
+		priv->trigger_closure_retries > TRIGGER_MAX_CLOSURE_RETRIES &&
+		g_queue_get_length (priv->thread_list_data) <= 0 &&
+		priv->thread_monitor_handler <= 0)
+	{
+		/*DEBUG_PRINT ("%s", "removing signals trigger");*/
+		/* remove the trigger coz we don't need it anymore... */
+		g_source_remove (priv->timeout_trigger_handler);
+		priv->timeout_trigger_handler = 0;
+		return FALSE;
+	}
+	
+	return TRUE;
+}
+
+static gboolean
+sdb_engine_thread_monitor (gpointer data)
+{
+	gpointer output;
+	SymbolDBEngine *dbe = (SymbolDBEngine *) data;
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (data != NULL, FALSE);
+	
+	priv = dbe->priv;
+	
+	if (priv->shutting_mutex)
+		g_mutex_lock (priv->shutting_mutex);
+	
+	if (priv->shutting_down == TRUE)
+	{
+		/*DEBUG_PRINT ("%s", "SymbolDBEngine is shutting down: removing thread monitor");*/
+		/* remove the thread monitor */
+		g_source_remove (priv->thread_monitor_handler);
+		priv->thread_monitor_handler = 0;
+		g_mutex_unlock (priv->shutting_mutex);
+		return FALSE;
+	}
+		
+	if (priv->concurrent_threads > THREADS_MAX_CONCURRENT) 
+	{
+		/* monitor acted here. There are plenty threads already working. */
+		g_mutex_unlock (priv->shutting_mutex);
+		return TRUE;
+	}
+	
+	output = g_queue_pop_head (priv->thread_list_data);
+ 
+	if (output != NULL)
+	{
+		priv->concurrent_threads ++;
+		g_thread_create ((GThreadFunc)sdb_engine_ctags_output_thread, output, 
+					 FALSE, NULL);
+		priv->thread_closure_retries = 0;
+	}
+	else 
+	{
+		priv->thread_closure_retries++;
+	}
+
+	if (priv->thread_closure_retries > THREAD_MAX_CLOSURE_RETRIES &&
+		g_queue_get_length (priv->thread_list_data) <= 0)
+	{
+		/*DEBUG_PRINT ("%s", "removing thread monitor");*/
+		/* remove the thread monitor */
+		g_source_remove (priv->thread_monitor_handler);
+		priv->thread_monitor_handler = 0;
+		g_mutex_unlock (priv->shutting_mutex);
+		return FALSE;
+	}
+	
+	g_mutex_unlock (priv->shutting_mutex);
+	/* recall this monitor */
+	return TRUE;	
+}
+
+static void
+sdb_engine_ctags_output_callback_1 (AnjutaLauncher * launcher,
+								  AnjutaLauncherOutputType output_type,
+								  const gchar * chars, gpointer user_data)
+{ 
+	ThreadDataOutput *output;
+	SymbolDBEngine *dbe = (SymbolDBEngine *) user_data;
+	SymbolDBEnginePriv *priv;
+
+	g_return_if_fail (user_data != NULL);
+	
+	priv = dbe->priv;	
+	
+	if (priv->shutting_down == TRUE)
+		return;
+	
+	output  = g_new0 (ThreadDataOutput, 1);
+	output->chars = g_strdup (chars);
+	output->user_data = user_data;
+
+	g_queue_push_tail (priv->thread_list_data, output);
+
+	/* thread monitor */
+	if (priv->thread_monitor_handler <= 0)
+	{
+		priv->thread_monitor_handler = 
+			g_timeout_add_full (G_PRIORITY_LOW,
+					THREADS_MONITOR_TIMEOUT, 
+					sdb_engine_thread_monitor, 
+					user_data,
+					NULL);
+		priv->thread_closure_retries = 0;
+	}
+	
+	/* signals monitor */
+	if (priv->timeout_trigger_handler <= 0)
+	{
+		priv->timeout_trigger_handler = 
+			g_timeout_add_full (G_PRIORITY_LOW, TRIGGER_SIGNALS_DELAY, 
+						   sdb_engine_timeout_trigger_signals, user_data, NULL);
+		priv->trigger_closure_retries = 0;
+	}
+}
+
+static void
+on_scan_files_end_1 (AnjutaLauncher * launcher, int child_pid,
+				   int exit_status, gulong time_taken_in_seconds,
+				   gpointer data)
+{
+	DEBUG_PRINT ("%s", "***** ctags ended *****");
+}
+
+
+static void
+sdb_engine_ctags_launcher_create (SymbolDBEngine * dbe)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *exe_string;
+		
+	priv = dbe->priv;
+	
+	DEBUG_PRINT ("%s", "creating anjuta_launcher");
+
+	priv->ctags_launcher = anjuta_launcher_new ();
+
+	anjuta_launcher_set_check_passwd_prompt (priv->ctags_launcher, FALSE);
+	anjuta_launcher_set_encoding (priv->ctags_launcher, NULL);
+		
+	g_signal_connect (G_OBJECT (priv->ctags_launcher), "child-exited",
+						  G_CALLBACK (on_scan_files_end_1), NULL);
+
+	exe_string = g_strdup_printf ("%s --sort=no --fields=afmiKlnsStz --c++-kinds=+p "
+								  "--filter=yes --filter-terminator='"CTAGS_MARKER"'",
+								  priv->ctags_path);
+		
+	anjuta_launcher_execute (priv->ctags_launcher,
+								 exe_string, sdb_engine_ctags_output_callback_1, 
+								 dbe);
+	g_free (exe_string);
+}
+
+/* Scans with ctags and produce an output 'tags' file [shared memory file]
+ * containing language symbols. This function will call ctags 
+ * executale and then sdb_engine_populate_db_by_tags () when it'll detect some
+ * output.
+ * Please note the files_list/real_files_list parameter:
+ * this version of sdb_engine_scan_files_1 () let you scan for text buffer(s) that
+ * will be claimed as buffers for the real files.
+ * 1. simple mode: files_list represents the real files on disk and so we don't 
+ * need real_files_list, which will be NULL.
+ * 2. advanced mode: files_list represents temporary flushing of buffers on disk, i.e.
+ * /tmp/anjuta_XYZ.cxx. real_files_list is the representation of those files on 
+ * database. On the above example we can have anjuta_XYZ.cxx mapped as /src/main.c 
+ * on db. In this mode files_list and real_files_list must have the same size.
+ *
+ */
+/* server mode version */
+static gboolean
+sdb_engine_scan_files_1 (SymbolDBEngine * dbe, const GPtrArray * files_list,
+						 const GPtrArray *real_files_list, gboolean symbols_update)
+{
+	SymbolDBEnginePriv *priv;
+	gint i;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	g_return_val_if_fail (files_list != NULL, FALSE);
+	
+	if (files_list->len == 0)
+		return FALSE;	
+	
+	/* start process in server mode */
+	priv = dbe->priv;
+
+	if (real_files_list != NULL && (files_list->len != real_files_list->len)) 
+	{
+		g_warning ("no matched size between real_files_list and files_list");		
+		return FALSE;
+	}
+	
+	/* if ctags_launcher isn't initialized, then do it now. */
+	/* lazy initialization */
+	if (priv->ctags_launcher == NULL) 
+	{
+		sdb_engine_ctags_launcher_create (dbe);
+	}
+	
+	/* create the shared memory file */
+	if (priv->shared_mem_file == 0)
+	{
+		gchar *temp_file;
+		while (TRUE)
+		{
+			temp_file = g_strdup_printf ("/anjuta-%d_%ld.tags", getpid (),
+								 time (NULL));
+			gchar *test;
+			test = g_strconcat (SHARED_MEMORY_PREFIX, temp_file, NULL);
+			if (g_file_test (test, G_FILE_TEST_EXISTS) == TRUE)
+			{
+				DEBUG_PRINT ("file %s already exists... retrying", test);
+				g_free (test);
+				g_free (temp_file);
+				continue;
+			}
+			else
+			{
+				g_free (test);
+				break;
+			}
+		}
+
+		priv->shared_mem_str = temp_file;
+		
+		if ((priv->shared_mem_fd = 
+			 shm_open (temp_file, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0)
+		{
+			g_warning ("Error while trying to open a shared memory file. Be"
+					   "sure to have "SHARED_MEMORY_PREFIX" mounted with tmpfs");
+		}
+	
+		priv->shared_mem_file = fdopen (priv->shared_mem_fd, "a+b");
+		DEBUG_PRINT ("temp_file %s", temp_file);
+
+		/* no need to free temp_file (alias shared_mem_str). It will be freed on plugin finalize */
+	}
+	
+	priv->scanning_status = TRUE;	
+
+	for (i = 0; i < files_list->len; i++)
+	{
+		gchar *node = (gchar *) g_ptr_array_index (files_list, i);
+		
+		if (g_file_test (node, G_FILE_TEST_EXISTS) == FALSE)
+		{
+			g_warning ("File %s not scanned because it does not exist", node);
+			continue;
+		}
+			
+		DEBUG_PRINT ("sent to stdin [%d] %s", i, node);
+		anjuta_launcher_send_stdin (priv->ctags_launcher, node);
+		anjuta_launcher_send_stdin (priv->ctags_launcher, "\n");
+
+		if (symbols_update == TRUE) 
+		{
+			/* will this be the last file in the list? */
+			if (i + 1 >= files_list->len) 
+			{
+				/* yes */
+				g_async_queue_push (priv->scan_queue, GINT_TO_POINTER (DO_UPDATE_SYMS_AND_EXIT));
+			}
+			else 
+			{
+				/* no */
+				g_async_queue_push (priv->scan_queue, GINT_TO_POINTER (DO_UPDATE_SYMS));
+			}
+		}
+		else 
+		{
+			if (i + 1 >= files_list->len) 
+			{
+				/* yes */
+				g_async_queue_push (priv->scan_queue, GINT_TO_POINTER (DONT_UPDATE_SYMS_AND_EXIT));
+			}
+			else {
+				/* no */
+				g_async_queue_push (priv->scan_queue, GINT_TO_POINTER (DONT_UPDATE_SYMS));
+			}
+		}
+
+		/* don't forget to add the real_files if the caller provided a list for
+		 * them! */
+		if (real_files_list != NULL)
+		{
+			g_async_queue_push (priv->scan_queue, 
+								(gpointer)g_strdup (
+								g_ptr_array_index (real_files_list, i)));
+		}
+		else 
+		{
+			/* else add a DONT_FAKE_UPDATE_SYMS marker, just to notify that this 
+			 * is not a fake file scan 
+			 */
+			g_async_queue_push (priv->scan_queue, GINT_TO_POINTER (DONT_FAKE_UPDATE_SYMS));
+		}
+	}
+
+	priv->scanning_status = FALSE;
+
+	return TRUE;
+}
+
+static void
+sdb_engine_init (SymbolDBEngine * object)
+{
+	SymbolDBEngine *sdbe;
+	GHashTable *h;
+	gint i;
+	
+	sdbe = SYMBOL_DB_ENGINE (object);
+	sdbe->priv = g_new0 (SymbolDBEnginePriv, 1);
+
+	/* initialize an hash table to be used and shared with Iterators */
+	sdbe->priv->sym_type_conversion_hash =
+		g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);	
+	h = sdbe->priv->sym_type_conversion_hash;
+
+	/* please if you change some value below here remember to change also on */
+	g_hash_table_insert (h, g_strdup("class"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_CLASS));
+
+	g_hash_table_insert (h, g_strdup("enum"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_ENUM));
+
+	g_hash_table_insert (h, g_strdup("enumerator"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_ENUMERATOR));
+
+	g_hash_table_insert (h, g_strdup("field"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_FIELD));
+
+	g_hash_table_insert (h, g_strdup("function"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_FUNCTION));
+
+	g_hash_table_insert (h, g_strdup("interface"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_INTERFACE));
+
+	g_hash_table_insert (h, g_strdup("member"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_MEMBER));
+
+	g_hash_table_insert (h, g_strdup("method"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_METHOD));
+
+	g_hash_table_insert (h, g_strdup("namespace"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_NAMESPACE));
+
+	g_hash_table_insert (h, g_strdup("package"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_PACKAGE));
+
+	g_hash_table_insert (h, g_strdup("prototype"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_PROTOTYPE));
+				
+	g_hash_table_insert (h, g_strdup("struct"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_STRUCT));
+				
+	g_hash_table_insert (h, g_strdup("typedef"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_TYPEDEF));
+				
+	g_hash_table_insert (h, g_strdup("union"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_UNION));
+				
+	g_hash_table_insert (h, g_strdup("variable"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_VARIABLE));
+
+	g_hash_table_insert (h, g_strdup("externvar"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_EXTERNVAR));
+
+	g_hash_table_insert (h, g_strdup("macro"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_MACRO));
+
+	g_hash_table_insert (h, g_strdup("macro_with_arg"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG));
+
+	g_hash_table_insert (h, g_strdup("file"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_FILE));
+
+	g_hash_table_insert (h, g_strdup("other"), 
+				GINT_TO_POINTER (IANJUTA_SYMBOL_TYPE_OTHER));
+	
+	
+	/* create the hash table that will store shared memory files strings used for 
+	 * buffer scanning. Un Engine destroy will unlink () them.
+	 */
+	sdbe->priv->garbage_shared_mem_files = g_hash_table_new_full (g_str_hash, g_str_equal, 
+													  g_free, NULL);	
+	
+	sdbe->priv->ctags_launcher = NULL;
+	sdbe->priv->removed_launchers = NULL;
+	sdbe->priv->shutting_down = FALSE;
+	sdbe->priv->shutting_mutex = g_mutex_new ();
+	sdbe->priv->shutting_cond = g_cond_new ();
+
+	/* set the ctags executable path to NULL */
+	sdbe->priv->ctags_path = NULL;
+
+	/* identify the scan process with an id. There can be multiple files associated
+	 * within a process. A call to scan_files () will put inside the queue an id
+	 * returned and emitted by scan-end.
+	 */
+	sdbe->priv->scan_process_id_queue = g_async_queue_new ();
+	sdbe->priv->scan_process_id = 1;
+	
+	/* the scan_queue? It will contain mainly 
+	 * ints that refer to the force_update status.
+	 */
+	sdbe->priv->scan_queue = g_async_queue_new ();
+
+	/* the thread list data */
+	sdbe->priv->thread_list_data = g_queue_new ();
+	
+	/* some signals queues */
+	sdbe->priv->signals_queue = g_async_queue_new ();
+	sdbe->priv->updated_symbols_id = g_async_queue_new ();
+	sdbe->priv->updated_scope_symbols_id = g_async_queue_new ();
+	sdbe->priv->inserted_symbols_id = g_async_queue_new ();
+	
+	
+	/*
+	 * STATIC QUERY STRUCTURE INITIALIZE
+	 */
+	
+	/* -- workspace -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_WORKSPACE_NEW, 
+		"INSERT INTO workspace (workspace_name, analyse_time) "
+	 	"VALUES (## /* name:'wsname' type:gchararray */,"
+	 	"datetime ('now', 'localtime'))");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME, 
+	 	"SELECT workspace_id FROM workspace WHERE workspace_name = ## /* name:'wsname' "
+	 	"type:gchararray */ LIMIT 1");
+
+	/* -- project -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_PROJECT_NEW, 
+	 	"INSERT INTO project (project_name, wrkspace_id, analyse_time) "
+	 	"VALUES (## /* name:'prjname' type:gchararray */,"
+	 	"## /* name:'wsid' type:gint */, datetime ('now', 'localtime'))");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME, 
+	 	"SELECT project_id FROM project WHERE project_name = ## /* name:'prjname' "
+	 	"type:gchararray */ LIMIT 1");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_UPDATE_PROJECT_ANALYSE_TIME, 
+	 	"UPDATE project SET analyse_time = datetime('now', 'localtime', '+10 seconds') WHERE "
+	 	"project_name = ## /* name:'prjname' type:gchararray */");
+	
+	/* -- file -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_FILE_NEW, 
+	 	"INSERT INTO file (file_path, prj_id, lang_id, analyse_time) VALUES ("
+	 	"## /* name:'filepath' type:gchararray */, ## /* name:'prjid' "
+	 	"type:gint */, ## /* name:'langid' type:gint */, "
+	 	"datetime ('now', 'localtime'))");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME, 
+		"SELECT file_id FROM file WHERE file_path = ## /* name:'filepath' "
+	 	"type:gchararray */ LIMIT 1");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME,
+		"SELECT * FROM file WHERE prj_id = (SELECT project_id FROM project "
+	 	"WHERE project_name = ## /* name:'prjname' type:gchararray */)");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID,
+		"SELECT file_id, file_path AS db_file_path, prj_id, lang_id, analyse_time FROM file "
+	 	"WHERE prj_id = ## /* name:'prjid' type:gint */");
+/*
+		"SELECT * FROM file JOIN project on project_id = prj_id WHERE "\
+		"project.name = ## / * name:'prjname' type:gchararray * /",
+*/
+									
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_UPDATE_FILE_ANALYSE_TIME,
+		"UPDATE file SET analyse_time = datetime('now', 'localtime') WHERE "
+	 	"file_path = ## /* name:'filepath' type:gchararray */");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_ALL_FROM_FILE_WHERE_NOT_IN_SYMBOLS,
+		"SELECT file_id, file_path AS db_file_path FROM file WHERE file_id NOT IN "
+		"(SELECT file_defined_id FROM symbol)");
+	
+	/* -- language -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_LANGUAGE_NEW,
+		"INSERT INTO language (language_name) VALUES (## /* name:'langname' "
+	 	"type:gchararray */)");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
+	 	"SELECT language_id FROM language WHERE language_name = ## /* name:'langname' "
+	 	"type:gchararray */ LIMIT 1");
+	
+	/* -- sym type -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_SYM_TYPE_NEW,
+		"INSERT INTO sym_type (type_type, type_name) VALUES (## /* name:'type' "
+	 	"type:gchararray */, ## /* name:'typename' type:gchararray */)");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_SYM_TYPE_ID,
+	 	"SELECT type_id FROM sym_type WHERE type_type = ## /* name:'type' "
+	 	"type:gchararray */ AND type_name = ## /* name:'typename' "
+	 	"type:gchararray */ LIMIT 1");
+
+	/* -- sym kind -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_SYM_KIND_NEW,
+	 	"INSERT INTO sym_kind (kind_name) VALUES(## /* name:'kindname' "
+	 	"type:gchararray */)");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
+		"SELECT sym_kind_id FROM sym_kind WHERE kind_name = ## /* "
+	 	"name:'kindname' type:gchararray */");
+	
+	/* -- sym access -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_SYM_ACCESS_NEW,
+		"INSERT INTO sym_access (access_name) VALUES(## /* name:'accesskind' "
+	 	"type:gchararray */)");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+									PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
+		"SELECT access_kind_id FROM sym_access WHERE access_name = ## /* "
+	 	"name:'accesskind' type:gchararray */ LIMIT 1");
+	
+	/* -- sym implementation -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+		 							PREP_QUERY_SYM_IMPLEMENTATION_NEW,
+	 	"INSERT INTO sym_implementation (implementation_name) VALUES(## /* name:'implekind' "
+	 	"type:gchararray */)");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
+	 	"SELECT sym_impl_id FROM sym_implementation WHERE kind = ## /* "
+	 	"name:'implekind' type:gchararray */ LIMIT 1");
+	
+	/* -- heritage -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_HERITAGE_NEW,
+	 	"INSERT INTO heritage (symbol_id_base, symbol_id_derived) VALUES(## /* "
+	 	"name:'symbase' type:gint */, ## /* name:'symderived' type:gint */)");	
+	
+	/* -- scope -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_SCOPE_NEW,
+	 	"INSERT INTO scope (scope_name, type_id) VALUES(## /* name:'scope' "
+	 	"type:gchararray */, ## /* name:'typeid' type:gint */)");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SCOPE_ID,
+	 	"SELECT scope_id FROM scope WHERE scope_name = ## /* name:'scope' "
+	 	"type:gchararray */ AND type_id = ## /* name:'typeid' type:gint */ LIMIT 1");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID_NO_FILE,
+	 	"SELECT symbol.symbol_id, symbol.file_defined_id, "
+	 	"symbol.file_position, symbol.scope_definition_id, symbol.scope_id "
+	 	"FROM symbol WHERE symbol.scope_definition_id = ( "
+	 	"SELECT symbol.scope_id FROM symbol WHERE symbol.symbol_id = "
+	 	"## /* name:'symid' type:gint */) "
+	 	"AND symbol.scope_definition_id > 0");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID,
+	 	"SELECT symbol.symbol_id, symbol.file_defined_id, "
+	 	"symbol.file_position, symbol.scope_definition_id, symbol.scope_id "
+	 	"FROM symbol JOIN file "
+	 	"ON symbol.file_defined_id = file.file_id "
+	 	"WHERE symbol.scope_definition_id = ( "
+	 	"SELECT symbol.scope_id FROM symbol WHERE symbol.symbol_id = "
+	 	"## /* name:'symid' type:gint */) "
+	 	"AND symbol.scope_definition_id > 0 "
+	 	"AND file.file_path = ## /* name:'dbfile' type:gchararray */");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID_BY_SYMBOL_ID,
+	 	"SELECT symbol.scope_definition_id FROM symbol WHERE "
+	 	"file_defined_id = (SELECT file_defined_id FROM symbol WHERE symbol_id = "
+	 	"## /* name:'scopedsymid' type:gint */) "
+	 	"AND file_position < (SELECT file_position FROM symbol WHERE symbol_id = "
+	 	"## /* name:'scopedsymid' type:gint */) "
+	 	"ORDER BY file_position DESC");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SCOPE_DEFINITION_ID_BY_WALK_DOWN_SCOPE_PATH,
+	 	"SELECT scope_definition_id FROM symbol "
+	 	"WHERE scope_id = ## /* name:'scopeid' type:gint */ AND scope_definition_id = ("
+		 	"SELECT scope.scope_id FROM scope "
+			"INNER JOIN sym_type ON scope.type_id = sym_type.type_id "
+			"WHERE sym_type.type_type = ## /* name:'symtype' type:gchararray */ "
+				"AND scope.scope_name = ## /* name:'scopename' type:gchararray */) LIMIT 1");
+	
+	/* -- tmp heritage -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_TMP_HERITAGE_NEW,
+	 	"INSERT INTO __tmp_heritage_scope (symbol_referer_id, field_inherits, "
+	 	"field_struct, field_typeref, field_enum, field_union, "
+	 	"field_class, field_namespace) VALUES (## /* name:'symreferid' "
+	 	"type:gint */, ## /* name:'finherits' type:gchararray */, ## /* "
+	 	"name:'fstruct' type:gchararray */, ## /* name:'ftyperef' "
+	 	"type:gchararray */, ## /* name:'fenum' type:gchararray */, ## /* "
+	 	"name:'funion' type:gchararray */, ## /* name:'fclass' type:gchararray "
+	 	"*/, ## /* name:'fnamespace' type:gchararray */)");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE,
+	 	"SELECT * FROM __tmp_heritage_scope");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS,
+	 	"SELECT * FROM __tmp_heritage_scope WHERE field_inherits != ''");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_TMP_HERITAGE_DELETE_ALL,
+	 	"DELETE FROM __tmp_heritage_scope");
+	
+	/* -- symbol -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_SYMBOL_NEW,
+	 	"INSERT INTO symbol (file_defined_id, name, file_position, "
+	 	"is_file_scope, signature, scope_definition_id, scope_id, type_id, "
+	 	"kind_id, access_kind_id, implementation_kind_id, update_flag) VALUES("
+	 	"## /* name:'filedefid' type:gint */, ## /* name:'name' "
+	 	"type:gchararray */, ## /* name:'fileposition' type:gint */, ## /* "
+	 	"name:'isfilescope' type:gint */, ## /* name:'signature' "
+	 	"type:gchararray */,## /* name:'scopedefinitionid' type:gint */, ## "
+	 	"/* name:'scopeid' type:gint */,## /* name:'typeid' type:gint */, ## "
+	 	"/* name:'kindid' type:gint */,## /* name:'accesskindid' type:gint */, "
+	 	"## /* name:'implementationkindid' type:gint */, ## /* "
+	 	"name:'updateflag' type:gint */)");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
+	 	"SELECT scope_definition_id FROM symbol JOIN sym_type ON symbol.type_id "
+	 	"= sym_type.type_id WHERE sym_type.type_type = ## /* name:'tokenname' "
+	 	"type:gchararray */ AND sym_type.type_name = ## /* name:'objectname' "
+	 	"type:gchararray */ LIMIT 1");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
+	 	"SELECT symbol_id FROM symbol JOIN sym_type ON symbol.type_id = "
+	 	"sym_type.type_id AND symbol.scope_id = 0 WHERE sym_type.type_type='class' AND "
+	 	"name = ## /* name:'klassname' type:gchararray */ LIMIT 1");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
+	 	"SELECT symbol_id FROM symbol JOIN scope ON symbol.scope_id = "
+	 	"scope.scope_id JOIN sym_type ON scope.type_id = sym_type.type_id "
+	 	"WHERE symbol.name = ## /* name:'klassname' type:gchararray */ AND "
+	 	"scope.scope_name = ## /* name:'namespacename' type:gchararray */ AND "
+	 	"sym_type.type_type = 'namespace' LIMIT 1");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID,
+	 	"UPDATE symbol SET scope_id =  ## /* name:'scopeid' type:gint */ "
+	 	"WHERE symbol_id = ## /* name:'symbolid' type:gint */");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID_MIXED,
+		"UPDATE symbol SET scope_id = (SELECT scope_definition_id FROM symbol "
+		"JOIN sym_type ON symbol.type_id "
+	 	"= sym_type.type_id WHERE sym_type.type_type = ## /* name:'tokenname' "
+	 	"type:gchararray */ AND sym_type.type_name = ## /* name:'objectname' "
+	 	"type:gchararray */ LIMIT 1) "
+	 	"WHERE symbol_id = ## /* name:'symbolid' type:gint */");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY,
+	 	"SELECT symbol_id FROM symbol WHERE name = ## /* name:'symname' "
+	 	"type:gchararray */ AND file_defined_id =  ## /* name:'filedefid' " 
+	 	"type:gint */ AND type_id = ## /* name:'typeid' type:gint */ LIMIT 1");	
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY_EXT,
+	 	"SELECT symbol_id FROM symbol WHERE name = ## /* name:'symname' "
+	 	"type:gchararray */ AND file_defined_id =  ## /* name:'filedefid' "
+	 	"type:gint */ AND file_position = ## /* name:'filepos' type:gint */ "
+		"AND type_id = ## /* name:'typeid' type:gint */ AND "
+		"update_flag = 0 LIMIT 1");
+
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY_EXT2,
+	 	"SELECT symbol_id FROM symbol WHERE name = ## /* name:'symname' "
+	 	"type:gchararray */ AND file_defined_id =  ## /* name:'filedefid' "
+	 	"type:gint */ AND type_id = ## /* name:'typeid' type:gint */ AND "
+		"update_flag = 0 LIMIT 1");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_UPDATE_SYMBOL_ALL,
+	 	"UPDATE symbol SET is_file_scope = ## /* name:'isfilescope' type:gint "
+	 	"*/, file_position = ## /* name:'fileposition' type:gint */, "
+	 	"signature = ## /* name:'signature' type:gchararray */, "
+	 	"scope_definition_id = ## /* name:'scopedefinitionid' type:gint */, "
+	 	"scope_id = ## /* name:'scopeid' type:gint */, kind_id = "
+	 	"## /* name:'kindid' type:gint */, access_kind_id = ## /* name:"
+	 	"'accesskindid' type:gint */, implementation_kind_id = ## /* name:"
+	 	"'implementationkindid' type:gint */, update_flag = ## /* name:"
+	 	"'updateflag' type:gint */ WHERE symbol_id = ## /* name:'symbolid' type:"
+	 	"gint */");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_REMOVE_NON_UPDATED_SYMBOLS,
+	 	"DELETE FROM symbol WHERE file_defined_id = (SELECT file_id FROM file "
+	 	"WHERE file.file_path = ## /* name:'filepath' type:gchararray */) "
+	 	"AND update_flag = 0");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_RESET_UPDATE_FLAG_SYMBOLS,
+	 	"UPDATE symbol SET update_flag = 0 "
+	 	"WHERE file_defined_id = (SELECT file_id FROM file WHERE "
+	 	"file_path = ## /* name:'filepath' type:gchararray */)");
+	
+	/* -- tmp_removed -- */
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_GET_REMOVED_IDS,
+	 	"SELECT symbol_removed_id FROM __tmp_removed");
+	
+	STATIC_QUERY_POPULATE_INIT_NODE(sdbe->priv->static_query_list, 
+	 								PREP_QUERY_TMP_REMOVED_DELETE_ALL,
+	 	"DELETE FROM __tmp_removed");
+
+	
+	/*
+	 * DYNAMIC QUERY STRUCTURE INITIALIZE
+	 */
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_GET_CLASS_PARENTS,
+									TRUE);
+	
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_GET_CLASS_PARENTS_BY_SYMBOL_ID,
+									FALSE);
+	
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_GET_GLOBAL_MEMBERS_FILTERED,
+									TRUE);
+	
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_GET_SCOPE_MEMBERS,
+									FALSE);
+	
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_GET_CURRENT_SCOPE,				
+									FALSE);
+	
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_GET_FILE_SYMBOLS,
+									FALSE);
+
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+								 	DYN_PREP_QUERY_GET_SYMBOL_INFO_BY_ID,
+									FALSE);
+
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+								 	DYN_PREP_QUERY_FIND_SYMBOL_NAME_BY_PATTERN,
+									FALSE);
+
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED,			
+									TRUE);
+
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+								 	DYN_PREP_QUERY_GET_SCOPE_MEMBERS_BY_SYMBOL_ID,
+									TRUE);
+
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+								 	DYN_PREP_QUERY_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED,
+									TRUE);
+	
+	DYN_QUERY_POPULATE_INIT_NODE(sdbe->priv->dyn_query_list,
+									DYN_PREP_QUERY_GET_FILES_FOR_PROJECT,
+								 	TRUE);
+	
+	/* init cache hashtables */
+	sdb_engine_init_caches (sdbe);
+	
+	sdbe->priv->file_symbols_cache = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
+										 NULL,
+										 NULL,
+										 NULL);
+	
+	/* init memory pool object for GValue strings */
+#ifdef USE_ASYNC_QUEUE	
+	sdbe->priv->mem_pool_string = g_async_queue_new_full (g_free);
+	sdbe->priv->mem_pool_int = g_async_queue_new_full (g_free);
+#else
+	sdbe->priv->mem_pool_string = g_queue_new ();
+	sdbe->priv->mem_pool_int = g_queue_new ();	
+#endif
+	
+	for (i = 0; i < MEMORY_POOL_STRING_SIZE; i++) 
+	{
+		GValue *value = gda_value_new (G_TYPE_STRING);
+#ifdef USE_ASYNC_QUEUE	
+		g_async_queue_push (sdbe->priv->mem_pool_string, value);
+#else
+		g_queue_push_head (sdbe->priv->mem_pool_string, value);
+#endif		
+	}
+
+	for (i = 0; i < MEMORY_POOL_INT_SIZE; i++) 
+	{
+		GValue *value = gda_value_new (G_TYPE_INT);
+#ifdef USE_ASYNC_QUEUE			
+		g_async_queue_push (sdbe->priv->mem_pool_int, value);		
+#else
+		g_queue_push_head (sdbe->priv->mem_pool_int, value);		
+#endif		
+	}	
+}
+
+static void
+sdb_engine_unlink_shared_files (gpointer key, gpointer value, gpointer user_data)
+{
+	shm_unlink (key);
+}
+
+static void 
+sdb_engine_unref_removed_launchers (gpointer data, gpointer user_data)
+{
+	g_object_unref (data);
+}
+
+static void
+sdb_engine_terminate_threads (SymbolDBEngine *dbe)
+{
+	SymbolDBEnginePriv *priv;	
+	
+	priv = dbe->priv;
+	
+	priv->shutting_down = TRUE;
+
+	/* get a lock to share with the monitor */
+	g_mutex_lock (priv->shutting_mutex);	
+	
+	while (priv->concurrent_threads > 0)
+	{		
+		/* wait for the thread to notify us that it has just finished its execution */
+		g_cond_wait (priv->shutting_cond, priv->shutting_mutex);
+	}	
+	
+	g_mutex_unlock (priv->shutting_mutex);
+}
+
+static void
+sdb_engine_finalize (GObject * object)
+{
+	SymbolDBEngine *dbe;
+	SymbolDBEnginePriv *priv;
+	
+	dbe = SYMBOL_DB_ENGINE (object);
+	priv = dbe->priv;
+	
+	/* we're shutting down the plugin. Let the threads finish their work... */
+	sdb_engine_terminate_threads (dbe);
+	
+	if (priv->ctags_launcher)
+	{
+		g_object_unref (priv->ctags_launcher);
+		priv->ctags_launcher = NULL;
+	}		
+	
+	if (priv->removed_launchers)
+	{
+		g_list_foreach (priv->removed_launchers, 
+						sdb_engine_unref_removed_launchers, NULL);
+		g_list_free (priv->removed_launchers);
+		priv->removed_launchers = NULL;
+	}
+	
+	if (priv->mutex)
+	{
+		g_mutex_free (priv->mutex);
+		priv->mutex = NULL;
+	}
+	
+	if (priv->shutting_cond)
+	{
+		g_cond_free (priv->shutting_cond);
+		priv->shutting_cond = NULL;
+	}
+	
+	if (priv->timeout_trigger_handler > 0)
+		g_source_remove (priv->timeout_trigger_handler);
+	
+	if (priv->thread_monitor_handler > 0)
+		g_source_remove (priv->thread_monitor_handler);
+		
+	if (priv->thread_list_data != NULL)
+		g_queue_free  (priv->thread_list_data);
+	
+
+	sdb_engine_disconnect_from_db (dbe);	
+	sdb_engine_free_cached_queries (dbe);
+	sdb_engine_free_cached_dynamic_queries (dbe);
+	
+	if (priv->scan_process_id_queue)
+	{
+		g_async_queue_unref (priv->scan_process_id_queue);
+		priv->scan_process_id_queue = NULL;
+	}
+	
+	if (priv->scan_queue)
+	{
+		g_async_queue_unref (priv->scan_queue);
+		priv->scan_queue = NULL;
+	}
+	
+	if (priv->updated_symbols_id)
+	{
+		g_async_queue_unref (priv->updated_symbols_id);
+		priv->updated_symbols_id = NULL;
+	}	
+
+	if (priv->updated_scope_symbols_id)
+	{
+		g_async_queue_unref (priv->updated_scope_symbols_id);
+		priv->updated_scope_symbols_id = NULL;
+	}	
+	
+	if (priv->inserted_symbols_id)
+	{
+		g_async_queue_unref (priv->inserted_symbols_id);
+		priv->inserted_symbols_id = NULL;
+	}	
+	
+	if (priv->shared_mem_file) 
+	{
+		fclose (priv->shared_mem_file);
+		priv->shared_mem_file = NULL; 
+	}	
+	
+	if (priv->shared_mem_str)
+	{
+		shm_unlink (priv->shared_mem_str);
+		g_free (priv->shared_mem_str);
+		priv->shared_mem_str = NULL;
+	}
+	
+	if (priv->garbage_shared_mem_files)
+	{
+		g_hash_table_foreach (priv->garbage_shared_mem_files, 
+							  sdb_engine_unlink_shared_files,
+							  NULL);
+		/* destroy the hash table */
+		g_hash_table_destroy (priv->garbage_shared_mem_files);
+	}
+	
+
+	if (priv->sym_type_conversion_hash)
+		g_hash_table_destroy (priv->sym_type_conversion_hash);
+	
+	if (priv->signals_queue)
+		g_async_queue_unref (priv->signals_queue);
+	
+	sdb_engine_clear_caches (dbe);
+
+	g_tree_destroy (priv->file_symbols_cache);
+
+#ifdef USE_ASYNC_QUEUE	
+	g_async_queue_unref (priv->mem_pool_string);
+	g_async_queue_unref (priv->mem_pool_int);
+	priv->mem_pool_string = NULL;
+	priv->mem_pool_int = NULL;	
+#else
+	g_queue_foreach (priv->mem_pool_string, (GFunc)gda_value_free, NULL);
+	g_queue_free (priv->mem_pool_string);
+	
+	g_queue_foreach (priv->mem_pool_int, (GFunc)gda_value_free, NULL);
+	g_queue_free (priv->mem_pool_int);	
+	
+	priv->mem_pool_string = NULL;
+	priv->mem_pool_int = NULL;	
+#endif
+		
+	g_mutex_free (priv->shutting_mutex);
+	priv->shutting_mutex = NULL;	
+	
+	g_free (priv);
+	
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+sdb_engine_class_init (SymbolDBEngineClass * klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+
+	object_class->finalize = sdb_engine_finalize;
+
+	signals[SINGLE_FILE_SCAN_END]
+		= g_signal_new ("single-file-scan-end",
+						G_OBJECT_CLASS_TYPE (object_class),
+						G_SIGNAL_RUN_FIRST,
+						G_STRUCT_OFFSET (SymbolDBEngineClass, single_file_scan_end),
+						NULL, NULL,
+						g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+	
+	signals[SCAN_END]
+		= g_signal_new ("scan-end",
+						G_OBJECT_CLASS_TYPE (object_class),
+						G_SIGNAL_RUN_FIRST,
+						G_STRUCT_OFFSET (SymbolDBEngineClass, scan_end),
+						NULL, NULL,
+						g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 
+						1,
+						G_TYPE_INT);
+
+	signals[SYMBOL_INSERTED]
+		= g_signal_new ("symbol-inserted",
+						G_OBJECT_CLASS_TYPE (object_class),
+						G_SIGNAL_RUN_FIRST,
+						G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_inserted),
+						NULL, NULL,
+						g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 
+						1,
+						G_TYPE_INT);
+	
+	signals[SYMBOL_UPDATED]
+		= g_signal_new ("symbol-updated",
+						G_OBJECT_CLASS_TYPE (object_class),
+						G_SIGNAL_RUN_FIRST,
+						G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_updated),
+						NULL, NULL,
+						g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 
+						1,
+						G_TYPE_INT);
+
+	signals[SYMBOL_SCOPE_UPDATED]
+		= g_signal_new ("symbol-scope-updated",
+						G_OBJECT_CLASS_TYPE (object_class),
+						G_SIGNAL_RUN_FIRST,
+						G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_scope_updated),
+						NULL, NULL,
+						g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 
+						1,
+						G_TYPE_INT);
+	
+	signals[SYMBOL_REMOVED]
+		= g_signal_new ("symbol-removed",
+						G_OBJECT_CLASS_TYPE (object_class),
+						G_SIGNAL_RUN_FIRST,
+						G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_removed),
+						NULL, NULL,
+						g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 
+						1,
+						G_TYPE_INT);	
+}
+
+GType
+sdb_engine_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+	{
+		static const GTypeInfo our_info = {
+			sizeof (SymbolDBEngineClass),	/* class_size */
+			(GBaseInitFunc) NULL,	/* base_init */
+			(GBaseFinalizeFunc) NULL,	/* base_finalize */
+			(GClassInitFunc) sdb_engine_class_init,	/* class_init */
+			(GClassFinalizeFunc) NULL,	/* class_finalize */
+			NULL /* class_data */ ,
+			sizeof (SymbolDBEngine),	/* instance_size */
+			0,					/* n_preallocs */
+			(GInstanceInitFunc) sdb_engine_init,	/* instance_init */
+			NULL				/* value_table */
+		};
+
+		our_type = g_type_register_static (G_TYPE_OBJECT, "SymbolDBEngine",
+										   &our_info, 0);
+	}
+
+	return our_type;
+}
+
+void 
+symbol_db_engine_set_ctags_path (SymbolDBEngine * dbe, const gchar * ctags_path)
+{
+	SymbolDBEnginePriv *priv;
+
+	g_return_if_fail (dbe != NULL);
+	g_return_if_fail (ctags_path != NULL);
+	
+	priv = dbe->priv;
+	
+	/* Check if ctags is really installed */
+	if (!anjuta_util_prog_is_installed (ctags_path, TRUE))
+	{
+		g_warning ("symbol_db_engine_set_ctags_path (): Wrong path for ctags. Keeping "
+				   "the old value %s", priv->ctags_path);
+		return;
+	}	
+	
+	/* have we already got it? */
+	if (priv->ctags_path != NULL && 
+		strcmp (priv->ctags_path, ctags_path) == 0)
+		return;
+
+	/* free the old value */
+	g_free (priv->ctags_path);
+	
+	/* is anjutalauncher already created? */
+	if (priv->ctags_launcher != NULL)
+	{
+		AnjutaLauncher *tmp;
+		tmp = priv->ctags_launcher;
+
+		/* recreate it on the fly */
+		sdb_engine_ctags_launcher_create (dbe);
+
+		/* keep the launcher alive to avoid crashes */
+		priv->removed_launchers = g_list_prepend (priv->removed_launchers, tmp);
+	}	
+	
+	/* set the new one */
+	priv->ctags_path = g_strdup (ctags_path);	
+}
+
+SymbolDBEngine *
+symbol_db_engine_new (const gchar * ctags_path)
+{
+	SymbolDBEngine *sdbe;
+	SymbolDBEnginePriv *priv;
+	
+	g_return_val_if_fail (ctags_path != NULL, NULL);
+	sdbe = g_object_new (SYMBOL_TYPE_DB_ENGINE, NULL);
+	
+	priv = sdbe->priv;
+	priv->mutex = g_mutex_new ();
+
+	/* set the mandatory ctags_path */
+	symbol_db_engine_set_ctags_path (sdbe, ctags_path);
+		
+	return sdbe;
+}
+
+/**
+ * Set some default parameters to use with the current database.
+ */
+static void
+sdb_engine_set_defaults_db_parameters (SymbolDBEngine * dbe)
+{	
+	sdb_engine_execute_unknown_sql (dbe, "PRAGMA page_size = 32768");
+	sdb_engine_execute_unknown_sql (dbe, "PRAGMA cache_size = 12288");
+	sdb_engine_execute_unknown_sql (dbe, "PRAGMA synchronous = OFF");
+	sdb_engine_execute_unknown_sql (dbe, "PRAGMA temp_store = MEMORY");
+	sdb_engine_execute_unknown_sql (dbe, "PRAGMA case_sensitive_like = 1");
+}
+
+/* Will create priv->db_connection.
+ * Connect to database identified by db_directory.
+ * Usually db_directory is defined also into priv. We let it here as parameter 
+ * because it is required and cannot be null.
+ */
+static gboolean
+sdb_engine_connect_to_db (SymbolDBEngine * dbe, const gchar *cnc_string)
+{
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	priv = dbe->priv;	
+	
+	if (priv->db_connection != NULL)
+	{
+		/* if it's the case that the connection isn't NULL, we 
+		 * should notify the user
+		 * and return FALSE. It's his task to disconnect and retry to connect */
+		g_warning ("connection is already established. Please disconnect "
+				   "and then try to reconnect.");
+		return FALSE;
+	}
+
+	/* establish a connection. If the sqlite file does not exist it will 
+	 * be created 
+	 */
+	priv->db_connection
+		= gda_connection_open_from_string ("SQLite", cnc_string, NULL, 
+										   GDA_CONNECTION_OPTIONS_NONE, NULL);	
+	
+	if (!GDA_IS_CONNECTION (priv->db_connection))
+	{
+		g_warning ("Could not open connection to %s\n", cnc_string);
+		return FALSE;		
+	}
+
+	priv->sql_parser = gda_connection_create_parser (priv->db_connection);
+	
+	if (!GDA_IS_SQL_PARSER (priv->sql_parser)) 
+	{
+		g_warning ("Could not create sql parser. Check your libgda installation");
+		return FALSE;
+	}
+	
+	DEBUG_PRINT ("connected to database %s", cnc_string);
+	return TRUE;
+}
+
+
+/**
+ * Creates required tables for the database to work.
+ * @param tables_sql_file File containing sql code.
+ */
+static gboolean
+sdb_engine_create_db_tables (SymbolDBEngine * dbe, const gchar * tables_sql_file)
+{
+	GError *err;
+	SymbolDBEnginePriv *priv;
+	gchar *contents;
+	gsize sizez;
+
+	g_return_val_if_fail (tables_sql_file != NULL, FALSE);
+
+	priv = dbe->priv;
+
+	g_return_val_if_fail (priv->db_connection != NULL, FALSE);
+
+	/* read the contents of the file */
+	if (g_file_get_contents (tables_sql_file, &contents, &sizez, &err) == FALSE)
+	{
+		g_warning ("Something went wrong while trying to read %s",
+				   tables_sql_file);
+
+		if (err != NULL)
+			g_message ("%s", err->message);
+		return FALSE;
+	}
+
+	sdb_engine_execute_non_select_sql (dbe, contents);
+	
+	g_free (contents);
+	return TRUE;
+}
+
+gboolean
+symbol_db_engine_db_exists (SymbolDBEngine * dbe, const gchar * prj_directory)
+{
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (prj_directory != NULL, FALSE);
+
+	priv = dbe->priv;
+
+	/* check whether the db filename already exists.*/
+	gchar *tmp_file = g_strdup_printf ("%s/%s.db", prj_directory,
+									   ANJUTA_DB_FILE);
+	
+	if (g_file_test (tmp_file, G_FILE_TEST_EXISTS) == FALSE)
+	{
+		DEBUG_PRINT ("db %s does not exist", tmp_file);
+		g_free (tmp_file);
+		return FALSE;
+	}
+
+	g_free (tmp_file);
+	return TRUE;
+}
+
+gboolean
+symbol_db_engine_file_exists (SymbolDBEngine * dbe, const gchar * abs_file_path)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *relative;
+	gint file_defined_id;
+	GValue *value;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	g_return_val_if_fail (abs_file_path != NULL, FALSE);
+	
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	
+	relative = symbol_db_engine_get_file_db_path (dbe, abs_file_path);
+	if (relative == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return FALSE;
+	}	
+	MP_LEND_OBJ_STR(priv, value);	
+	g_value_set_static_string (value, relative);	
+
+	if ((file_defined_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+													PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
+													"filepath",
+													value)) < 0)
+	{	
+		g_free (relative);
+		MP_RETURN_OBJ_STR(priv, value);
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return FALSE;	
+	}
+	
+	g_free (relative);
+	MP_RETURN_OBJ_STR (priv, value);
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return TRUE;	
+}
+
+gboolean 
+symbol_db_engine_close_db (SymbolDBEngine *dbe)
+{
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	
+	priv = dbe->priv;
+	
+	/* terminate threads, if ever they're running... */
+	sdb_engine_terminate_threads (dbe);
+	
+	return sdb_engine_disconnect_from_db (dbe);
+}
+
+gboolean
+symbol_db_engine_open_db (SymbolDBEngine * dbe, const gchar * base_db_path,
+						  const gchar * prj_directory)
+{
+	SymbolDBEnginePriv *priv;
+	gboolean needs_tables_creation = FALSE;
+	gchar *cnc_string;
+
+	DEBUG_PRINT ("SymbolDBEngine: opening project %s with base dir %s", 
+				 prj_directory, base_db_path);
+	
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	g_return_val_if_fail (base_db_path != NULL, FALSE);
+
+	priv = dbe->priv;
+
+	/* check whether the db filename already exists. If it's not the case
+	 * create the tables for the database. */
+	gchar *tmp_file = g_strdup_printf ("%s/%s.db", base_db_path,
+									   ANJUTA_DB_FILE);
+
+	if (g_file_test (tmp_file, G_FILE_TEST_EXISTS) == FALSE)
+	{
+		needs_tables_creation = TRUE;
+	}
+	g_free (tmp_file);
+
+
+	priv->db_directory = g_strdup (base_db_path);
+	
+	/* save the project_directory */
+	priv->project_directory = g_strdup (prj_directory);
+
+	cnc_string = g_strdup_printf ("DB_DIR=%s;DB_NAME=%s", base_db_path,
+								ANJUTA_DB_FILE);
+
+	DEBUG_PRINT ("symbol_db_engine_open_db (): opening/connecting to "
+				 "database with %s...", cnc_string);
+	sdb_engine_connect_to_db (dbe, cnc_string);
+
+	if (needs_tables_creation == TRUE)
+	{
+		DEBUG_PRINT ("%s", "symbol_db_engine_open_db (): creating tables: it needs tables...");
+		sdb_engine_create_db_tables (dbe, TABLES_SQL);
+	}
+
+	sdb_engine_set_defaults_db_parameters (dbe);
+	
+	return TRUE;
+}
+
+gboolean
+symbol_db_engine_add_new_workspace (SymbolDBEngine * dbe,
+									const gchar * workspace_name)
+{
+/*
+CREATE TABLE workspace (workspace_id integer PRIMARY KEY AUTOINCREMENT,
+                        workspace_name varchar (50) not null unique,
+                        analyse_time DATE
+                        );
+*/
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);	
+	priv = dbe->priv;
+
+	g_return_val_if_fail (priv->db_connection != NULL, FALSE);
+
+	if ((stmt =
+		 sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_WORKSPACE_NEW)) == NULL)
+	{
+		g_warning ("query is null");
+		return FALSE;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_WORKSPACE_NEW);
+
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "wsname")) == NULL)
+	{
+		g_warning ("param is NULL from pquery!\n");
+		return FALSE;
+	}
+	gda_holder_set_value_str (param, NULL, workspace_name, NULL);
+	
+	/* execute the query with parametes just set */
+	if (gda_connection_statement_execute_non_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  (GdaSet*)plist, NULL, NULL) == -1)
+	{		
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+gboolean
+symbol_db_engine_project_exists (SymbolDBEngine * dbe,	/*gchar* workspace, */
+							   	const gchar * project_name)
+{
+	GValue *value;
+	SymbolDBEnginePriv *priv;
+	gint prj_id;
+
+	priv = dbe->priv;
+
+	g_return_val_if_fail (priv->db_connection != NULL, FALSE);
+	MP_LEND_OBJ_STR(priv,value);	
+	g_value_set_static_string (value, project_name);
+
+	/* test the existence of the project in db */
+	if ((prj_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+				PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
+				"prjname",
+				 value)) <= 0)
+	{
+		MP_RETURN_OBJ_STR (priv, value);
+		return FALSE;
+	}
+
+	MP_RETURN_OBJ_STR (priv, value);
+
+	/* we found it */
+	return TRUE;
+}
+
+gboolean
+symbol_db_engine_add_new_project (SymbolDBEngine * dbe, const gchar * workspace,
+								  const gchar * project)
+{
+/*
+CREATE TABLE project (project_id integer PRIMARY KEY AUTOINCREMENT,
+                      project_name varchar (50) not null unique,
+                      wrkspace_id integer REFERENCES workspace (workspace_id),
+                      analyse_time DATE
+                      );
+*/
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	const gchar *workspace_name;
+	gint wks_id;
+	SymbolDBEnginePriv *priv;
+	GValue *ret_value;
+	GValue *value;
+	gboolean ret_bool;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);	
+	priv = dbe->priv;
+
+	if (workspace == NULL)
+	{
+		GValue *value;
+		workspace_name = "anjuta_workspace_default";	
+		
+		DEBUG_PRINT ("adding default workspace... '%s'", workspace_name);
+		MP_LEND_OBJ_STR(priv, value);		
+		g_value_set_static_string (value, workspace_name);
+		
+		if ((wks_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+				 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
+				 "wsname",
+				 value)) <= 0)
+		{ 
+			if (symbol_db_engine_add_new_workspace (dbe, workspace_name) == FALSE)
+			{
+				MP_RETURN_OBJ_STR (priv, value);
+				DEBUG_PRINT ("%s", "Project cannot be added because a default workspace "
+							 "cannot be created");
+				return FALSE;
+			}
+		}
+		MP_RETURN_OBJ_STR (priv, value);
+	}
+	else
+	{
+		workspace_name = workspace;
+	}
+
+	MP_LEND_OBJ_STR (priv, value);
+	g_value_set_static_string (value, workspace_name);
+
+	/* get workspace id */
+	if ((wks_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+				 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
+				 "wsname",
+				 value)) <= 0)
+	{
+		DEBUG_PRINT ("%s", "symbol_db_engine_add_new_project (): no workspace id");
+		MP_RETURN_OBJ_STR (priv, value);
+		return FALSE;
+	}
+	
+	MP_RETURN_OBJ_STR (priv, value);
+	
+	/* insert new project */
+	if ((stmt =
+		 sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_PROJECT_NEW)) == NULL)
+	{
+		g_warning ("query is null");
+		return FALSE;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_PROJECT_NEW);	
+	
+	/* lookup parameters */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "prjname")) == NULL)
+	{
+		g_warning ("param prjname is NULL from pquery!");
+		return FALSE;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, project, ret_bool, ret_value);	
+		
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "wsid")) == NULL)
+	{
+		g_warning ("param prjname is NULL from pquery!");
+		return FALSE;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, wks_id, ret_bool, ret_value);	
+		
+	/* execute the query with parametes just set */
+	if (gda_connection_statement_execute_non_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  (GdaSet*)plist, NULL, NULL) == -1)
+	{		
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gint
+sdb_engine_add_new_language (SymbolDBEngine * dbe, const gchar *language)
+{
+/*
+CREATE TABLE language (language_id integer PRIMARY KEY AUTOINCREMENT,
+                       language_name varchar (50) not null unique);
+*/
+	gint table_id;
+	GValue *value;
+	SymbolDBEnginePriv *priv;		
+	
+	g_return_val_if_fail (language != NULL, -1);
+	
+	priv = dbe->priv;
+
+	MP_LEND_OBJ_STR(priv, value);
+	g_value_set_static_string (value, language);
+
+	/* check for an already existing table with language "name". */
+	if ((table_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+						PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
+						"langname",
+						value)) < 0)
+	{
+		/* insert a new entry on db */
+		const GdaSet *plist;
+		const GdaStatement *stmt;
+		GdaHolder *param;
+		GdaSet *last_inserted;
+		GValue *ret_value;
+		gboolean ret_bool;
+
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_LANGUAGE_NEW))
+			== NULL)
+		{
+			g_warning ("query is null");
+			return FALSE;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_LANGUAGE_NEW);
+
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "langname")) == NULL)
+		{
+			g_warning ("param langname is NULL from pquery!");
+			return FALSE;
+		}
+		
+		MP_SET_HOLDER_BATCH_STR(priv, param, language, ret_bool, ret_value);		
+				
+		/* execute the query with parametes just set */
+		if (gda_connection_statement_execute_non_select (priv->db_connection, 
+														 (GdaStatement*)stmt, 
+														 (GdaSet*)plist, &last_inserted,
+														 NULL) == -1)
+		{		
+			table_id = -1;
+		}
+		else {
+			const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+			table_id = g_value_get_int (value);
+		}		
+	}
+	MP_RETURN_OBJ_STR(priv, value);	
+	
+	return table_id;
+}
+
+/* Add a file to project. 
+ * This function requires an opened db, i.e. calling before
+ * symbol_db_engine_open_db ()
+ * filepath: referes to a full file path.
+ * project: 
+ * WARNING: we suppose that project_directory is already set.
+ * WARNING2: we suppose that the given local_filepath include the project_directory path.
+ * + correct example: local_filepath: /home/user/projects/foo_project/src/main.c
+ *                    project_directory: /home/user/projects/foo_project
+ * - wrong one: local_filepath: /tmp/foo.c
+ *                    project_directory: /home/user/projects/foo_project
+ */
+static gboolean
+sdb_engine_add_new_file (SymbolDBEngine * dbe, const gchar * project_name,
+						 const gchar * local_filepath, const gchar * language)
+{
+/*
+CREATE TABLE file (file_id integer PRIMARY KEY AUTOINCREMENT,
+                   file_path TEXT not null unique,
+                   prj_id integer REFERENCES project (projec_id),
+                   lang_id integer REFERENCES language (language_id),
+                   analyse_time DATE
+                   );
+*/
+	SymbolDBEnginePriv *priv;
+	gint project_id;
+	gint language_id;
+	gint file_id;
+	GValue *value;
+	
+	priv = dbe->priv;
+
+	/* check if the file is a correct one compared to the local_filepath */
+	if (strstr (local_filepath, priv->project_directory) == NULL)
+		return FALSE;
+
+	MP_LEND_OBJ_STR(priv, value);	
+	g_value_set_static_string (value, project_name);
+
+	/* check for an already existing table with project "project". */
+	if ((project_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+								  PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
+								  "prjname",
+								  value)) < 0)
+	{
+		g_warning ("no project with that name exists");
+		MP_RETURN_OBJ_STR (priv, value);
+		return FALSE;
+	}
+	
+
+	/* we're gonna set the file relative to the project folder, not the full one.
+	 * e.g.: we have a file on disk: "/tmp/foo/src/file.c" and a db_directory located on
+	 * "/tmp/foo/". The entry on db will be "src/file.c" 
+	 */
+	gchar *relative_path = symbol_db_engine_get_file_db_path (dbe, local_filepath);
+	if (relative_path == NULL)
+	{
+		DEBUG_PRINT ("%s", "relative_path == NULL");
+		MP_RETURN_OBJ_STR(priv, value);
+		return FALSE;
+	}	
+	g_value_set_static_string (value, relative_path);	
+
+	if ((file_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+								   PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
+								   "filepath",
+								   value)) < 0)
+	{
+		/* insert a new entry on db */
+		const GdaSet *plist;
+		const GdaStatement *stmt;
+		GdaHolder *param;
+		GValue *ret_value;
+		gboolean ret_bool;
+
+		
+		language_id = sdb_engine_add_new_language (dbe, language);
+
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_FILE_NEW))
+			== NULL)
+		{
+			g_warning ("query is null");
+			g_free (relative_path);
+			return FALSE;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_FILE_NEW);
+		
+		/* filepath parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "filepath")) == NULL)
+		{
+			g_warning ("param langname is NULL from pquery!");
+			g_free (relative_path);			
+			return FALSE;
+		}
+		
+		MP_SET_HOLDER_BATCH_STR(priv, param, relative_path, ret_bool, ret_value);
+								
+		/* project id parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "prjid")) == NULL)
+		{
+			g_warning ("param prjid is NULL from pquery!");
+			g_free (relative_path);
+			MP_RETURN_OBJ_STR (priv, ret_value);
+			return FALSE;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, project_id, ret_bool, ret_value);
+		
+		/* language id parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "langid")) == NULL)
+		{
+			g_warning ("param langid is NULL from pquery!");
+			g_free (relative_path);
+			return FALSE;
+		}		
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, language_id, ret_bool, ret_value);
+		
+		/* execute the query with parametes just set */
+		if (gda_connection_statement_execute_non_select (priv->db_connection, 
+														 (GdaStatement*)stmt, 
+														 (GdaSet*)plist, NULL,
+														 NULL) == -1)
+		{		
+			g_free (relative_path);
+			return FALSE;
+		}	
+	}
+
+	MP_RETURN_OBJ_STR(priv, value);
+	g_free (relative_path);
+	
+	return TRUE;
+} 
+
+static gint 
+sdb_engine_get_unique_scan_id (SymbolDBEngine * dbe)
+{
+	SymbolDBEnginePriv *priv;
+	gint ret_id;
+	
+	priv = dbe->priv;
+	
+	if (priv->mutex)
+		g_mutex_lock (priv->mutex);
+	
+	priv->scan_process_id++;	
+	ret_id = priv->scan_process_id;
+	
+	/* add the current scan_process id into a queue */
+	g_async_queue_push (priv->scan_process_id_queue, 
+						GINT_TO_POINTER(priv->scan_process_id));
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return ret_id;
+}
+							   
+gint
+symbol_db_engine_add_new_files (SymbolDBEngine * dbe, 
+								const gchar * project_name,
+								const GPtrArray * files_path, 
+								const GPtrArray * languages,
+								gboolean force_scan)
+{
+	gint i;
+	SymbolDBEnginePriv *priv;
+	GPtrArray * filtered_files_path;
+	GPtrArray * filtered_languages;
+	gboolean ret_code;
+	gint ret_id;
+	
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	g_return_val_if_fail (files_path != NULL, FALSE);
+	g_return_val_if_fail (languages != NULL, FALSE);
+	priv = dbe->priv;
+	
+	g_return_val_if_fail (priv->db_connection != NULL, FALSE);
+	g_return_val_if_fail (files_path->len > 0, FALSE);
+	g_return_val_if_fail (languages->len > 0, FALSE);
+
+	filtered_files_path = g_ptr_array_new ();
+	filtered_languages = g_ptr_array_new ();
+	
+	for (i = 0; i < files_path->len; i++)
+	{
+		gchar *node_file = (gchar *) g_ptr_array_index (files_path, i);
+		gchar *node_lang = (gchar *) g_ptr_array_index (languages, i);
+		
+		/* test the existance of node file */
+		if (g_file_test (node_file, G_FILE_TEST_EXISTS) == FALSE)
+		{
+			g_warning ("symbol_db_engine_add_new_files (): File %s does NOT exist", node_file);
+			continue;
+		}
+		
+		if (force_scan == FALSE)
+		{
+			if (symbol_db_engine_file_exists (dbe, node_file) == TRUE)
+				/* we don't want to touch the already present file... within 
+				 * its symbols
+				 */
+				continue;
+		}
+		
+		if (project_name != NULL && 
+			sdb_engine_add_new_file (dbe, project_name, node_file, 
+									 node_lang) == FALSE)
+		{
+			g_warning ("symbol_db_engine_add_new_files (): "
+					   "Error processing file %s, db_directory %s, project_name %s, "
+					   "project_directory %s", node_file, 
+					   priv->db_directory, project_name, priv->project_directory);
+			return FALSE;
+		}
+		
+		/* note: we don't use g_strdup () here because we'll free the filtered_files_path
+		 * before returning from this function.
+		 */
+		g_ptr_array_add (filtered_files_path, node_file);
+	}
+
+	/* perform the scan of files. It will spawn a fork() process with 
+	 * AnjutaLauncher and ctags in server mode. After the ctags cmd has been 
+	 * executed, the populating process'll take place.
+	 */
+	ret_code = sdb_engine_scan_files_1 (dbe, filtered_files_path, NULL, FALSE);
+	g_ptr_array_free (filtered_files_path, TRUE);
+	
+	if (ret_code == TRUE)
+		ret_id = sdb_engine_get_unique_scan_id (dbe);
+	else
+		ret_id = -1;
+	
+	return ret_id;
+}
+
+static inline gint
+sdb_engine_add_new_sym_type (SymbolDBEngine * dbe, const tagEntry * tag_entry)
+{
+/*
+	CREATE TABLE sym_type (type_id integer PRIMARY KEY AUTOINCREMENT,
+                   type_type varchar (256) not null ,
+                   type_name varchar (256) not null
+                   unique (type_type, type_name)
+                   );
+*/
+	const gchar *type;
+	const gchar *type_name;
+	gint table_id;	
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaSet *last_inserted;
+	SymbolDBEnginePriv *priv;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	priv = dbe->priv;
+		
+	/* we assume that tag_entry is != NULL */
+	type = tag_entry->kind;
+	type_name = tag_entry->name;
+	
+	/* it does not exist. Create a new tuple. */
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_SYM_TYPE_NEW))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_SYM_TYPE_NEW);
+
+	/* type parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "type")) == NULL)
+	{
+		g_warning ("param type is NULL from pquery!");
+		return -1;
+	}
+
+	MP_SET_HOLDER_BATCH_STR(priv, param, type, ret_bool, ret_value);
+
+	/* type_name parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "typename")) == NULL)
+	{
+		g_warning ("param typename is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, type_name, ret_bool, ret_value);
+	
+	/* execute the query with parametes just set */
+	if (gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt, 
+													 (GdaSet*)plist, &last_inserted,
+													 NULL) == -1)
+	{
+		GValue *value1, *value2;
+
+		MP_LEND_OBJ_STR (priv, value1);
+		g_value_set_static_string (value1, type);
+
+		MP_LEND_OBJ_STR (priv, value2);
+		g_value_set_static_string (value2, type_name);		
+
+		if ((table_id = sdb_engine_get_tuple_id_by_unique_name2 (dbe,
+													 PREP_QUERY_GET_SYM_TYPE_ID,
+													 "type", value1,
+													 "typename", value2)) < 0)
+		{
+			table_id = -1;
+		}
+		
+		MP_RETURN_OBJ_STR (priv, value1);
+		MP_RETURN_OBJ_STR (priv, value2);		
+		return table_id;
+	}	
+	else 
+	{
+		const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+		table_id = g_value_get_int (value);
+	}		
+	
+	return table_id;
+}
+
+static gint
+sdb_engine_add_new_sym_kind (SymbolDBEngine * dbe, const tagEntry * tag_entry)
+{
+/* 
+	CREATE TABLE sym_kind (sym_kind_id integer PRIMARY KEY AUTOINCREMENT,
+                       kind_name varchar (50) not null unique
+                       );
+*/
+	const gchar *kind_name;
+	gint table_id;
+	GValue *value;
+	SymbolDBEnginePriv *priv;
+	
+	priv = dbe->priv;
+		
+	/* we assume that tag_entry is != NULL */
+	kind_name = tag_entry->kind;
+
+	/* no kind associated with current tag */
+	if (kind_name == NULL)
+		return -1;
+
+	table_id = sdb_engine_cache_lookup (priv->kind_cache, kind_name);
+	if (table_id != -1)
+	{
+		return table_id;
+	}
+
+	MP_LEND_OBJ_STR(priv, value);	
+	g_value_set_static_string (value, kind_name);
+	
+	if ((table_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+										PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
+										"kindname",
+										value)) < 0)
+	{
+		const GdaSet *plist;
+		const GdaStatement *stmt;
+		GdaHolder *param;
+		GdaSet *last_inserted;
+		GValue *ret_value;
+		gboolean ret_bool;
+
+		/* not found. Go on with inserting  */
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_SYM_KIND_NEW))
+			== NULL)
+		{
+			g_warning ("query is null");
+			return -1;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_SYM_KIND_NEW);
+		
+		/* kindname parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "kindname")) == NULL)
+		{
+			g_warning ("param kindname is NULL from pquery!");
+			return FALSE;
+		}
+
+		MP_SET_HOLDER_BATCH_STR(priv, param, kind_name, ret_bool, ret_value);
+	
+		/* execute the query with parametes just set */
+		GError *err = NULL;
+		if (gda_connection_statement_execute_non_select (priv->db_connection, 
+														 (GdaStatement*)stmt, 
+														 (GdaSet*)plist, &last_inserted,
+														 &err) == -1)
+		{		
+			table_id = -1;		
+		}			
+		else
+		{
+			const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+			table_id = g_value_get_int (value);
+			/* we should cache only tables which are != -1 */
+			sdb_engine_insert_cache (priv->kind_cache, kind_name, table_id);
+		}
+	}
+
+	MP_RETURN_OBJ_STR(priv, value);
+	
+	return table_id;
+}
+
+static gint
+sdb_engine_add_new_sym_access (SymbolDBEngine * dbe, const tagEntry * tag_entry)
+{
+/* 
+	CREATE TABLE sym_access (access_kind_id integer PRIMARY KEY AUTOINCREMENT,
+                         access_name varchar (50) not null unique
+                         );
+*/	
+	const gchar *access;
+	gint table_id;
+	GValue *value;
+	SymbolDBEnginePriv *priv;
+
+	priv = dbe->priv;
+		
+	
+	/* we assume that tag_entry is != NULL */	
+	if ((access = tagsField (tag_entry, "access")) == NULL)
+	{
+		/* no access associated with current tag */
+		return -1;
+	}
+	
+	table_id = sdb_engine_cache_lookup (priv->access_cache, access);
+	if (table_id != -1)
+	{
+		return table_id;
+	}
+
+	MP_LEND_OBJ_STR(priv, value);	
+	g_value_set_static_string (value, access);
+
+	if ((table_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+									PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
+									"accesskind",
+									value)) < 0)
+	{
+		const GdaSet *plist;
+		const GdaStatement *stmt;
+		GdaHolder *param;
+		GdaSet *last_inserted;
+		GValue *ret_value;
+		gboolean ret_bool;		
+
+		/* not found. Go on with inserting  */
+		if ((stmt =
+			 sdb_engine_get_statement_by_query_id (dbe,
+										 PREP_QUERY_SYM_ACCESS_NEW)) == NULL)
+		{
+ 			g_warning ("query is null");
+			return -1;
+		}
+		
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_SYM_ACCESS_NEW);
+		
+		/* accesskind parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "accesskind")) == NULL)
+		{			
+			g_warning ("param accesskind is NULL from pquery!");
+			return -1;
+		}
+		
+		MP_SET_HOLDER_BATCH_STR(priv, param, access, ret_bool, ret_value);
+		
+		/* execute the query with parametes just set */
+		GError *err = NULL;
+		if (gda_connection_statement_execute_non_select (priv->db_connection, 
+														 (GdaStatement*)stmt, 
+														 (GdaSet*)plist, &last_inserted,
+														 &err) == -1)
+		{		
+			table_id = -1;		
+		}			
+		else
+		{
+			const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+			table_id = g_value_get_int (value);
+			/* we should cache only tables which are != -1 */
+			sdb_engine_insert_cache (priv->access_cache, access, table_id);
+		}		
+	}
+	
+	MP_RETURN_OBJ_STR(priv, value);
+	
+	return table_id;
+}
+
+static gint
+sdb_engine_add_new_sym_implementation (SymbolDBEngine * dbe,
+									   const tagEntry * tag_entry)
+{
+/*	
+	CREATE TABLE sym_implementation (sym_impl_id integer PRIMARY KEY AUTOINCREMENT,
+                                 implementation_name varchar (50) not null unique
+                                 );
+*/
+	const gchar *implementation;
+	gint table_id;
+	GValue *value;
+	SymbolDBEnginePriv *priv;
+
+	priv = dbe->priv;
+			
+	/* we assume that tag_entry is != NULL */	
+	if ((implementation = tagsField (tag_entry, "implementation")) == NULL)
+	{
+		/* no implementation associated with current tag */
+		return -1;
+	}
+	table_id = sdb_engine_cache_lookup (priv->implementation_cache, implementation);
+	if (table_id != -1)
+	{
+		return table_id;
+	}
+
+	MP_LEND_OBJ_STR(priv, value);	
+	g_value_set_static_string (value, implementation);
+
+	if ((table_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+							PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
+							"implekind",
+							value)) < 0)
+	{
+		const GdaSet *plist;
+		const GdaStatement *stmt;
+		GdaHolder *param;
+		GdaSet *last_inserted;
+		GValue *ret_value;
+		gboolean ret_bool;
+
+		/* not found. Go on with inserting  */
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe,
+										 PREP_QUERY_SYM_IMPLEMENTATION_NEW)) ==
+			NULL)
+		{
+			g_warning ("query is null");
+			return -1;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_SYM_IMPLEMENTATION_NEW);
+		
+		/* implekind parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "implekind")) == NULL)
+		{			
+			g_warning ("param accesskind is NULL from pquery!");
+			return -1;
+		}
+		
+		MP_SET_HOLDER_BATCH_STR(priv, param, implementation, ret_bool, ret_value);		
+
+		/* execute the query with parametes just set */
+		GError *err = NULL;
+		if (gda_connection_statement_execute_non_select (priv->db_connection, 
+														 (GdaStatement*)stmt, 
+														 (GdaSet*)plist, &last_inserted,
+														 &err) == -1)
+		{		
+			table_id = -1;		
+		}			
+		else
+		{
+			const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+			table_id = g_value_get_int (value);			
+			/* we should cache only tables which are != -1 */
+			sdb_engine_insert_cache (priv->implementation_cache, implementation, 
+									 table_id);	
+		}
+	}
+	
+	MP_RETURN_OBJ_STR(priv, value);
+	
+	return table_id;
+}
+
+static void
+sdb_engine_add_new_heritage (SymbolDBEngine * dbe, gint base_symbol_id,
+							 gint derived_symbol_id)
+{
+/*
+	CREATE TABLE heritage (symbol_id_base integer REFERENCES symbol (symbol_id),
+                       symbol_id_derived integer REFERENCES symbol (symbol_id),
+                       PRIMARY KEY (symbol_id_base, symbol_id_derived)
+                       );
+*/
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GValue *ret_value;
+	gboolean ret_bool;
+	SymbolDBEnginePriv *priv;
+	
+	
+	g_return_if_fail (base_symbol_id > 0);
+	g_return_if_fail (derived_symbol_id > 0);
+
+	priv = dbe->priv;
+	
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_HERITAGE_NEW))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_HERITAGE_NEW);
+		
+	/* symbase parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "symbase")) == NULL)
+	{			
+		g_warning ("param accesskind is NULL from pquery!");
+		return;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, base_symbol_id, ret_bool, ret_value);		
+
+	/* symderived id parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "symderived")) == NULL)
+	{
+		g_warning ("param symderived is NULL from pquery!");
+		return;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, derived_symbol_id, ret_bool, ret_value);		
+	
+	/* execute the query with parametes just set */
+	if (gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt, 
+													 (GdaSet*)plist, NULL,
+													 NULL) == -1)
+	{		
+		g_warning ("Error adding heritage");
+	}	
+}
+
+static inline gint
+sdb_engine_add_new_scope_definition (SymbolDBEngine * dbe, const tagEntry * tag_entry,
+									 gint type_table_id)
+{
+/*
+	CREATE TABLE scope (scope_id integer PRIMARY KEY AUTOINCREMENT,
+                    scope_name varchar(256) not null,
+                    type_id integer REFERENCES sym_type (type_id),
+					unique (scope_name, type_id)
+                    );
+*/
+	const gchar *scope;
+	gint table_id;
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaSet *last_inserted;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (tag_entry->kind != NULL, -1);
+
+	priv = dbe->priv;
+	
+	
+	/* This symbol will define a scope which name is tag_entry->name
+	 * For example if we get a tag MyFoo with kind "namespace", it will define 
+	 * the "MyFoo" scope, which type is "namespace MyFoo"
+	 */
+	scope = tag_entry->name;
+
+	/* filter out 'variable' and 'member' kinds. They define no scope. */
+	if (strcmp (tag_entry->kind, "variable") == 0 ||
+		strcmp (tag_entry->kind, "member") == 0)
+	{
+		return -1;
+	}
+
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_SCOPE_NEW))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_SCOPE_NEW);
+		
+	/* scope parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "scope")) == NULL)
+	{			
+		g_warning ("param scope is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, scope, ret_bool, ret_value);	
+
+	/* typeid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "typeid")) == NULL)
+	{
+		g_warning ("param typeid is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, type_table_id, ret_bool, ret_value);
+
+	/* execute the query with parameters just set */
+	if (gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt, 
+													 (GdaSet*)plist, &last_inserted,
+													 NULL) == -1)
+	{
+		GValue *value1, *value2;
+		/* let's check for an already present scope table with scope and type_id infos. */
+		MP_LEND_OBJ_STR (priv, value1);
+		g_value_set_static_string (value1, scope);
+
+		MP_LEND_OBJ_INT (priv, value2);		
+		g_value_set_int (value2, type_table_id);
+	
+		if ((table_id = sdb_engine_get_tuple_id_by_unique_name2 (dbe,
+												 PREP_QUERY_GET_SCOPE_ID,
+												 "scope", 
+												 value1,
+												 "typeid",
+												 value2)) < 0)
+		{
+			table_id = -1;
+		}
+
+		MP_RETURN_OBJ_STR(priv, value1);
+		MP_RETURN_OBJ_INT(priv, value2);
+	}
+	else  {
+		const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+		table_id = g_value_get_int (value);
+	}	
+
+	return table_id;
+}
+
+/**
+ * Saves the tagEntry info for a second pass parsing.
+ * Usually we don't know all the symbol at the first scan of the tags. We need
+ * a second one. These tuples are created for that purpose.
+ *
+ * @return the table_id of the inserted tuple. -1 on error.
+ */
+static inline gint
+sdb_engine_add_new_tmp_heritage_scope (SymbolDBEngine * dbe,
+									   const tagEntry * tag_entry,
+									   gint symbol_referer_id)
+{
+/*
+	CREATE TABLE __tmp_heritage_scope (tmp_heritage_scope_id integer PRIMARY KEY 
+							AUTOINCREMENT,
+							symbol_referer_id integer not null,
+							field_inherits varchar(256) not null,
+							field_struct varchar(256),
+							field_typeref varchar(256),
+							field_enum varchar(256),
+							field_union varchar(256),
+							field_class varchar(256),
+							field_namespace varchar(256)
+							);
+*/
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaSet *last_inserted;
+	gint table_id;
+	SymbolDBEnginePriv *priv;
+	const gchar *field_inherits, *field_struct, *field_typeref,
+		*field_enum, *field_union, *field_class, *field_namespace;
+	gboolean good_tag;
+	GValue *ret_value;
+	gboolean ret_bool;
+
+	/* we assume that tag_entry is != NULL */
+	/* init the flag */
+	good_tag = FALSE;
+
+	priv = dbe->priv;
+	
+		
+	if ((field_inherits = tagsField (tag_entry, "inherits")) == NULL)
+	{
+		field_inherits = "";
+	}
+	else
+		good_tag = TRUE;
+
+	if ((field_struct = tagsField (tag_entry, "struct")) == NULL)
+	{
+		field_struct = "";
+	}
+	else
+		good_tag = TRUE;
+
+	if ((field_typeref = tagsField (tag_entry, "typeref")) == NULL)
+	{
+		field_typeref = "";
+	}
+	else
+		good_tag = TRUE;
+
+	if ((field_enum = tagsField (tag_entry, "enum")) == NULL)
+	{
+		field_enum = "";
+	}
+	else
+		good_tag = TRUE;
+
+	if ((field_union = tagsField (tag_entry, "union")) == NULL)
+	{
+		field_union = "";
+	}
+	else
+		good_tag = TRUE;
+ 
+	if ((field_class = tagsField (tag_entry, "class")) == NULL)
+	{
+		field_class = "";
+	}
+	else
+		good_tag = TRUE;
+
+	if ((field_namespace = tagsField (tag_entry, "namespace")) == NULL)
+	{
+		field_namespace = "";
+	}
+	else
+		good_tag = TRUE;
+
+	if (!good_tag)
+		return -1;
+
+
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_TMP_HERITAGE_NEW))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe,PREP_QUERY_TMP_HERITAGE_NEW);
+		
+	/* symreferid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "symreferid")) == NULL)
+	{
+		g_warning ("param symreferid is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, symbol_referer_id, ret_bool, ret_value);	
+	
+	/* finherits parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "finherits")) == NULL)
+	{
+		g_warning ("param finherits is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, field_inherits, ret_bool, ret_value);	
+	
+
+	/* fstruct parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "fstruct")) == NULL)
+	{
+		g_warning ("param fstruct is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, field_struct, ret_bool, ret_value);	
+	
+	/* ftyperef parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "ftyperef")) == NULL)
+	{
+		g_warning ("param ftyperef is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, field_typeref, ret_bool, ret_value);	
+	
+	/* fenum parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "fenum")) == NULL)
+	{
+		g_warning ("param fenum is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, field_enum, ret_bool, ret_value);		
+	
+	/* funion parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "funion")) == NULL)
+	{
+		g_warning ("param funion is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, field_union, ret_bool, ret_value);
+		
+	/* fclass parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "fclass")) == NULL)
+	{
+		g_warning ("param fclass is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, field_class, ret_bool, ret_value);	
+
+	/* fnamespace parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "fnamespace")) == NULL)
+	{
+		g_warning ("param fnamespace is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, field_namespace, ret_bool, ret_value);		
+
+	/* execute the query with parametes just set */
+	if (gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt, 
+													 (GdaSet*)plist, &last_inserted,
+													 NULL) == -1)
+	{
+		table_id = -1;
+	}
+	else 
+	{
+		const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+		table_id = g_value_get_int (value);
+	}
+	
+	return table_id;
+}
+
+/** Return the symbol_id of the changed symbol */
+// FIXME: find a quicker way to handle the thing here.
+static inline gint
+sdb_engine_second_pass_update_scope_1 (SymbolDBEngine * dbe,
+									   GdaDataModel * data, gint data_row,
+									   gchar * token_name,
+									   const GValue * token_value)
+{
+	gint scope_id;
+	GValue *value1, *value2;
+	const GValue *value_id2;
+	gint symbol_referer_id;
+	const gchar *tmp_str;
+	gchar **tmp_str_splitted;
+	gint tmp_str_splitted_length;
+	gchar *object_name = NULL;
+	gboolean free_token_name = FALSE;
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	SymbolDBEnginePriv *priv;
+	GValue *ret_value;
+	gboolean ret_bool;
+
+	g_return_val_if_fail (G_VALUE_HOLDS_STRING (token_value), FALSE);
+		
+	priv = dbe->priv;
+	tmp_str = g_value_get_string (token_value);
+
+	/* we don't need empty strings */
+	if (strlen (tmp_str) <= 0)
+	{
+		return -1;
+	}
+
+	/* we could have something like "First::Second::Third::Fourth" as tmp_str, so 
+	 * take only the lastscope, in this case 'Fourth'.
+	 */
+	tmp_str_splitted = g_strsplit (tmp_str, ":", 0);
+	tmp_str_splitted_length = g_strv_length (tmp_str_splitted);
+
+	if (tmp_str_splitted_length > 0)
+	{
+		/* handle special typedef case. Usually we have something like struct:my_foo.
+		 * splitting we have [0]-> struct [1]-> my_foo
+		 */
+		if (strcmp (token_name, "typedef") == 0)
+		{
+			free_token_name = TRUE;
+			token_name = g_strdup (tmp_str_splitted[0]);
+		}
+
+		object_name = g_strdup (tmp_str_splitted[tmp_str_splitted_length - 1]);
+	}
+	else
+	{
+		g_strfreev (tmp_str_splitted);
+		return -1;
+	}
+
+	g_strfreev (tmp_str_splitted);
+
+	MP_LEND_OBJ_STR (priv, value1);	
+	g_value_set_static_string (value1, token_name);
+
+	MP_LEND_OBJ_STR (priv, value2);
+	g_value_set_static_string (value2, object_name);
+
+	/* we're gonna access db. Let's lock here */
+	if (priv->mutex)
+		g_mutex_lock (priv->mutex);
+	
+	if ((scope_id = sdb_engine_get_tuple_id_by_unique_name2 (dbe,
+									 PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
+									 "tokenname",
+									 value1,
+									 "objectname",
+									 value2)) < 0)
+	{
+		if (free_token_name)
+			g_free (token_name);
+
+		MP_RETURN_OBJ_STR (priv, value1);
+		MP_RETURN_OBJ_STR (priv, value2);
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);					
+		
+		return -1;
+	}
+	MP_RETURN_OBJ_STR (priv, value1);
+	MP_RETURN_OBJ_STR (priv, value2);
+	
+	if (free_token_name)
+		g_free (token_name);
+
+	
+	/* if we reach this point we should have a good scope_id.
+	 * Go on with symbol updating.
+	 */
+	value_id2 = gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "symbol_referer_id"), 
+											 data_row, NULL);
+	symbol_referer_id = g_value_get_int (value_id2);
+	
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe,
+											 PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID))
+		== NULL)
+	{
+		g_warning ("query is null");
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);					
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID);
+
+	/* scopeid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "scopeid")) == NULL)
+	{
+		g_warning ("param scopeid is NULL from pquery!");
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);					
+		return -1;
+	}
+
+	MP_SET_HOLDER_BATCH_INT(priv, param, scope_id, ret_bool, ret_value);		
+
+	/* symbolid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "symbolid")) == NULL)
+	{
+		g_warning ("param symbolid is NULL from pquery!");
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);					
+		return -1;
+	}
+
+	MP_SET_HOLDER_BATCH_INT(priv, param, symbol_referer_id, ret_bool, ret_value);
+
+	/* execute the query with parametes just set */
+	gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt, 
+													 (GdaSet*)plist, NULL,
+													 NULL);
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);					
+	return symbol_referer_id;
+}
+
+
+/**
+ * @param data Must be filled with some values. It must have num_rows > 0
+ * @note *CALL THIS BEFORE second_pass_update_heritage ()*
+ * @note *DO NOT FREE data* inside this function.
+ */
+static void
+sdb_engine_second_pass_update_scope (SymbolDBEngine * dbe, GdaDataModel * data)
+{
+	SymbolDBEnginePriv *priv;
+	/*
+	 * Fill up the scope. 
+	 * The case: "my_foo_func_1" is the name of the current tag parsed. 
+	 * Suppose we have a namespace MyFooNamespace, under which is declared
+	 * a class MyFooClass. Under that class there are some funcs like 
+	 * my_foo_func_1 () etc. ctags will present us this info about 
+	 * my_foo_func_1 ():
+	 * "class : MyFooNamespace::MyFooClass"
+	 * but hey! We don't need to know the namespace here, we just want to 
+	 * know that my_foo_func_1 is in the scope of MyFooClass. That one will 
+	 * then be mapped inside MyFooNamespace, but that's another thing.
+	 * Go on with the parsing then.
+	 */
+	gint i;
+	
+	priv = dbe->priv;
+	
+	DEBUG_PRINT ("%s", "sdb_engine_second_pass_update_scope()");
+	
+	/* temporary unlock. This function may take a while to be completed
+	 * so let other db-task to be executed, so that main thread
+	 * isn't locked up. 
+	 * sdb_engine_second_pass_update_scope_1 () which is called later on will
+	 * access db and then will lock again.
+	 */
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);					
+	
+	DEBUG_PRINT ("processing %d rows", gda_data_model_get_n_rows (data));
+	
+	for (i = 0; i < gda_data_model_get_n_rows (data); i++)
+	{
+		GValue *value;		
+		
+		if ((value =
+			 (GValue *) gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "field_class"),
+															  i, NULL)) != NULL)
+		{
+			sdb_engine_second_pass_update_scope_1 (dbe, data, i, "class",
+												   value);
+		}
+
+		if ((value =
+			 (GValue *) gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data,"field_struct"),
+															  i, NULL)) != NULL)
+		{
+			sdb_engine_second_pass_update_scope_1 (dbe, data, i, "struct",
+												   value);
+		}
+
+		if ((value =
+			 (GValue *) gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "field_typeref"),
+															  i, NULL)) != NULL)
+		{
+			/* this is a "typedef", not a "typeref". */
+			sdb_engine_second_pass_update_scope_1 (dbe, data, i, "typedef",
+												   value);
+		}
+
+		if ((value =
+			 (GValue *) gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "field_enum"),
+															  i, NULL)) != NULL)
+		{
+			sdb_engine_second_pass_update_scope_1 (dbe, data, i, "enum", value);
+		}
+
+		if ((value =
+			 (GValue *) gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "field_union"),
+															  i, NULL)) != NULL)
+		{
+			sdb_engine_second_pass_update_scope_1 (dbe, data, i, "union",
+												   value);
+		}
+
+		if ((value =
+			 (GValue *) gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "field_namespace"),
+															  i, NULL)) != NULL)
+		{
+			sdb_engine_second_pass_update_scope_1 (dbe, data, i, "namespace",
+												   value);
+		}
+	}
+
+	/* relock */
+	if (priv->mutex)
+		g_mutex_lock (priv->mutex);
+}
+
+
+/**
+ * @param data Must be filled with some values. It must have num_rows > 0
+ * @note *CALL THIS AFTER second_pass_update_scope ()*
+ */
+static void
+sdb_engine_second_pass_update_heritage (SymbolDBEngine * dbe,
+										GdaDataModel * data)
+{
+	gint i;
+	SymbolDBEnginePriv *priv;
+	
+	g_return_if_fail (dbe != NULL);
+	
+	priv = dbe->priv;
+	
+	DEBUG_PRINT ("%s", "sdb_engine_second_pass_update_heritage ()");
+	/* unlock */
+	if (priv->mutex)
+		g_mutex_unlock (dbe->priv->mutex);
+	
+	for (i = 0; i < gda_data_model_get_n_rows (data); i++)
+	{
+		const GValue *value;
+		const gchar *inherits;
+		gchar *item;
+		gchar **inherits_list;
+		gint j;
+		
+		value = gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "field_inherits"), i, 
+											 NULL);
+		inherits = g_value_get_string (value);
+
+		/* there can be multiple inheritance. Check that. */
+		inherits_list = g_strsplit (inherits, ",", 0);
+
+		if (inherits_list != NULL)
+			DEBUG_PRINT ("inherits %s\n", inherits);
+
+		/* retrieve as much info as we can from the items */
+		for (j = 0; j < g_strv_length (inherits_list); j++)
+		{
+			gchar **namespaces;
+			gchar *klass_name;
+			gchar *namespace_name;
+			gint namespaces_length;
+			gint base_klass_id;
+			gint derived_klass_id;
+			const GValue *value;
+
+			item = inherits_list[j];
+			DEBUG_PRINT ("heritage %s\n", item);
+
+			/* A item may have this string form:
+			 * MyFooNamespace1::MyFooNamespace2::MyFooClass
+			 * We should find the field 'MyFooNamespace2' because it's the one 
+			 * that is reachable by the scope_id value of the symbol.
+			 */
+
+			namespaces = g_strsplit (item, "::", 0);
+			namespaces_length = g_strv_length (namespaces);
+
+			if (namespaces_length > 1)
+			{
+				/* this is the case in which we have the case with 
+				 * namespace + class
+				 */
+				namespace_name = g_strdup (namespaces[namespaces_length - 2]);
+				klass_name = g_strdup (namespaces[namespaces_length - 1]);
+			}
+			else
+			{
+				/* have a last check before setting namespace_name to null.
+				 * check whether the field_namespace is void or not.
+				 */
+				const GValue *namespace_value;
+				const gchar *tmp_namespace;
+				gchar **tmp_namespace_array = NULL;
+				gint tmp_namespace_length;
+
+				namespace_value =
+					gda_data_model_get_value_at (data, 
+						gda_data_model_get_column_index(data, "field_namespace"),
+												 i, NULL);
+				tmp_namespace = g_value_get_string (namespace_value);
+				if (tmp_namespace != NULL)
+				{
+					tmp_namespace_array = g_strsplit (tmp_namespace, "::", 0);
+					tmp_namespace_length = g_strv_length (tmp_namespace_array);
+
+					if (tmp_namespace_length > 0)
+						namespace_name =
+							g_strdup (tmp_namespace_array
+									  [tmp_namespace_length - 1]);
+					else
+						namespace_name = NULL;
+				}
+				else
+				{
+					namespace_name = NULL;
+				}
+
+				klass_name = g_strdup (namespaces[namespaces_length - 1]);
+
+				g_strfreev (tmp_namespace_array);
+			}
+
+			g_strfreev (namespaces);
+
+			/* get the derived_klass_id. It should be the 
+			 * symbol_referer_id field into __tmp_heritage_scope table
+			 */
+			if ((value = (GValue *) gda_data_model_get_value_at (data,
+																 1, i, NULL)) != NULL)
+			{
+				derived_klass_id = g_value_get_int (value);
+			}
+			else
+			{
+				derived_klass_id = 0;
+			}
+
+			/* we're on the query side of the function. It needs some locking... */
+			if (priv->mutex)
+				g_mutex_lock (dbe->priv->mutex);
+			
+			/* ok, search for the symbol_id of the base class */
+			if (namespace_name == NULL)
+			{
+				GValue *value1;
+
+				MP_LEND_OBJ_STR (priv, value1);
+				g_value_set_static_string (value1, klass_name);
+				
+				if ((base_klass_id =
+					 sdb_engine_get_tuple_id_by_unique_name (dbe,
+										 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
+										 "klassname",
+										 value1)) < 0)
+				{
+					MP_RETURN_OBJ_STR(priv, value1);
+
+					if (priv->mutex)
+						g_mutex_unlock (dbe->priv->mutex);
+
+					continue;
+				}
+				MP_RETURN_OBJ_STR(priv, value1);
+			}
+			else
+			{
+				GValue *value1;
+				GValue *value2;
+
+				MP_LEND_OBJ_STR (priv, value1);
+				g_value_set_static_string (value1, klass_name);
+
+				MP_LEND_OBJ_STR (priv, value2);
+				g_value_set_static_string (value2, namespace_name);
+
+				DEBUG_PRINT ("value1 : %s value2 : %s", klass_name, namespace_name);
+				if ((base_klass_id =
+					 sdb_engine_get_tuple_id_by_unique_name2 (dbe,
+						  PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
+						  "klassname",
+						  value1,
+						  "namespacename",
+						  value2)) < 0)
+				{
+					MP_RETURN_OBJ_STR(priv, value1);
+					MP_RETURN_OBJ_STR(priv, value2);
+
+					if (priv->mutex)
+						g_mutex_unlock (dbe->priv->mutex);
+
+					continue;
+				}
+				MP_RETURN_OBJ_STR(priv, value1);
+				MP_RETURN_OBJ_STR(priv, value2);
+			}
+
+			g_free (namespace_name);
+			g_free (klass_name);
+			
+			DEBUG_PRINT ("gonna sdb_engine_add_new_heritage with "
+						 "base_klass_id %d, derived_klass_id %d", base_klass_id, 
+						 derived_klass_id);
+			sdb_engine_add_new_heritage (dbe, base_klass_id, derived_klass_id);
+			if (priv->mutex)
+				g_mutex_unlock (dbe->priv->mutex);
+			
+		}
+
+		g_strfreev (inherits_list);			
+	}
+	
+	/* relock before leaving... */
+	if (priv->mutex)
+		g_mutex_lock (dbe->priv->mutex);
+	
+}
+
+/**
+ * Process the temporary table to update the symbols on scope and inheritance 
+ * fields.
+ * *CALL THIS FUNCTION ONLY AFTER HAVING PARSED ALL THE TAGS ONCE*
+ *
+ */
+static void
+sdb_engine_second_pass_do (SymbolDBEngine * dbe)
+{
+	const GdaStatement *stmt1, *stmt2, *stmt3;
+	GdaDataModel *data_model;
+	SymbolDBEnginePriv *priv;
+
+	priv = dbe->priv;
+	
+	DEBUG_PRINT ("%s", "sdb_engine_second_pass_do()");	
+
+	/* prepare for scope second scan */
+	if ((stmt1 =
+		 sdb_engine_get_statement_by_query_id (dbe,
+									 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return;
+	}
+
+	/* execute the query */
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt1, 
+														  NULL, NULL);
+	
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model)) <= 0)
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		data_model = NULL;
+	}
+	else
+	{
+		sdb_engine_second_pass_update_scope (dbe, data_model);
+	}
+
+	if (data_model != NULL)
+		g_object_unref (data_model);
+
+	/* prepare for heritage second scan */
+	if ((stmt2 =
+		 sdb_engine_get_statement_by_query_id (dbe,
+						 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return;
+	}
+
+	/* execute the query */
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt2, 
+														  NULL, NULL);
+
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model)) <= 0)
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		data_model = NULL;
+	}
+	else
+	{
+		sdb_engine_second_pass_update_heritage (dbe, data_model);
+	}
+
+	if (data_model != NULL)
+		g_object_unref (data_model);
+
+	/* clean tmp heritage table */
+	if ((stmt3 =
+		 sdb_engine_get_statement_by_query_id (dbe,
+									 PREP_QUERY_TMP_HERITAGE_DELETE_ALL))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return;
+	}
+
+	/* execute the query */
+	gda_connection_statement_execute_non_select (priv->db_connection, 
+														  (GdaStatement*)stmt3, 
+														  NULL, NULL, NULL);	
+}
+
+/* base_prj_path can be NULL. In that case path info tag_entry will be taken
+ * as an absolute path.
+ * fake_file can be used when a buffer updating is being executed. In that 
+ * particular case both base_prj_path and tag_entry->file will be ignored. 
+ * fake_file is real_path of file on disk
+ */
+static gint
+sdb_engine_add_new_symbol (SymbolDBEngine * dbe, const tagEntry * tag_entry,
+						   gint file_defined_id,
+						   gboolean sym_update)
+{
+/*
+	CREATE TABLE symbol (symbol_id integer PRIMARY KEY AUTOINCREMENT,
+                     file_defined_id integer not null REFERENCES file (file_id),
+                     name varchar (256) not null,
+                     file_position integer,
+                     is_file_scope integer,
+                     signature varchar (256),
+                     scope_definition_id integer,
+                     scope_id integer,
+                     type_id integer REFERENCES sym_type (type_id),
+                     kind_id integer REFERENCES sym_kind (sym_kind_id),
+                     access_kind_id integer REFERENCES sym_access (sym_access_id),
+                     implementation_kind_id integer REFERENCES sym_implementation 
+								(sym_impl_id)
+                     );
+*/
+	SymbolDBEnginePriv *priv;
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GdaSet *last_inserted;
+	const gchar *tmp_str;
+	gint table_id, symbol_id;
+	const gchar* name;
+	gint file_position = 0;
+	gint is_file_scope = 0;
+	const gchar *signature;
+	gint scope_definition_id = 0;
+	gint scope_id = 0;
+	gint type_id = 0;
+	gint kind_id = 0;
+	gint access_kind_id = 0;
+	gint implementation_kind_id = 0;
+	GValue *value1, *value2, *value3, *value4;
+	gboolean sym_was_updated = FALSE;
+	gint update_flag;
+	GValue *ret_value;
+	gboolean ret_bool;
+		
+	g_return_val_if_fail (dbe != NULL, -1);
+	priv = dbe->priv;
+
+	/* keep it at 0 if sym_update == false */
+	if (sym_update == FALSE)
+		update_flag = 0;
+	else
+		update_flag = 1;
+
+	g_return_val_if_fail (tag_entry != NULL, -1);
+
+	/* parse the entry name */
+	if (strlen (tag_entry->name) > 256)
+	{
+		g_warning ("tag_entry->name too big for database");
+		return -1;
+	}
+	name = tag_entry->name;
+	file_position = tag_entry->address.lineNumber;
+	is_file_scope = tag_entry->fileScope;
+
+	if ((tmp_str = tagsField (tag_entry, "signature")) != NULL)
+	{
+		signature = tmp_str;
+	}
+	else
+	{
+		signature = NULL;
+	}
+	
+	type_id = sdb_engine_add_new_sym_type (dbe, tag_entry);
+
+	/* scope_definition_id tells what scope this symbol defines
+	 * this call *MUST BE DONE AFTER* sym_type table population.
+	 */
+	scope_definition_id = sdb_engine_add_new_scope_definition (dbe, tag_entry,
+															   type_id);
+
+	/* the container scopes can be: union, struct, typeref, class, namespace etc.
+	 * this field will be parse in the second pass.
+	 */
+	scope_id = 0;
+
+	kind_id = sdb_engine_add_new_sym_kind (dbe, tag_entry);
+	
+	access_kind_id = sdb_engine_add_new_sym_access (dbe, tag_entry);
+	implementation_kind_id =
+		sdb_engine_add_new_sym_implementation (dbe, tag_entry);
+	
+	/* ok: was the symbol updated [at least on it's type_id/name]? 
+	 * There are 3 cases:
+	 * #1. The symbol remain the same [at least on unique index key]. We will 
+	 *     perform only a simple update.
+	 * #2. The symbol has changed: at least on name/type/file. We will insert a 
+	 *     new symbol on table 'symbol'. Deletion of old one will take place 
+	 *     at a second stage, when a delete of all symbols with 
+	 *     'tmp_flag = 0' will be done.
+	 * #3. The symbol has been deleted. As above it will be deleted at 
+	 *     a second stage because of the 'tmp_flag = 0'. Triggers will remove 
+	 *     also scope_ids and other things.
+	 */
+
+	
+	if (update_flag == FALSE)
+	{
+		/* FIXME: are we sure to force this to -1? */
+		symbol_id = -1;
+	}
+	else 
+	{
+		GList *sym_list;		
+		MP_LEND_OBJ_STR (priv, value1);	
+		g_value_set_static_string (value1, name);
+
+		MP_LEND_OBJ_INT (priv, value2);
+		g_value_set_int (value2, file_defined_id);
+
+		MP_LEND_OBJ_INT (priv, value3);		
+		g_value_set_int (value3, type_id);
+		
+		MP_LEND_OBJ_INT (priv, value4);		
+		g_value_set_int (value4, file_position);
+
+		sym_list = g_tree_lookup (priv->file_symbols_cache, GINT_TO_POINTER(type_id));
+		
+		symbol_id = sdb_engine_get_tuple_id_by_unique_name4 (dbe,
+								  PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY_EXT,
+								  "symname", value1,
+								  "filedefid",value2,
+								  "typeid", value3,
+								  "filepos", value4);
+		
+		/* no luck, retry widely */
+		if (symbol_id <= 0)
+		{
+			symbol_id = sdb_engine_get_tuple_id_by_unique_name3 (dbe,
+								  PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY_EXT2,
+								  "symname", value1,
+								  "filedefid",value2,
+								  "typeid", value3);			
+		}
+
+		if (symbol_id > 0) {
+			/* attach to list the value of symbol: when this will have parsed all its
+			 * symbols we'll be ready to check the lists with more than an element:
+			 * those for sure will have an high probability for an updated scope.
+			 */
+			sym_list = g_list_prepend (sym_list, GINT_TO_POINTER(symbol_id));
+			g_tree_insert (priv->file_symbols_cache, GINT_TO_POINTER(type_id), 
+							   sym_list);
+		}
+		
+		MP_RETURN_OBJ_STR (priv, value1);
+		MP_RETURN_OBJ_INT (priv, value2);
+		MP_RETURN_OBJ_INT (priv, value3);
+		MP_RETURN_OBJ_INT (priv, value4);
+	}
+		 
+
+	/* ok then, parse the symbol id value */
+	if (symbol_id <= 0)
+	{
+		/* case 2 and 3 */
+		sym_was_updated = FALSE;
+
+		/* create specific query for a fresh new symbol */
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_SYMBOL_NEW))
+			== NULL)
+		{
+			g_warning ("query is null");
+			return -1;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_SYMBOL_NEW);
+		
+		/* filedefid parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "filedefid")) == NULL)
+		{
+			g_warning ("param filedefid is NULL from pquery!");
+			return -1;
+		}
+		
+		MP_SET_HOLDER_BATCH_INT(priv, param, file_defined_id, ret_bool, ret_value);
+
+		/* name parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "name")) == NULL)
+		{
+			g_warning ("param name is NULL from pquery!");			
+			return -1;
+		}
+		
+		MP_SET_HOLDER_BATCH_STR(priv, param, name, ret_bool, ret_value);		
+
+		/* typeid parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "typeid")) == NULL)
+		{
+			g_warning ("param typeid is NULL from pquery!");
+			return -1;			
+		}
+		
+		MP_SET_HOLDER_BATCH_INT(priv, param, type_id, ret_bool, ret_value);		
+	}
+	else
+	{
+		/* case 1 */
+		sym_was_updated = TRUE;
+
+		/* create specific query for a fresh new symbol */
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe,
+												 PREP_QUERY_UPDATE_SYMBOL_ALL))
+			== NULL)
+		{
+			g_warning ("query is null");
+			return -1;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_UPDATE_SYMBOL_ALL);
+		
+		/* symbolid parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "symbolid")) == NULL)
+		{
+			g_warning ("param isfilescope is NULL from pquery!");
+			return -1;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, symbol_id, ret_bool, ret_value);
+	}
+	
+	/* common params */
+
+	/* fileposition parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "fileposition")) == NULL)
+	{
+		g_warning ("param fileposition is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, file_position, ret_bool, ret_value);
+	
+	/* isfilescope parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "isfilescope")) == NULL)	
+	{
+		g_warning ("param isfilescope is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, is_file_scope, ret_bool, ret_value);
+	
+	/* signature parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "signature")) == NULL)	
+	{
+		g_warning ("param signature is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, signature, ret_bool, ret_value);
+	
+	/* scopedefinitionid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "scopedefinitionid")) == NULL)	
+	{
+		g_warning ("param scopedefinitionid is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, scope_definition_id, ret_bool, ret_value);
+	
+	/* scopeid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "scopeid")) == NULL)	
+	{
+		g_warning ("param scopeid is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, scope_id, ret_bool, ret_value);
+	
+	/* kindid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "kindid")) == NULL)	
+	{
+		g_warning ("param kindid is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, kind_id, ret_bool, ret_value);
+	
+	/* accesskindid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "accesskindid")) == NULL)	
+	{
+		g_warning ("param accesskindid is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, access_kind_id, ret_bool, ret_value);
+
+	/* implementationkindid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "implementationkindid")) == NULL)	
+	{
+		g_warning ("param implementationkindid is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, implementation_kind_id, ret_bool, ret_value);
+	
+	/* updateflag parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "updateflag")) == NULL)
+	{
+		g_warning ("param updateflag is NULL from pquery!");
+		return -1;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, update_flag, ret_bool, ret_value);
+	
+	/* execute the query with parametes just set */
+	gint nrows;
+	nrows = gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt, 
+													 (GdaSet*)plist, &last_inserted,
+													 NULL);
+	
+	if (sym_was_updated == FALSE)
+	{
+		if (nrows > 0)
+		{
+			const GValue *value = gda_set_get_holder_value (last_inserted, "+0");
+			table_id = g_value_get_int (value);			
+		
+			/* This is a wrong place to emit the symbol-updated signal. Infact
+		 	 * db is in a inconsistent state, e.g. inheritance references are still
+		 	 * *not* calculated.
+		 	 * So add the symbol id into a queue that will be parsed once and emitted.
+		 	 */		
+			g_async_queue_push (priv->inserted_symbols_id, GINT_TO_POINTER(table_id));			
+		}
+		else
+		{
+			table_id = -1;
+		}
+	}
+	else
+	{
+		if (nrows > 0)
+		{
+			table_id = symbol_id;
+						
+			g_async_queue_push (priv->updated_symbols_id, GINT_TO_POINTER(table_id));
+		}
+		else 
+		{
+			table_id = -1;
+		}
+	}
+
+	
+	/* before returning the table_id we have to fill some infoz on temporary tables
+	 * so that in a second pass we can parse also the heritage and scope fields.
+	 */
+	if (table_id > 0)
+		sdb_engine_add_new_tmp_heritage_scope (dbe, tag_entry, table_id);
+	
+	return table_id;
+}
+
+/**
+ * Select * from __tmp_removed and emits removed signals.
+ */
+static void
+sdb_engine_detects_removed_ids (SymbolDBEngine *dbe)
+{
+	const GdaStatement *stmt1, *stmt2;
+	GdaDataModel *data_model;
+	SymbolDBEnginePriv *priv;
+	gint i, num_rows;	
+		
+	priv = dbe->priv;
+	
+	/* ok, now we should read from __tmp_removed all the symbol ids which have
+	 * been removed, and emit a signal 
+	 */
+	if ((stmt1 = sdb_engine_get_statement_by_query_id (dbe,
+											 PREP_QUERY_GET_REMOVED_IDS))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return;
+	}
+
+	
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+												   (GdaStatement*)stmt1, 
+													NULL, NULL);
+
+	
+	if (GDA_IS_DATA_MODEL (data_model)) 
+	{
+		if ((num_rows = gda_data_model_get_n_rows (data_model)) <= 0)
+		{
+			DEBUG_PRINT ("%s", "sdb_engine_detects_removed_ids (): nothing to remove");
+			g_object_unref (data_model);
+			return;
+		}
+	}
+	else
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		return;
+	}
+
+	/* get and parse the results. */
+	for (i = 0; i < num_rows; i++) 
+	{
+		const GValue *val;
+		gint tmp;
+		val = gda_data_model_get_value_at (data_model, 0, i, NULL);
+		tmp = g_value_get_int (val);
+	
+		DEBUG_PRINT ("%s", "EMITTING symbol-removed");
+		g_async_queue_push (priv->signals_queue, GINT_TO_POINTER(SYMBOL_REMOVED + 1));
+		g_async_queue_push (priv->signals_queue, GINT_TO_POINTER(tmp));
+	}
+
+	g_object_unref (data_model);
+	
+	/* let's clean the tmp_table */
+	if ((stmt2 = sdb_engine_get_statement_by_query_id (dbe,
+											 PREP_QUERY_TMP_REMOVED_DELETE_ALL))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return;
+	}
+
+	/* bye bye */
+	gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt2, 
+													 NULL, NULL,
+													 NULL);
+}
+
+/**
+ * WARNING: do not use this function thinking that it would do a scan of symbols
+ * too. Use symbol_db_engine_update_files_symbols () instead. This one will set
+ * up some things on db, like removing the 'old' symbols which have not been 
+ * updated.
+ */
+static gboolean
+sdb_engine_update_file (SymbolDBEngine * dbe, const gchar * file_on_db)
+{
+	const GdaSet *plist1, *plist2, *plist3;
+	const GdaStatement *stmt1, *stmt2, *stmt3;
+	GdaHolder *param;
+	SymbolDBEnginePriv *priv;
+
+	priv = dbe->priv;
+
+	/* if we're updating symbols we must do some other operations on db 
+	 * symbols, like remove the ones which don't have an update_flag = 1 
+	 * per updated file.
+	 */
+
+	/* good. Go on with removing of old symbols, marked by a 
+	 * update_flag = 0. 
+	 */
+
+	/* Triggers will take care of updating/deleting connected symbols
+	 * tuples, like sym_kind, sym_type etc */
+	if ((stmt1 = sdb_engine_get_statement_by_query_id (dbe, 
+									PREP_QUERY_REMOVE_NON_UPDATED_SYMBOLS)) == NULL)
+	{
+		g_warning ("query is null");
+		return FALSE;
+	}
+
+	plist1 = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_REMOVE_NON_UPDATED_SYMBOLS);
+	
+	if ((param = gda_set_get_holder ((GdaSet*)plist1, "filepath")) == NULL)
+	{
+		g_warning ("param filepath is NULL from pquery!");
+		return FALSE;
+	}
+	gda_holder_set_value_str (param, NULL, file_on_db, NULL);
+	
+	gda_connection_statement_execute_non_select (priv->db_connection, (GdaStatement*)stmt1, 
+														 (GdaSet*)plist1, NULL, NULL);	
+
+	/* emits removed symbols signals */
+	sdb_engine_detects_removed_ids (dbe);
+
+	/* reset the update_flag to 0 */	
+	if ((stmt2 = sdb_engine_get_statement_by_query_id (dbe, 
+									PREP_QUERY_RESET_UPDATE_FLAG_SYMBOLS)) == NULL)
+	{
+		g_warning ("query is null");
+		return FALSE;
+	}
+	
+	plist2 = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_RESET_UPDATE_FLAG_SYMBOLS);
+	
+	if ((param = gda_set_get_holder ((GdaSet*)plist2, "filepath")) == NULL)
+	{
+		g_warning ("param filepath is NULL from pquery!");
+		return FALSE;
+	}
+	gda_holder_set_value_str (param, NULL, file_on_db, NULL);
+
+	
+	gda_connection_statement_execute_non_select (priv->db_connection, (GdaStatement*)stmt2, 
+														 (GdaSet*)plist2, NULL, NULL);	
+
+
+	/* last but not least, update the file analyse_time */
+	if ((stmt3 = sdb_engine_get_statement_by_query_id (dbe,
+											 PREP_QUERY_UPDATE_FILE_ANALYSE_TIME))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return FALSE;
+	}
+
+	plist3 = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_UPDATE_FILE_ANALYSE_TIME);
+	
+	/* filepath parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist3, "filepath")) == NULL)
+	{
+		g_warning ("param filepath is NULL from pquery!");
+		return FALSE;
+	}
+	gda_holder_set_value_str (param, NULL, file_on_db, NULL);
+
+	gda_connection_statement_execute_non_select (priv->db_connection, (GdaStatement*)stmt3, 
+														 (GdaSet*)plist3, NULL, NULL);	
+	return TRUE;
+}
+
+/**
+ * @param data is a GPtrArray *files_to_scan
+ * It will be freed when this callback will be called.
+ */
+static void
+on_scan_update_files_symbols_end (SymbolDBEngine * dbe, 
+								  gint process_id,
+								  UpdateFileSymbolsData* update_data)
+{
+	SymbolDBEnginePriv *priv;
+	GPtrArray *files_to_scan;
+	gint i;
+
+	DEBUG_PRINT ("%s", "on_scan_update_files_symbols_end  ();");
+
+	g_return_if_fail (dbe != NULL);
+	g_return_if_fail (update_data != NULL);
+	
+	priv = dbe->priv;
+	files_to_scan = update_data->files_path;
+	
+	sdb_engine_clear_caches (dbe);
+	
+	/* we need a reinitialization */
+	sdb_engine_init_caches (dbe);
+	
+	for (i = 0; i < files_to_scan->len; i++)
+	{
+		gchar *node = (gchar *) g_ptr_array_index (files_to_scan, i);
+		
+		if (strstr (node, priv->project_directory) == NULL) 
+		{
+			g_warning ("on_scan_update_files_symbols_end  node %s is shorter than "
+					   "prj_directory %s",
+					   node, priv->project_directory);
+			continue;
+		}
+		
+		/* clean the db from old un-updated with the last update step () */
+		if (sdb_engine_update_file (dbe, node + 
+									strlen (priv->project_directory)) == FALSE)
+		{
+			g_warning ("Error processing file %s", node + 
+					   strlen (priv->project_directory) );
+			return;
+		}
+		g_free (node);
+	}
+		
+	g_signal_handlers_disconnect_by_func (dbe, on_scan_update_files_symbols_end,
+										  update_data);
+
+	/* if true, we'll update the project scanning time too. 
+	 * warning: project time scanning won't could be set before files one.
+	 * This why we'll fork the process calling sdb_engine_scan_files ()
+	 */
+	if (update_data->update_prj_analyse_time == TRUE)
+	{
+		const GdaSet *plist;
+		const GdaStatement *stmt;
+		GdaHolder *param;
+
+		/* and the project analyse_time */
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe,
+									PREP_QUERY_UPDATE_PROJECT_ANALYSE_TIME))
+			== NULL)
+		{
+			g_warning ("query is null");
+			return;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_UPDATE_PROJECT_ANALYSE_TIME);
+			
+		/* prjname parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "prjname")) == NULL)
+		{
+			g_warning ("param prjname is NULL from pquery!");
+			return;
+		}
+		gda_holder_set_value_str (param, NULL, update_data->project, NULL);
+	
+		gda_connection_statement_execute_non_select (priv->db_connection, 
+													 (GdaStatement*)stmt, 
+													 (GdaSet*)plist, NULL, NULL);
+	}	
+	
+	/* free the GPtrArray. */
+	g_ptr_array_free (files_to_scan, TRUE);
+
+	g_free (update_data->project);
+	g_free (update_data);
+}
+
+const GHashTable*
+symbol_db_engine_get_sym_type_conversion_hash (SymbolDBEngine *dbe)
+{
+	SymbolDBEnginePriv *priv;
+	g_return_val_if_fail (dbe != NULL, NULL);
+	
+	priv = dbe->priv;
+		
+	return priv->sym_type_conversion_hash;
+}
+
+GPtrArray *
+symbol_db_engine_fill_type_array (IAnjutaSymbolType match_types)
+{
+	GPtrArray *filter_array;
+	filter_array = g_ptr_array_new ();
+
+	if (match_types & IANJUTA_SYMBOL_TYPE_CLASS)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("class"));
+	}
+
+	if (match_types & IANJUTA_SYMBOL_TYPE_ENUM)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("enum"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_ENUMERATOR)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("enumerator"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_FIELD)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("field"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_FUNCTION)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("function"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_INTERFACE)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("interface"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_MEMBER)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("member"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_METHOD)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("method"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_NAMESPACE)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("namespace"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_PACKAGE)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("package"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_PROTOTYPE)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("prototype"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_STRUCT)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("struct"));
+	}
+
+	if (match_types & IANJUTA_SYMBOL_TYPE_TYPEDEF)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("typedef"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_STRUCT)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("struct"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_UNION)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("union"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_VARIABLE)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("variable"));
+	}
+				
+	if (match_types & IANJUTA_SYMBOL_TYPE_EXTERNVAR)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("externvar"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_MACRO)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("macro"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("macro_with_arg"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_FILE)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("file"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_VARIABLE)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("variable"));
+	}
+	
+	if (match_types & IANJUTA_SYMBOL_TYPE_OTHER)
+	{
+		g_ptr_array_add (filter_array, g_strdup ("other"));
+	}
+
+	return filter_array;
+}
+
+gint
+symbol_db_engine_update_files_symbols (SymbolDBEngine * dbe, const gchar * project, 
+									   GPtrArray * files_path,
+									   gboolean update_prj_analyse_time)
+{
+	SymbolDBEnginePriv *priv;
+	UpdateFileSymbolsData *update_data;
+	gboolean ret_code;
+	gint ret_id;
+	
+	priv = dbe->priv;
+
+	g_return_val_if_fail (priv->db_connection != NULL, FALSE);
+	g_return_val_if_fail (project != NULL, FALSE);
+
+	update_data = g_new0 (UpdateFileSymbolsData, 1);
+	
+	update_data->update_prj_analyse_time = update_prj_analyse_time;
+	update_data->files_path = files_path;
+	update_data->project = g_strdup (project);
+	
+	/* data will be freed when callback will be called. The signal will be
+	 * disconnected too, don't worry about disconneting it by hand.
+	 */
+	g_signal_connect (G_OBJECT (dbe), "scan-end",
+					  G_CALLBACK (on_scan_update_files_symbols_end), update_data);
+	
+	ret_code = sdb_engine_scan_files_1 (dbe, files_path, NULL, TRUE);
+	if (ret_code == TRUE)
+		ret_id = sdb_engine_get_unique_scan_id (dbe);
+	else
+		ret_id = -1;
+	
+	return ret_id;
+}
+
+/* Update symbols of the whole project. It scans all file symbols etc. 
+ * FIXME: libgda does not support nested prepared queries like 
+ * PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME. When it will do please
+ * remember to update this function.
+ */
+gint
+symbol_db_engine_update_project_symbols (SymbolDBEngine *dbe, const gchar *project)
+{
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GValue *value;
+	GdaDataModel *data_model;
+	gint project_id;
+	gint num_rows = 0;
+	gint i;
+	GPtrArray *files_to_scan;
+	SymbolDBEnginePriv *priv;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	
+	priv = dbe->priv;
+	
+	g_return_val_if_fail (project != NULL, FALSE);
+	g_return_val_if_fail (priv->project_directory != NULL, FALSE);
+	
+
+	MP_LEND_OBJ_STR(priv, value);	
+	g_value_set_static_string (value, project);
+
+	/* get project id */
+	if ((project_id = sdb_engine_get_tuple_id_by_unique_name (dbe,
+									 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
+									 "prjname",
+									 value)) <= 0)
+	{
+		MP_RETURN_OBJ_STR(priv, value);
+		return FALSE;
+	}
+
+	MP_RETURN_OBJ_STR(priv, value);
+	
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe,
+								 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID))
+		== NULL)
+	{
+		g_warning ("query is null");
+		return FALSE;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, 
+								PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID);
+
+	/* prjid parameter */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "prjid")) == NULL)
+	{
+		g_warning ("param prjid is NULL from pquery!");
+		return FALSE;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, project_id, ret_bool, ret_value);	
+
+	/* execute the query with parametes just set */
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+												   (GdaStatement*)stmt, NULL, NULL);
+
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		(num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model))) <= 0)
+	{
+		DEBUG_PRINT ("no rows");
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		data_model = NULL;
+	}
+
+	/* initialize the array */
+	files_to_scan = g_ptr_array_new ();
+
+	/* we can now scan each filename entry to check the last modification time. */
+	for (i = 0; i < num_rows; i++)
+	{
+		const GValue *value, *value1;
+		const gchar *file_name;
+		gchar *file_abs_path = NULL;
+		struct tm filetm;
+		time_t db_file_time;
+		gchar *date_string;
+		GFile *gfile;
+		GFileInfo* gfile_info;
+		GFileInputStream* gfile_is;
+
+		if ((value =
+			 gda_data_model_get_value_at (data_model, 
+						gda_data_model_get_column_index(data_model,
+												   "db_file_path"), 
+										  i, NULL)) == NULL)
+		{
+			continue;
+		}
+
+		/* build abs path. */
+		file_name = g_value_get_string (value);
+		if (priv->project_directory != NULL)
+		{
+			file_abs_path = g_strdup_printf ("%s%s", priv->project_directory,
+										file_name);
+		}
+
+		gfile = g_file_new_for_path (file_abs_path);
+		if (gfile == NULL)
+			continue;
+		
+		gfile_is = g_file_read (gfile, NULL, NULL);
+		/* retrieve data/time info */
+		if (gfile_is == NULL)
+		{
+			g_message ("could not open path %s", file_abs_path);
+			g_free (file_abs_path);
+			g_object_unref (gfile);
+			continue;
+		}
+		g_object_unref (gfile_is);
+				
+		gfile_info = g_file_query_info (gfile, "*", G_FILE_QUERY_INFO_NONE,
+										NULL, NULL);
+
+		if (gfile_info == NULL)
+		{
+			g_message ("cannot get file info from handle");
+			g_free (file_abs_path);
+			g_object_unref (gfile);
+			continue;
+		}
+
+		if ((value1 = gda_data_model_get_value_at (data_model, 
+						gda_data_model_get_column_index(data_model,
+												   "analyse_time"), i, NULL)) == NULL)
+		{
+			continue;
+		}
+
+		/* weirdly we have a strange libgda behaviour here too. 
+		 * as from ChangeLog GDA_TYPE_TIMESTAMP as SQLite does not impose a 
+		 * known format for dates (there is no date datatype).
+		 * We have then to do some hackery to retrieve the date.        
+		 */
+		date_string = (gchar *) g_value_get_string (value1);	
+	
+		/* fill a struct tm with the date retrieved by the string. */
+		/* string is something like '2007-04-18 23:51:39' */
+		memset (&filetm, 0, sizeof (struct tm));
+		filetm.tm_year = atoi (date_string) - 1900;
+		date_string += 5;
+		filetm.tm_mon = atoi (date_string) - 1;
+		date_string += 3;
+		filetm.tm_mday = atoi (date_string);
+		date_string += 3;
+		filetm.tm_hour = atoi (date_string);
+		date_string += 3;
+		filetm.tm_min = atoi (date_string);
+		date_string += 3;
+		filetm.tm_sec = atoi (date_string);
+		
+		/* subtract one hour to the db_file_time. */
+		db_file_time = mktime (&filetm) /*- 3600*/;
+
+		
+		if (difftime (db_file_time, g_file_info_get_attribute_uint32 (gfile_info, 
+										  G_FILE_ATTRIBUTE_TIME_MODIFIED)) < 0)
+		{
+			g_ptr_array_add (files_to_scan, file_abs_path);
+		}
+		
+		g_object_unref (gfile_info);
+		g_object_unref (gfile);
+		/* no need to free file_abs_path, it's been added to files_to_scan */
+	}
+	
+	if (data_model)
+		g_object_unref (data_model);
+	
+	if (files_to_scan->len > 0)
+	{
+		/* at the end let the scanning function do its job */
+		return symbol_db_engine_update_files_symbols (dbe, project,
+											   files_to_scan, TRUE);
+	}
+	return -1;
+}
+
+gboolean
+symbol_db_engine_remove_file (SymbolDBEngine * dbe, const gchar * project,
+							  const gchar * file)
+{
+	gchar *query_str;
+	SymbolDBEnginePriv *priv;	
+	
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	g_return_val_if_fail (project != NULL, FALSE);
+	g_return_val_if_fail (file != NULL, FALSE);
+	priv = dbe->priv;
+	
+	if (strlen (file) < strlen (priv->project_directory)) 
+	{
+		g_warning ("wrong file to delete.");
+		return FALSE;
+	}
+	
+	DEBUG_PRINT ("deleting %s", file);
+	
+	/* Triggers will take care of updating/deleting connected symbols
+	 * tuples, like sym_kind, sym_type etc */
+	query_str = g_strdup_printf ("DELETE FROM file WHERE prj_id "
+				 "= (SELECT project_id FROM project WHERE project_name = '%s') AND "
+				 "file_path = '%s'", project, file + strlen (priv->project_directory));
+
+	sdb_engine_execute_non_select_sql (dbe, query_str);
+	g_free (query_str);
+	
+	/* emits removed symbols signals */
+	sdb_engine_detects_removed_ids (dbe);
+	return TRUE;
+}
+
+void
+symbol_db_engine_remove_files (SymbolDBEngine * dbe, const gchar * project,
+							  const GPtrArray * files)
+{
+	SymbolDBEnginePriv *priv;	
+	gint i;
+	
+	g_return_if_fail (dbe != NULL);
+	g_return_if_fail (project != NULL);
+	g_return_if_fail (files != NULL);
+	priv = dbe->priv;
+
+	for (i = 0; i < files->len; i++)
+	{
+		symbol_db_engine_remove_file (dbe, project, g_ptr_array_index (files, i));
+	}	
+}
+
+static void
+on_scan_update_buffer_end (SymbolDBEngine * dbe, gint process_id, gpointer data)
+{
+	SymbolDBEnginePriv *priv;
+	GPtrArray *files_to_scan;
+	gint i;
+
+	g_return_if_fail (dbe != NULL);
+	g_return_if_fail (data != NULL);
+
+	priv = dbe->priv;
+	files_to_scan = (GPtrArray *) data;
+
+	for (i = 0; i < files_to_scan->len; i++)
+	{
+		gchar *node = (gchar *) g_ptr_array_index (files_to_scan, i);
+		gchar *relative_path = symbol_db_engine_get_file_db_path (dbe, node);
+		if (relative_path != NULL)
+		{
+			/* will be emitted removed signals */
+			if (sdb_engine_update_file (dbe, relative_path) == FALSE)
+			{
+				g_warning ("Error processing file %s", node);
+				g_free (relative_path);
+				return;
+			}
+			g_free (relative_path);
+		}
+		g_free (node);
+	}
+		
+	g_signal_handlers_disconnect_by_func (dbe, on_scan_update_buffer_end,
+										  files_to_scan);
+
+	/* free the GPtrArray. */
+	g_ptr_array_free (files_to_scan, TRUE);
+	data = files_to_scan = NULL;
+}
+
+gint
+symbol_db_engine_update_buffer_symbols (SymbolDBEngine * dbe, const gchar *project,
+										GPtrArray * real_files_list,
+										const GPtrArray * text_buffers,
+										const GPtrArray * buffer_sizes)
+{
+	SymbolDBEnginePriv *priv;
+	gint i;
+	gint ret_id;
+	gboolean ret_code;
+	/* array that'll represent the /dev/shm/anjuta-XYZ files */
+	GPtrArray *temp_files;
+	GPtrArray *real_files_on_db;
+	
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	priv = dbe->priv;
+	
+	g_return_val_if_fail (priv->db_connection != NULL, FALSE);
+	g_return_val_if_fail (project != NULL, FALSE);
+	g_return_val_if_fail (real_files_list != NULL, FALSE);
+	g_return_val_if_fail (text_buffers != NULL, FALSE);
+	g_return_val_if_fail (buffer_sizes != NULL, FALSE);
+	
+	DEBUG_PRINT ("%s", "symbol_db_engine_update_buffer_symbols ()");
+
+	temp_files = g_ptr_array_new();	
+	real_files_on_db = g_ptr_array_new();
+	
+	/* obtain a GPtrArray with real_files on database */
+	for (i=0; i < real_files_list->len; i++) 
+	{
+		gchar *relative_path = symbol_db_engine_get_file_db_path (dbe, 
+									g_ptr_array_index (real_files_list, i));
+		if (relative_path == NULL)
+		{
+			g_warning ("symbol_db_engine_update_buffer_symbols  (): "
+					   "relative_path is NULL");
+			return FALSE;
+		}
+		g_ptr_array_add (real_files_on_db, relative_path);
+	}	
+	
+	/* create a temporary file for each buffer */
+	for (i=0; i < real_files_list->len; i++) 
+	{
+		FILE *buffer_mem_file;
+		const gchar *temp_buffer;
+		gint buffer_mem_fd;
+		gint temp_size;
+		gchar *shared_temp_file;
+		gchar *base_filename;
+		const gchar *curr_real_file;
+				
+		curr_real_file = g_ptr_array_index (real_files_list, i);
+		
+		/* it's ok to have just the base filename to create the
+		 * target buffer one */
+		base_filename = g_filename_display_basename (curr_real_file);
+		
+		shared_temp_file = g_strdup_printf ("/anjuta-%d-%ld-%s", getpid (),
+						 time (NULL), base_filename);
+		g_free (base_filename);
+		
+		if ((buffer_mem_fd = 
+			 shm_open (shared_temp_file, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0)
+		{
+			g_warning ("Error while trying to open a shared memory file. Be"
+					   "sure to have "SHARED_MEMORY_PREFIX" mounted with tmpfs");
+			return FALSE;
+		}
+	
+		buffer_mem_file = fdopen (buffer_mem_fd, "w+b");
+		
+		temp_buffer = g_ptr_array_index (text_buffers, i);
+		temp_size = GPOINTER_TO_INT(g_ptr_array_index (buffer_sizes, i));
+		
+		fwrite (temp_buffer, sizeof(gchar), temp_size, buffer_mem_file);
+		fflush (buffer_mem_file);
+		fclose (buffer_mem_file);
+		
+		/* add the temp file to the array. */
+		g_ptr_array_add (temp_files, g_strdup_printf (SHARED_MEMORY_PREFIX"%s", 
+													  shared_temp_file));
+		
+		/* check if we already have an entry stored in the hash table, else
+		 * insert it 
+		 */		
+		if (g_hash_table_lookup (priv->garbage_shared_mem_files, shared_temp_file) 
+			== NULL)
+		{
+			DEBUG_PRINT ("inserting into garbage hash table %s", shared_temp_file);
+			g_hash_table_insert (priv->garbage_shared_mem_files, shared_temp_file, 
+								 NULL);
+		}
+		else 
+		{
+			/* the item is already stored. Just free it here. */
+			g_free (shared_temp_file);
+		}
+	}
+	
+	/* data will be freed when callback will be called. The signal will be
+	 * disconnected too, don't worry about disconnecting it by hand.
+	 */
+	g_signal_connect (G_OBJECT (dbe), "scan-end",
+					  G_CALLBACK (on_scan_update_buffer_end), real_files_list);
+	
+	ret_code = sdb_engine_scan_files_1 (dbe, temp_files, real_files_on_db, TRUE);
+	if (ret_code == TRUE)
+		ret_id = sdb_engine_get_unique_scan_id (dbe);
+	else
+		ret_id = -1;
+	
+	/* let's free the temp_files array */
+	for (i=0; i < temp_files->len; i++)
+		g_free (g_ptr_array_index (temp_files, i));
+	
+	g_ptr_array_free (temp_files, TRUE);
+	
+	/* and the real_files_on_db too */
+	for (i=0; i < real_files_on_db->len; i++)
+		g_free (g_ptr_array_index (real_files_on_db, i));
+	
+	g_ptr_array_free (real_files_on_db, TRUE);
+	return ret_id;
+}
+

Added: trunk/plugins/symbol-db/symbol-db-engine-core.h
==============================================================================
--- (empty file)
+++ trunk/plugins/symbol-db/symbol-db-engine-core.h	Sat Dec 20 17:44:46 2008
@@ -0,0 +1,248 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2007-2008 <maxcvs email it>
+ * 
+ * anjuta is free software.
+ * 
+ * You may 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 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 anjuta.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _SYMBOL_DB_ENGINE_CORE_H_
+#define _SYMBOL_DB_ENGINE_CORE_H_
+
+#include <glib-object.h>
+#include <glib.h>
+#include <libanjuta/interfaces/ianjuta-symbol.h>
+#include <libanjuta/anjuta-plugin.h>
+#include "symbol-db-engine-iterator.h"
+
+G_BEGIN_DECLS
+
+#define SYMBOL_TYPE_DB_ENGINE             (sdb_engine_get_type ())
+#define SYMBOL_DB_ENGINE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), SYMBOL_TYPE_DB_ENGINE, SymbolDBEngine))
+#define SYMBOL_DB_ENGINE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SYMBOL_TYPE_DB_ENGINE, SymbolDBEngineClass))
+#define SYMBOL_IS_DB_ENGINE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SYMBOL_TYPE_DB_ENGINE))
+#define SYMBOL_IS_DB_ENGINE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SYMBOL_TYPE_DB_ENGINE))
+#define SYMBOL_DB_ENGINE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SYMBOL_TYPE_DB_ENGINE, SymbolDBEngineClass))
+
+typedef struct _SymbolDBEngineClass SymbolDBEngineClass;
+typedef struct _SymbolDBEngine SymbolDBEngine;
+typedef struct _SymbolDBEnginePriv SymbolDBEnginePriv;
+
+struct _SymbolDBEngineClass
+{
+	GObjectClass parent_class;
+	
+	/* signals */
+	void (* single_file_scan_end) 	();
+	void (* scan_end) 				(gint process_id);
+	void (* symbol_inserted) 		(gint symbol_id);
+	void (* symbol_updated)  		(gint symbol_id);
+	void (* symbol_scope_updated)  	(gint symbol_id);	
+	void (* symbol_removed)  		(gint symbol_id);
+};
+
+struct _SymbolDBEngine
+{
+	GObject parent_instance;
+	SymbolDBEnginePriv *priv;
+};
+
+/* WARNING: these must match the ones on libanjuta.idl [AnjutaSymbol::Field] */
+typedef enum {
+	SYMINFO_SIMPLE = 1,
+	SYMINFO_FILE_PATH = 2,
+	SYMINFO_IMPLEMENTATION = 4,
+	SYMINFO_ACCESS = 8,
+	SYMINFO_KIND = 16,
+	SYMINFO_TYPE = 32,
+	SYMINFO_TYPE_NAME = 64,
+	SYMINFO_LANGUAGE = 128,
+	SYMINFO_FILE_IGNORE = 256,
+	SYMINFO_FILE_INCLUDE = 512,
+	SYMINFO_PROJECT_NAME = 1024,
+	SYMINFO_WORKSPACE_NAME = 2048
+	
+} SymExtraInfo;
+
+GType sdb_engine_get_type (void) G_GNUC_CONST;
+
+
+/**
+ * Create a new instance of an engine. 
+ * @param ctags_path is mandatory. No NULL value is accepted.
+ */
+SymbolDBEngine* 
+symbol_db_engine_new (const gchar * ctags_path);
+
+/**
+ * Set a new path for ctags executable.
+ */ 
+void 
+symbol_db_engine_set_ctags_path (SymbolDBEngine *dbe,
+								  const gchar * ctags_path);
+
+/**
+ * Be sure to check lock status with this function before calling
+ * something else below. If you call a scanning function while
+ * dbe is locked there can be some weird behaviours.
+ */
+gboolean
+symbol_db_engine_is_locked (SymbolDBEngine *dbe);
+
+/**
+ * Open or create a new database at given directory. 
+ * Be sure to give a base_db_path with the ending '/' for directory.
+ * @param base_db_path directory where .anjuta_sym_db.db will be stored. It can be
+ *        different from project_directory
+ *        E.g: a db on '/tmp/foo/' dir.
+ * @param prj_directory project directory. It may be different from base_db_path.
+ *        It's mainly used to map files inside the db. Say for example that you want to
+ *        add to a project a file /home/user/project/foo_prj/src/file.c with a project
+ *        directory of /home/user/project/foo_prj/. On db it'll be represented as
+ *        src/file.c. In this way you can move around the project dir without dealing
+ *        with relative paths.
+ */
+gboolean 
+symbol_db_engine_open_db (SymbolDBEngine *dbe, const gchar* base_db_path,
+						  const gchar * prj_directory);
+
+/** Disconnect db, gda client and db_connection */
+gboolean 
+symbol_db_engine_close_db (SymbolDBEngine *dbe);
+
+/**
+ * Check if the database already exists into the prj_directory
+ */
+gboolean
+symbol_db_engine_db_exists (SymbolDBEngine * dbe, const gchar * prj_directory);
+
+/**
+ * Check if a file is already present [and scanned] in db.
+ */
+gboolean
+symbol_db_engine_file_exists (SymbolDBEngine * dbe, const gchar * abs_file_path);
+
+/** Add a new workspace to an opened database. */
+gboolean 
+symbol_db_engine_add_new_workspace (SymbolDBEngine *dbe, const gchar* workspace);
+
+
+/** 
+ * Add a new project to workspace to an opened database.
+ *
+ * @param workspace Can be NULL. In that case a default workspace will be created, 
+ * 					and project will depend on that.
+ * @param project Project name. Must NOT be NULL.
+ */
+gboolean 
+symbol_db_engine_add_new_project (SymbolDBEngine *dbe, const gchar* workspace, 
+								  const gchar* project);
+
+/** 
+ * Test project existence. 
+ * @return false if project isn't found
+ */
+gboolean 
+symbol_db_engine_project_exists (SymbolDBEngine *dbe, /*gchar* workspace, */
+								  const gchar* project_name);
+
+
+/** 
+ * Add a group of files of a single language to a project. It will perform also 
+ * a symbols scannig/populating of db if scan_symbols is TRUE.
+ * This function requires an opened db, i.e. calling before
+ * symbol_db_engine_open_db ().
+ * @note if some file fails to enter the db the function will return without
+ * processing the remaining files.
+ * @param project_name something like 'foo_project', or 'helloworld_project'. Can be NULL,
+ *        for example when you're populating after abort.
+ * @param project_directory something like the base path '/home/user/projects/foo_project/'
+ *        Be sure not to exchange the db_directory with project_directory! they're different!
+ *        It can be NULL but ONLY if you're doing an 'import_after_abort' scan, i.e.
+ *        files entries have already a connection with the parent project.
+ * @param files_path requires full path to files on disk. Ctags itself requires that.
+ *        it must be something like "/home/path/to/my/foo/file.xyz". Also it requires
+ *		  a language string to represent the file.
+ *        An example of files_path array composition can be: 
+ *        "/home/user/foo_project/foo1.c", "/home/user/foo_project/foo2.cpp", 
+ * 		  "/home/user/foo_project/foo3.java".
+ * @param languages is an array of 'languages'. It must have the same number of 
+ *		  elments that files_path has. It should be populated like this: "C", "C++",
+ *		  "Java"
+ * 		  This is done to be uniform to the language-manager plugin.
+ * @param force_scan If FALSE a check on db will be done to see
+ *		  whether the file is already present or not.
+ * @return scan process id if insertion is successful, -1 on error.
+ */
+gint
+symbol_db_engine_add_new_files (SymbolDBEngine *dbe, 
+								const gchar * project_name,
+							    const GPtrArray *files_path,
+								const GPtrArray *languages,
+								gboolean force_scan);
+
+/**
+ * Update symbols of the whole project. It scans all file symbols etc. 
+ * If force is true then update forcely all the files.
+ */
+gint
+symbol_db_engine_update_project_symbols (SymbolDBEngine *dbe, const gchar *project);
+
+
+/** Remove a file, together with its symbols, from a project. */
+gboolean 
+symbol_db_engine_remove_file (SymbolDBEngine *dbe, const gchar* project, 
+							  const gchar* file);
+
+void
+symbol_db_engine_remove_files (SymbolDBEngine * dbe, const gchar * project,
+							  const GPtrArray * files);
+
+/**
+ * Update symbols of saved files. 
+ * @note WARNING: files_path and it's contents will be freed on 
+ * on_scan_update_files_symbols_end () callback.
+ * @return scan process id if insertion is successful, -1 on 'no files scanned'.
+ */
+gint
+symbol_db_engine_update_files_symbols (SymbolDBEngine *dbe, const gchar *project, 
+									   GPtrArray *files_path,
+									   gboolean update_prj_analyse_time);
+
+/**
+ * Update symbols of a file by a memory-buffer to perform a real-time updating 
+ * of symbols. 
+ * real_files_list: full path on disk to 'real file' to update. e.g.
+ * /home/foouser/fooproject/src/main.c. 
+ * They'll be freed inside this function when the scan has ended. 
+ * @return scan process id if insertion is successful, -1 on error.
+ */
+gint
+symbol_db_engine_update_buffer_symbols (SymbolDBEngine * dbe, const gchar * project,
+										GPtrArray * real_files_list,
+										const GPtrArray * text_buffers,
+										const GPtrArray * buffer_sizes);
+
+
+
+
+G_END_DECLS
+
+#endif /* _SYMBOL_DB_ENGINE_H_ */
+

Added: trunk/plugins/symbol-db/symbol-db-engine-queries.c
==============================================================================
--- (empty file)
+++ trunk/plugins/symbol-db/symbol-db-engine-queries.c	Sat Dec 20 17:44:46 2008
@@ -0,0 +1,2619 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2007-2008 <maxcvs email it>
+ * 
+ * anjuta is free software.
+ * 
+ * You may 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 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 anjuta.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#include <libanjuta/anjuta-debug.h>
+
+#include "symbol-db-engine-queries.h"
+#include "symbol-db-engine-priv.h"
+
+
+/*
+ * extern declarations 
+ */
+
+extern inline const GdaStatement *
+sdb_engine_get_statement_by_query_id (SymbolDBEngine * dbe, static_query_type query_id);
+
+extern inline const GdaSet *
+sdb_engine_get_query_parameters_list (SymbolDBEngine *dbe, static_query_type query_id);
+
+extern inline const DynChildQueryNode *
+sdb_engine_get_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 SymExtraInfo sym_info, gsize other_parameters);
+
+extern inline const DynChildQueryNode *
+sdb_engine_insert_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 	SymExtraInfo sym_info, gsize other_parameters,
+										const gchar *sql);
+
+/*
+ * implementation starts here 
+ */
+
+static inline gint
+sdb_engine_walk_down_scope_path (SymbolDBEngine *dbe, const GPtrArray* scope_path) 
+{
+	SymbolDBEnginePriv *priv;
+	gint final_definition_id;
+	gint scope_path_len;
+	gint i;
+	GdaDataModel *data;
+	const GdaSet *plist;
+	const GdaStatement *stmt;
+	GdaHolder *param;
+	GValue *ret_value;
+	gboolean ret_bool;	
+	
+		
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	priv = dbe->priv;
+	
+	scope_path_len = scope_path->len;
+	
+	/* we'll return if the length is even or minor than 3 */
+	if (scope_path_len < 3 || scope_path_len % 2 == 0)
+	{
+		g_warning ("bad scope_path.");
+		return -1;
+	}
+	
+	if ((stmt =
+		 sdb_engine_get_statement_by_query_id (dbe, 
+			PREP_QUERY_GET_SCOPE_DEFINITION_ID_BY_WALK_DOWN_SCOPE_PATH)) == NULL)
+	{
+		g_warning ("query is null"); 
+		return -1;
+	}
+
+	plist = sdb_engine_get_query_parameters_list (dbe, 
+			PREP_QUERY_GET_SCOPE_DEFINITION_ID_BY_WALK_DOWN_SCOPE_PATH);	
+	final_definition_id = 0;
+	for (i=0; i < scope_path_len -1; i = i + 2)
+	{
+		const GValue *value;
+
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "symtype")) == NULL)
+		{
+			return -1;
+		}
+		
+		MP_SET_HOLDER_BATCH_STR(priv, param, (gchar*)g_ptr_array_index (scope_path, i), 
+								ret_bool, ret_value);
+		
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "scopename")) == NULL)
+		{
+			return -1;
+		}
+
+		MP_SET_HOLDER_BATCH_STR(priv, param, (gchar*)g_ptr_array_index (scope_path, i + 1), 
+								ret_bool, ret_value);		
+		
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "scopeid")) == NULL)
+		{
+			return -1;
+		}
+		
+		MP_SET_HOLDER_BATCH_INT(priv, param, final_definition_id, ret_bool, ret_value);
+
+		data = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  (GdaSet*)plist, NULL);
+	
+		if (!GDA_IS_DATA_MODEL (data) ||
+			gda_data_model_get_n_rows (GDA_DATA_MODEL (data)) <= 0)
+		{
+			if (data != NULL)
+				g_object_unref (data);
+			return -1;
+		}
+		
+		value = gda_data_model_get_value_at (data, 0, 0, NULL);
+		if (G_VALUE_HOLDS (value, G_TYPE_INT))
+		{
+			final_definition_id = g_value_get_int (value);
+			g_object_unref (data);
+		}
+		else
+		{
+			/* something went wrong. Our symbol cannot be retrieved coz of a
+			 * bad scope path.
+			 */
+			final_definition_id = -1;
+			break;
+		}
+	}	
+	
+	return final_definition_id;
+}
+
+static inline void
+sdb_engine_prepare_file_info_sql (SymbolDBEngine *dbe, GString *info_data,
+									GString *join_data, SymExtraInfo sym_info) 
+{
+	if (sym_info & SYMINFO_FILE_PATH 	|| 
+		sym_info & SYMINFO_LANGUAGE  	||
+		sym_info & SYMINFO_PROJECT_NAME ||
+		sym_info & SYMINFO_FILE_IGNORE  ||
+		sym_info & SYMINFO_FILE_INCLUDE) 
+	{
+		info_data = g_string_append (info_data, ",file.file_path AS db_file_path ");
+		join_data = g_string_append (join_data, "LEFT JOIN file ON "
+				"symbol.file_defined_id = file.file_id ");
+	}
+
+	if (sym_info & SYMINFO_LANGUAGE)
+	{
+		info_data = g_string_append (info_data, ",language.language_name "
+									 "AS language_name ");
+		join_data = g_string_append (join_data, "LEFT JOIN language ON "
+				"file.lang_id = language.language_id ");
+	}
+	
+	if (sym_info & SYMINFO_PROJECT_NAME ||
+		sym_info & SYMINFO_FILE_IGNORE  ||
+		sym_info & SYMINFO_FILE_INCLUDE)
+	{
+		info_data = g_string_append (info_data, ",project.project_name AS project_name ");
+		join_data = g_string_append (join_data, "LEFT JOIN project ON "
+				"file.prj_id = project.project_id ");
+	}	
+
+	if (sym_info & SYMINFO_FILE_IGNORE)
+	{
+		info_data = g_string_append (info_data, ",file_ignore.file_ignore_type "
+									 "AS ignore_type ");
+		join_data = g_string_append (join_data, "LEFT JOIN ext_ignore ON "
+				"ext_ignore.prj_id = project.project_id "
+				"LEFT JOIN file_ignore ON "
+				"ext_ignore.file_ign_id = file_ignore.file_ignore_id ");
+	}
+
+	if (sym_info & SYMINFO_FILE_INCLUDE)
+	{
+		info_data = g_string_append (info_data, ",file_include.file_include_type "
+									 "AS file_include_type ");
+		join_data = g_string_append (join_data, "LEFT JOIN ext_include ON "
+				"ext_include.prj_id = project.project_id "
+				"LEFT JOIN file_include ON "
+				"ext_include.file_incl_id = file_include.file_include_id ");
+	}	
+}
+
+static inline void
+sdb_engine_prepare_symbol_info_sql (SymbolDBEngine *dbe, GString *info_data,
+									GString *join_data, SymExtraInfo sym_info) 
+{
+	if (sym_info & SYMINFO_FILE_PATH 	|| 
+		sym_info & SYMINFO_LANGUAGE  	||
+		sym_info & SYMINFO_PROJECT_NAME ||
+		sym_info & SYMINFO_FILE_IGNORE  ||
+		sym_info & SYMINFO_FILE_INCLUDE) 
+	{
+		info_data = g_string_append (info_data, ",file.file_path AS db_file_path ");
+		join_data = g_string_append (join_data, "LEFT JOIN file ON "
+				"symbol.file_defined_id = file.file_id ");
+	}
+
+	if (sym_info & SYMINFO_LANGUAGE)
+	{
+		info_data = g_string_append (info_data, ",language.language_name "
+									 "AS language_name ");
+		join_data = g_string_append (join_data, "LEFT JOIN language ON "
+				"file.lang_id = language.language_id ");
+	}
+	
+	if (sym_info & SYMINFO_IMPLEMENTATION)
+	{
+		info_data = g_string_append (info_data, ",sym_implementation.implementation_name "
+									 "AS implementation_name " );
+		join_data = g_string_append (join_data, "LEFT JOIN sym_implementation ON "
+				"symbol.implementation_kind_id = sym_implementation.sym_impl_id ");
+	}
+	
+	if (sym_info & SYMINFO_ACCESS)
+	{
+		info_data = g_string_append (info_data, ",sym_access.access_name AS access_name ");
+		join_data = g_string_append (join_data, "LEFT JOIN sym_access ON "
+				"symbol.access_kind_id = sym_access.access_kind_id ");
+	}
+	
+	if (sym_info & SYMINFO_KIND)
+	{
+		info_data = g_string_append (info_data, ",sym_kind.kind_name AS kind_name");
+		join_data = g_string_append (join_data, "LEFT JOIN sym_kind ON "
+				"symbol.kind_id = sym_kind.sym_kind_id ");
+	}
+	
+	if (sym_info & SYMINFO_TYPE || sym_info & SYMINFO_TYPE_NAME)
+	{
+		info_data = g_string_append (info_data, ",sym_type.type_type AS type_type, "
+									 "sym_type.type_name AS type_name");
+		join_data = g_string_append (join_data, "LEFT JOIN sym_type ON "
+				"symbol.type_id = sym_type.type_id ");
+	}
+
+	if (sym_info & SYMINFO_PROJECT_NAME ||
+		sym_info & SYMINFO_FILE_IGNORE  ||
+		sym_info & SYMINFO_FILE_INCLUDE)
+	{
+		info_data = g_string_append (info_data, ",project.project_name AS project_name ");
+		join_data = g_string_append (join_data, "LEFT JOIN project ON "
+				"file.prj_id = project.project_id ");
+	}	
+
+	if (sym_info & SYMINFO_FILE_IGNORE)
+	{
+		info_data = g_string_append (info_data, ",file_ignore.file_ignore_type "
+									 "AS ignore_type ");
+		join_data = g_string_append (join_data, "LEFT JOIN ext_ignore ON "
+				"ext_ignore.prj_id = project.project_id "
+				"LEFT JOIN file_ignore ON "
+				"ext_ignore.file_ign_id = file_ignore.file_ignore_id ");
+	}
+
+	if (sym_info & SYMINFO_FILE_INCLUDE)
+	{
+		info_data = g_string_append (info_data, ",file_include.file_include_type "
+									 "AS file_include_type ");
+		join_data = g_string_append (join_data, "LEFT JOIN ext_include ON "
+				"ext_include.prj_id = project.project_id "
+				"LEFT JOIN file_include ON "
+				"ext_include.file_incl_id = file_include.file_include_id ");
+	}
+}
+
+
+/**
+ * Same behaviour as symbol_db_engine_get_class_parents () but this is quicker because
+ * of the child_klass_symbol_id, aka the derived class symbol_id.
+ * Return an iterator (eventually) containing the base classes or NULL if error occurred.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_class_parents_by_symbol_id (SymbolDBEngine *dbe, 
+												 gint child_klass_symbol_id,
+												 SymExtraInfo sym_info)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *query_str;
+	GdaDataModel *data;
+	GdaHolder *param;
+	GString *info_data;
+	GString *join_data;
+	GValue *ret_value;
+	gboolean ret_bool;
+	const DynChildQueryNode *dyn_node;
+	
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+					DYN_PREP_QUERY_GET_CLASS_PARENTS_BY_SYMBOL_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 "
+				"%s FROM heritage "
+				"JOIN symbol ON heritage.symbol_id_base = symbol.symbol_id %s "
+				"WHERE heritage.symbol_id_derived = ## /* name:'childklassid' type:gint */", 
+						info_data->str, join_data->str);
+	
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_GET_CLASS_PARENTS_BY_SYMBOL_ID,
+						sym_info, 0,
+						query_str);
+		
+		g_free (query_str);
+		g_string_free (info_data, TRUE);
+		g_string_free (join_data, TRUE);
+	}
+
+	if (dyn_node == NULL) 
+	{		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	/*DEBUG_PRINT ("symbol_db_engine_get_class_parents_by_symbol_id () query_str is: %s",
+					dyn_node->query_str);*/
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "childklassid")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, child_klass_symbol_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);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/** 
+ * Returns an iterator to the data retrieved from database. 
+ * The iterator, if not null, will contain a list of parent classes for the given 
+ * symbol name.
+ * scope_path can be NULL.
+ */
+#define DYN_GET_CLASS_PARENTS_EXTRA_PAR_FINAL_DEF_ZERO		1
+#define DYN_GET_CLASS_PARENTS_EXTRA_PAR_FINAL_DEF_POSITIVE	2
+
+SymbolDBEngineIterator *
+symbol_db_engine_get_class_parents (SymbolDBEngine *dbe, const gchar *klass_name, 
+									 const GPtrArray *scope_path, SymExtraInfo sym_info)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *query_str;
+	GdaDataModel *data;
+	GdaHolder *param;
+	GString *info_data;
+	GString *join_data;
+	gint final_definition_id;
+	const DynChildQueryNode *dyn_node;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	priv = dbe->priv;
+	
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	
+	final_definition_id = -1;
+	if (scope_path != NULL)	
+		final_definition_id = sdb_engine_walk_down_scope_path (dbe, scope_path);
+
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+					DYN_PREP_QUERY_GET_CLASS_PARENTS, sym_info, 
+					final_definition_id > 0 ? 
+					DYN_GET_CLASS_PARENTS_EXTRA_PAR_FINAL_DEF_POSITIVE :
+					DYN_GET_CLASS_PARENTS_EXTRA_PAR_FINAL_DEF_ZERO)) == NULL)
+	{
+		
+		/* info_data contains the stuff after SELECT and before 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);
+	
+		if (final_definition_id > 0)
+		{		
+			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 "
+				"%s FROM heritage "
+				"JOIN symbol ON heritage.symbol_id_base = symbol.symbol_id %s "
+				"WHERE symbol_id_derived = ("
+					"SELECT symbol_id FROM symbol "
+						"JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
+						"WHERE symbol.name = ## /* name:'klassname' type:gchararray */ "
+							"AND sym_kind.kind_name = 'class' "
+							"AND symbol.scope_id = ## /* name:'defid' type:gint */"
+					")", info_data->str, join_data->str);
+			
+			dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+							DYN_PREP_QUERY_GET_CLASS_PARENTS,
+							sym_info, DYN_GET_CLASS_PARENTS_EXTRA_PAR_FINAL_DEF_POSITIVE,
+							query_str);
+		}
+		else 
+		{
+			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 %s FROM heritage "
+				"JOIN symbol ON heritage.symbol_id_base = symbol.symbol_id %s "
+				"WHERE symbol_id_derived = ("
+					"SELECT symbol_id FROM symbol "
+						"JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
+						"WHERE symbol.name = ## /* name:'klassname' type:gchararray */ "
+							"AND sym_kind.kind_name = 'class' "
+					")", info_data->str, join_data->str);
+			
+			dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+							DYN_PREP_QUERY_GET_CLASS_PARENTS,
+							sym_info, DYN_GET_CLASS_PARENTS_EXTRA_PAR_FINAL_DEF_ZERO,
+							query_str);
+		}	
+		
+		g_free (query_str);
+		g_string_free (info_data, TRUE);
+		g_string_free (join_data, TRUE);
+	}
+
+	
+	if (dyn_node == NULL) 
+	{		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "klassname")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, klass_name, ret_bool, ret_value);	
+	
+	if (final_definition_id > 0)
+	{
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "defid")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+		
+		MP_SET_HOLDER_BATCH_INT(priv, param, final_definition_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 (GDA_DATA_MODEL (data)) <= 0)
+	{
+		if (data != NULL)
+			g_object_unref (data);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);
+}
+
+/**
+ * Personalized GTree mapping:
+ * Considering that a gint on a x86 is 4 bytes: we'll reserve:
+ * 3 bytes to map the main parameters.
+ * 1 byte is for filter_kinds number, so you'll be able to filter up to 255 parameters.
+ * |--------------------------------|-------------|
+ *        main parameters [3 bytes]  extra [1 byte]
+ */
+#define DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_LIMIT					0x0100
+#define DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_OFFSET				0x0200
+#define DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_GROUP_YES				0x0400
+#define DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_GROUP_NO				0x0800
+#define DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES 	0x1000
+#define DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO	 	0x2000
+
+SymbolDBEngineIterator *
+symbol_db_engine_get_global_members_filtered (SymbolDBEngine *dbe, 
+									const GPtrArray *filter_kinds,
+									gboolean include_kinds, 
+									gboolean group_them,
+									gint results_limit, 
+									gint results_offset,
+								 	SymExtraInfo sym_info)
+{
+	SymbolDBEnginePriv *priv;
+	GdaDataModel *data;
+	GString *info_data;
+	GString *join_data;
+	GString *filter_str;
+	gchar *query_str;
+	const gchar *group_by_option;
+	gchar *limit = "";
+	gboolean limit_free = FALSE;
+	gchar *offset = "";
+	gboolean offset_free = FALSE;
+	const DynChildQueryNode *dyn_node = NULL;
+	GdaHolder *param;
+	GValue *ret_value;
+	gboolean ret_bool;
+
+	/* use to merge multiple extra_parameters flags */
+	gint other_parameters = 0;	
+	
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	
+	/* check for an already flagged sym_info with KIND. SYMINFO_KIND on sym_info
+	 * is already contained into the default query infos.
+	 */
+	sym_info = sym_info & ~SYMINFO_KIND;
+
+	if (group_them == TRUE)
+	{
+		other_parameters |= DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_GROUP_YES;
+		group_by_option = "GROUP BY symbol.name";
+	}
+	else 
+	{
+		other_parameters |= DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_GROUP_NO;
+		group_by_option = "";
+	}
+
+	if (results_limit > 0)
+	{
+		other_parameters |= DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_LIMIT;
+		limit_free = TRUE;
+		limit = g_strdup_printf ("LIMIT ## /* name:'limit' type:gint */");
+	}
+	
+	if (results_offset > 0)
+	{
+		other_parameters |= DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_OFFSET;
+		offset = g_strdup_printf ("OFFSET ## /* name:'offset' type:gint */");
+		offset_free = TRUE;
+	}
+	
+	/* test if user gave an array with more than 255 filter_kinds. In that case
+	 * we'll not be able to save/handle it, so consider it as a NULL array 
+	 */
+	if (filter_kinds == NULL || filter_kinds->len > 255 || filter_kinds->len <= 0) 
+	{
+		if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+					DYN_PREP_QUERY_GET_CLASS_PARENTS, sym_info, 
+					other_parameters)) == 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, sym_kind.kind_name AS kind_name %s FROM symbol "
+					"JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id %s "
+					"WHERE symbol.scope_id <= 0 AND symbol.is_file_scope = 0 "
+							"%s %s %s", info_data->str, join_data->str,
+						 	group_by_option, limit, offset);
+			
+			dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+							DYN_PREP_QUERY_GET_GLOBAL_MEMBERS_FILTERED,
+							sym_info, other_parameters,
+							query_str);			
+			
+			g_free (query_str);
+			g_string_free (join_data, TRUE);
+			g_string_free (info_data, TRUE);
+		}
+	}
+	else
+	{
+		if (include_kinds == TRUE)
+		{
+			other_parameters |= 
+				DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES;
+		}
+		else
+		{
+			other_parameters |= 
+				DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO;
+		}
+		
+		/* set the number of parameters in the less important byte */
+		other_parameters |= filter_kinds->len;
+		
+		if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+				DYN_PREP_QUERY_GET_CLASS_PARENTS, sym_info, 
+				other_parameters)) == NULL)
+		{		
+			gint i;
+			/* 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);				
+
+			/* prepare the dynamic filter string before the final query */
+			filter_str = g_string_new ("");
+			
+			if (include_kinds == TRUE)
+			{				
+				filter_str = g_string_append (filter_str , 
+					"AND sym_kind.kind_name IN (## /* name:'filter0' type:gchararray */");
+			}
+			else
+			{
+				filter_str = g_string_append (filter_str , 
+					"AND sym_kind.kind_name NOT IN (## /* name:'filter0' type:gchararray */");
+			}
+			
+			for (i = 1; i < filter_kinds->len; i++)
+			{				
+				g_string_append_printf (filter_str , 
+						",## /* name:'filter%d' type:gchararray */", i);
+			}
+			filter_str = g_string_append (filter_str , ")");
+			
+			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, "
+					"sym_kind.kind_name AS kind_name %s FROM symbol "
+					"%s JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
+					"WHERE symbol.scope_id <= 0 AND symbol.is_file_scope = 0 "
+					"%s %s %s %s", info_data->str, join_data->str, 
+							 filter_str->str, group_by_option, limit, offset);
+		
+			dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_GET_GLOBAL_MEMBERS_FILTERED,
+						sym_info, other_parameters,
+						query_str);
+				
+			g_free (query_str);
+			g_string_free (join_data, TRUE);
+			g_string_free (info_data, TRUE);
+			g_string_free (filter_str, TRUE);
+		}
+	}	
+	
+	if (limit_free)
+		g_free (limit);
+	
+	if (offset_free)
+		g_free (offset);
+	
+	if (dyn_node == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	if (other_parameters & DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_LIMIT)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "limit")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_limit, ret_bool, ret_value);
+	}
+
+	if (other_parameters & DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_OFFSET)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "offset")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_offset, ret_bool, ret_value);		
+	}
+	
+	
+	if (other_parameters & DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES ||
+		other_parameters & DYN_GET_GLOBAL_MEMBERS_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO)
+	{	
+		gint i;
+		for (i = 0; i < filter_kinds->len; i++)
+		{
+			gchar *curr_str = g_strdup_printf ("filter%d", i);
+			param = gda_set_get_holder ((GdaSet*)dyn_node->plist, curr_str);
+
+			MP_SET_HOLDER_BATCH_STR(priv, param, g_ptr_array_index (filter_kinds, i), 
+									ret_bool, ret_value);
+			g_free (curr_str);
+		}
+	}	
+
+	/*DEBUG_PRINT ("symbol_db_engine_get_global_members_filtered  () query_str is %s",
+				 dyn_node->query_str);*/
+	
+	/* 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 (GDA_DATA_MODEL (data)) <= 0)
+	{
+		if (data != NULL)
+			g_object_unref (data);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/**
+ * A filtered version of the symbol_db_engine_get_scope_members_by_symbol_id ().
+ * You can specify which kind of symbols to retrieve, and if include them or exclude.
+ * Kinds are 'namespace', 'class' etc.
+ * @param filter_kinds cannot be NULL.
+ * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
+ * @param results_offset Skip results_offset results. -1 If you don't want to use this par. 
+ *
+ *
+ * Personalized GTree mapping:
+ * Considering that a gint on a x86 is 4 bytes: we'll reserve:
+ * 3 bytes to map the main parameters.
+ * 1 byte is for filter_kinds number, so you'll be able to filter up to 255 parameters.
+ * |--------------------------------|-------------|
+ *        main parameters [3 bytes]  extra [1 byte] 
+ */
+#define DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_LIMIT					0x0100
+#define DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_OFFSET				0x0200
+#define DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES		0x0400
+#define DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO		0x0800
+
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_members_by_symbol_id_filtered (SymbolDBEngine *dbe, 
+									gint scope_parent_symbol_id, 
+									const GPtrArray *filter_kinds,
+									gboolean include_kinds,
+									gint results_limit,
+									gint results_offset,
+									SymExtraInfo sym_info)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *query_str;	
+	GdaDataModel *data;
+	GString *info_data;
+	GString *join_data;
+	GString *filter_str;
+	gchar *limit = "";
+	gboolean limit_free = FALSE;
+	gchar *offset = "";
+	gboolean offset_free = FALSE;
+	gint other_parameters;
+	const DynChildQueryNode *dyn_node = NULL;
+	GdaHolder *param;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	
+	if (scope_parent_symbol_id <= 0)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	/* syminfo kind is already included in results */
+	sym_info = sym_info & ~SYMINFO_KIND;
+
+	/* init parameters */
+	other_parameters = 0;	
+
+	if (results_limit > 0)
+	{
+		limit = g_strdup_printf ("LIMIT ## /* name:'limit' type:gint */");
+		limit_free = TRUE;
+		other_parameters |= 
+			DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_LIMIT;
+	}
+	
+	if (results_offset > 0)
+	{
+		offset = g_strdup_printf ("OFFSET ## /* name:'offset' type:gint */");
+		offset_free = TRUE;
+		other_parameters |=
+			DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_OFFSET;
+	}
+		
+	/* build filter string */
+	if (include_kinds == TRUE)
+	{
+		other_parameters |= 
+			DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES;
+	}
+	else
+	{
+		other_parameters |= 
+			DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO;
+	}
+	
+	/* we'll take into consideration the number of filter_kinds only it the number
+	 * is fillable in a byte.
+	 */
+	if (filter_kinds != NULL && filter_kinds->len < 255 
+		&& filter_kinds->len > 0)
+	{		
+		/* set the number of parameters in the less important byte */
+		other_parameters |= filter_kinds->len;	
+	}
+	
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+				DYN_PREP_QUERY_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED, sym_info, 
+				other_parameters)) == NULL)
+	{	
+		gint i;		
+		
+		/* 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);
+
+		filter_str = g_string_new ("");
+		if (include_kinds == TRUE)
+		{			
+			filter_str = g_string_append (filter_str , 
+				"AND sym_kind.kind_name IN (## /* name:'filter0' type:gchararray */");
+		}
+		else
+		{
+			filter_str = g_string_append (filter_str , 
+				"AND sym_kind.kind_name NOT IN (## /* name:'filter0' type:gchararray */");
+		}
+		
+		for (i = 1; i < filter_kinds->len; i++)
+		{				
+			g_string_append_printf (filter_str , 
+					",## /* name:'filter%d' type:gchararray */", i);
+		}
+		filter_str = g_string_append (filter_str , ")");
+		
+		/* ok, beware that we use an 'alias hack' to accomplish compatibility with 
+	 	 * sdb_engine_prepare_symbol_info_sql () function. In particular we called
+	 	 * the first joining table 'a', the second one 'symbol', where there is the info we
+	 	 * want 
+	 	 */		
+		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, "
+			"sym_kind.kind_name AS kind_name %s "
+			"FROM symbol a, symbol symbol "
+			"%s JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
+			"WHERE a.symbol_id = ## /* name:'scopeparentsymid' type:gint */ "
+			"AND symbol.scope_id = a.scope_definition_id "
+			"AND symbol.scope_id > 0 %s %s %s", info_data->str, join_data->str,
+									 filter_str->str, limit, offset);		
+									 
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+							DYN_PREP_QUERY_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED,
+							sym_info, other_parameters,
+							query_str);
+			
+		g_free (query_str);
+		g_string_free (join_data, TRUE);
+		g_string_free (info_data, TRUE);
+		g_string_free (filter_str, TRUE);
+	}	
+	
+	if (limit_free)
+		g_free (limit);
+	
+	if (offset_free)
+		g_free (offset);
+
+	if (dyn_node == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}	
+	
+	if (other_parameters & DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_LIMIT)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "limit")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_limit, ret_bool, ret_value);
+	}
+
+	if (other_parameters & DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_OFFSET)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "offset")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_offset, ret_bool, ret_value);
+	}	
+	
+	if (other_parameters & 
+			DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES ||
+		other_parameters & 
+			DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO)
+	{	
+		gint i;
+		for (i = 0; i < filter_kinds->len; i++)
+		{
+			gchar *curr_str = g_strdup_printf ("filter%d", i);
+			param = gda_set_get_holder ((GdaSet*)dyn_node->plist, curr_str);
+			
+			MP_SET_HOLDER_BATCH_STR(priv, param, g_ptr_array_index (filter_kinds, i), 
+									ret_bool, ret_value);
+			g_free (curr_str);
+		}
+	}	
+
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "scopeparentsymid")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+
+	MP_SET_HOLDER_BATCH_INT(priv, param, scope_parent_symbol_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 (GDA_DATA_MODEL (data)) <= 0)
+	{
+		if (data != NULL)
+			g_object_unref (data);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/**
+ * Sometimes it's useful going to query just with ids [and so integers] to have
+ * a little speed improvement.
+ */
+#define DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_EXTRA_PAR_LIMIT		1
+#define DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_EXTRA_PAR_OFFSET		2
+
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_members_by_symbol_id (SymbolDBEngine *dbe, 
+									gint scope_parent_symbol_id, 
+									gint results_limit,
+									gint results_offset,
+									SymExtraInfo sym_info)
+{
+/*
+select b.* from symbol a, symbol b where a.symbol_id = 348 and 
+			b.scope_id = a.scope_definition_id;
+*/
+	SymbolDBEnginePriv *priv;
+	gchar *query_str;	
+	GdaDataModel *data;
+	GString *info_data;
+	GString *join_data;
+	gchar *limit = "";
+	gboolean limit_free = FALSE;
+	gchar *offset = "";
+	gboolean offset_free = FALSE;
+	gint other_parameters;
+	const DynChildQueryNode *dyn_node = NULL;
+	GdaHolder *param;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	
+	if (scope_parent_symbol_id <= 0)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+
+	other_parameters = 0;
+	
+	if (results_limit > 0)
+	{
+		limit = g_strdup_printf ("LIMIT ## /* name:'limit' type:gint */");
+		limit_free = TRUE;
+		other_parameters |= DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_EXTRA_PAR_LIMIT;
+	}
+	
+	if (results_offset > 0)
+	{
+		offset = g_strdup_printf ("OFFSET ## /* name:'offset' type:gint */");
+		offset_free = TRUE;
+		other_parameters |= DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_EXTRA_PAR_OFFSET;
+	}
+	
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+				DYN_PREP_QUERY_GET_SCOPE_MEMBERS_BY_SYMBOL_ID, sym_info, 
+				other_parameters)) == 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);		
+	
+	
+		/* ok, beware that we use an 'alias hack' to accomplish compatibility with 
+	 	 * sdb_engine_prepare_symbol_info_sql () function. In particular we called
+	 	 * the first joining table 'a', the second one 'symbol', where is the info we
+	 	 * want 
+	 	 */
+		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 "
+			"%s FROM symbol a, symbol symbol "
+			"%s WHERE a.symbol_id = ## /* name:'scopeparentsymid' type:gint */ "
+			"AND symbol.scope_id = a.scope_definition_id "
+			"AND symbol.scope_id > 0 %s %s", info_data->str, join_data->str,
+								 limit, offset);	
+		
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+							DYN_PREP_QUERY_GET_SCOPE_MEMBERS_BY_SYMBOL_ID,
+							sym_info, other_parameters,
+							query_str);
+		
+		g_free (query_str);
+		g_string_free (info_data, TRUE);
+		g_string_free (join_data, TRUE);
+	}
+	
+	if (limit_free)
+		g_free (limit);
+	
+	if (offset_free)
+		g_free (offset);
+
+	if (dyn_node == NULL) 
+	{		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	
+	if (other_parameters & DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_EXTRA_PAR_LIMIT)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "limit")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_limit, ret_bool, ret_value);	
+	}
+
+	if (other_parameters & DYN_GET_SCOPE_MEMBERS_BY_SYMBOL_ID_EXTRA_PAR_OFFSET)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "offset")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_offset, ret_bool, ret_value);	
+	}
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "scopeparentsymid")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+
+	MP_SET_HOLDER_BATCH_INT(priv, param, scope_parent_symbol_id, ret_bool, ret_value);	
+	
+	/*DEBUG_PRINT ("symbol_db_engine_get_scope_members_by_symbol_id (): %s", 
+				 dyn_node->query_str);*/
+	
+	/* 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);
+	
+	/*gda_data_model_dump (data, stdout);*/
+	if (!GDA_IS_DATA_MODEL (data) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data)) <= 0)
+	{
+		if (data != NULL)
+			g_object_unref (data);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/** 
+ * scope_path cannot be NULL.
+ * scope_path will be something like "scope1_kind", "scope1_name", "scope2_kind", 
+ * "scope2_name", NULL 
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_members (SymbolDBEngine *dbe, 
+									const GPtrArray* scope_path, 
+									SymExtraInfo sym_info)
+{
+/*
+simple scope 
+	
+select * from symbol where scope_id = (
+	select scope.scope_id from scope
+		inner join sym_type on scope.type_id = sym_type.type_id 
+		where sym_type.type = 'class' 
+			and scope.scope_name = 'MyClass'
+	);
+	
+select * from symbol where scope_id = (
+	select scope.scope_id from scope 
+		inner join sym_type on scope.type_id = sym_type.type_id 
+		where sym_type.type = 'struct' 
+			and scope.scope_name = '_faa_1');
+	
+	
+es. scope_path = First, namespace, Second, namespace, NULL, 
+	symbol_name = Second_1_class	
+*/
+	SymbolDBEnginePriv *priv;
+	gchar *query_str;	
+	GdaDataModel *data;
+	gint final_definition_id;
+	GString *info_data;
+	GString *join_data;
+	GdaHolder *param;
+	GValue *ret_value;
+	gboolean ret_bool;	
+	const DynChildQueryNode *dyn_node;
+	
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);	
+	}
+	
+	final_definition_id = sdb_engine_walk_down_scope_path (dbe, scope_path);
+	
+	if (final_definition_id <= 0) 
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+		DYN_PREP_QUERY_GET_SCOPE_MEMBERS, 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 "
+			"%s FROM symbol "
+			"%s WHERE scope_id = ## /* name:'defid' type:gint */", 
+									 info_data->str, join_data->str);
+		
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_GET_SCOPE_MEMBERS,
+						sym_info, 0,
+						query_str);
+		
+		g_free (query_str);
+		g_string_free (info_data, TRUE);
+		g_string_free (join_data, TRUE);		
+	}
+
+	if (dyn_node == NULL) 
+	{		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}	
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "defid")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	MP_SET_HOLDER_BATCH_INT(priv, param, final_definition_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);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/**
+ * Returns an iterator to the data retrieved from database. 
+ * It will be possible to get the scope specified by the line of the file. 
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_current_scope (SymbolDBEngine *dbe, const gchar* full_local_file_path,
+									gulong line, SymExtraInfo sym_info)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *query_str;
+	GdaDataModel *data;
+	GString *info_data;
+	GString *join_data;
+	GdaHolder *param;
+	const DynChildQueryNode *dyn_node;
+	gchar *db_relative_file;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+	
+	db_relative_file = symbol_db_engine_get_file_db_path (dbe, full_local_file_path);
+	if (db_relative_file == NULL)
+		return NULL;
+	
+	DEBUG_PRINT ("db_relative_file  %s", db_relative_file);
+	DEBUG_PRINT ("full_local_file_path %s", full_local_file_path);
+	
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+
+	sym_info = sym_info & ~SYMINFO_FILE_PATH;
+	
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+		DYN_PREP_QUERY_GET_CURRENT_SCOPE, 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 "
+			"%s FROM symbol "
+				"JOIN file ON file_defined_id = file_id "
+				"%s WHERE file.file_path = ## /* name:'filepath' type:gchararray */ "
+					"AND symbol.file_position <= ## /* name:'linenum' type:gint */  "
+					"ORDER BY symbol.file_position DESC LIMIT 1", 
+									 info_data->str, join_data->str);
+/*		DEBUG_PRINT ("symbol_db_engine_get_current_scope () %s", query_str);*/
+		
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_GET_CURRENT_SCOPE,
+						sym_info, 0,
+						query_str);
+		
+		g_string_free (info_data, TRUE);
+		g_string_free (join_data, TRUE);		
+		g_free (query_str);
+	}
+	
+	if (dyn_node == NULL) 
+	{		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		g_free (db_relative_file);
+		return NULL;
+	}
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "linenum")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		g_free (db_relative_file);
+		return NULL;
+	}
+		
+	MP_SET_HOLDER_BATCH_INT(priv, param, line, ret_bool, ret_value);	
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "filepath")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		g_free (db_relative_file);
+		return NULL;
+	}
+
+	MP_SET_HOLDER_BATCH_STR(priv, param, db_relative_file, 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);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		g_free (db_relative_file);
+		return NULL;
+	}
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	
+	g_free (db_relative_file);
+	
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/**
+ * @param file_path Full local file path, e.g. /home/user/foo/file.c
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_file_symbols (SymbolDBEngine *dbe, 
+								   const gchar *file_path, 
+								   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);
+	g_return_val_if_fail (file_path != NULL, NULL);
+	priv = dbe->priv;	
+	g_return_val_if_fail (priv->db_directory != NULL, NULL);
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	/* check for an already flagged sym_info with FILE_PATH. SYMINFO_FILE_PATH on 
+	 * sym_info is already contained into the default query infos.
+	 */
+	sym_info = sym_info & ~SYMINFO_FILE_PATH;
+	
+
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+		DYN_PREP_QUERY_GET_FILE_SYMBOLS, 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);
+
+		/* rember to do a file_path + strlen(priv->db_directory): a project relative 
+	 	 * file path 
+	 	 */
+		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 "
+			"%s FROM symbol "
+				"JOIN file ON symbol.file_defined_id = file.file_id "
+			"%s WHERE file.file_path = ## /* name:'filepath' type:gchararray */", 
+						info_data->str, join_data->str);
+	
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_GET_FILE_SYMBOLS,
+						sym_info, 0,
+						query_str);
+		
+		g_free (query_str);
+		g_string_free (info_data, TRUE);
+		g_string_free (join_data, TRUE);
+	}
+
+	if (dyn_node == NULL) 
+	{		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+	
+	/*DEBUG_PRINT ("query for symbol_db_engine_get_file_symbols is %s [filepath: %s]",
+				 dyn_node->query_str, file_path);*/
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "filepath")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+		
+	gchar *relative_path = symbol_db_engine_get_file_db_path (dbe, file_path);
+	if (relative_path == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+	
+	MP_SET_HOLDER_BATCH_STR(priv, param, relative_path, 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);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	g_free (relative_path);
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												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;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+
+	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 "
+			"%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)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		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);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/**
+ * Use this function to find symbols names by patterns like '%foo_func%'
+ * that will return a family of my_foo_func_1, your_foo_func_2 etc
+ * @pattern must not be NULL.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_find_symbol_by_name_pattern (SymbolDBEngine *dbe, 
+									const gchar *pattern, 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;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+		DYN_PREP_QUERY_FIND_SYMBOL_NAME_BY_PATTERN, 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 "
+			"%s FROM symbol "
+			"%s WHERE symbol.name LIKE ## /* name:'pattern' type:gchararray */", 
+									 info_data->str, join_data->str);
+		
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_FIND_SYMBOL_NAME_BY_PATTERN,
+						sym_info, 0,
+						query_str);
+		
+		g_free (query_str);
+		g_string_free (info_data, TRUE);
+		g_string_free (join_data, TRUE);
+	}
+
+	if (dyn_node == NULL) 
+	{		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "pattern")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	MP_SET_HOLDER_BATCH_STR(priv, param, pattern, 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);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/** 
+ * No iterator for now. We need the quickest query possible. 
+ * @param db_file Can be NULL. In that case there won't be any check on file.
+ */
+gint
+symbol_db_engine_get_parent_scope_id_by_symbol_id (SymbolDBEngine *dbe,
+									gint scoped_symbol_id,
+									const gchar * db_file)
+{
+/*
+select * from symbol where scope_definition_id = (
+	select scope_id from symbol where symbol_id = 26
+	);
+*/
+	SymbolDBEnginePriv *priv;
+	GdaDataModel *data;
+	const GValue* value;
+	GdaHolder *param;
+	gint res;
+	gint num_rows;
+	const GdaSet *plist;
+	const GdaStatement *stmt, *stmt2;	
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+	
+	g_return_val_if_fail (dbe != NULL, -1);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+
+	if (db_file == NULL)
+	{
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe, 
+						PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID_NO_FILE))
+			== NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return -1;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, 
+						PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID_NO_FILE);		
+	}
+	else 
+	{
+		if ((stmt = sdb_engine_get_statement_by_query_id (dbe, 
+						PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID))
+			== NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return -1;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, 
+						PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID);
+		
+		/* dbfile parameter */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "dbfile")) == NULL)
+		{			
+			g_warning ("param dbfile is NULL from pquery!");
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return -1;
+		}
+		
+		MP_SET_HOLDER_BATCH_STR(priv, param, db_file, ret_bool, ret_value);
+	}
+
+	/* scoped symbol id */
+	if ((param = gda_set_get_holder ((GdaSet*)plist, "symid")) == NULL)
+	{			
+		g_warning ("param symid is NULL from pquery!");
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return -1;
+	}	
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, scoped_symbol_id, ret_bool, ret_value);		
+	
+	/* execute the query with parametes just set */
+	data = gda_connection_statement_execute_select (priv->db_connection, 
+													  (GdaStatement*)stmt, 
+													  (GdaSet*)plist, NULL);
+		
+	if (!GDA_IS_DATA_MODEL (data) ||
+		(num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (data))) <= 0)
+	{
+		if (data != NULL)
+			g_object_unref (data);
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return -1;
+	}
+
+	/* Hey, we can go in trouble here. Imagine this situation:
+	 * We have two namespaces, 'Editor' and 'Entwickler'. Inside
+	 * them there are two classes with the same name, 'Preferences', hence 
+	 * the same scope. We still aren't able to retrieve the real parent_symbol_id
+	 * of a method into these classes.
+	 *
+	 * This is how the above query will result:
+	 * 
+	 * 324|31|Preferences|28|0||192|92|276|3|-1|-1|0
+	 * 365|36|Preferences|33|0||192|2|276|3|-1|-1|0
+	 *
+	 * Say that 92 is 'Editor' scope, and '2' is 'Entwickler' one. We're looking 
+	 * for the latter, and so we know that the right answer is symbol_id 365.
+	 * 1. We'll store the symbold_id(s) and the scope_id(s) of both 324 and 365.
+	 * 2. We'll query the db to retrieve all the symbols written before our 
+	 *    scoped_symbol_id in the file where scoped_symbol_id is.
+	 * 3. Compare every symbol's scope_definition_id retrieved on step 2 against
+	 *    all the ones saved at point 1. The first match is our parent_scope symbol_id.
+	 */
+	if (num_rows > 1) 
+	{
+		gint i;
+		
+		GList *candidate_parents = NULL;
+		typedef struct _candidate_node {
+			gint symbol_id;
+			gint scope_id;
+		} candidate_node;
+			
+		GdaDataModel *detailed_data;
+		
+		/* step 1 */
+		for (i=0; i < num_rows; i++)
+		{
+			candidate_node *node;
+			const GValue *tmp_value, *tmp_value1;
+			
+			node = g_new0 (candidate_node, 1);
+			
+			/* get the symbol_id from the former 'data' result set */
+			tmp_value = gda_data_model_get_value_at (data, 0, i, NULL);
+			node->symbol_id = tmp_value != NULL && G_VALUE_HOLDS_INT (tmp_value)
+				? g_value_get_int (tmp_value) : -1;
+			
+			/* get scope_id [or the definition] */
+			/* handles this case:
+			 * 
+			 * namespace_foo [scope_id 0 or > 0, scope_def X]
+			 * |
+			 * +--- class_foo 
+			 *      |
+			 *      +---- scoped_symbol_id
+  		     *
+			 */
+			tmp_value1 = gda_data_model_get_value_at (data, 4, i, NULL);
+			node->scope_id = tmp_value1 != NULL && G_VALUE_HOLDS_INT (tmp_value1)
+				? g_value_get_int (tmp_value1) : -1;
+
+			/* handles this case:
+			 * 
+			 * namespace_foo [scope_id 0, scope_def X]
+			 * |
+			 * +--- scoped_symbol_id
+			 *
+			 */
+			if (node->scope_id <= 0)
+			{
+				tmp_value1 = gda_data_model_get_value_at (data, 3, i, NULL);
+				node->scope_id = tmp_value1 != NULL && G_VALUE_HOLDS_INT (tmp_value1)
+					? g_value_get_int (tmp_value1) : -1;
+			}
+						
+			candidate_parents = g_list_prepend (candidate_parents, node);
+		}
+
+		
+		/* step 2 */
+		if ((stmt2 = sdb_engine_get_statement_by_query_id (dbe, 
+					PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID_BY_SYMBOL_ID)) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return -1;
+		}
+
+		plist = sdb_engine_get_query_parameters_list (dbe, 
+						PREP_QUERY_GET_PARENT_SCOPE_ID_BY_SYMBOL_ID_BY_SYMBOL_ID);		
+
+		/* scoped symbol id */
+		if ((param = gda_set_get_holder ((GdaSet*)plist, "scopedsymid")) == NULL)
+		{			
+			g_warning ("param scopedsymid is NULL from pquery!");
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return -1;
+		}	
+		
+		MP_SET_HOLDER_BATCH_INT(priv, param, scoped_symbol_id, ret_bool, ret_value);		
+	
+		/* we should receive just ONE row. If it's > 1 than we have surely an
+		 * error on code.
+		 */
+		detailed_data = gda_connection_statement_execute_select (priv->db_connection, 
+													  (GdaStatement*)stmt2, 
+													  (GdaSet*)plist, NULL);
+				
+		if (!GDA_IS_DATA_MODEL (detailed_data) ||
+			(num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (detailed_data))) <= 0)
+		{
+			if (detailed_data != NULL)
+				g_object_unref (detailed_data);
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);		
+			res = -1;
+		}	
+		else		/* ok we have a good result here */
+		{
+			gint j;
+			gboolean found = FALSE;
+			gint parent_scope_definition_id;
+			gint found_symbol_id = -1;
+			candidate_node *node = NULL;
+			
+			for (j=0; j < gda_data_model_get_n_rows (detailed_data); j++)
+			{
+				const GValue *tmp_value;				
+				gint k;
+
+				tmp_value = gda_data_model_get_value_at (detailed_data, 0, j, NULL);
+				parent_scope_definition_id = tmp_value != NULL && G_VALUE_HOLDS_INT (tmp_value)
+					? g_value_get_int (tmp_value) : -1;
+				
+				for (k = 0; k < g_list_length (candidate_parents); k++) 
+				{
+					node = g_list_nth_data (candidate_parents, k); 
+					/*DEBUG_PRINT ("node->symbol_id %d node->scope_id %d", 
+								 node->symbol_id, node->scope_id);*/
+					if (node->scope_id == parent_scope_definition_id) 
+					{
+						found = TRUE;
+						found_symbol_id = node->symbol_id;
+						break;
+					}						
+				}
+				
+				if (found)
+					break;
+			}
+			res = found_symbol_id;
+		}
+		
+		if (detailed_data)
+			g_object_unref (detailed_data);
+
+		for (i=0; i < g_list_length (candidate_parents); i++) 
+		{
+			g_free (g_list_nth_data (candidate_parents, i));
+		}
+		g_list_free (candidate_parents);
+	}
+	else
+	{
+		value = gda_data_model_get_value_at (data, 0, 0, NULL);
+		res = value != NULL && G_VALUE_HOLDS_INT (value)
+			? g_value_get_int (value) : -1;		
+	}
+	g_object_unref (data);
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return res;
+}
+
+/**
+ * @param pattern Pattern you want to search for. If NULL it will use '%' and LIKE for query.
+ *        Please provide a pattern with '%' if you also specify a exact_match = FALSE
+ * @param exact_match Should the pattern be searched for an exact match?
+ * @param filter_kinds Can be NULL. In that case these filters will not be taken into consideration.
+ * @param include_kinds Should the filter_kinds (if not null) be applied as inluded or excluded?
+ * @param global_symbols_search If TRUE only global public function will be searched. If false
+ *		  even private or static (for C language) will be searched.
+ * @param session_projects Should the search, a global search, be filtered by some packages (projects)?
+ *        If yes then provide a GList, if no then pass NULL.
+ * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
+ * @param results_offset Skip results_offset results. -1 If you don't want to use this par.	 
+ * @param sym_info Infos about symbols you want to know.
+ *
+ * Personalized GTree mapping:
+ * Considering that a gint on a x86 is 4 bytes: we'll reserve:
+ * 2 bytes to map the main parameters.
+ * 1 byte is for session number.
+ * 1 byte is for filter_kinds number, so you'll be able to filter up to 255 parameters.
+ * |--------------------------|-------------|-------------|
+ *   main parameters [2 bytes]  sessions [1]   filter [1]
+ */
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_EXACT_MATCH_YES			0x010000
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_EXACT_MATCH_NO			0x020000
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES		0x040000
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO			0x080000
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_GLOBAL_SEARCH_YES		0x100000
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_GLOBAL_SEARCH_NO			0x200000
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_LIMIT					0x400000
+#define DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_OFFSET					0x800000
+
+SymbolDBEngineIterator *
+symbol_db_engine_find_symbol_by_name_pattern_filtered (SymbolDBEngine *dbe, 
+									const gchar *pattern, 
+									gboolean exact_match,
+									const GPtrArray *filter_kinds,
+									gboolean include_kinds,
+									gboolean global_symbols_search,
+									GList *session_projects,
+									gint results_limit, 
+									gint results_offset,
+									SymExtraInfo sym_info)
+{
+	SymbolDBEnginePriv *priv;
+	GdaDataModel *data;
+	GString *info_data;
+	GString *join_data;
+	GString *filter_str;
+	gchar *query_str;
+	const gchar *match_str;
+	GdaHolder *param;
+	const DynChildQueryNode *dyn_node;
+	gint other_parameters;
+	gchar *limit = "";
+	gboolean limit_free = FALSE;
+	gchar *offset = "";
+	gboolean offset_free = FALSE;
+	GValue *ret_value;
+	gboolean ret_bool;
+	
+
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	
+	sym_info = sym_info & ~SYMINFO_KIND;
+	
+	/* initialize dynamic stuff */
+	other_parameters = 0;
+	dyn_node = NULL;
+
+	
+	/* check for a null pattern. If NULL we'll set a patter like '%' 
+	 * and exact_match = FALSE . In this way we will match everything.
+	 */
+	if (pattern == NULL)
+	{
+		pattern = "%";
+		exact_match = FALSE;
+		other_parameters |= DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_EXACT_MATCH_NO;
+	}
+	
+	/* check for match */
+	if (exact_match == TRUE)
+	{
+		other_parameters |= 
+			DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_EXACT_MATCH_YES;
+		match_str = " = ## /* name:'pattern' type:gchararray */";
+	}
+	else
+	{
+		other_parameters |= 
+			DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_EXACT_MATCH_NO;
+		match_str = " LIKE ## /* name:'pattern' type:gchararray */";
+	}
+	
+	if (global_symbols_search == TRUE)
+	{
+		other_parameters |= 
+			DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_GLOBAL_SEARCH_YES;
+	}
+	else
+	{
+		other_parameters |= 
+			DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_GLOBAL_SEARCH_NO;
+	}
+	
+	if (results_limit > 0)
+	{
+		other_parameters |= DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_LIMIT;
+		limit_free = TRUE;
+		limit = g_strdup_printf ("LIMIT ## /* name:'limit' type:gint */");
+	}
+	
+	if (results_offset > 0)
+	{
+		other_parameters |= DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_OFFSET;
+		offset = g_strdup_printf ("OFFSET ## /* name:'offset' type:gint */");
+		offset_free = TRUE;
+	}
+
+	if (session_projects != NULL)
+	{
+		gint list_length = g_list_length (session_projects);
+		if (list_length < 255 && list_length > 0) 
+		{		
+			/* shift the bits. We want to put the result on the third byte */
+			list_length <<= 8;
+			other_parameters |= list_length;
+		}
+		else 
+		{
+			g_warning ("symbol_db_engine_find_symbol_by_name_pattern_filtered (): "
+				"session_projects has 0 length.");						   
+		}
+	}
+	
+	if (filter_kinds == NULL || filter_kinds->len > 255 || filter_kinds->len <= 0) 
+	{
+		if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+			DYN_PREP_QUERY_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED, sym_info, 
+														 other_parameters)) == NULL)
+		{
+			gint i;
+			GString *filter_projects;
+			/* 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);
+			
+			/* build session projects filter string */
+			filter_projects = g_string_new ("");
+			if (session_projects != NULL)
+			{
+				filter_projects = g_string_append (filter_projects,
+				"AND symbol.file_defined_id IN "
+				"(SELECT file.file_id FROM file JOIN project ON file.prj_id = "
+					"project.project_id WHERE project.project_name IN ( "
+					"## /* name:'prj_filter0' type:gchararray */");
+				
+				for (i = 1; i < g_list_length (session_projects); i++)
+				{				
+					g_string_append_printf (filter_projects, 
+						",## /* name:'prj_filter%d' type:gchararray */", i);
+				}				
+				filter_projects = g_string_append (filter_projects, "))");
+			}
+
+			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, "
+					"sym_kind.kind_name AS kind_name "
+					"%s FROM symbol %s JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
+					"WHERE symbol.name %s AND symbol.is_file_scope = "
+					"## /* name:'globalsearch' type:gint */ %s %s %s", 
+				info_data->str, join_data->str, match_str, filter_projects->str, 
+										 limit, offset);			
+
+			dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED,
+						sym_info, other_parameters,
+						query_str);
+
+			g_free (query_str);
+			g_string_free (info_data, TRUE);
+			g_string_free (join_data, TRUE);
+			g_string_free (filter_projects, TRUE);
+		}
+	}
+	else
+	{		
+		if (include_kinds == TRUE)
+		{
+			other_parameters |= 
+				DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES;
+		}
+		else
+		{
+			other_parameters |= 
+				DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO;
+		}
+
+		/* set the number of parameters in the less important byte */
+		other_parameters |= filter_kinds->len;
+		
+		if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+				DYN_PREP_QUERY_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED, sym_info, 
+				other_parameters)) == NULL)
+		{					
+			gint i;
+			GString *filter_projects;
+			
+			/* info_data contains the stuff after SELECT and before 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);
+			/* prepare the dynamic filter string before the final query */
+			filter_str = g_string_new ("");
+		
+			if (include_kinds == TRUE)
+			{				
+				filter_str = g_string_append (filter_str , 
+					"AND sym_kind.kind_name IN (## /* name:'filter0' type:gchararray */");		
+				for (i = 1; i < filter_kinds->len; i++)
+				{				
+					g_string_append_printf (filter_str , 
+							",## /* name:'filter%d' type:gchararray */", i);
+				}
+				filter_str = g_string_append (filter_str , ")");				
+			}
+			else
+			{
+				filter_str = g_string_append (filter_str , 
+					"AND sym_kind.kind_name NOT IN (## /* name:'filter0' type:gchararray */");
+				for (i = 1; i < filter_kinds->len; i++)
+				{				
+					g_string_append_printf (filter_str , 
+							",## /* name:'filter%d' type:gchararray */", i);
+				}
+				filter_str = g_string_append (filter_str , ")");				
+			}
+			
+			/* build session projects filter string */
+			filter_projects = g_string_new ("");
+			if (session_projects != NULL)
+			{
+				filter_projects = g_string_append (filter_projects,
+				"AND symbol.file_defined_id IN "
+				"(SELECT file.file_id FROM file JOIN project ON file.prj_id = "
+					"project.project_id WHERE project.project_name IN ( "
+					"## /* name:'prj_filter0' type:gchararray */");
+				
+				for (i = 1; i < g_list_length (session_projects); i++)
+				{				
+					g_string_append_printf (filter_projects, 
+						",## /* name:'prj_filter%d' type:gchararray */", i);
+				}				
+				filter_projects = g_string_append (filter_projects, "))");
+			}			
+			
+			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, "
+				"sym_kind.kind_name AS kind_name "
+					"%s FROM symbol %s JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
+					"WHERE symbol.name %s AND symbol.is_file_scope = "
+					"## /* name:'globalsearch' type:gint */ %s %s GROUP BY symbol.name %s %s", 
+			 		info_data->str, join_data->str, match_str, 
+			 		filter_str->str, filter_projects->str, limit, offset);
+			
+			dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+						DYN_PREP_QUERY_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED,
+						sym_info, other_parameters,
+						query_str);
+			g_free (query_str);
+			g_string_free (info_data, TRUE);
+			g_string_free (join_data, TRUE);				
+			g_string_free (filter_str, TRUE);
+			g_string_free (filter_projects, TRUE);
+		}
+	}
+	
+	
+	if (limit_free)
+		g_free (limit);
+	
+	if (offset_free)
+		g_free (offset);
+
+	if (dyn_node == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	if (other_parameters & DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_LIMIT)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "limit")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_limit, ret_bool, ret_value);		
+	}
+
+	if (other_parameters & DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_OFFSET)
+	{	
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "offset")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_INT(priv, param, results_offset, ret_bool, ret_value);		
+	}
+	
+	/* fill parameters for filter kinds */
+	if (other_parameters & DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_INCLUDE_KINDS_YES ||
+		other_parameters & DYN_FIND_SYMBOL_BY_NAME_PATTERN_FILTERED_EXTRA_PAR_INCLUDE_KINDS_NO)
+	{	
+		gint i;
+		for (i = 0; i < filter_kinds->len; i++)
+		{
+			gchar *curr_str = g_strdup_printf ("filter%d", i);
+			param = gda_set_get_holder ((GdaSet*)dyn_node->plist, curr_str);
+			MP_SET_HOLDER_BATCH_STR(priv, param, g_ptr_array_index (filter_kinds, i), ret_bool, ret_value);		
+			g_free (curr_str);
+		}
+	}
+
+	/* fill parameters for filter projects (packages) */
+	if (session_projects != NULL)
+	{
+		gint i = 0;
+		GList *item;
+		item = session_projects;
+		while (item != NULL)
+		{
+			gchar *curr_str = g_strdup_printf ("prj_filter%d", i);
+			param = gda_set_get_holder ((GdaSet*)dyn_node->plist, curr_str);
+			MP_SET_HOLDER_BATCH_STR(priv, param, item->data, ret_bool, ret_value);
+			g_free (curr_str);
+			
+			item = item->next;
+			i++;
+		}
+	}
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "globalsearch")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+	
+	MP_SET_HOLDER_BATCH_INT(priv, param, !global_symbols_search, ret_bool, ret_value);
+	
+	if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "pattern")) == NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+
+	MP_SET_HOLDER_BATCH_STR(priv, param, pattern, ret_bool, ret_value);
+	
+	/*DEBUG_PRINT ("symbol_db_engine_find_symbol_by_name_pattern_filtered query: %s",
+				 dyn_node->query_str);*/
+		
+	/* 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 (GDA_DATA_MODEL (data)) <= 0)
+	{
+		if (data != NULL)
+			g_object_unref (data);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}
+
+/**
+ * Gets the files of a project.
+ * @param project_name name of project you want to know the files of.
+ *        It can be NULL. In that case all the files will be returned.
+ */
+#define DYN_GET_FILES_FOR_PROJECT_EXTRA_PAR_ALL					1
+#define DYN_GET_FILES_FOR_PROJECT_EXTRA_PAR_PROJECT				2
+
+SymbolDBEngineIterator *
+symbol_db_engine_get_files_for_project (SymbolDBEngine *dbe, 
+									const gchar *project_name,
+								 	SymExtraInfo sym_info)
+{
+	SymbolDBEnginePriv *priv;
+	GdaDataModel *data;
+	GString *info_data;
+	GString *join_data;
+	gchar *query_str;
+	GdaHolder *param;
+	const DynChildQueryNode *dyn_node;
+	gint other_parameters;
+	GValue *ret_value;
+	gboolean ret_bool;
+
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+
+	if (priv->mutex)
+	{
+		g_mutex_lock (priv->mutex);
+	}
+	
+	sym_info = sym_info & ~SYMINFO_FILE_PATH;
+	sym_info = sym_info & ~SYMINFO_PROJECT_NAME;
+	
+	/* initialize dynamic stuff */
+	other_parameters = 0;
+	dyn_node = NULL;
+
+	if (project_name == NULL)
+	{
+		other_parameters |= DYN_GET_FILES_FOR_PROJECT_EXTRA_PAR_ALL;
+	}
+	else
+	{
+		other_parameters |= DYN_GET_FILES_FOR_PROJECT_EXTRA_PAR_PROJECT;
+	}
+	
+	/* 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_file_info_sql (dbe, info_data, join_data, sym_info);
+
+	if ((dyn_node = sdb_engine_get_dyn_query_node_by_id (dbe, 
+			DYN_PREP_QUERY_GET_FILES_FOR_PROJECT, sym_info, 
+			other_parameters)) == NULL)
+	{					
+		if (project_name == NULL)
+		{
+			query_str = g_strdup_printf ("SELECT file.file_path AS db_file_path "
+				"%s FROM file %s ",
+		 		info_data->str, join_data->str);
+		}
+		else 
+		{
+			query_str = g_strdup_printf ("SELECT file.file_path AS db_file_path, "
+				"project.project_name AS project_name "
+				"%s FROM file JOIN project ON file.prj_id = project.project_id %s "
+				"WHERE project.project_name = ## /* name:'prj_name' type:gchararray */",
+		 		info_data->str, join_data->str);
+			
+		}
+			
+		dyn_node = sdb_engine_insert_dyn_query_node_by_id (dbe, 
+					DYN_PREP_QUERY_GET_FILES_FOR_PROJECT,
+					sym_info, other_parameters,
+					query_str);
+		g_free (query_str);
+	}
+
+	g_string_free (info_data, TRUE);
+	g_string_free (join_data, TRUE);				
+	
+	/* last check */
+	if (other_parameters & DYN_GET_FILES_FOR_PROJECT_EXTRA_PAR_PROJECT)
+	{
+		if ((param = gda_set_get_holder ((GdaSet*)dyn_node->plist, "prj_name")) == NULL)
+		{
+			if (priv->mutex)
+				g_mutex_unlock (priv->mutex);
+			return NULL;
+		}
+
+		MP_SET_HOLDER_BATCH_STR(priv, param, project_name, 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);
+		
+/*	DEBUG_PRINT ("symbol_db_engine_get_files_for_project (): query_str is %s",
+				 dyn_node->query_str);
+	DEBUG_PRINT ("%s", "symbol_db_engine_get_files_for_project (): data dump \n");
+	gda_data_model_dump (data, stdout);*/
+	
+	if (!GDA_IS_DATA_MODEL (data) ||
+		gda_data_model_get_n_rows (GDA_DATA_MODEL (data)) <= 0)
+	{
+		if (data != NULL)
+			g_object_unref (data);
+		
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);		
+		return NULL;
+	}
+
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data, 
+												priv->sym_type_conversion_hash,
+												priv->project_directory);	
+}

Added: trunk/plugins/symbol-db/symbol-db-engine-queries.h
==============================================================================
--- (empty file)
+++ trunk/plugins/symbol-db/symbol-db-engine-queries.h	Sat Dec 20 17:44:46 2008
@@ -0,0 +1,201 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2007-2008 <maxcvs email it>
+ * 
+ * anjuta is free software.
+ * 
+ * You may 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 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 anjuta.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _SYMBOL_DB_ENGINE_QUERIES_H_
+#define _SYMBOL_DB_ENGINE_QUERIES_H_
+
+#include <glib-object.h>
+#include <glib.h>
+
+#include "symbol-db-engine.h"
+#include "symbol-db-engine-iterator.h"
+
+
+
+/**********************
+ * ITERATABLE QUERIES
+ **********************/
+
+/**
+ * Use this function to find symbols names by patterns like '%foo_func%'
+ * that will return a family of my_foo_func_1, your_foo_func_2 etc
+ * @name must not be NULL.
+ * @name must include the optional '%' character to have a wider match, e.g. "foo_func%"
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_find_symbol_by_name_pattern (SymbolDBEngine *dbe, 
+									const gchar *pattern, SymExtraInfo sym_info);
+
+/**
+ * @param pattern Pattern you want to search for. If NULL it will use '%' and LIKE for query.
+ *        Please provide a pattern with '%' if you also specify a exact_match = FALSE
+ * @param exact_match Should the pattern be searched for an exact match?
+ * @param filter_kinds Can be NULL. In that case these filters will not be taken into consideration.
+ * @param include_kinds Should the filter_kinds (if not null) be applied as inluded or excluded?
+ * @param global_symbols_search If TRUE only global public function will be searched. If false
+ *		  even private or static (for C language) will be searched.
+ * @param session_projects Should the search, a global search, be filtered by some packages (projects)?
+ *        If yes then provide a GList, if no then pass NULL.	 
+ * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
+ * @param results_offset Skip results_offset results. -1 If you don't want to use this par.
+ * @param sym_info Infos about symbols you want to know.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_find_symbol_by_name_pattern_filtered (SymbolDBEngine *dbe, 
+									const gchar *pattern, 
+									gboolean exact_match,
+									const GPtrArray *filter_kinds,
+									gboolean include_kinds,
+									gboolean global_symbols_search,
+									GList *session_projects,													   
+									gint results_limit, 
+									gint results_offset,
+									SymExtraInfo sym_info);
+
+
+/**
+ * Return an iterator to the data retrieved from database. 
+ * The iterator, if not null, will contain a list of parent classes for the 
+ * given symbol name.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_class_parents (SymbolDBEngine *dbe, const gchar *klass_name, 
+									 const GPtrArray *scope_path, SymExtraInfo sym_info);
+
+/**
+ * Use this function to get parent symbols of a given class.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_class_parents_by_symbol_id (SymbolDBEngine *dbe, 
+												 gint child_klass_symbol_id,
+												 SymExtraInfo sym_info);
+
+/**
+ * Get the scope specified by the line of the file. 
+ * Iterator should contain just one element if the query is successful, no element
+ * or NULL is returned if function went wrong.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_current_scope (SymbolDBEngine *dbe, 
+									const gchar* full_local_file_path, gulong line, 
+									 SymExtraInfo sym_info);
+
+
+/**
+ * Use this function to get symbols of a file.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_file_symbols (SymbolDBEngine *dbe, 
+								   const gchar *file_path, 
+								   SymExtraInfo sym_info);
+
+/**
+ * Use this function to get global symbols only. I.e. private or file-only scoped symbols
+ * will NOT be returned.
+ * @param filter_kinds Can be NULL. In that case we'll return all the kinds of symbols found
+ * at root level [global level]. A maximum of 5 filter_kinds are admitted.
+ * @param include_kinds Should we include in the result the filter_kinds or not?
+ * @param group_them If TRUE then will be issued a 'group by symbol.name' option.
+ * 		If FALSE you can have as result more symbols with the same name but different
+ * 		symbols id. See for example more namespaces declared on different files.
+ * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
+ * @param results_offset Skip results_offset results. -1 If you don't want to use this par. 
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_global_members_filtered (SymbolDBEngine *dbe, 
+									const GPtrArray *filter_kinds,
+									gboolean include_kinds, 
+									gboolean group_them,
+									gint results_limit, 
+									gint results_offset,
+								 	SymExtraInfo sym_info);
+
+/** 
+ * No iterator for now. We need the quickest query possible.
+ * @param scoped_symbol_id Symbol you want to know the parent of.
+ * @param db_file db-relative filename path. eg. /src/foo.c
+ */
+gint
+symbol_db_engine_get_parent_scope_id_by_symbol_id (SymbolDBEngine *dbe, 
+									gint scoped_symbol_id,
+									const gchar* db_file);
+
+/** 
+ * scope_path cannot be NULL.
+ * scope_path will be something like "scope1_kind", "scope1_name", "scope2_kind", 
+ * "scope2_name", NULL 
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_members (SymbolDBEngine *dbe, 
+									const GPtrArray* scope_path, 
+									SymExtraInfo sym_info);
+
+/**
+ * Sometimes it's useful going to query just with ids [and so integers] to have
+ * a little speed improvement.
+ * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
+ * @param results_offset Skip results_offset results. -1 If you don't want to use this par. 
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_members_by_symbol_id (SymbolDBEngine *dbe, 
+									gint scope_parent_symbol_id, 
+									gint results_limit,
+									gint results_offset,
+									SymExtraInfo sym_info);
+
+/**
+ * A filtered version of the symbol_db_engine_get_scope_members_by_symbol_id ().
+ * You can specify which kind of symbols to retrieve, and if include them or exclude.
+ * Kinds are 'namespace', 'class' etc.
+ * @param filter_kinds cannot be NULL.
+ * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
+ * @param results_offset Skip results_offset results. -1 If you don't want to use this par. 
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_scope_members_by_symbol_id_filtered (SymbolDBEngine *dbe, 
+									gint scope_parent_symbol_id, 
+									const GPtrArray *filter_kinds,
+									gboolean include_kinds,														  
+									gint results_limit,
+									gint results_offset,
+									SymExtraInfo sym_info);
+
+/**
+ * Use this function to get infos about a symbol.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_symbol_info_by_id (SymbolDBEngine *dbe, 
+									gint sym_id, 
+									SymExtraInfo sym_info);
+
+/**
+ * Gets the files of a project.
+ * @param project_name name of project you want to know the files of.
+ *        It can be NULL. In that case all the files will be returned.
+ */
+SymbolDBEngineIterator *
+symbol_db_engine_get_files_for_project (SymbolDBEngine *dbe, 
+									const gchar *project_name,
+								 	SymExtraInfo sym_info);
+#endif

Added: trunk/plugins/symbol-db/symbol-db-engine-utils.c
==============================================================================
--- (empty file)
+++ trunk/plugins/symbol-db/symbol-db-engine-utils.c	Sat Dec 20 17:44:46 2008
@@ -0,0 +1,182 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2007-2008 <maxcvs email it>
+ * 
+ * anjuta is free software.
+ * 
+ * You may 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 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 anjuta.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#include <libanjuta/anjuta-debug.h>
+
+#include "symbol-db-engine-queries.h"
+#include "symbol-db-engine-priv.h"
+
+/*
+ * extern declarations 
+ */
+extern inline const GdaStatement *
+sdb_engine_get_statement_by_query_id (SymbolDBEngine * dbe, static_query_type query_id);
+
+extern inline const GdaSet *
+sdb_engine_get_query_parameters_list (SymbolDBEngine *dbe, static_query_type query_id);
+
+extern inline const DynChildQueryNode *
+sdb_engine_get_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 SymExtraInfo sym_info, gsize other_parameters);
+
+extern inline const DynChildQueryNode *
+sdb_engine_insert_dyn_query_node_by_id (SymbolDBEngine *dbe, dyn_query_type query_id,
+									 	SymExtraInfo sym_info, gsize other_parameters,
+										const gchar *sql);
+
+/*
+ * implementation starts here 
+ */
+
+gint 
+symbol_db_glist_compare_func (gconstpointer a, gconstpointer b)
+{
+	return strcmp ((const gchar*)a, (const gchar*)b);
+}
+
+gint
+symbol_db_gtree_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+	return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
+}
+
+gboolean
+symbol_db_engine_is_locked (SymbolDBEngine * dbe)
+{
+	SymbolDBEnginePriv *priv;
+
+	g_return_val_if_fail (dbe != NULL, FALSE);
+	
+	priv = dbe->priv;
+	return priv->scanning_status;
+}
+
+gchar*
+symbol_db_engine_get_full_local_path (SymbolDBEngine *dbe, const gchar* file)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *full_path;
+	
+	g_return_val_if_fail (dbe != NULL, NULL);
+	
+	priv = dbe->priv;
+	full_path = g_strdup_printf ("%s%s", priv->project_directory, file);
+	return full_path;	
+}
+
+gchar*
+symbol_db_engine_get_file_db_path (SymbolDBEngine *dbe, const gchar* full_local_file_path)
+{
+	SymbolDBEnginePriv *priv;
+	gchar *relative_path;
+	const gchar *tmp;
+	g_return_val_if_fail (dbe != NULL, NULL);
+	g_return_val_if_fail (full_local_file_path != NULL, NULL);
+		
+	priv = dbe->priv;
+	
+	if (priv->db_directory == NULL)
+		return NULL;
+
+	if (strlen (priv->project_directory) >= strlen (full_local_file_path)) 
+	{
+		return NULL;
+	}
+
+	tmp = full_local_file_path + strlen (priv->project_directory);
+	relative_path = strdup (tmp);
+
+	return relative_path;
+}
+
+GPtrArray *
+symbol_db_engine_get_files_with_zero_symbols (SymbolDBEngine *dbe)
+{
+	/*select * from file where file_id not in (select file_defined_id from symbol);*/
+	SymbolDBEnginePriv *priv;
+	GdaDataModel *data_model;
+	GPtrArray *files_to_scan;
+	const GdaStatement *stmt;
+	gint i, num_rows = 0;
+
+	g_return_val_if_fail (dbe != NULL, NULL);
+	priv = dbe->priv;
+	
+	if (priv->mutex)
+		g_mutex_lock (priv->mutex);	
+	
+	if ((stmt = sdb_engine_get_statement_by_query_id (dbe,
+								 PREP_QUERY_GET_ALL_FROM_FILE_WHERE_NOT_IN_SYMBOLS))
+		== NULL)
+	{
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}
+
+	data_model = gda_connection_statement_execute_select (priv->db_connection, 
+														  (GdaStatement*)stmt, 
+														  NULL, NULL);
+	
+	if (!GDA_IS_DATA_MODEL (data_model) ||
+		(num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (data_model))) <= 0)
+	{
+		if (data_model != NULL)
+			g_object_unref (data_model);
+		if (priv->mutex)
+			g_mutex_unlock (priv->mutex);
+		return NULL;
+	}	
+		
+	/* initialize the array */
+	files_to_scan = g_ptr_array_new ();
+
+	/* we can now scan each filename entry to check the last modification time. */
+	for (i = 0; i < num_rows; i++)
+	{
+		const GValue *value;
+		const gchar *file_name;
+		gchar *file_abs_path = NULL;
+
+		if ((value =
+			 gda_data_model_get_value_at (data_model, 
+						gda_data_model_get_column_index(data_model, "db_file_path"),
+										  i, NULL)) == NULL)
+		{
+			continue;
+		}
+
+		/* build abs path. */
+		file_name = g_value_get_string (value);
+		file_abs_path = symbol_db_engine_get_full_local_path (dbe, file_name);
+		g_ptr_array_add (files_to_scan, file_abs_path);
+	}
+
+	g_object_unref (data_model);
+	
+	if (priv->mutex)
+		g_mutex_unlock (priv->mutex);
+	
+	return files_to_scan;
+}

Added: trunk/plugins/symbol-db/symbol-db-engine-utils.h
==============================================================================
--- (empty file)
+++ trunk/plugins/symbol-db/symbol-db-engine-utils.h	Sat Dec 20 17:44:46 2008
@@ -0,0 +1,86 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Massimo Cora' 2007-2008 <maxcvs email it>
+ * 
+ * anjuta is free software.
+ * 
+ * You may 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 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 anjuta.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _SYMBOL_DB_ENGINE_UTILS_H_
+#define _SYMBOL_DB_ENGINE_UTILS_H_
+
+#include <glib-object.h>
+#include <glib.h>
+
+
+/**
+ * Simple compare function for GTree(s)
+ */
+gint
+symbol_db_gtree_compare_func (gconstpointer a, gconstpointer b, gpointer user_data);
+
+/**
+ * Simple compare function for GList(s)
+ */
+gint
+symbol_db_glist_compare_func (gconstpointer a, gconstpointer b);
+
+
+/**
+ * Return full_local_path given a relative-to-db file path.
+ * User must care to free the returned string.
+ * @param db_file Relative path inside project.
+ */
+gchar*
+symbol_db_engine_get_full_local_path (SymbolDBEngine *dbe, const gchar* db_file);
+
+
+/**
+ * Return a db-relativ file path. Es. given the full_local_file_path 
+ * /home/user/foo_project/src/foo.c returned file should be /src/foo.c.
+ * Return NULL on error.
+ */
+gchar*
+symbol_db_engine_get_file_db_path (SymbolDBEngine *dbe, const gchar* full_local_file_path);
+
+/** 
+ * Hash table that converts from a char like 'class' 'struct' etc to an 
+ * IANJUTA_SYMBOL_TYPE
+ */
+const GHashTable*
+symbol_db_engine_get_sym_type_conversion_hash (SymbolDBEngine *dbe);
+
+/**
+ * Return a GPtrArray that must be freed from caller.
+ */
+GPtrArray *
+symbol_db_engine_fill_type_array (IAnjutaSymbolType match_types);
+
+/**
+ * Try to get all the files with zero symbols: these should be the ones
+ * excluded by an abort on population process.
+ * @return A GPtrArray with paths on disk of the files. Must be freed by caller.
+ * @return NULL if no files are found.
+ */
+GPtrArray *
+symbol_db_engine_get_files_with_zero_symbols (SymbolDBEngine *dbe);
+
+
+
+#endif

Modified: trunk/plugins/symbol-db/symbol-db-engine.h
==============================================================================
--- trunk/plugins/symbol-db/symbol-db-engine.h	(original)
+++ trunk/plugins/symbol-db/symbol-db-engine.h	Sat Dec 20 17:44:46 2008
@@ -25,427 +25,14 @@
 #ifndef _SYMBOL_DB_ENGINE_H_
 #define _SYMBOL_DB_ENGINE_H_
 
-#include <glib-object.h>
-#include <glib.h>
-#include <libanjuta/interfaces/ianjuta-symbol.h>
-#include <libanjuta/anjuta-plugin.h>
-#include "symbol-db-engine-iterator.h"
-
-G_BEGIN_DECLS
-
-#define SYMBOL_TYPE_DB_ENGINE             (sdb_engine_get_type ())
-#define SYMBOL_DB_ENGINE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), SYMBOL_TYPE_DB_ENGINE, SymbolDBEngine))
-#define SYMBOL_DB_ENGINE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SYMBOL_TYPE_DB_ENGINE, SymbolDBEngineClass))
-#define SYMBOL_IS_DB_ENGINE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SYMBOL_TYPE_DB_ENGINE))
-#define SYMBOL_IS_DB_ENGINE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SYMBOL_TYPE_DB_ENGINE))
-#define SYMBOL_DB_ENGINE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SYMBOL_TYPE_DB_ENGINE, SymbolDBEngineClass))
-
-typedef struct _SymbolDBEngineClass SymbolDBEngineClass;
-typedef struct _SymbolDBEngine SymbolDBEngine;
-typedef struct _SymbolDBEnginePriv SymbolDBEnginePriv;
-
-struct _SymbolDBEngineClass
-{
-	GObjectClass parent_class;
-	
-	/* signals */
-	void (* single_file_scan_end) 	();
-	void (* scan_end) 				(gint process_id);
-	void (* symbol_inserted) 		(gint symbol_id);
-	void (* symbol_updated)  		(gint symbol_id);
-	void (* symbol_scope_updated)  	(gint symbol_id);	
-	void (* symbol_removed)  		(gint symbol_id);
-};
-
-struct _SymbolDBEngine
-{
-	GObject parent_instance;
-	SymbolDBEnginePriv *priv;
-};
-
-/* WARNING: these must match the ones on libanjuta.idl [AnjutaSymbol::Field] */
-typedef enum {
-	SYMINFO_SIMPLE = 1,
-	SYMINFO_FILE_PATH = 2,
-	SYMINFO_IMPLEMENTATION = 4,
-	SYMINFO_ACCESS = 8,
-	SYMINFO_KIND = 16,
-	SYMINFO_TYPE = 32,
-	SYMINFO_TYPE_NAME = 64,
-	SYMINFO_LANGUAGE = 128,
-	SYMINFO_FILE_IGNORE = 256,
-	SYMINFO_FILE_INCLUDE = 512,
-	SYMINFO_PROJECT_NAME = 1024,
-	SYMINFO_WORKSPACE_NAME = 2048
-	
-} SymExtraInfo;
-
-GType sdb_engine_get_type (void) G_GNUC_CONST;
-
-
-/**
- * Create a new instance of an engine. 
- * @param ctags_path is mandatory. No NULL value is accepted.
+/* if you need to use symbo-db-engine in your program, just include this
+ * header file. It'll automatically include all the things needed
  */
-SymbolDBEngine* 
-symbol_db_engine_new (const gchar * ctags_path);
-
-/**
- * Set a new path for ctags executable.
- */ 
-void 
-symbol_db_engine_set_ctags_path (SymbolDBEngine *dbe,
-								  const gchar * ctags_path);
-
-/**
- * Be sure to check lock status with this function before calling
- * something else below. If you call a scanning function while
- * dbe is locked there can be some weird behaviours.
- */
-gboolean
-symbol_db_engine_is_locked (SymbolDBEngine *dbe);
-
-/**
- * Open or create a new database at given directory. 
- * Be sure to give a base_db_path with the ending '/' for directory.
- * @param base_db_path directory where .anjuta_sym_db.db will be stored. It can be
- *        different from project_directory
- *        E.g: a db on '/tmp/foo/' dir.
- * @param prj_directory project directory. It may be different from base_db_path.
- *        It's mainly used to map files inside the db. Say for example that you want to
- *        add to a project a file /home/user/project/foo_prj/src/file.c with a project
- *        directory of /home/user/project/foo_prj/. On db it'll be represented as
- *        src/file.c. In this way you can move around the project dir without dealing
- *        with relative paths.
- */
-gboolean 
-symbol_db_engine_open_db (SymbolDBEngine *dbe, const gchar* base_db_path,
-						  const gchar * prj_directory);
-
-/** Disconnect db, gda client and db_connection */
-gboolean 
-symbol_db_engine_close_db (SymbolDBEngine *dbe);
-
-/**
- * Check if the database already exists into the prj_directory
- */
-gboolean
-symbol_db_engine_db_exists (SymbolDBEngine * dbe, const gchar * prj_directory);
-
-/**
- * Check if a file is already present [and scanned] in db.
- */
-gboolean
-symbol_db_engine_file_exists (SymbolDBEngine * dbe, const gchar * abs_file_path);
-
-/** Add a new workspace to an opened database. */
-gboolean 
-symbol_db_engine_add_new_workspace (SymbolDBEngine *dbe, const gchar* workspace);
-
-
-/** 
- * Add a new project to workspace to an opened database.
- *
- * @param workspace Can be NULL. In that case a default workspace will be created, 
- * 					and project will depend on that.
- * @param project Project name. Must NOT be NULL.
- */
-gboolean 
-symbol_db_engine_add_new_project (SymbolDBEngine *dbe, const gchar* workspace, 
-								  const gchar* project);
-
-/** 
- * Test project existence. 
- * @return false if project isn't found
- */
-gboolean 
-symbol_db_engine_project_exists (SymbolDBEngine *dbe, /*gchar* workspace, */
-								  const gchar* project_name);
-
-
-/** 
- * Add a group of files of a single language to a project. It will perform also 
- * a symbols scannig/populating of db if scan_symbols is TRUE.
- * This function requires an opened db, i.e. calling before
- * symbol_db_engine_open_db ().
- * @note if some file fails to enter the db the function will return without
- * processing the remaining files.
- * @param project_name something like 'foo_project', or 'helloworld_project'. Can be NULL,
- *        for example when you're populating after abort.
- * @param project_directory something like the base path '/home/user/projects/foo_project/'
- *        Be sure not to exchange the db_directory with project_directory! they're different!
- *        It can be NULL but ONLY if you're doing an 'import_after_abort' scan, i.e.
- *        files entries have already a connection with the parent project.
- * @param files_path requires full path to files on disk. Ctags itself requires that.
- *        it must be something like "/home/path/to/my/foo/file.xyz". Also it requires
- *		  a language string to represent the file.
- *        An example of files_path array composition can be: 
- *        "/home/user/foo_project/foo1.c", "/home/user/foo_project/foo2.cpp", 
- * 		  "/home/user/foo_project/foo3.java".
- * @param languages is an array of 'languages'. It must have the same number of 
- *		  elments that files_path has. It should be populated like this: "C", "C++",
- *		  "Java"
- * 		  This is done to be uniform to the language-manager plugin.
- * @param force_scan If FALSE a check on db will be done to see
- *		  whether the file is already present or not.
- * @return scan process id if insertion is successful, -1 on error.
- */
-gint
-symbol_db_engine_add_new_files (SymbolDBEngine *dbe, 
-								const gchar * project_name,
-							    const GPtrArray *files_path,
-								const GPtrArray *languages,
-								gboolean force_scan);
-
-/**
- * Update symbols of the whole project. It scans all file symbols etc. 
- * If force is true then update forcely all the files.
- */
-gint
-symbol_db_engine_update_project_symbols (SymbolDBEngine *dbe, const gchar *project);
-
-
-/** Remove a file, together with its symbols, from a project. */
-gboolean 
-symbol_db_engine_remove_file (SymbolDBEngine *dbe, const gchar* project, 
-							  const gchar* file);
-
-void
-symbol_db_engine_remove_files (SymbolDBEngine * dbe, const gchar * project,
-							  const GPtrArray * files);
-
-/**
- * Update symbols of saved files. 
- * @note WARNING: files_path and it's contents will be freed on 
- * on_scan_update_files_symbols_end () callback.
- * @return scan process id if insertion is successful, -1 on 'no files scanned'.
- */
-gint
-symbol_db_engine_update_files_symbols (SymbolDBEngine *dbe, const gchar *project, 
-									   GPtrArray *files_path,
-									   gboolean update_prj_analyse_time);
-
-/**
- * Update symbols of a file by a memory-buffer to perform a real-time updating 
- * of symbols. 
- * real_files_list: full path on disk to 'real file' to update. e.g.
- * /home/foouser/fooproject/src/main.c. 
- * They'll be freed inside this function when the scan has ended. 
- * @return scan process id if insertion is successful, -1 on error.
- */
-gint
-symbol_db_engine_update_buffer_symbols (SymbolDBEngine * dbe, const gchar * project,
-										GPtrArray * real_files_list,
-										const GPtrArray * text_buffers,
-										const GPtrArray * buffer_sizes);
-
-/**
- * Return full_local_path given a relative-to-db file path.
- * User must care to free the returned string.
- * @param db_file Relative path inside project.
- */
-gchar*
-symbol_db_engine_get_full_local_path (SymbolDBEngine *dbe, const gchar* db_file);
-
 
-/**
- * Return a db-relativ file path. Es. given the full_local_file_path 
- * /home/user/foo_project/src/foo.c returned file should be /src/foo.c.
- * Return NULL on error.
- */
-gchar*
-symbol_db_engine_get_file_db_path (SymbolDBEngine *dbe, const gchar* full_local_file_path);
-
-/** 
- * Hash table that converts from a char like 'class' 'struct' etc to an 
- * IANJUTA_SYMBOL_TYPE
- */
-const GHashTable*
-symbol_db_engine_get_sym_type_conversion_hash (SymbolDBEngine *dbe);
-
-/**
- * Return a GPtrArray that must be freed from caller.
- */
-GPtrArray *
-symbol_db_engine_fill_type_array (IAnjutaSymbolType match_types);
-
-/**
- * Try to get all the files with zero symbols: these should be the ones
- * excluded by an abort on population process.
- * @return A GPtrArray with paths on disk of the files. Must be freed by caller.
- * @return NULL if no files are found.
- */
-GPtrArray *
-symbol_db_engine_get_files_with_zero_symbols (SymbolDBEngine *dbe);
-
-
-/**********************
- * ITERATABLE QUERIES
- **********************/
-
-/**
- * Use this function to find symbols names by patterns like '%foo_func%'
- * that will return a family of my_foo_func_1, your_foo_func_2 etc
- * @name must not be NULL.
- * @name must include the optional '%' character to have a wider match, e.g. "foo_func%"
- */
-SymbolDBEngineIterator *
-symbol_db_engine_find_symbol_by_name_pattern (SymbolDBEngine *dbe, 
-									const gchar *pattern, SymExtraInfo sym_info);
-
-/**
- * @param pattern Pattern you want to search for. If NULL it will use '%' and LIKE for query.
- *        Please provide a pattern with '%' if you also specify a exact_match = FALSE
- * @param exact_match Should the pattern be searched for an exact match?
- * @param filter_kinds Can be NULL. In that case these filters will not be taken into consideration.
- * @param include_kinds Should the filter_kinds (if not null) be applied as inluded or excluded?
- * @param global_symbols_search If TRUE only global public function will be searched. If false
- *		  even private or static (for C language) will be searched.
- * @param session_projects Should the search, a global search, be filtered by some packages (projects)?
- *        If yes then provide a GList, if no then pass NULL.	 
- * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
- * @param results_offset Skip results_offset results. -1 If you don't want to use this par.
- * @param sym_info Infos about symbols you want to know.
- */
-SymbolDBEngineIterator *
-symbol_db_engine_find_symbol_by_name_pattern_filtered (SymbolDBEngine *dbe, 
-									const gchar *pattern, 
-									gboolean exact_match,
-									const GPtrArray *filter_kinds,
-									gboolean include_kinds,
-									gboolean global_symbols_search,
-									GList *session_projects,													   
-									gint results_limit, 
-									gint results_offset,
-									SymExtraInfo sym_info);
-
-
-/**
- * Return an iterator to the data retrieved from database. 
- * The iterator, if not null, will contain a list of parent classes for the 
- * given symbol name.
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_class_parents (SymbolDBEngine *dbe, const gchar *klass_name, 
-									 const GPtrArray *scope_path, SymExtraInfo sym_info);
-
-/**
- * Use this function to get parent symbols of a given class.
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_class_parents_by_symbol_id (SymbolDBEngine *dbe, 
-												 gint child_klass_symbol_id,
-												 SymExtraInfo sym_info);
-
-/**
- * Get the scope specified by the line of the file. 
- * Iterator should contain just one element if the query is successful, no element
- * or NULL is returned if function went wrong.
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_current_scope (SymbolDBEngine *dbe, 
-									const gchar* full_local_file_path, gulong line, 
-									 SymExtraInfo sym_info);
-
-
-/**
- * Use this function to get symbols of a file.
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_file_symbols (SymbolDBEngine *dbe, 
-								   const gchar *file_path, 
-								   SymExtraInfo sym_info);
-
-/**
- * Use this function to get global symbols only. I.e. private or file-only scoped symbols
- * will NOT be returned.
- * @param filter_kinds Can be NULL. In that case we'll return all the kinds of symbols found
- * at root level [global level]. A maximum of 5 filter_kinds are admitted.
- * @param include_kinds Should we include in the result the filter_kinds or not?
- * @param group_them If TRUE then will be issued a 'group by symbol.name' option.
- * 		If FALSE you can have as result more symbols with the same name but different
- * 		symbols id. See for example more namespaces declared on different files.
- * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
- * @param results_offset Skip results_offset results. -1 If you don't want to use this par. 
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_global_members_filtered (SymbolDBEngine *dbe, 
-									const GPtrArray *filter_kinds,
-									gboolean include_kinds, 
-									gboolean group_them,
-									gint results_limit, 
-									gint results_offset,
-								 	SymExtraInfo sym_info);
-
-/** 
- * No iterator for now. We need the quickest query possible.
- * @param scoped_symbol_id Symbol you want to know the parent of.
- * @param db_file db-relative filename path. eg. /src/foo.c
- */
-gint
-symbol_db_engine_get_parent_scope_id_by_symbol_id (SymbolDBEngine *dbe, 
-									gint scoped_symbol_id,
-									const gchar* db_file);
-
-/** 
- * scope_path cannot be NULL.
- * scope_path will be something like "scope1_kind", "scope1_name", "scope2_kind", 
- * "scope2_name", NULL 
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_scope_members (SymbolDBEngine *dbe, 
-									const GPtrArray* scope_path, 
-									SymExtraInfo sym_info);
-
-/**
- * Sometimes it's useful going to query just with ids [and so integers] to have
- * a little speed improvement.
- * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
- * @param results_offset Skip results_offset results. -1 If you don't want to use this par. 
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_scope_members_by_symbol_id (SymbolDBEngine *dbe, 
-									gint scope_parent_symbol_id, 
-									gint results_limit,
-									gint results_offset,
-									SymExtraInfo sym_info);
-
-/**
- * A filtered version of the symbol_db_engine_get_scope_members_by_symbol_id ().
- * You can specify which kind of symbols to retrieve, and if include them or exclude.
- * Kinds are 'namespace', 'class' etc.
- * @param filter_kinds cannot be NULL.
- * @param results_limit Limit results to an upper bound. -1 If you don't want to use this par.
- * @param results_offset Skip results_offset results. -1 If you don't want to use this par. 
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_scope_members_by_symbol_id_filtered (SymbolDBEngine *dbe, 
-									gint scope_parent_symbol_id, 
-									const GPtrArray *filter_kinds,
-									gboolean include_kinds,														  
-									gint results_limit,
-									gint results_offset,
-									SymExtraInfo sym_info);
-
-/**
- * Use this function to get infos about a symbol.
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_symbol_info_by_id (SymbolDBEngine *dbe, 
-									gint sym_id, 
-									SymExtraInfo sym_info);
-
-/**
- * Gets the files of a project.
- * @param project_name name of project you want to know the files of.
- *        It can be NULL. In that case all the files will be returned.
- */
-SymbolDBEngineIterator *
-symbol_db_engine_get_files_for_project (SymbolDBEngine *dbe, 
-									const gchar *project_name,
-								 	SymExtraInfo sym_info);
-
-G_END_DECLS
-
-#endif /* _SYMBOL_DB_ENGINE_H_ */
+#include "symbol-db-engine-core.h"
+#include "symbol-db-engine-queries.h"
+#include "symbol-db-engine-utils.h"
+#include "symbol-db-engine-iterator.h"
+#include "symbol-db-engine-iterator-node.h"
 
+#endif

Modified: trunk/plugins/symbol-db/symbol-db-view-locals.c
==============================================================================
--- trunk/plugins/symbol-db/symbol-db-view-locals.c	(original)
+++ trunk/plugins/symbol-db/symbol-db-view-locals.c	Sat Dec 20 17:44:46 2008
@@ -29,8 +29,6 @@
 
 #include "symbol-db-view-locals.h"
 #include "symbol-db-engine.h"
-#include "symbol-db-engine-iterator.h"
-#include "symbol-db-engine-iterator-node.h"
 #include "symbol-db-view.h"
 
 
@@ -88,12 +86,6 @@
 trigger_on_symbol_inserted (SymbolDBViewLocals *dbvl, gint symbol_id);
 
 
-static gint
-gtree_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
-{
-	return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
-}
-
 static void
 waiting_for_symbol_destroy (WaitingForSymbol *wfs)
 {
@@ -1432,12 +1424,12 @@
 	}
 	else 
 	{	
-		priv->nodes_displayed = g_tree_new_full ((GCompareDataFunc)&gtree_compare_func, 
+		priv->nodes_displayed = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
 										 NULL,
 										 NULL,
 										 (GDestroyNotify)&gtk_tree_row_reference_free);		
 
-		priv->waiting_for = g_tree_new_full ((GCompareDataFunc)&gtree_compare_func, 
+		priv->waiting_for = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
 										 NULL,
 										 NULL,
 										 NULL);

Modified: trunk/plugins/symbol-db/symbol-db-view-search.c
==============================================================================
--- trunk/plugins/symbol-db/symbol-db-view-search.c	(original)
+++ trunk/plugins/symbol-db/symbol-db-view-search.c	Sat Dec 20 17:44:46 2008
@@ -35,8 +35,6 @@
 
 #include "symbol-db-view-search.h"
 #include "symbol-db-engine.h"
-#include "symbol-db-engine-iterator.h"
-#include "symbol-db-engine-iterator-node.h"
 #include "symbol-db-view.h"
 
 /* private class */

Modified: trunk/plugins/symbol-db/symbol-db-view-search.h
==============================================================================
--- trunk/plugins/symbol-db/symbol-db-view-search.h	(original)
+++ trunk/plugins/symbol-db/symbol-db-view-search.h	Sat Dec 20 17:44:46 2008
@@ -27,7 +27,6 @@
 
 #include <glib-object.h>
 #include <gtk/gtk.h>
-#include "symbol-db-engine-iterator.h"
 #include "symbol-db-engine.h"
 
 G_BEGIN_DECLS

Modified: trunk/plugins/symbol-db/symbol-db-view.c
==============================================================================
--- trunk/plugins/symbol-db/symbol-db-view.c	(original)
+++ trunk/plugins/symbol-db/symbol-db-view.c	Sat Dec 20 17:44:46 2008
@@ -28,8 +28,6 @@
 #include <libanjuta/anjuta-debug.h>
 #include "symbol-db-view.h"
 #include "symbol-db-engine.h"
-#include "symbol-db-engine-iterator.h"
-#include "symbol-db-engine-iterator-node.h"
 
 #define DUMMY_SYMBOL_ID		G_MININT32+1
 
@@ -80,12 +78,6 @@
 trigger_on_symbol_inserted (SymbolDBView *dbv, gint symbol_id);
 
 
-static gint
-gtree_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
-{
-	return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
-}
-
 static void
 waiting_for_symbol_destroy (WaitingForSymbol *wfs)
 {	
@@ -189,7 +181,7 @@
 		 * one proposed by the doc is too complex.. create a list of the items
 		 * and reparse them with g_tree_remove...
 		 */
-		priv->waiting_for = g_tree_new_full ((GCompareDataFunc)&gtree_compare_func, 
+		priv->waiting_for = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
 									 NULL,
 									 NULL,
 									 NULL);
@@ -1412,7 +1404,7 @@
 	/* create a GTree where to store the row_expanding ids of the gfuncs.
 	 * we would be able then to g_source_remove them on row_collapsed
 	 */
-	priv->expanding_gfunc_ids = g_tree_new_full ((GCompareDataFunc)&gtree_compare_func, 
+	priv->expanding_gfunc_ids = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
 										 NULL, NULL, NULL);
 	
 	/* Tree and his model */
@@ -1852,12 +1844,12 @@
 	store = sdb_view_create_new_store ();
 	gtk_tree_view_set_model (GTK_TREE_VIEW (dbv), GTK_TREE_MODEL (store));
 	
-	priv->nodes_displayed = g_tree_new_full ((GCompareDataFunc)&gtree_compare_func, 
+	priv->nodes_displayed = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
 										 NULL,
 										 NULL,
 										 (GDestroyNotify)&gtk_tree_row_reference_free);
 
-	priv->waiting_for = g_tree_new_full ((GCompareDataFunc)&gtree_compare_func, 
+	priv->waiting_for = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func, 
 									 NULL,
 									 NULL,
 									 NULL);



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