2007-12-01 Massimo Cora\' <maxcvs@email.it>
[anjuta-git-plugin.git] / plugins / symbol-db / symbol-db-engine.c
blob1782a5a28fdd4c03506893d440d7f10c383e0788
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta
4 * Copyright (C) Massimo Cora' 2007 <maxcvs@email.it>
5 *
6 * anjuta is free software.
7 *
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
13 * anjuta is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with anjuta. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
27 interesting queries:
29 ------------------------
30 * get all namespaces.
31 select symbol.name from symbol join sym_kind on symbol.kind_id =
32 sym_kind.sym_kind_id where sym_kind.kind_name = "namespace";
34 ------------------------
35 * get all symbols_id which scope is under all namespaces' ones
36 select * from symbol where scope_id in (select symbol.scope_definition_id
37 from symbol join sym_kind on symbol.kind_id = sym_kind.sym_kind_id where
38 sym_kind.kind_name = "namespace");
40 ------------------------
41 * get all symbols which have a scope_id of symbol X. X is a symbol of kind namespace,
42 class, struct etc. Symbol X can be retrieved by something like
43 select * from symbol join sym_type on symbol.type_id = sym_type.type_id where
44 symbol.name = "First" and sym_type.type = "namespace";
45 our query is:
46 select * from symbol where scope_id = ;
47 at the end we have:
49 select * from symbol where scope_id = (select scope_definition_id from symbol join
50 sym_type on symbol.type_id = sym_type.type_id where symbol.name =
51 "First" and sym_type.type = "namespace");
54 ------------------------
55 * get a symbol by its name and type. In this case we want to search for the
56 class Fourth_2_class
57 select * from symbol join sym_type on symbol.type_id = sym_type.type_id where
58 symbol.name = "Fourth_2_class" and sym_type.type = "class";
60 sqlite> select * from symbol join sym_kind on symbol.kind_id = sym_kind.sym_kind_id
61 join scope on scope.scope_id = symbol.scope_id
62 join sym_type on sym_type.type_id = scope.type_id
63 where symbol.name = "Fourth_2_class"
64 and sym_kind.kind_name = "class"
65 and scope = "Fourth"
66 and sym_type.type = "namespace";
68 183|13|Fourth_2_class|52|0||140|137|175|8|-1|-1|0|8|class|137|Fourth|172|172|namespace|Fourth
70 //// alternativa ////
71 = get the *derived symbol*
72 select * from symbol
73 join sym_kind on symbol.kind_id = sym_kind.sym_kind_id
74 where symbol.name = "Fourth_2_class"
75 and sym_kind.kind_name = "class"
76 and symbol.scope_id in (select scope.scope_id from scope
77 join sym_type on scope.type_id = sym_type.type_id
78 where sym_type.type = 'namespace'
79 and sym_type.type_name = 'Fourth');
81 query that get the symbol's parent classes
83 select symbol_id_base, symbol.name from heritage
84 join symbol on heritage.symbol_id_base = symbol.symbol_id
85 where symbol_id_derived = (
86 select symbol_id from symbol
87 join sym_kind on symbol.kind_id = sym_kind.sym_kind_id
88 where symbol.name = "Fourth_2_class"
89 and sym_kind.kind_name = "class"
90 and symbol.scope_id in (
91 select scope.scope_id from scope
92 join sym_type on scope.type_id = sym_type.type_id
93 where sym_type.type = 'namespace'
94 and sym_type.type_name = 'Fourth'
99 182|Fourth_1_class
104 #include <time.h>
105 #include <unistd.h>
106 #include <sys/types.h>
107 #include <sys/mman.h>
108 #include <signal.h>
109 #include <fcntl.h> /* For O_* constants */
110 #include <string.h>
112 #include <libgnomevfs/gnome-vfs.h>
113 #include <libanjuta/anjuta-debug.h>
114 #include <libanjuta/anjuta-launcher.h>
115 #include <libgda/libgda.h>
116 #include "readtags.h"
117 #include "symbol-db-engine.h"
118 #include "symbol-db-engine-iterator.h"
120 /* file should be specified without the ".db" extension. */
121 #define ANJUTA_DB_FILE ".anjuta_sym_db"
123 #define TABLES_SQL ANJUTA_DATA_DIR"/tables.sql"
125 #define CTAGS_MARKER "#_#\n"
127 // FIXME: detect it by prefs
128 #define CTAGS_PATH "/usr/bin/ctags"
130 #define THREADS_MONITOR_LAUNCH_DELAY 200
131 #define THREADS_MAX_CONCURRENT 15
132 #define TRIGGER_SIGNALS_DELAY 500
133 #define TRIGGER_MAX_CLOSURE_RETRIES 10
134 #define THREAD_MAX_CLOSURE_RETRIES 20
136 enum {
137 DO_UPDATE_SYMS = 1,
138 DO_UPDATE_SYMS_AND_EXIT,
139 DONT_UPDATE_SYMS,
140 DONT_UPDATE_SYMS_AND_EXIT,
141 DONT_FAKE_UPDATE_SYMS,
142 END_UPDATE_GROUP_SYMS
145 typedef enum
147 PREP_QUERY_WORKSPACE_NEW = 0,
148 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
149 PREP_QUERY_PROJECT_NEW,
150 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
151 PREP_QUERY_UPDATE_PROJECT_ANALIZE_TIME,
152 PREP_QUERY_FILE_NEW,
153 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
154 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME,
155 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID,
156 PREP_QUERY_UPDATE_FILE_ANALIZE_TIME,
157 PREP_QUERY_LANGUAGE_NEW,
158 PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
159 PREP_QUERY_SYM_TYPE_NEW,
160 PREP_QUERY_GET_SYM_TYPE_ID,
161 PREP_QUERY_SYM_KIND_NEW,
162 PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
163 PREP_QUERY_SYM_ACCESS_NEW,
164 PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
165 PREP_QUERY_SYM_IMPLEMENTATION_NEW,
166 PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
167 PREP_QUERY_HERITAGE_NEW,
168 PREP_QUERY_SCOPE_NEW,
169 PREP_QUERY_GET_SCOPE_ID,
170 PREP_QUERY_TMP_HERITAGE_NEW,
171 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE,
172 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS,
173 PREP_QUERY_TMP_HERITAGE_DELETE_ALL,
174 PREP_QUERY_SYMBOL_NEW,
175 PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
176 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
177 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
178 PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID,
179 PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY,
180 PREP_QUERY_UPDATE_SYMBOL_ALL,
181 PREP_QUERY_GET_REMOVED_IDS,
182 PREP_QUERY_TMP_REMOVED_DELETE_ALL,
183 PREP_QUERY_COUNT
184 } query_type;
187 typedef struct _query_node
189 query_type query_id;
190 gchar *query_str;
191 GdaQuery *query;
193 } query_node;
196 /* *MUST* respect query_type enum order. */
197 /* FIXME: 'LIMIT' keyword. This can be used to
198 * speed up some select(s). Please upgrade them as soon as the library support
199 * it.
201 static query_node query_list[PREP_QUERY_COUNT] = {
202 /* -- workspace -- */
204 PREP_QUERY_WORKSPACE_NEW,
205 "INSERT INTO workspace (workspace_name, analize_time) "
206 "VALUES (## /* name:'wsname' type:gchararray */,"
207 "datetime ('now', 'localtime'))",
208 NULL
211 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
212 "SELECT workspace_id FROM workspace WHERE workspace_name = ## /* name:'wsname' "
213 "type:gchararray */",
214 NULL
216 /* -- project -- */
218 PREP_QUERY_PROJECT_NEW,
219 "INSERT INTO project (project_name, wrkspace_id, analize_time) "
220 "VALUES (## /* name:'prjname' type:gchararray */,"
221 "## /* name:'wsid' type:gint */, datetime ('now', 'localtime'))",
222 NULL
225 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
226 "SELECT project_id FROM project WHERE project_name = ## /* name:'prjname' "
227 "type:gchararray */",
228 NULL
231 PREP_QUERY_UPDATE_PROJECT_ANALIZE_TIME,
232 "UPDATE project SET analize_time = datetime('now', 'localtime') WHERE "
233 "project_name = ## /* name:'prjname' type:gchararray */",
234 NULL
236 /* -- file -- */
238 PREP_QUERY_FILE_NEW,
239 "INSERT INTO file (file_path, prj_id, lang_id, analize_time) VALUES ("
240 "## /* name:'filepath' type:gchararray */, ## /* name:'prjid' "
241 "type:gint */, ## /* name:'langid' type:gint */, "
242 "datetime ('now', 'localtime'))",
243 NULL
246 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
247 "SELECT file_id FROM file WHERE file_path = ## /* name:'filepath' "
248 "type:gchararray */",
249 NULL
252 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME,
253 "SELECT * FROM file WHERE prj_id = (SELECT project_id FROM project "
254 "WHERE project_name = ## /* name:'prjname' type:gchararray */)",
255 NULL
258 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID,
259 "SELECT * FROM file WHERE prj_id = ## /* name:'prjid' type:gint */",
261 "SELECT * FROM file JOIN project on project_id = prj_id WHERE "\
262 "project.name = ## / * name:'prjname' type:gchararray * /",
264 NULL
267 PREP_QUERY_UPDATE_FILE_ANALIZE_TIME,
268 "UPDATE file SET analize_time = datetime('now', 'localtime') WHERE "
269 "file_path = ## /* name:'filepath' type:gchararray */",
270 NULL},
271 /* -- language -- */
273 PREP_QUERY_LANGUAGE_NEW,
274 "INSERT INTO language (language_name) VALUES (## /* name:'langname' "
275 "type:gchararray */)",
276 NULL
279 PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
280 "SELECT language_id FROM language WHERE language_name = ## /* name:'langname' "
281 "type:gchararray */",
282 NULL
284 /* -- sym type -- */
286 PREP_QUERY_SYM_TYPE_NEW,
287 "INSERT INTO sym_type (type, type_name) VALUES (## /* name:'type' "
288 "type:gchararray */, ## /* name:'typename' type:gchararray */)",
289 NULL
292 PREP_QUERY_GET_SYM_TYPE_ID,
293 "SELECT type_id FROM sym_type WHERE type = ## /* name:'type' "
294 "type:gchararray */ AND type_name = ## /* name:'typename' "
295 "type:gchararray */",
296 NULL
298 /* -- sym kind -- */
300 PREP_QUERY_SYM_KIND_NEW,
301 "INSERT INTO sym_kind (kind_name) VALUES(## /* name:'kindname' "
302 "type:gchararray */)",
303 NULL
306 PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
307 "SELECT sym_kind_id FROM sym_kind WHERE kind_name = ## /* "
308 "name:'kindname' type:gchararray */",
309 NULL
311 /* -- sym access -- */
313 PREP_QUERY_SYM_ACCESS_NEW,
314 "INSERT INTO sym_access (access_name) VALUES(## /* name:'accesskind' "
315 "type:gchararray */)",
316 NULL
319 PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
320 "SELECT access_kind_id FROM sym_access WHERE access_name = ## /* "
321 "name:'accesskind' type:gchararray */",
322 NULL
324 /* -- sym implementation -- */
326 PREP_QUERY_SYM_IMPLEMENTATION_NEW,
327 "INSERT INTO sym_implementation (implementation_name) VALUES(## /* name:'implekind' "
328 "type:gchararray */)",
329 NULL
332 PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
333 "SELECT sym_impl_id FROM sym_implementation WHERE kind = ## /* "
334 "name:'implekind' type:gchararray */",
335 NULL
337 /* -- heritage -- */
339 PREP_QUERY_HERITAGE_NEW,
340 "INSERT INTO heritage (symbol_id_base, symbol_id_derived) VALUES(## /* "
341 "name:'symbase' type:gint */, ## /* name:'symderived' type:gint */)",
342 NULL
344 /* -- scope -- */
346 PREP_QUERY_SCOPE_NEW,
347 "INSERT INTO scope (scope_name, type_id) VALUES(## /* name:'scope' "
348 "type:gchararray */, ## /* name:'typeid' type:gint */)",
349 NULL
352 PREP_QUERY_GET_SCOPE_ID,
353 "SELECT scope_id FROM scope WHERE scope_name = ## /* name:'scope' "
354 "type:gchararray */ AND type_id = ## /* name:'typeid' type:gint */",
355 NULL
357 /* -- tmp heritage -- */
359 PREP_QUERY_TMP_HERITAGE_NEW,
360 "INSERT INTO __tmp_heritage_scope (symbol_referer_id, field_inherits, "
361 "field_struct, field_typeref, field_enum, field_union, "
362 "field_class, field_namespace) VALUES (## /* name:'symreferid' "
363 "type:gint */, ## /* name:'finherits' type:gchararray */, ## /* "
364 "name:'fstruct' type:gchararray */, ## /* name:'ftyperef' "
365 "type:gchararray */, ## /* name:'fenum' type:gchararray */, ## /* "
366 "name:'funion' type:gchararray */, ## /* name:'fclass' type:gchararray "
367 "*/, ## /* name:'fnamespace' type:gchararray */)",
368 NULL
371 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE,
372 "SELECT * FROM __tmp_heritage_scope",
373 NULL
376 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS,
377 "SELECT * FROM __tmp_heritage_scope WHERE field_inherits != ''",
378 NULL
381 PREP_QUERY_TMP_HERITAGE_DELETE_ALL,
382 "DELETE FROM __tmp_heritage_scope",
383 NULL
385 /* -- symbol -- */
387 PREP_QUERY_SYMBOL_NEW,
388 "INSERT INTO symbol (file_defined_id, name, file_position, "
389 "is_file_scope, signature, scope_definition_id, scope_id, type_id, "
390 "kind_id, access_kind_id, implementation_kind_id, update_flag) VALUES("
391 "## /* name:'filedefid' type:gint */, ## /* name:'name' "
392 "type:gchararray */, ## /* name:'fileposition' type:gint */, ## /* "
393 "name:'isfilescope' type:gint */, ## /* name:'signature' "
394 "type:gchararray */,## /* name:'scopedefinitionid' type:gint */, ## "
395 "/* name:'scopeid' type:gint */,## /* name:'typeid' type:gint */, ## "
396 "/* name:'kindid' type:gint */,## /* name:'accesskindid' type:gint */, "
397 "## /* name:'implementationkindid' type:gint */, ## /* "
398 "name:'updateflag' type:gint */)",
399 NULL
402 PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
403 "SELECT scope_definition_id FROM symbol JOIN sym_type ON symbol.type_id "
404 "= sym_type.type_id WHERE sym_type.type = ## /* name:'tokenname' "
405 "type:gchararray */ AND sym_type.type_name = ## /* name:'objectname' "
406 "type:gchararray */ LIMIT 1",
407 NULL
410 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
411 "SELECT symbol_id FROM symbol JOIN sym_type ON symbol.type_id = "
412 "sym_type.type_id WHERE scope_id=0 AND sym_type.type='class' AND "
413 "name = ## /* name:'klassname' type:gchararray */",
414 NULL
417 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
418 "SELECT symbol_id FROM symbol JOIN scope ON symbol.scope_id = "
419 "scope.scope_id JOIN sym_type ON scope.type_id = sym_type.type_id "
420 "WHERE symbol.name = /* name:'klassname' type:gchararray */ AND "
421 "scope.scope_name = /* name:'namespacename' type:gchararray */ AND "
422 "sym_type.type='namespace'",
423 NULL
426 PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID,
427 "UPDATE symbol SET scope_id = ## /* name:'scopeid' type:gint */ "
428 "WHERE symbol_id = ## /* name:'symbolid' type:gint */",
429 NULL
432 PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY,
433 "SELECT symbol_id FROM symbol WHERE name = ## /* name:'symname' "
434 "type:gchararray */ AND file_defined_id = ## /* name:'filedefid' "
435 "type:gint */ AND type_id = ## /* name:'typeid' type:gint */",
436 NULL
439 PREP_QUERY_UPDATE_SYMBOL_ALL,
440 "UPDATE symbol SET is_file_scope = ## /* name:'isfilescope' type:gint "
441 "*/, file_position = ## /* name:'fileposition' type:gint */, "
442 "signature = ## /* name:'signature' type:gchararray */, "
443 "scope_definition_id = ## /* name:'scopedefinitionid' type:gint */, "
444 "scope_id = ## /* name:'scopeid' type:gint */, kind_id = "
445 "## /* name:'kindid' type:gint */, access_kind_id = ## /* name:"
446 "'accesskindid' type:gint */, implementation_kind_id = ## /* name:"
447 "'implementationkindid' type:gint */, update_flag = ## /* name:"
448 "'updateflag' type:gint */ WHERE symbol_id = ## /* name:'symbolid' type:"
449 "gint */",
450 NULL
452 /* -- tmp_removed -- */
454 PREP_QUERY_GET_REMOVED_IDS,
455 "SELECT symbol_removed_id FROM __tmp_removed",
456 NULL
459 PREP_QUERY_TMP_REMOVED_DELETE_ALL,
460 "DELETE FROM __tmp_removed",
461 NULL
465 typedef void (SymbolDBEngineCallback) (SymbolDBEngine * dbe,
466 gpointer user_data);
468 enum
470 SINGLE_FILE_SCAN_END,
471 SCAN_END,
472 SYMBOL_INSERTED,
473 SYMBOL_UPDATED,
474 SYMBOL_SCOPE_UPDATED,
475 SYMBOL_REMOVED,
476 LAST_SIGNAL
479 static unsigned int signals[LAST_SIGNAL] = { 0 };
481 struct _SymbolDBEnginePriv
483 GdaConnection *db_connection;
484 GdaClient *gda_client;
485 gchar *dsn_name;
486 gchar *project_name;
487 gchar *data_source;
489 GAsyncQueue *scan_queue;
490 GAsyncQueue *updated_symbols_id;
491 GAsyncQueue *inserted_symbols_id;
493 gchar *shared_mem_str;
494 FILE *shared_mem_file;
495 gint shared_mem_fd;
496 AnjutaLauncher *ctags_launcher;
497 gboolean scanning_status;
498 gboolean force_sym_update;
500 GMutex* mutex;
501 GAsyncQueue* signals_queue;
502 GQueue* thread_list;
504 gboolean thread_status;
505 gint concurrent_threads;
507 gint thread_monitor_handler;
508 gint timeout_trigger_handler;
510 gint trigger_closure_retries;
511 gint thread_closure_retries;
514 static GObjectClass *parent_class = NULL;
517 typedef struct _ThreadDataOutput {
518 gchar * chars;
519 gpointer user_data;
521 } ThreadDataOutput;
523 static void sdb_engine_second_pass_do (SymbolDBEngine * dbe);
524 static gint
525 sdb_engine_add_new_symbol (SymbolDBEngine * dbe, tagEntry * tag_entry,
526 const gchar * base_prj_path, const gchar * fake_file,
527 gboolean sym_update);
531 * Malerba here http://bugzilla.gnome.org/show_bug.cgi?id=488860 says that
532 * GdaQueries can be seen by a provider as prepared queries. I'm not 100% sure
533 * about this but anyway give it a try.
535 static void inline
536 sdb_engine_execute_non_select_sql (SymbolDBEngine * dbe, const gchar * buffer)
538 SymbolDBEnginePriv *priv;
539 GdaQuery *query;
540 GdaObject *obj;
542 priv = dbe->priv;
544 query = gda_query_new_from_sql (NULL, buffer, NULL);
545 obj = gda_query_execute (query, NULL, FALSE, NULL);
547 if (obj != NULL)
549 g_object_unref (obj);
552 if (query != NULL)
554 g_object_unref (query);
559 * User must care to g_object_unref () the returned data_model.
561 static GdaDataModel *
562 sdb_engine_execute_select_sql (SymbolDBEngine * dbe, const gchar * buffer)
564 SymbolDBEnginePriv *priv;
565 GdaQuery *query;
566 GdaObject *obj;
567 GError *error = NULL;
569 priv = dbe->priv;
571 query = gda_query_new_from_sql (NULL, buffer, &error);
573 if (error)
574 g_print ("Parser ERROR: %s\n", error->message);
576 obj = gda_query_execute (query, NULL, FALSE, NULL);
579 if (query != NULL)
581 g_object_unref (query);
584 if (GDA_DATA_MODEL (obj) == FALSE)
586 DEBUG_PRINT ("sdb_engine_execute_select_sql (): returning NULL");
587 if (obj)
588 g_object_unref (obj);
589 return NULL;
592 return GDA_DATA_MODEL (obj);
597 * Will test the opened project within the dbe plugin and the passed one.
599 gboolean inline
600 symbol_db_engine_is_project_opened (SymbolDBEngine *dbe, const gchar* project_name)
602 SymbolDBEnginePriv *priv;
604 g_return_val_if_fail (dbe != NULL, FALSE);
605 priv = dbe->priv;
607 if (priv->project_name == NULL)
608 return FALSE;
610 return strcmp (project_name, priv->project_name) == 0 ? TRUE : FALSE;
615 * Use a proxy to return an already present or a fresh new prepared query
616 * from static 'query_list'. We should perform actions in the fastest way, because
617 * these queries are time-critical.
619 static inline const GdaQuery *
620 sdb_engine_get_query_by_id (SymbolDBEngine * dbe, query_type query_id)
622 query_node *node;
623 SymbolDBEnginePriv *priv;
625 priv = dbe->priv;
627 /* no way: if connection is NULL we will break here. There must be
628 * a connection established to db before using this function */
629 g_return_val_if_fail (priv->db_connection != NULL, NULL);
631 node = &query_list[query_id];
633 if (node->query == NULL)
635 DEBUG_PRINT ("generating new query.... %d", query_id);
636 /* create a new GdaQuery */
637 node->query =
638 gda_query_new_from_sql (NULL, node->query_str, NULL);
641 return node->query;
644 static inline gint
645 sdb_engine_get_last_insert_id (SymbolDBEngine * dbe)
647 gint table_id;
648 SymbolDBEnginePriv *priv;
649 gchar *res;
651 priv = dbe->priv;
652 res = gda_connection_get_last_insert_id (priv->db_connection, NULL);
653 table_id = atoi (res);
654 g_free (res);
655 return table_id;
659 * Clear the static cached queries data. You should call this function when closing/
660 * destroying SymbolDBEngine object.
662 static void
663 sdb_engine_free_cached_queries (SymbolDBEngine * dbe)
665 gint i;
666 query_node *node;
667 SymbolDBEnginePriv *priv;
669 priv = dbe->priv;
671 for (i = 0; i < PREP_QUERY_COUNT; i++)
673 node = &query_list[i];
675 if (node->query != NULL)
677 g_object_unref ((gpointer) node->query);
678 node->query = NULL;
683 static gboolean
684 sdb_engine_disconnect_from_db (SymbolDBEngine * dbe)
686 SymbolDBEnginePriv *priv;
688 g_return_val_if_fail (dbe != NULL, FALSE);
689 priv = dbe->priv;
691 if (priv->gda_client)
693 gda_client_close_all_connections (priv->gda_client);
694 g_object_unref (priv->gda_client);
696 priv->gda_client = NULL;
697 priv->db_connection = NULL;
699 g_free (priv->data_source);
700 priv->data_source = NULL;
702 g_free (priv->dsn_name);
703 priv->dsn_name = NULL;
705 return TRUE;
708 static GTimer *sym_timer_DEBUG = NULL;
709 static gint files_scanned_DEBUG = 0;
712 * If base_prj_path != NULL then fake_file will not be parsed. Else
713 * if fake_file is != NULL we claim and assert that tags contents which are
714 * scanned belong to the fake_file in the project.
715 * More: the fake_file refers to just one single file and cannot be used
716 * for multiple fake_files.
718 static void
719 sdb_engine_populate_db_by_tags (SymbolDBEngine * dbe, FILE* fd,
720 gchar * base_prj_path, gchar * fake_file_on_db,
721 gboolean force_sym_update)
723 tagFile *tag_file;
724 tagFileInfo tag_file_info;
725 tagEntry tag_entry;
726 GdaCommand *command;
728 SymbolDBEnginePriv *priv;
730 g_return_if_fail (dbe != NULL);
732 priv = dbe->priv;
734 g_return_if_fail (priv->db_connection != NULL);
735 g_return_if_fail (fd != NULL);
737 if (priv->updated_symbols_id == NULL)
738 priv->updated_symbols_id = g_async_queue_new ();
740 if (priv->inserted_symbols_id == NULL)
741 priv->inserted_symbols_id = g_async_queue_new ();
743 DEBUG_PRINT ("sdb_engine_populate_db_by_tags ()");
744 if ((tag_file = tagsOpen_1 (fd, &tag_file_info)) == NULL)
746 g_warning ("error in opening ctags file");
749 gda_connection_begin_transaction (priv->db_connection, NULL,
750 GDA_TRANSACTION_ISOLATION_READ_UNCOMMITTED,
751 NULL);
753 if (sym_timer_DEBUG == NULL)
754 sym_timer_DEBUG = g_timer_new ();
755 else
756 g_timer_reset (sym_timer_DEBUG);
757 gint tags_total_DEBUG = 0;
759 while (tagsNext (tag_file, &tag_entry) != TagFailure)
761 sdb_engine_add_new_symbol (dbe, &tag_entry, fake_file_on_db == NULL ?
762 base_prj_path : NULL, fake_file_on_db,
763 force_sym_update);
765 tags_total_DEBUG ++;
768 gdouble elapsed_DEBUG = g_timer_elapsed (sym_timer_DEBUG, NULL);
769 DEBUG_PRINT ("elapsed: %f for (%d) [%f per symbol]", elapsed_DEBUG,
770 tags_total_DEBUG, elapsed_DEBUG / tags_total_DEBUG);
773 if (files_scanned_DEBUG++ > 50)
775 DEBUG_PRINT ("analyzing...");
776 command = gda_command_new ("ANALYZE", GDA_COMMAND_TYPE_SQL,
777 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
778 gda_connection_execute_non_select_command (priv->db_connection,
779 command, NULL, NULL);
780 gda_command_free (command);
782 files_scanned_DEBUG = 0;
785 DEBUG_PRINT ("EMITTING single-file-scan-end");
786 /* notify listeners that another file has been scanned */
787 g_async_queue_push (priv->signals_queue, (gpointer)(SINGLE_FILE_SCAN_END +1));
789 gda_connection_commit_transaction (priv->db_connection, NULL, NULL);
792 static gpointer
793 sdb_engine_ctags_output_thread (gpointer data)
795 ThreadDataOutput *output;
796 gint len_chars;
797 gchar *chars, *chars_ptr;
798 gint remaining_chars;
799 gint len_marker;
800 SymbolDBEnginePriv *priv;
801 SymbolDBEngine *dbe;
803 output = (ThreadDataOutput *)data;
804 dbe = output->user_data;
805 chars = chars_ptr = output->chars;
807 g_return_val_if_fail (dbe != NULL, (gpointer)-1);
808 g_return_val_if_fail (chars_ptr != NULL, (gpointer)-1);
810 priv = dbe->priv;
812 /* lock */
813 if (priv->mutex)
814 g_mutex_lock (priv->mutex);
815 priv->thread_status = TRUE;
817 remaining_chars = len_chars = strlen (chars_ptr);
818 len_marker = strlen (CTAGS_MARKER);
820 if ( len_chars >= len_marker )
822 gchar *marker_ptr = NULL;
823 gint tmp_str_length = 0;
825 /* is it an end file marker? */
826 marker_ptr = strstr (chars_ptr, CTAGS_MARKER);
828 do {
829 if (marker_ptr != NULL)
831 gint scan_flag;
832 gchar *real_file;
833 DEBUG_PRINT ("found marker!");
835 /* set the length of the string parsed */
836 tmp_str_length = marker_ptr - chars_ptr;
838 /*DEBUG_PRINT ("program output [new version]: ==>%s<==", chars_ptr);*/
839 /* write to shm_file all the chars_ptr received without the marker ones */
840 fwrite (chars_ptr, sizeof(gchar), tmp_str_length, priv->shared_mem_file);
842 chars_ptr = marker_ptr + len_marker;
843 remaining_chars -= (tmp_str_length + len_marker);
844 fflush (priv->shared_mem_file);
846 /* get the scan flag from the queue. We need it to know whether
847 * an update of symbols must be done or not */
848 scan_flag = (int)g_async_queue_try_pop (priv->scan_queue);
849 real_file = g_async_queue_try_pop (priv->scan_queue);
851 /* and now call the populating function */
852 if (scan_flag == DO_UPDATE_SYMS ||
853 scan_flag == DO_UPDATE_SYMS_AND_EXIT)
855 sdb_engine_populate_db_by_tags (dbe, priv->shared_mem_file,
856 priv->data_source,
857 (int)real_file == DONT_FAKE_UPDATE_SYMS ? NULL : real_file,
858 TRUE);
860 else
862 sdb_engine_populate_db_by_tags (dbe, priv->shared_mem_file,
863 priv->data_source,
864 (int)real_file == DONT_FAKE_UPDATE_SYMS ? NULL : real_file,
865 FALSE);
868 /* don't forget to free the real_file, if it's a char */
869 if ((int)real_file != DONT_FAKE_UPDATE_SYMS)
870 g_free (real_file);
872 /* check also if, together with an end file marker, we have an
873 * end group-of-files end marker.
875 if (scan_flag == DO_UPDATE_SYMS_AND_EXIT ||
876 scan_flag == DONT_UPDATE_SYMS_AND_EXIT )
878 gint tmp_inserted;
879 gint tmp_updated;
881 /* proceed with second passes */
882 DEBUG_PRINT ("FOUND end-of-group-files marker.\n"
883 "go on with sdb_engine_second_pass_do ()");
885 chars_ptr += len_marker;
886 remaining_chars -= len_marker;
888 /* will emit symbol_scope_updated */
889 sdb_engine_second_pass_do (dbe);
891 /* Here we are. It's the right time to notify the listeners
892 * about out fresh new inserted/updated symbols...
893 * Go on by emitting them.
895 while ((tmp_inserted = (int)
896 g_async_queue_try_pop (priv->inserted_symbols_id)) > 0)
898 DEBUG_PRINT ("EMITTING symbol-inserted %d", tmp_inserted);
899 /* we must be sure to insert both signals at once */
900 g_async_queue_lock (priv->signals_queue);
902 /* the +1 is because asyn_queue doesn't want NULL values */
903 g_async_queue_push_unlocked (priv->signals_queue,
904 (gpointer)(SYMBOL_INSERTED + 1));
905 g_async_queue_push_unlocked (priv->signals_queue,
906 (gpointer) tmp_inserted);
907 g_async_queue_unlock (priv->signals_queue);
910 while ((tmp_updated = (int)
911 g_async_queue_try_pop (priv->updated_symbols_id)) > 0)
913 DEBUG_PRINT ("EMITTING symbol-updated");
914 g_async_queue_lock (priv->signals_queue);
915 g_async_queue_push_unlocked (priv->signals_queue, (gpointer)
916 (SYMBOL_UPDATED + 1));
917 g_async_queue_push_unlocked (priv->signals_queue,
918 (gpointer) tmp_updated);
919 g_async_queue_unlock (priv->signals_queue);
923 /* emit signal. The end of files-group can be cannot be
924 * determined by the caller. This is the only way.
926 DEBUG_PRINT ("EMITTING scan-end");
927 g_async_queue_push (priv->signals_queue, (gpointer)(SCAN_END + 1));
928 DEBUG_PRINT ("queue length = %d",
929 g_async_queue_length (priv->signals_queue));
932 /* truncate the file to 0 length */
933 ftruncate (priv->shared_mem_fd, 0);
935 else
937 /* marker_ptr is NULL here. We should then exit the loop. */
938 /* write to shm_file all the chars received */
939 fwrite (chars_ptr, sizeof(gchar), remaining_chars,
940 priv->shared_mem_file);
942 fflush (priv->shared_mem_file);
943 break;
946 /* found out a new marker */
947 marker_ptr = strstr (marker_ptr + len_marker, CTAGS_MARKER);
948 } while (remaining_chars + len_marker < len_chars);
950 else
952 DEBUG_PRINT ("no len_chars > len_marker");
955 priv->thread_status = FALSE;
956 priv->concurrent_threads--;
957 if (priv->mutex)
958 g_mutex_unlock (priv->mutex);
960 g_free (chars);
961 g_free (output);
963 return 0;
967 static gboolean
968 sdb_engine_timeout_trigger_signals (gpointer user_data)
970 SymbolDBEngine *dbe = (SymbolDBEngine *) user_data;
971 SymbolDBEnginePriv *priv;
973 g_return_val_if_fail (user_data != NULL, FALSE);
975 priv = dbe->priv;
977 DEBUG_PRINT ("signals trigger");
978 if (g_async_queue_length (priv->signals_queue) > 0)
980 gpointer tmp;
981 gpointer sign = NULL;
982 gint real_signal;
984 while ((sign = g_async_queue_try_pop (priv->signals_queue)) != NULL) {
986 if (sign== NULL) {
987 return g_async_queue_length (priv->signals_queue) > 0 ? TRUE : FALSE;
990 real_signal = (gint)sign- 1;
992 switch (real_signal) {
993 case SINGLE_FILE_SCAN_END:
994 g_signal_emit (dbe, signals[SINGLE_FILE_SCAN_END], 0);
995 break;
997 case SCAN_END:
998 g_signal_emit (dbe, signals[SCAN_END], 0);
999 break;
1001 case SYMBOL_INSERTED:
1002 tmp = g_async_queue_try_pop (priv->signals_queue);
1003 g_signal_emit (dbe, signals[SYMBOL_INSERTED], 0, tmp);
1004 break;
1006 case SYMBOL_UPDATED:
1007 tmp = g_async_queue_try_pop (priv->signals_queue);
1008 g_signal_emit (dbe, signals[SYMBOL_UPDATED], 0, tmp);
1009 break;
1011 case SYMBOL_SCOPE_UPDATED:
1012 tmp = g_async_queue_try_pop (priv->signals_queue);
1013 g_signal_emit (dbe, signals[SYMBOL_SCOPE_UPDATED], 0, tmp);
1014 break;
1016 case SYMBOL_REMOVED:
1017 tmp = g_async_queue_try_pop (priv->signals_queue);
1018 g_signal_emit (dbe, signals[SYMBOL_REMOVED], 0, tmp);
1019 break;
1022 /* reset to 0 the retries */
1023 priv->trigger_closure_retries = 0;
1025 else {
1026 priv->trigger_closure_retries++;
1029 if (priv->trigger_closure_retries > TRIGGER_MAX_CLOSURE_RETRIES &&
1030 g_queue_get_length (priv->thread_list) <= 0)
1032 DEBUG_PRINT ("removing trigger");
1033 /* remove the trigger coz we don't need it anymore... */
1034 g_source_remove (priv->timeout_trigger_handler);
1035 priv->timeout_trigger_handler = 0;
1038 return TRUE;
1041 static gboolean
1042 sdb_engine_thread_monitor (gpointer data)
1044 gpointer output;
1045 SymbolDBEngine *dbe = (SymbolDBEngine *) data;
1046 SymbolDBEnginePriv *priv;
1048 g_return_val_if_fail (data != NULL, FALSE);
1050 priv = dbe->priv;
1051 DEBUG_PRINT ("thread monitor");
1053 if (priv->concurrent_threads > THREADS_MAX_CONCURRENT) {
1054 /* monitor acted here. There plenty threads already working. */
1055 return TRUE;
1058 output = g_queue_pop_head (priv->thread_list);
1060 if (output != NULL)
1062 priv->concurrent_threads ++;
1063 g_thread_create ((GThreadFunc)sdb_engine_ctags_output_thread, output,
1064 FALSE, NULL);
1065 priv->thread_closure_retries = 0;
1067 else
1069 priv->thread_closure_retries++;
1072 if (priv->thread_closure_retries > THREAD_MAX_CLOSURE_RETRIES)
1074 DEBUG_PRINT ("removing thread monitor");
1075 /* remove the thread monitor */
1076 g_source_remove (priv->thread_monitor_handler);
1077 priv->thread_monitor_handler = 0;
1080 /* recall this monitor */
1081 return TRUE;
1084 static void
1085 sdb_engine_ctags_output_callback_1 (AnjutaLauncher * launcher,
1086 AnjutaLauncherOutputType output_type,
1087 const gchar * chars, gpointer user_data)
1089 ThreadDataOutput *output;
1090 SymbolDBEngine *dbe = (SymbolDBEngine *) user_data;
1091 SymbolDBEnginePriv *priv;
1093 g_return_if_fail (user_data != NULL);
1095 priv = dbe->priv;
1097 output = g_new0 (ThreadDataOutput, 1);
1098 output->chars = g_strdup (chars);
1099 output->user_data = user_data;
1101 if (priv->thread_list == NULL)
1102 priv->thread_list = g_queue_new ();
1104 g_queue_push_tail (priv->thread_list, output);
1106 /* thread monitor */
1107 if (priv->thread_monitor_handler <= 0)
1109 priv->thread_monitor_handler =
1110 g_timeout_add (THREADS_MONITOR_LAUNCH_DELAY,
1111 sdb_engine_thread_monitor, user_data);
1112 priv->thread_closure_retries = 0;
1115 /* signals monitor */
1116 if (priv->timeout_trigger_handler <= 0)
1118 priv->timeout_trigger_handler =
1119 g_timeout_add (TRIGGER_SIGNALS_DELAY,
1120 sdb_engine_timeout_trigger_signals, user_data);
1121 priv->trigger_closure_retries = 0;
1125 static void
1126 on_scan_files_end_1 (AnjutaLauncher * launcher, int child_pid,
1127 int exit_status, gulong time_taken_in_seconds,
1128 gpointer data)
1130 DEBUG_PRINT ("ctags ended");
1133 /* Scans with ctags and produce an output 'tags' file [shared memory file]
1134 * containing language symbols. This function will call ctags
1135 * executale and then sdb_engine_populate_db_by_tags () when it'll detect some
1136 * output.
1137 * Please note the files_list/real_files_list parameter:
1138 * this version of sdb_engine_scan_files_1 () let you scan for text buffer(s) that
1139 * will be claimed as buffers for the real files.
1140 * 1. simple mode: files_list represents the real files on disk and so we don't
1141 * need real_files_list, which will be NULL.
1142 * 2. advanced mode: files_list represents temporary flushing of buffers on disk, i.e.
1143 * /tmp/anjuta_XYZ.cxx. real_files_list is the representation of those files on
1144 * database. On the above example we can have anjuta_XYZ.cxx mapped as /src/main.c
1145 * on db. In this mode files_list and real_files_list must have the same size.
1148 /* server mode version */
1149 static gboolean
1150 sdb_engine_scan_files_1 (SymbolDBEngine * dbe, const GPtrArray * files_list,
1151 const GPtrArray *real_files_list, gboolean symbols_update)
1153 SymbolDBEnginePriv *priv;
1154 gint i;
1156 g_return_val_if_fail (dbe != NULL, FALSE);
1157 g_return_val_if_fail (files_list != NULL, FALSE);
1159 if (files_list->len == 0)
1160 return FALSE;
1162 /* start process in server mode */
1163 priv = dbe->priv;
1165 if (real_files_list != NULL && (files_list->len != real_files_list->len))
1167 g_warning ("no matched size between real_files_list and files_list");
1168 return FALSE;
1171 /* if ctags_launcher isn't initialized, then do it now. */
1172 if (priv->ctags_launcher == NULL)
1174 gchar *exe_string;
1176 DEBUG_PRINT ("creating anjuta_launcher");
1177 priv->ctags_launcher = anjuta_launcher_new ();
1179 g_signal_connect (G_OBJECT (priv->ctags_launcher), "child-exited",
1180 G_CALLBACK (on_scan_files_end_1), NULL);
1182 exe_string = g_strdup_printf ("%s --fields=afmiKlnsStz --c++-kinds=+p "
1183 "--filter=yes --filter-terminator='"CTAGS_MARKER"'",
1184 CTAGS_PATH);
1186 anjuta_launcher_execute (priv->ctags_launcher,
1187 exe_string, sdb_engine_ctags_output_callback_1,
1188 dbe);
1189 g_free (exe_string);
1192 /* what about the scan_queue? is it initialized? It will contain mainly
1193 * ints that refers to the force_update status.
1195 if (priv->scan_queue == NULL)
1197 priv->scan_queue = g_async_queue_new ();
1200 /* create the shared memory file */
1201 if (priv->shared_mem_file == 0)
1203 gchar *temp_file;
1204 temp_file = g_strdup_printf ("/anjuta-%d_%ld.tags", getpid (),
1205 time (NULL));
1207 priv->shared_mem_str = temp_file;
1209 if ((priv->shared_mem_fd =
1210 shm_open (temp_file, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0)
1212 g_warning ("Error while trying to open a shared memory file. Be"
1213 "sure to have /dev/shm mounted with tmpfs");
1216 priv->shared_mem_file = fdopen (priv->shared_mem_fd, "a+b");
1217 DEBUG_PRINT ("temp_file %s", temp_file);
1219 /* no need to free temp_file. It will be freed on plugin finalize */
1222 priv->scanning_status = TRUE;
1224 DEBUG_PRINT ("sdb_engine_scan_files_1 (): PUSHING files_list->len %d to scan",
1225 files_list->len);
1226 for (i = 0; i < files_list->len; i++)
1228 gchar *node = (gchar *) g_ptr_array_index (files_list, i);
1230 if (g_file_test (node, G_FILE_TEST_EXISTS) == FALSE)
1232 g_warning ("File %s not scanned because it does not exist", node);
1233 continue;
1236 DEBUG_PRINT ("sent to stdin %d", i);
1237 anjuta_launcher_send_stdin (priv->ctags_launcher, node);
1238 anjuta_launcher_send_stdin (priv->ctags_launcher, "\n");
1240 if (symbols_update == TRUE)
1242 /* will this be the last file in the list? */
1243 if (i + 1 >= files_list->len)
1245 /* yes */
1246 g_async_queue_push (priv->scan_queue, (gpointer) DO_UPDATE_SYMS_AND_EXIT);
1248 else {
1249 /* no */
1250 g_async_queue_push (priv->scan_queue, (gpointer) DO_UPDATE_SYMS);
1253 else
1255 if (i + 1 >= files_list->len)
1257 /* yes */
1258 g_async_queue_push (priv->scan_queue, (gpointer) DONT_UPDATE_SYMS_AND_EXIT);
1260 else {
1261 /* no */
1262 g_async_queue_push (priv->scan_queue, (gpointer) DONT_UPDATE_SYMS);
1266 /* don't forget to add the real_files if the caller provided a list for
1267 * them! */
1268 if (real_files_list != NULL)
1270 g_async_queue_push (priv->scan_queue,
1271 (gpointer)g_strdup (
1272 g_ptr_array_index (real_files_list, i)));
1274 else
1276 /* else add a DONT_FAKE_UPDATE_SYMS marker, just to notify that this
1277 * is not a fake file scan
1279 g_async_queue_push (priv->scan_queue, (gpointer) DONT_FAKE_UPDATE_SYMS);
1283 priv->scanning_status = FALSE;
1285 return TRUE;
1288 static void
1289 sdb_engine_init (SymbolDBEngine * object)
1291 SymbolDBEngine *sdbe;
1293 sdbe = SYMBOL_DB_ENGINE (object);
1294 sdbe->priv = g_new0 (SymbolDBEnginePriv, 1);
1296 /* initialize some priv data */
1297 sdbe->priv->gda_client = NULL;
1298 sdbe->priv->db_connection = NULL;
1299 sdbe->priv->dsn_name = NULL;
1300 sdbe->priv->project_name = NULL;
1301 sdbe->priv->data_source = NULL;
1303 sdbe->priv->scan_queue = NULL;
1304 sdbe->priv->updated_symbols_id = NULL;
1305 sdbe->priv->inserted_symbols_id = NULL;
1306 sdbe->priv->shared_mem_file = NULL;
1307 sdbe->priv->shared_mem_fd = 0;
1308 sdbe->priv->shared_mem_str = NULL;
1309 sdbe->priv->scanning_status = FALSE;
1310 sdbe->priv->force_sym_update = FALSE;
1312 sdbe->priv->mutex = NULL;
1313 sdbe->priv->signals_queue = NULL;
1314 sdbe->priv->thread_list = NULL;
1315 sdbe->priv->thread_status = FALSE;
1316 sdbe->priv->concurrent_threads = 0;
1317 sdbe->priv->thread_monitor_handler = 0;
1318 sdbe->priv->timeout_trigger_handler = 0;
1319 sdbe->priv->trigger_closure_retries = 0;
1320 sdbe->priv->thread_closure_retries = 0;
1322 /* Initialize gda library. */
1323 gda_init ("AnjutaGda", NULL, 0, NULL);
1325 /* create Anjuta Launcher instance. It will be used for tags parsing. */
1326 sdbe->priv->ctags_launcher = NULL;
1329 static void
1330 sdb_engine_finalize (GObject * object)
1332 SymbolDBEngine *dbe;
1333 SymbolDBEnginePriv *priv;
1335 dbe = SYMBOL_DB_ENGINE (object);
1336 priv = dbe->priv;
1338 sdb_engine_disconnect_from_db (dbe);
1339 sdb_engine_free_cached_queries (dbe);
1341 g_free (priv->project_name);
1343 if (priv->scan_queue)
1345 g_async_queue_unref (priv->scan_queue);
1346 priv->scan_queue = NULL;
1349 if (priv->updated_symbols_id)
1351 g_async_queue_unref (priv->updated_symbols_id);
1352 priv->updated_symbols_id = NULL;
1356 if (priv->inserted_symbols_id)
1358 g_async_queue_unref (priv->inserted_symbols_id);
1359 priv->inserted_symbols_id = NULL;
1362 if (priv->shared_mem_file)
1364 fclose (priv->shared_mem_file);
1365 priv->shared_mem_file = NULL;
1369 if (priv->shared_mem_str)
1371 shm_unlink (priv->shared_mem_str);
1372 g_free (priv->shared_mem_str);
1373 priv->shared_mem_str = NULL;
1376 if (priv->ctags_launcher)
1378 anjuta_launcher_signal (priv->ctags_launcher, SIGINT);
1379 g_object_unref (priv->ctags_launcher);
1382 if (priv->mutex)
1384 g_mutex_lock (priv->mutex);
1385 g_mutex_free (priv->mutex);
1386 priv->mutex = NULL;
1389 if (priv->timeout_trigger_handler >= 0)
1390 g_source_remove (priv->timeout_trigger_handler);
1392 if (priv->thread_monitor_handler >= 0)
1393 g_source_remove (priv->thread_monitor_handler);
1395 g_async_queue_unref (priv->signals_queue);
1397 g_queue_free (priv->thread_list);
1400 G_OBJECT_CLASS (parent_class)->finalize (object);
1403 static void
1404 sdb_engine_class_init (SymbolDBEngineClass * klass)
1406 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1407 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
1409 object_class->finalize = sdb_engine_finalize;
1411 signals[SINGLE_FILE_SCAN_END]
1412 = g_signal_new ("single-file-scan-end",
1413 G_OBJECT_CLASS_TYPE (object_class),
1414 G_SIGNAL_RUN_FIRST,
1415 G_STRUCT_OFFSET (SymbolDBEngineClass, single_file_scan_end),
1416 NULL, NULL,
1417 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
1419 signals[SCAN_END]
1420 = g_signal_new ("scan-end",
1421 G_OBJECT_CLASS_TYPE (object_class),
1422 G_SIGNAL_RUN_FIRST,
1423 G_STRUCT_OFFSET (SymbolDBEngineClass, scan_end),
1424 NULL, NULL,
1425 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
1427 signals[SYMBOL_INSERTED]
1428 = g_signal_new ("symbol-inserted",
1429 G_OBJECT_CLASS_TYPE (object_class),
1430 G_SIGNAL_RUN_FIRST,
1431 G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_inserted),
1432 NULL, NULL,
1433 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
1435 G_TYPE_INT);
1437 signals[SYMBOL_UPDATED]
1438 = g_signal_new ("symbol-updated",
1439 G_OBJECT_CLASS_TYPE (object_class),
1440 G_SIGNAL_RUN_FIRST,
1441 G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_updated),
1442 NULL, NULL,
1443 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
1445 G_TYPE_INT);
1447 signals[SYMBOL_SCOPE_UPDATED]
1448 = g_signal_new ("symbol-scope-updated",
1449 G_OBJECT_CLASS_TYPE (object_class),
1450 G_SIGNAL_RUN_FIRST,
1451 G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_scope_updated),
1452 NULL, NULL,
1453 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
1455 G_TYPE_INT);
1457 signals[SYMBOL_REMOVED]
1458 = g_signal_new ("symbol-removed",
1459 G_OBJECT_CLASS_TYPE (object_class),
1460 G_SIGNAL_RUN_FIRST,
1461 G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_removed),
1462 NULL, NULL,
1463 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
1465 G_TYPE_INT);
1469 GType
1470 sdb_engine_get_type (void)
1472 static GType our_type = 0;
1474 if (our_type == 0)
1476 static const GTypeInfo our_info = {
1477 sizeof (SymbolDBEngineClass), /* class_size */
1478 (GBaseInitFunc) NULL, /* base_init */
1479 (GBaseFinalizeFunc) NULL, /* base_finalize */
1480 (GClassInitFunc) sdb_engine_class_init, /* class_init */
1481 (GClassFinalizeFunc) NULL, /* class_finalize */
1482 NULL /* class_data */ ,
1483 sizeof (SymbolDBEngine), /* instance_size */
1484 0, /* n_preallocs */
1485 (GInstanceInitFunc) sdb_engine_init, /* instance_init */
1486 NULL /* value_table */
1489 our_type = g_type_register_static (G_TYPE_OBJECT, "SymbolDBEngine",
1490 &our_info, 0);
1493 return our_type;
1496 SymbolDBEngine *
1497 symbol_db_engine_new (void)
1499 SymbolDBEngine *sdbe;
1501 sdbe = g_object_new (SYMBOL_TYPE_DB_ENGINE, NULL);
1502 return sdbe;
1505 /* Will create priv->db_connection, priv->gda_client.
1506 * Connect to database identified by data_source.
1507 * Usually data_source is defined also into priv. We let it here as parameter
1508 * because it is required and cannot be null.
1510 static gboolean
1511 sdb_engine_connect_to_db (SymbolDBEngine * dbe, const gchar * data_source)
1513 SymbolDBEnginePriv *priv;
1515 g_return_val_if_fail (dbe != NULL, FALSE);
1516 priv = dbe->priv;
1518 priv->mutex = g_mutex_new ();
1519 priv->signals_queue = g_async_queue_new ();
1521 if (priv->db_connection != NULL)
1523 /* if it's the case that the connection isn't NULL, we
1524 * should notify the user
1525 * and return FALSE. It's his task to disconnect and retry to connect */
1526 g_warning ("connection is already established. Please disconnect "
1527 "and then try to reconnect.");
1528 return FALSE;
1531 /* create new client */
1532 priv->gda_client = gda_client_new ();
1534 /* establish a connection. If the sqlite file does not exist it will
1535 * be created
1537 priv->db_connection
1538 = gda_client_open_connection (priv->gda_client, data_source,
1539 NULL, NULL,
1540 GDA_CONNECTION_OPTIONS_DONT_SHARE, NULL);
1542 if (!GDA_IS_CONNECTION (priv->db_connection))
1544 g_warning ("could not open connection to %s\n", data_source);
1545 return FALSE;
1548 gda_dict_set_connection (default_dict, priv->db_connection);
1550 DEBUG_PRINT ("connected to database %s", data_source);
1551 return TRUE;
1556 * Creates required tables for the database to work.
1557 * @param tables_sql_file File containing sql code.
1559 static gboolean
1560 sdb_engine_create_db_tables (SymbolDBEngine * dbe, gchar * tables_sql_file)
1562 GError *err;
1563 GdaCommand *command;
1564 SymbolDBEnginePriv *priv;
1565 gchar *contents;
1566 gsize sizez;
1568 g_return_val_if_fail (tables_sql_file != NULL, FALSE);
1570 priv = dbe->priv;
1572 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
1574 /* read the contents of the file */
1575 if (g_file_get_contents (tables_sql_file, &contents, &sizez, &err) == FALSE)
1577 g_warning ("Something went wrong while trying to read %s",
1578 tables_sql_file);
1580 if (err != NULL)
1581 g_message ("%s", err->message);
1582 return FALSE;
1585 command = gda_command_new (contents, GDA_COMMAND_TYPE_SQL,
1586 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
1587 gda_connection_execute_non_select_command (priv->db_connection, command,
1588 NULL, NULL);
1589 gda_command_free (command);
1591 g_free (contents);
1592 return TRUE;
1596 * Check if the database already exists into the prj_directory
1598 gboolean
1599 symbol_db_engine_db_exists (SymbolDBEngine * dbe, const gchar * prj_directory)
1601 SymbolDBEnginePriv *priv;
1603 g_return_val_if_fail (prj_directory != NULL, FALSE);
1605 priv = dbe->priv;
1607 /* check whether the db filename already exists.*/
1608 gchar *tmp_file = g_strdup_printf ("%s/%s.db", prj_directory,
1609 ANJUTA_DB_FILE);
1611 if (g_file_test (tmp_file, G_FILE_TEST_EXISTS) == FALSE)
1613 DEBUG_PRINT ("db %s does not exist", tmp_file);
1614 g_free (tmp_file);
1615 return FALSE;
1618 DEBUG_PRINT ("db %s does exist", tmp_file);
1619 g_free (tmp_file);
1621 return TRUE;
1625 * Open or create a new database at given directory.
1627 gboolean
1628 symbol_db_engine_open_db (SymbolDBEngine * dbe, const gchar * prj_directory)
1630 SymbolDBEnginePriv *priv;
1631 /* Connection data */
1632 gchar *dsn_name;
1633 gboolean needs_tables_creation = FALSE;
1635 g_return_val_if_fail (prj_directory != NULL, FALSE);
1637 priv = dbe->priv;
1639 /* check whether the db filename already exists. If it's not the case
1640 * create the tables for the database. */
1641 gchar *tmp_file = g_strdup_printf ("%s/%s.db", prj_directory,
1642 ANJUTA_DB_FILE);
1644 if (g_file_test (tmp_file, G_FILE_TEST_EXISTS) == FALSE)
1646 needs_tables_creation = TRUE;
1648 g_free (tmp_file);
1651 priv->data_source = g_strdup (prj_directory);
1653 dsn_name = g_strdup_printf ("DB_DIR=%s;DB_NAME=%s", prj_directory,
1654 ANJUTA_DB_FILE);
1656 if (gda_config_save_data_source (priv->data_source, "SQLite",
1657 dsn_name, "Anjuta Project",
1658 "", "", FALSE) == FALSE)
1660 return FALSE;
1663 /* store the dsn name into Priv data. We can avoid to free it here coz it will
1664 * used later again. */
1665 priv->dsn_name = dsn_name;
1667 DEBUG_PRINT ("symbol_db_engine_open_db (): opening/connecting to database...");
1668 sdb_engine_connect_to_db (dbe, priv->data_source);
1670 if (needs_tables_creation == TRUE)
1672 DEBUG_PRINT ("symbol_db_engine_open_db (): creating tables: it needs tables...");
1673 sdb_engine_create_db_tables (dbe, TABLES_SQL);
1676 return TRUE;
1680 * @return -1 on error. Otherwise the id of table
1682 static gint
1683 sdb_engine_get_table_id_by_unique_name (SymbolDBEngine * dbe, query_type qtype,
1684 gchar * param_key,
1685 const GValue * param_value)
1687 const GdaQuery *query;
1688 GdaObject *query_result;
1689 GdaParameterList *par_list;
1690 GdaParameter *param;
1691 const GValue *num;
1692 gint table_id;
1694 /* get prepared query */
1695 if ((query = sdb_engine_get_query_by_id (dbe, qtype)) == NULL)
1697 g_warning ("query is null");
1698 return -1;
1701 if (GDA_QUERY_TYPE_NON_PARSED_SQL
1702 == gda_query_get_query_type ((GdaQuery *) query))
1704 g_warning ("sdb_engine_get_table_id_by_unique_name: non parsed "
1705 "sql error");
1706 return -1;
1709 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1711 g_warning ("par_list is NULL!\n");
1712 return -1;
1715 if ((param = gda_parameter_list_find_param (par_list, param_key)) == NULL)
1717 g_warning ("sdb_engine_get_table_id_by_unique_name: param is NULL "
1718 "from pquery!\n");
1719 return -1;
1722 gda_parameter_set_value (param, param_value);
1724 /* execute the query with parametes just set */
1725 query_result = gda_query_execute ((GdaQuery *) query, par_list, FALSE,
1726 NULL);
1728 if (!GDA_IS_DATA_MODEL (query_result) ||
1729 gda_data_model_get_n_rows (GDA_DATA_MODEL (query_result)) <= 0)
1731 if (query_result != NULL)
1732 g_object_unref (query_result);
1733 return -1;
1736 /* get and parse the results. */
1737 num = gda_data_model_get_value_at (GDA_DATA_MODEL (query_result), 0, 0);
1739 table_id = g_value_get_int (num);
1740 g_object_unref (query_result);
1741 return table_id;
1745 * This is the same as sdb_engine_get_table_id_by_unique_name () but for two
1746 * unique parameters. This should be the quickest way. Surely quicker than
1747 * use g_strdup_printf () with a va_list for example.
1748 * @return -1 on error. Otherwise the id of table
1751 static gint
1752 sdb_engine_get_table_id_by_unique_name2 (SymbolDBEngine * dbe, query_type qtype,
1753 gchar * param_key1,
1754 const GValue * value1,
1755 gchar * param_key2,
1756 const GValue * value2)
1758 const GdaQuery *query;
1759 GdaObject *query_result;
1760 GdaParameterList *par_list;
1761 GdaParameter *param;
1762 const GValue *num;
1763 gint table_id;
1765 /* get prepared query */
1766 if ((query = sdb_engine_get_query_by_id (dbe, qtype)) == NULL)
1768 g_warning ("query is null");
1769 return -1;
1772 if (GDA_QUERY_TYPE_NON_PARSED_SQL
1773 == gda_query_get_query_type ((GdaQuery *) query))
1775 g_warning
1776 ("sdb_engine_get_table_id_by_unique_name2: non parsed sql error");
1777 return -1;
1780 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1782 g_warning ("par_list is NULL!\n");
1783 return -1;
1786 /* look for and set the first parameter */
1787 if ((param = gda_parameter_list_find_param (par_list, param_key1)) == NULL)
1789 g_warning ("sdb_engine_get_table_id_by_unique_name2: "
1790 "param is NULL from pquery! [par1: %s] [par2: %s]\n",
1791 param_key1, param_key2);
1792 return -1;
1795 gda_parameter_set_value (param, value1);
1797 /* ...and the second one */
1798 if ((param = gda_parameter_list_find_param (par_list, param_key2)) == NULL)
1800 g_warning ("param is NULL from pquery!\n");
1801 return -1;
1804 gda_parameter_set_value (param, value2);
1806 /* execute the query with parametes just set */
1807 query_result = gda_query_execute ((GdaQuery *) query, par_list,
1808 FALSE, NULL);
1810 if (!GDA_IS_DATA_MODEL (query_result) ||
1811 ((gda_data_model_get_n_rows (GDA_DATA_MODEL (query_result))) <= 0))
1813 if (query_result != NULL)
1814 g_object_unref (query_result);
1815 return -1;
1818 /* get and parse the results. */
1819 num = gda_data_model_get_value_at (GDA_DATA_MODEL (query_result), 0, 0);
1821 table_id = g_value_get_int (num);
1822 g_object_unref (query_result);
1823 return table_id;
1826 static gint
1827 sdb_engine_get_table_id_by_unique_name3 (SymbolDBEngine * dbe, query_type qtype,
1828 gchar * param_key1,
1829 const GValue * value1,
1830 gchar * param_key2,
1831 const GValue * value2,
1832 gchar * param_key3,
1833 const GValue * value3)
1835 const GdaQuery *query;
1836 GdaObject *query_result;
1837 GdaParameterList *par_list;
1838 GdaParameter *param;
1839 const GValue *num;
1840 gint table_id;
1842 /* get prepared query */
1843 if ((query = sdb_engine_get_query_by_id (dbe, qtype)) == NULL)
1845 g_warning ("query is null");
1846 return -1;
1849 if (GDA_QUERY_TYPE_NON_PARSED_SQL
1850 == gda_query_get_query_type ((GdaQuery *) query))
1852 g_warning
1853 ("sdb_engine_get_table_id_by_unique_name2: non parsed sql error");
1854 return -1;
1857 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1859 g_warning ("par_list is NULL!\n");
1860 return -1;
1863 /* look for and set the first parameter */
1864 if ((param = gda_parameter_list_find_param (par_list, param_key1)) == NULL)
1866 g_warning ("sdb_engine_get_table_id_by_unique_name2: "
1867 "param is NULL from pquery! [par1: %s] [par2: %s]\n",
1868 param_key1, param_key2);
1869 return -1;
1872 gda_parameter_set_value (param, value1);
1874 /* ...and the second one */
1875 if ((param = gda_parameter_list_find_param (par_list, param_key2)) == NULL)
1877 g_warning ("param is NULL from pquery!\n");
1878 return -1;
1881 gda_parameter_set_value (param, value2);
1883 /* ...and the third one */
1884 if ((param = gda_parameter_list_find_param (par_list, param_key3)) == NULL)
1886 g_warning ("param is NULL from pquery!\n");
1887 return -1;
1890 gda_parameter_set_value (param, value3);
1893 /* execute the query with parametes just set */
1894 query_result = gda_query_execute ((GdaQuery *) query, par_list,
1895 FALSE, NULL);
1897 if (!GDA_IS_DATA_MODEL (query_result) ||
1898 gda_data_model_get_n_rows (GDA_DATA_MODEL (query_result)) <= 0)
1901 if (query_result != NULL)
1902 g_object_unref (query_result);
1903 return -1;
1906 /* get and parse the results. */
1907 num = gda_data_model_get_value_at (GDA_DATA_MODEL (query_result), 0, 0);
1909 table_id = g_value_get_int (num);
1910 g_object_unref (query_result);
1911 return table_id;
1915 gboolean
1916 symbol_db_engine_add_new_workspace (SymbolDBEngine * dbe,
1917 const gchar * workspace_name)
1920 CREATE TABLE workspace (workspace_id integer PRIMARY KEY AUTOINCREMENT,
1921 workspace_name varchar (50) not null unique,
1922 analize_time DATE
1925 const GdaQuery *query;
1926 GdaObject *query_result;
1927 GdaParameterList *par_list;
1928 GdaParameter *param;
1929 GValue *value;
1930 SymbolDBEnginePriv *priv;
1932 priv = dbe->priv;
1934 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
1936 if ((query =
1937 sdb_engine_get_query_by_id (dbe, PREP_QUERY_WORKSPACE_NEW)) == NULL)
1939 g_warning ("query is null");
1940 return FALSE;
1943 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
1944 gda_query_get_query_type ((GdaQuery *) query))
1946 g_warning ("non parsed sql error");
1947 return FALSE;
1950 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1952 g_warning ("par_list is NULL!\n");
1953 return FALSE;
1956 if ((param = gda_parameter_list_find_param (par_list, "wsname")) == NULL)
1958 g_warning ("param is NULL from pquery!\n");
1959 return FALSE;
1962 value = gda_value_new (G_TYPE_STRING);
1963 g_value_set_string (value, workspace_name);
1965 gda_parameter_set_value (param, value);
1967 /* execute the query with parametes just set */
1968 GError *err = NULL;
1969 query_result =
1970 gda_query_execute ((GdaQuery *) query, par_list, FALSE, &err);
1971 gda_value_free (value);
1974 if (query_result != NULL)
1976 g_object_unref (query_result);
1977 return TRUE;
1979 else
1981 DEBUG_PRINT ("Error: %s", err->message);
1982 return FALSE;
1987 * Return the name of the opened project.
1988 * NULL on error. Returned string must be freed by caller.
1990 gchar*
1991 symbol_db_engine_get_opened_project_name (SymbolDBEngine * dbe)
1993 SymbolDBEnginePriv *priv;
1994 g_return_val_if_fail (dbe != NULL, NULL);
1995 priv = dbe->priv;
1997 g_return_val_if_fail (priv->db_connection != NULL, NULL);
1999 return g_strdup (priv->project_name);
2003 * Open a new project.
2004 * It will test if project was correctly created.
2006 gboolean
2007 symbol_db_engine_open_project (SymbolDBEngine * dbe, /*gchar* workspace, */
2008 const gchar * project_name)
2010 GValue *value;
2011 SymbolDBEnginePriv *priv;
2012 gint prj_id;
2014 priv = dbe->priv;
2016 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
2017 if (symbol_db_engine_is_project_opened (dbe, project_name) == TRUE) {
2018 g_warning ("symbol_db_engine_open_project (): "
2019 "project already opened, %s (priv %s)", project_name,
2020 priv->project_name);
2021 return FALSE;
2024 value = gda_value_new (G_TYPE_STRING);
2025 g_value_set_string (value, project_name);
2027 /* test the existence of the project in db */
2028 if ((prj_id = sdb_engine_get_table_id_by_unique_name (dbe,
2029 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
2030 "prjname",
2031 value)) <= 0)
2033 DEBUG_PRINT ("symbol_db_engine_open_project (): no project name found");
2034 gda_value_free (value);
2035 return FALSE;
2038 gda_value_free (value);
2040 /* open the project... */
2041 priv->project_name = g_strdup (project_name);
2043 return TRUE;
2047 gboolean
2048 symbol_db_engine_close_project (SymbolDBEngine *dbe, const gchar* project_name)
2050 SymbolDBEnginePriv *priv;
2052 priv = dbe->priv;
2054 g_free (priv->project_name);
2055 priv->project_name = NULL;
2057 return sdb_engine_disconnect_from_db (dbe);
2062 * @param workspace Can be NULL. In that case a default workspace will be created,
2063 * and project will depend on that.
2064 * @param project Project name. Must NOT be NULL.
2066 gboolean
2067 symbol_db_engine_add_new_project (SymbolDBEngine * dbe, const gchar * workspace,
2068 const gchar * project)
2071 CREATE TABLE project (project_id integer PRIMARY KEY AUTOINCREMENT,
2072 project_name varchar (50) not null unique,
2073 wrkspace_id integer REFERENCES workspace (workspace_id),
2074 analize_time DATE
2077 const GdaQuery *query;
2078 GdaObject *query_result;
2079 GdaParameterList *par_list;
2080 GdaParameter *param;
2081 GValue *value;
2082 const gchar *workspace_name;
2083 gint wks_id;
2084 SymbolDBEnginePriv *priv;
2086 g_return_val_if_fail (dbe != NULL, FALSE);
2088 priv = dbe->priv;
2090 if (symbol_db_engine_is_project_opened (dbe, project) == TRUE)
2092 g_warning ("You have an already opened project. Cannot continue.");
2093 return FALSE;
2096 if (workspace == NULL)
2098 workspace_name = "anjuta_workspace_default";
2100 DEBUG_PRINT ("adding default workspace... %s", workspace_name);
2101 value = gda_value_new (G_TYPE_STRING);
2102 g_value_set_string (value, workspace_name);
2104 if ((wks_id = sdb_engine_get_table_id_by_unique_name (dbe,
2105 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
2106 "wsname",
2107 value)) <= 0)
2109 if (symbol_db_engine_add_new_workspace (dbe, workspace_name) == FALSE)
2111 gda_value_free (value);
2112 DEBUG_PRINT ("Project cannot be added because a default workspace "
2113 "cannot be created");
2114 return FALSE;
2117 gda_value_free (value);
2119 else
2121 workspace_name = workspace;
2124 value = gda_value_new (G_TYPE_STRING);
2125 g_value_set_string (value, workspace_name);
2127 /* get workspace id */
2128 if ((wks_id = sdb_engine_get_table_id_by_unique_name (dbe,
2129 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
2130 "wsname",
2131 value)) <= 0)
2133 DEBUG_PRINT ("symbol_db_engine_add_new_project (): no workspace id");
2134 gda_value_free (value);
2135 return FALSE;
2138 /* insert new project */
2139 if ((query =
2140 sdb_engine_get_query_by_id (dbe, PREP_QUERY_PROJECT_NEW)) == NULL)
2142 g_warning ("query is null");
2143 gda_value_free (value);
2144 return FALSE;
2147 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2148 gda_query_get_query_type ((GdaQuery *) query))
2150 g_warning ("non parsed sql error");
2151 gda_value_free (value);
2152 return FALSE;
2155 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2157 g_warning ("par_list is NULL!\n");
2158 gda_value_free (value);
2159 return FALSE;
2162 if ((param = gda_parameter_list_find_param (par_list, "prjname")) == NULL)
2164 g_warning ("param prjname is NULL from pquery!");
2165 gda_value_free (value);
2166 return FALSE;
2169 gda_value_reset_with_type (value, G_TYPE_STRING);
2170 g_value_set_string (value, project);
2171 gda_parameter_set_value (param, value);
2173 if ((param = gda_parameter_list_find_param (par_list, "wsid")) == NULL)
2175 g_warning ("param is NULL from pquery!");
2176 return FALSE;
2179 gda_value_reset_with_type (value, G_TYPE_INT);
2180 g_value_set_int (value, wks_id);
2182 gda_parameter_set_value (param, value);
2184 /* execute the query with parametes just set */
2185 query_result =
2186 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2187 gda_value_free (value);
2189 if (query_result != NULL)
2191 g_object_unref (query_result);
2192 return TRUE;
2194 else
2195 return FALSE;
2199 static gint
2200 sdb_engine_add_new_language (SymbolDBEngine * dbe, const gchar *language)
2203 CREATE TABLE language (language_id integer PRIMARY KEY AUTOINCREMENT,
2204 language_name varchar (50) not null unique);
2206 gint table_id;
2207 GValue *value;
2209 g_return_val_if_fail (language != NULL, -1);
2211 value = gda_value_new (G_TYPE_STRING);
2212 g_value_set_string (value, language);
2214 /* check for an already existing table with language "name". */
2215 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
2216 PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
2217 "langname",
2218 value)) < 0)
2221 /* insert a new entry on db */
2222 const GdaQuery *query;
2223 GdaObject *query_result;
2224 GdaParameterList *par_list;
2225 GdaParameter *param;
2226 GValue *value;
2228 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_LANGUAGE_NEW))
2229 == NULL)
2231 g_warning ("query is null");
2232 return FALSE;
2235 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2236 gda_query_get_query_type ((GdaQuery *) query))
2238 g_warning ("non parsed sql error");
2239 return FALSE;
2242 if ((par_list =
2243 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2245 g_warning ("par_list is NULL!\n");
2246 return FALSE;
2249 if ((param =
2250 gda_parameter_list_find_param (par_list, "langname")) == NULL)
2252 g_warning ("param langname is NULL from pquery!");
2253 return FALSE;
2256 value = gda_value_new (G_TYPE_STRING);
2257 g_value_set_string (value, language);
2259 gda_parameter_set_value (param, value);
2260 gda_value_free (value);
2261 /* execute the query with parametes just set */
2262 query_result =
2263 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2265 if (query_result != NULL)
2267 table_id = sdb_engine_get_last_insert_id (dbe);
2268 g_object_unref (query_result);
2270 else
2272 table_id = -1;
2275 gda_value_free (value);
2276 return table_id;
2280 /* Add a file to project.
2281 * This function requires an opened db, i.e. calling before
2282 * symbol_db_engine_open_db ()
2283 * filepath: referes to a full file path.
2284 * WARNING: we suppose that project is already opened.
2286 static gboolean
2287 sdb_engine_add_new_file (SymbolDBEngine * dbe, const gchar * project,
2288 const gchar * filepath, const gchar * language)
2291 CREATE TABLE file (file_id integer PRIMARY KEY AUTOINCREMENT,
2292 file_path TEXT not null unique,
2293 prj_id integer REFERENCES project (projec_id),
2294 lang_id integer REFERENCES language (language_id),
2295 analize_time DATE
2298 SymbolDBEnginePriv *priv;
2299 gint project_id;
2300 gint language_id;
2301 gint file_id;
2302 GValue *value;
2304 priv = dbe->priv;
2306 value = gda_value_new (G_TYPE_STRING);
2307 g_value_set_string (value, project);
2309 /* check for an already existing table with project "project". */
2310 if ((project_id = sdb_engine_get_table_id_by_unique_name (dbe,
2311 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
2312 "prjname",
2313 value)) < 0)
2315 g_warning ("no project with that name exists");
2316 gda_value_free (value);
2317 return FALSE;
2320 gda_value_free (value);
2321 value = gda_value_new (G_TYPE_STRING);
2322 /* we're gonna set the file relative to the project folder, not the full one.
2323 * e.g.: we have a file on disk: "/tmp/foo/src/file.c" and a datasource located on
2324 * "/tmp/foo/". The entry on db will be "/src/file.c"
2326 g_value_set_string (value, filepath + strlen(priv->data_source));
2328 if ((file_id = sdb_engine_get_table_id_by_unique_name (dbe,
2329 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
2330 "filepath",
2331 value)) < 0)
2333 /* insert a new entry on db */
2334 const GdaQuery *query;
2335 GdaObject *query_result;
2336 GdaParameterList *par_list;
2337 GdaParameter *param;
2338 GValue *value;
2340 language_id = sdb_engine_add_new_language (dbe, language);
2342 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_FILE_NEW))
2343 == NULL)
2345 g_warning ("query is null");
2346 return FALSE;
2349 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2350 gda_query_get_query_type ((GdaQuery *) query))
2352 g_warning ("non parsed sql error");
2353 return FALSE;
2356 if ((par_list =
2357 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2359 g_warning ("par_list is NULL!\n");
2360 return FALSE;
2363 /* filepath parameter */
2364 if ((param =
2365 gda_parameter_list_find_param (par_list, "filepath")) == NULL)
2367 g_warning ("param filepath is NULL from pquery!");
2368 return FALSE;
2371 value = gda_value_new (G_TYPE_STRING);
2372 /* relative filepath */
2373 g_value_set_string (value, filepath + strlen(priv->data_source));
2374 gda_parameter_set_value (param, value);
2376 /* project id parameter */
2377 if ((param = gda_parameter_list_find_param (par_list, "prjid")) == NULL)
2379 g_warning ("param prjid is NULL from pquery!");
2380 return FALSE;
2383 gda_value_reset_with_type (value, G_TYPE_INT);
2384 g_value_set_int (value, project_id);
2385 gda_parameter_set_value (param, value);
2387 /* language id parameter */
2388 if ((param =
2389 gda_parameter_list_find_param (par_list, "langid")) == NULL)
2391 g_warning ("param langid is NULL from pquery!");
2392 return FALSE;
2395 gda_value_reset_with_type (value, G_TYPE_INT);
2396 g_value_set_int (value, language_id);
2397 gda_parameter_set_value (param, value);
2398 gda_value_free (value);
2400 /* execute the query with parametes just set */
2401 query_result = gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2403 if (query_result != NULL)
2404 g_object_unref (query_result);
2406 gda_value_free (value);
2408 return TRUE;
2412 static void
2413 sdb_engine_prepare_executing_commands (SymbolDBEngine *dbe)
2415 GdaCommand *command;
2416 SymbolDBEnginePriv *priv;
2417 priv = dbe->priv;
2419 command = gda_command_new ("PRAGMA page_size = 32768", GDA_COMMAND_TYPE_SQL,
2420 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2421 gda_connection_execute_non_select_command (priv->db_connection,
2422 command, NULL, NULL);
2423 gda_command_free (command);
2425 command = gda_command_new ("PRAGMA cache_size = 12288", GDA_COMMAND_TYPE_SQL,
2426 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2427 gda_connection_execute_non_select_command (priv->db_connection,
2428 command, NULL, NULL);
2429 gda_command_free (command);
2431 command = gda_command_new ("PRAGMA synchronous = OFF", GDA_COMMAND_TYPE_SQL,
2432 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2433 gda_connection_execute_non_select_command (priv->db_connection,
2434 command, NULL, NULL);
2435 gda_command_free (command);
2437 command = gda_command_new ("PRAGMA temp_store = MEMORY", GDA_COMMAND_TYPE_SQL,
2438 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2439 gda_connection_execute_non_select_command (priv->db_connection,
2440 command, NULL, NULL);
2441 gda_command_free (command);
2444 gboolean
2445 symbol_db_engine_add_new_files (SymbolDBEngine * dbe, const gchar * project,
2446 const GPtrArray * files_path,
2447 const GPtrArray * languages,
2448 gboolean scan_symbols)
2450 gint i;
2451 SymbolDBEnginePriv *priv;
2453 g_return_val_if_fail (dbe != NULL, FALSE);
2454 priv = dbe->priv;
2456 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
2457 g_return_val_if_fail (project != NULL, FALSE);
2459 /* FIXME try this... to see if things speed up*/
2460 sdb_engine_prepare_executing_commands (dbe);
2463 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
2465 g_warning ("your project isn't opened, %s (priv %s)", project,
2466 priv->project_name);
2467 return FALSE;
2470 for (i = 0; i < files_path->len; i++)
2472 gchar *node = (gchar *) g_ptr_array_index (files_path, i);
2473 gchar *node_lang = (gchar *) g_ptr_array_index (languages, i);
2475 /* test the existance of node file */
2476 if (g_file_test (node, G_FILE_TEST_EXISTS) == FALSE)
2478 g_warning ("File %s doesn't exist", node);
2479 continue;
2482 if (sdb_engine_add_new_file (dbe, project, node, node_lang) == FALSE)
2484 g_warning ("Error processing file %s", node);
2485 return FALSE;
2489 /* perform the scan of files. It will spawn a fork() process with
2490 * AnjutaLauncher and ctags in server mode. After the ctags cmd has been
2491 * executed, the populating process'll take place.
2494 if (scan_symbols)
2495 return sdb_engine_scan_files_1 (dbe, files_path, NULL, FALSE);
2497 return TRUE;
2501 static gint
2502 sdb_engine_add_new_sym_type (SymbolDBEngine * dbe, tagEntry * tag_entry)
2505 CREATE TABLE sym_type (type_id integer PRIMARY KEY AUTOINCREMENT,
2506 type varchar (256) not null ,
2507 type_name varchar (256) not null ,
2508 unique (type, type_name)
2511 const gchar *type;
2512 const gchar *type_name;
2513 gint table_id;
2515 const GdaQuery *query;
2516 GdaObject * query_result;
2517 GdaParameterList *par_list;
2518 GdaParameter *param;
2519 GValue *value;
2521 g_return_val_if_fail (tag_entry != NULL, -1);
2523 type = tag_entry->kind;
2524 type_name = tag_entry->name;
2526 /* it does not exist. Create a new tuple. */
2527 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SYM_TYPE_NEW))
2528 == NULL)
2530 g_warning ("query is null");
2531 return -1;
2534 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2535 gda_query_get_query_type ((GdaQuery *) query))
2537 g_warning ("non parsed sql error");
2538 return -1;
2541 if ((par_list =
2542 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2544 g_warning ("par_list is NULL!\n");
2545 return -1;
2548 /* type parameter */
2549 if ((param = gda_parameter_list_find_param (par_list, "type")) == NULL)
2551 g_warning ("param type is NULL from pquery!");
2552 return -1;
2555 value = gda_value_new (G_TYPE_STRING);
2556 g_value_set_string (value, type);
2557 gda_parameter_set_value (param, value);
2559 /* type_name parameter */
2560 if ((param =
2561 gda_parameter_list_find_param (par_list, "typename")) == NULL)
2563 g_warning ("param typename is NULL from pquery!");
2564 return -1;
2567 gda_value_reset_with_type (value, G_TYPE_STRING);
2568 g_value_set_string (value, type_name);
2569 gda_parameter_set_value (param, value);
2570 gda_value_free (value);
2572 /* execute the query with parametes just set */
2573 query_result =
2574 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2576 if (query_result != NULL)
2578 g_object_unref (query_result);
2579 table_id = sdb_engine_get_last_insert_id (dbe);
2581 else
2583 GValue *value1, *value2;
2585 value1 = gda_value_new (G_TYPE_STRING);
2586 g_value_set_string (value1, type);
2588 value2 = gda_value_new (G_TYPE_STRING);
2589 g_value_set_string (value2, type_name);
2591 if ((table_id = sdb_engine_get_table_id_by_unique_name2 (dbe,
2592 PREP_QUERY_GET_SYM_TYPE_ID,
2593 "type", value1,
2594 "typename",
2595 value2)) < 0)
2597 table_id = -1;
2600 gda_value_free (value1);
2601 gda_value_free (value2);
2604 return table_id;
2607 static gint
2608 sdb_engine_add_new_sym_kind (SymbolDBEngine * dbe, tagEntry * tag_entry)
2611 CREATE TABLE sym_kind (sym_kind_id integer PRIMARY KEY AUTOINCREMENT,
2612 kind_name varchar (50) not null unique
2615 const gchar *kind_name;
2616 gint table_id;
2617 GValue *value;
2619 g_return_val_if_fail (tag_entry != NULL, -1);
2621 kind_name = tag_entry->kind;
2623 /* no kind associated with current tag */
2624 if (kind_name == NULL)
2625 return -1;
2627 value = gda_value_new (G_TYPE_STRING);
2628 g_value_set_string (value, kind_name);
2630 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
2631 PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
2632 "kindname",
2633 value)) < 0)
2635 const GdaQuery *query;
2636 GdaObject *query_result;
2637 GdaParameterList *par_list;
2638 GdaParameter *param;
2639 GValue *value;
2641 /* not found. Go on with inserting */
2642 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SYM_KIND_NEW))
2643 == NULL)
2645 g_warning ("query is null");
2646 return -1;
2649 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2650 gda_query_get_query_type ((GdaQuery *) query))
2652 g_warning ("non parsed sql error");
2653 return -1;
2656 if ((par_list =
2657 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2659 g_warning ("par_list is NULL!\n");
2660 return -1;
2663 /* kindname parameter */
2664 if ((param =
2665 gda_parameter_list_find_param (par_list, "kindname")) == NULL)
2667 g_warning ("param kindname is NULL from pquery!");
2668 return -1;
2671 value = gda_value_new (G_TYPE_STRING);
2672 g_value_set_string (value, kind_name);
2673 gda_parameter_set_value (param, value);
2674 gda_value_free (value);
2676 /* execute the query with parametes just set */
2677 query_result =
2678 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2680 if (query_result != NULL)
2682 table_id = sdb_engine_get_last_insert_id (dbe);
2683 g_object_unref (query_result);
2685 else
2687 table_id = -1;
2690 gda_value_free (value);
2691 return table_id;
2694 static gint
2695 sdb_engine_add_new_sym_access (SymbolDBEngine * dbe, tagEntry * tag_entry)
2698 CREATE TABLE sym_access (access_kind_id integer PRIMARY KEY AUTOINCREMENT,
2699 access_name varchar (50) not null unique
2702 const gchar *access;
2703 gint table_id;
2704 GValue *value;
2706 g_return_val_if_fail (tag_entry != NULL, -1);
2708 if ((access = tagsField (tag_entry, "access")) == NULL)
2710 /* no access associated with current tag */
2711 return -1;
2714 value = gda_value_new (G_TYPE_STRING);
2715 g_value_set_string (value, access);
2717 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
2718 PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
2719 "accesskind",
2720 value)) < 0)
2722 const GdaQuery *query;
2723 GdaObject *query_result;
2724 GdaParameterList *par_list;
2725 GdaParameter *param;
2726 GValue *value;
2728 /* not found. Go on with inserting */
2729 if ((query =
2730 sdb_engine_get_query_by_id (dbe,
2731 PREP_QUERY_SYM_ACCESS_NEW)) == NULL)
2733 g_warning ("query is null");
2734 return -1;
2737 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2738 gda_query_get_query_type ((GdaQuery *) query))
2740 g_warning ("non parsed sql error");
2741 return -1;
2744 if ((par_list =
2745 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2747 g_warning ("par_list is NULL!\n");
2748 return -1;
2751 /* accesskind parameter */
2752 if ((param =
2753 gda_parameter_list_find_param (par_list, "accesskind")) == NULL)
2755 g_warning ("param accesskind is NULL from pquery!");
2756 return -1;
2759 value = gda_value_new (G_TYPE_STRING);
2760 g_value_set_string (value, access);
2761 gda_parameter_set_value (param, value);
2762 gda_value_free (value);
2764 /* execute the query with parametes just set */
2765 query_result =
2766 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2768 if (query_result != NULL)
2770 table_id = sdb_engine_get_last_insert_id (dbe);
2771 g_object_unref (query_result);
2773 else
2775 table_id = -1;
2778 gda_value_free (value);
2779 return table_id;
2782 static gint
2783 sdb_engine_add_new_sym_implementation (SymbolDBEngine * dbe,
2784 tagEntry * tag_entry)
2787 CREATE TABLE sym_implementation (sym_impl_id integer PRIMARY KEY AUTOINCREMENT,
2788 implementation_name varchar (50) not null unique
2791 const gchar *implementation;
2792 gint table_id;
2793 GValue *value;
2795 g_return_val_if_fail (tag_entry != NULL, -1);
2797 if ((implementation = tagsField (tag_entry, "implementation")) == NULL)
2799 /* no implementation associated with current tag */
2800 return -1;
2803 value = gda_value_new (G_TYPE_STRING);
2804 g_value_set_string (value, implementation);
2806 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
2807 PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
2808 "implekind",
2809 value)) < 0)
2811 const GdaQuery *query;
2812 GdaObject *query_result;
2813 GdaParameterList *par_list;
2814 GdaParameter *param;
2815 GValue *value;
2817 /* not found. Go on with inserting */
2818 if ((query =
2819 sdb_engine_get_query_by_id (dbe,
2820 PREP_QUERY_SYM_IMPLEMENTATION_NEW)) ==
2821 NULL)
2823 g_warning ("query is null");
2824 return -1;
2827 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2828 gda_query_get_query_type ((GdaQuery *) query))
2830 g_warning ("non parsed sql error");
2831 return -1;
2834 if ((par_list =
2835 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2837 g_warning ("par_list is NULL!\n");
2838 return -1;
2841 /* implekind parameter */
2842 if ((param =
2843 gda_parameter_list_find_param (par_list, "implekind")) == NULL)
2845 g_warning ("param implekind is NULL from pquery!");
2846 return -1;
2849 value = gda_value_new (G_TYPE_STRING);
2850 g_value_set_string (value, implementation);
2851 gda_parameter_set_value (param, value);
2852 gda_value_free (value);
2854 /* execute the query with parametes just set */
2855 query_result =
2856 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2858 if (query_result != NULL)
2860 table_id = sdb_engine_get_last_insert_id (dbe);
2861 g_object_unref (query_result);
2863 else
2865 table_id = -1;
2868 gda_value_free (value);
2869 return table_id;
2873 static void
2874 sdb_engine_add_new_heritage (SymbolDBEngine * dbe, gint base_symbol_id,
2875 gint derived_symbol_id)
2878 CREATE TABLE heritage (symbol_id_base integer REFERENCES symbol (symbol_id),
2879 symbol_id_derived integer REFERENCES symbol (symbol_id),
2880 PRIMARY KEY (symbol_id_base, symbol_id_derived)
2883 const GdaQuery *query;
2884 GdaObject *query_result;
2885 GdaParameterList *par_list;
2886 GdaParameter *param;
2887 GValue *value;
2889 g_return_if_fail (base_symbol_id > 0);
2890 g_return_if_fail (derived_symbol_id > 0);
2892 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_HERITAGE_NEW))
2893 == NULL)
2895 g_warning ("query is null");
2896 return;
2899 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2900 gda_query_get_query_type ((GdaQuery *) query))
2902 g_warning ("non parsed sql error");
2903 return;
2906 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2908 g_warning ("par_list is NULL!\n");
2909 return;
2912 /* symbase parameter */
2913 if ((param = gda_parameter_list_find_param (par_list, "symbase")) == NULL)
2915 g_warning ("param symbase is NULL from pquery!");
2916 return;
2919 value = gda_value_new (G_TYPE_INT);
2920 g_value_set_int (value, base_symbol_id);
2921 gda_parameter_set_value (param, value);
2923 /* symderived id parameter */
2924 if ((param =
2925 gda_parameter_list_find_param (par_list, "symderived")) == NULL)
2927 g_warning ("param symderived is NULL from pquery!");
2928 return;
2931 gda_value_reset_with_type (value, G_TYPE_INT);
2932 g_value_set_int (value, derived_symbol_id);
2933 gda_parameter_set_value (param, value);
2934 gda_value_free (value);
2936 /* execute the query with parametes just set */
2937 query_result =
2938 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2940 if (query_result != NULL)
2941 g_object_unref (query_result);
2945 static gint
2946 sdb_engine_add_new_scope_definition (SymbolDBEngine * dbe, tagEntry * tag_entry,
2947 gint type_table_id)
2950 CREATE TABLE scope (scope_id integer PRIMARY KEY AUTOINCREMENT,
2951 scope_name varchar(256) not null,
2952 type_id integer REFERENCES sym_type (type_id),
2953 unique (scope_name, type_id)
2956 const gchar *scope;
2957 gint table_id;
2958 const GdaQuery *query;
2959 GdaObject *query_result;
2960 GdaParameterList *par_list;
2961 GdaParameter *param;
2962 GValue *value;
2964 g_return_val_if_fail (tag_entry != NULL, -1);
2965 g_return_val_if_fail (tag_entry->kind != NULL, -1);
2967 /* This symbol will define a scope which name is tag_entry->name
2968 * For example if we get a tag MyFoo with kind "namespace", it will define
2969 * the "MyFoo" scope, which type is "namespace MyFoo"
2971 scope = tag_entry->name;
2973 /* filter out 'variable' and 'member' kinds. They define no scope. */
2974 if (strcmp (tag_entry->kind, "variable") == 0 ||
2975 strcmp (tag_entry->kind, "member") == 0)
2977 return -1;
2980 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SCOPE_NEW))
2981 == NULL)
2983 g_warning ("query is null");
2984 return -1;
2987 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2988 gda_query_get_query_type ((GdaQuery *) query))
2990 g_warning ("non parsed sql error");
2991 return -1;
2994 if ((par_list =
2995 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2997 g_warning ("par_list is NULL!\n");
2998 return -1;
3001 /* scope parameter */
3002 if ((param = gda_parameter_list_find_param (par_list, "scope")) == NULL)
3004 g_warning ("param scope is NULL from pquery!");
3005 return -1;
3008 value = gda_value_new (G_TYPE_STRING);
3009 g_value_set_string (value, scope);
3010 gda_parameter_set_value (param, value);
3012 /* typeid parameter */
3013 if ((param =
3014 gda_parameter_list_find_param (par_list, "typeid")) == NULL)
3016 g_warning ("param typeid is NULL from pquery!");
3017 return -1;
3020 gda_value_reset_with_type (value, G_TYPE_INT);
3021 g_value_set_int (value, type_table_id);
3022 gda_parameter_set_value (param, value);
3023 gda_value_free (value);
3025 /* execute the query with parameters just set */
3026 query_result = gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
3027 if (query_result == NULL)
3029 GValue *value1, *value2;
3030 /* DEBUG_PRINT ("sdb_engine_add_new_scope_definition (): BAD INSERTION "
3031 "[%s %s]", tag_entry->kind, scope);
3033 /* let's check for an already present scope table with scope and type_id infos. */
3034 value1 = gda_value_new (G_TYPE_STRING);
3035 g_value_set_string (value1, scope);
3037 value2 = gda_value_new (G_TYPE_INT);
3038 g_value_set_int (value2, type_table_id);
3040 if ((table_id = sdb_engine_get_table_id_by_unique_name2 (dbe,
3041 PREP_QUERY_GET_SCOPE_ID,
3042 "scope",
3043 value1,
3044 "typeid",
3045 value2)) < 0)
3047 table_id = -1;
3051 gda_value_free (value1);
3052 gda_value_free (value2);
3054 else {
3055 table_id = sdb_engine_get_last_insert_id (dbe);
3056 g_object_unref (query_result);
3059 return table_id;
3063 * Saves the tagEntry info for a second pass parsing.
3064 * Usually we don't know all the symbol at the first scan of the tags. We need
3065 * a second one. These tuples are created for that purpose.
3067 * @return the table_id of the inserted tuple. -1 on error.
3069 static gint
3070 sdb_engine_add_new_tmp_heritage_scope (SymbolDBEngine * dbe,
3071 tagEntry * tag_entry,
3072 gint symbol_referer_id)
3075 CREATE TABLE __tmp_heritage_scope (tmp_heritage_scope_id integer PRIMARY KEY
3076 AUTOINCREMENT,
3077 symbol_referer_id integer not null,
3078 field_inherits varchar(256) not null,
3079 field_struct varchar(256),
3080 field_typeref varchar(256),
3081 field_enum varchar(256),
3082 field_union varchar(256),
3083 field_class varchar(256),
3084 field_namespace varchar(256)
3087 const GdaQuery *query;
3088 GdaObject *query_result;
3089 GdaParameterList *par_list;
3090 GdaParameter *param;
3091 gint table_id;
3092 GValue *value;
3093 const gchar *field_inherits, *field_struct, *field_typeref,
3094 *field_enum, *field_union, *field_class, *field_namespace;
3095 gboolean good_tag;
3097 g_return_val_if_fail (tag_entry != NULL, -1);
3099 /* init the flag */
3100 good_tag = FALSE;
3102 if ((field_inherits = tagsField (tag_entry, "inherits")) == NULL)
3104 field_inherits = "";
3106 else
3107 good_tag = TRUE;
3109 if ((field_struct = tagsField (tag_entry, "struct")) == NULL)
3111 field_struct = "";
3113 else
3114 good_tag = TRUE;
3116 if ((field_typeref = tagsField (tag_entry, "typeref")) == NULL)
3118 field_typeref = "";
3120 else
3121 good_tag = TRUE;
3123 if ((field_enum = tagsField (tag_entry, "enum")) == NULL)
3125 field_enum = "";
3127 else
3128 good_tag = TRUE;
3130 if ((field_union = tagsField (tag_entry, "union")) == NULL)
3132 field_union = "";
3134 else
3135 good_tag = TRUE;
3137 if ((field_class = tagsField (tag_entry, "class")) == NULL)
3139 field_class = "";
3141 else
3142 good_tag = TRUE;
3144 if ((field_namespace = tagsField (tag_entry, "namespace")) == NULL)
3146 field_namespace = "";
3148 else
3149 good_tag = TRUE;
3151 if (!good_tag)
3152 return -1;
3155 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_TMP_HERITAGE_NEW))
3156 == NULL)
3158 g_warning ("query is null");
3159 return -1;
3162 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3163 gda_query_get_query_type ((GdaQuery *) query))
3165 g_warning ("non parsed sql error");
3166 return -1;
3169 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
3171 g_warning ("par_list is NULL!\n");
3172 return -1;
3175 /* symreferid parameter */
3176 if ((param =
3177 gda_parameter_list_find_param (par_list, "symreferid")) == NULL)
3179 g_warning ("param symreferid is NULL from pquery!");
3180 return -1;
3183 value = gda_value_new (G_TYPE_INT);
3184 g_value_set_int (value, symbol_referer_id);
3185 gda_parameter_set_value (param, value);
3187 /* finherits parameter */
3188 if ((param = gda_parameter_list_find_param (par_list, "finherits")) == NULL)
3190 g_warning ("param finherits is NULL from pquery!");
3191 return -1;
3194 gda_value_reset_with_type (value, G_TYPE_STRING);
3195 g_value_set_string (value, field_inherits);
3196 gda_parameter_set_value (param, value);
3198 /* fstruct parameter */
3199 if ((param = gda_parameter_list_find_param (par_list, "fstruct")) == NULL)
3201 g_warning ("param fstruct is NULL from pquery!");
3202 return -1;
3205 gda_value_reset_with_type (value, G_TYPE_STRING);
3206 g_value_set_string (value, field_struct);
3207 gda_parameter_set_value (param, value);
3209 /* ftyperef parameter */
3210 if ((param = gda_parameter_list_find_param (par_list, "ftyperef")) == NULL)
3212 g_warning ("param ftyperef is NULL from pquery!");
3213 return -1;
3216 gda_value_reset_with_type (value, G_TYPE_STRING);
3217 g_value_set_string (value, field_typeref);
3218 gda_parameter_set_value (param, value);
3220 /* fenum parameter */
3221 if ((param = gda_parameter_list_find_param (par_list, "fenum")) == NULL)
3223 g_warning ("param fenum is NULL from pquery!");
3224 return -1;
3227 gda_value_reset_with_type (value, G_TYPE_STRING);
3228 g_value_set_string (value, field_enum);
3229 gda_parameter_set_value (param, value);
3231 /* funion parameter */
3232 if ((param = gda_parameter_list_find_param (par_list, "funion")) == NULL)
3234 g_warning ("param funion is NULL from pquery!");
3235 return -1;
3238 gda_value_reset_with_type (value, G_TYPE_STRING);
3239 g_value_set_string (value, field_union);
3240 gda_parameter_set_value (param, value);
3242 /* fclass parameter */
3243 if ((param = gda_parameter_list_find_param (par_list, "fclass")) == NULL)
3245 g_warning ("param fclass is NULL from pquery!");
3246 return -1;
3249 gda_value_reset_with_type (value, G_TYPE_STRING);
3250 g_value_set_string (value, field_class);
3251 gda_parameter_set_value (param, value);
3253 /* fnamespace parameter */
3254 if ((param =
3255 gda_parameter_list_find_param (par_list, "fnamespace")) == NULL)
3257 g_warning ("param fnamespace is NULL from pquery!");
3258 return -1;
3261 gda_value_reset_with_type (value, G_TYPE_STRING);
3262 g_value_set_string (value, field_namespace);
3263 gda_parameter_set_value (param, value);
3264 gda_value_free (value);
3267 /* execute the query with parametes just set */
3268 query_result =
3269 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
3271 if (query_result != NULL)
3273 table_id = sdb_engine_get_last_insert_id (dbe);
3274 g_object_unref (query_result);
3276 else
3278 table_id = -1;
3281 return table_id;
3284 /** Return the symbol_id of the changed symbol */
3285 static gint
3286 sdb_engine_second_pass_update_scope_1 (SymbolDBEngine * dbe,
3287 GdaDataModel * data, gint data_row,
3288 gchar * token_name,
3289 const GValue * token_value)
3291 gint scope_id;
3292 GValue *value1, *value2, *value;
3293 const GValue *value_id2;
3294 gint symbol_referer_id;
3295 const gchar *tmp_str;
3296 gchar **tmp_str_splitted;
3297 gint tmp_str_splitted_length;
3298 gchar *object_name = NULL;
3299 gboolean free_token_name = FALSE;
3300 const GdaQuery *query;
3301 GdaParameterList *par_list;
3302 GdaParameter *param;
3303 SymbolDBEnginePriv *priv;
3305 g_return_val_if_fail (dbe != NULL, FALSE);
3306 g_return_val_if_fail (G_VALUE_HOLDS_STRING (token_value), FALSE);
3308 priv = dbe->priv;
3309 tmp_str = g_value_get_string (token_value);
3311 /* we don't need empty strings */
3312 if (strcmp (tmp_str, "") == 0)
3314 return -1;
3317 /* DEBUG_PRINT ("sdb_engine_second_pass_update_scope_1 ()---------------------");
3318 DEBUG_PRINT ("sdb_engine_second_pass_update_scope_1 (): %s", tmp_str);*/
3320 /* we could have something like "First::Second::Third::Fourth" as tmp_str, so
3321 * take only the lastscope, in this case 'Fourth'.
3323 tmp_str_splitted = g_strsplit (tmp_str, ":", 0);
3324 tmp_str_splitted_length = g_strv_length (tmp_str_splitted);
3326 if (tmp_str_splitted_length > 0)
3328 /* handle special typedef case. Usually we have something like struct:my_foo.
3329 * splitting we have [0]-> struct [1]-> my_foo
3331 if (strcmp (token_name, "typedef") == 0)
3333 free_token_name = TRUE;
3334 token_name = g_strdup (tmp_str_splitted[0]);
3337 object_name = g_strdup (tmp_str_splitted[tmp_str_splitted_length - 1]);
3339 else
3341 g_strfreev (tmp_str_splitted);
3342 return -1;
3345 g_strfreev (tmp_str_splitted);
3347 /* DEBUG_PRINT ("sdb_engine_second_pass_update_scope_1(): got %s %s (from %s)",
3348 token_name, object_name, tmp_str); */
3350 value1 = gda_value_new (G_TYPE_STRING);
3351 g_value_set_string (value1, token_name);
3353 value2 = gda_value_new (G_TYPE_STRING);
3354 g_value_set_string (value2, object_name);
3356 if ((scope_id = sdb_engine_get_table_id_by_unique_name2 (dbe,
3357 PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
3358 "tokenname",
3359 value1,
3360 "objectname",
3361 value2)) < 0)
3363 if (free_token_name)
3364 g_free (token_name);
3366 gda_value_free (value1);
3367 gda_value_free (value2);
3368 return -1;
3370 gda_value_free (value1);
3371 gda_value_free (value2);
3373 if (free_token_name)
3374 g_free (token_name);
3377 /* if we reach this point we should have a good scope_id.
3378 * Go on with symbol updating.
3380 value_id2 = gda_data_model_get_value_at_col_name (data, "symbol_referer_id",
3381 data_row);
3382 symbol_referer_id = g_value_get_int (value_id2);
3384 /* DEBUG_PRINT ("sdb_engine_second_pass_update_scope_1 () :updating sym %d "
3385 "with %d",
3386 symbol_referer_id, scope_id);*/
3388 if ((query = sdb_engine_get_query_by_id (dbe,
3389 PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID))
3390 == NULL)
3392 g_warning ("query is null");
3393 return -1;
3396 if (GDA_QUERY_TYPE_NON_PARSED_SQL
3397 == gda_query_get_query_type ((GdaQuery *) query))
3399 g_warning ("non parsed sql error");
3400 return -1;
3403 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
3405 g_warning ("par_list is NULL!\n");
3406 return -1;
3409 /* scopeid parameter */
3410 if ((param = gda_parameter_list_find_param (par_list, "scopeid")) == NULL)
3412 g_warning ("param scopeid is NULL from pquery!");
3413 return -1;
3416 value = gda_value_new (G_TYPE_INT);
3417 g_value_set_int (value, scope_id);
3418 gda_parameter_set_value (param, value);
3420 /* symbolid parameter */
3421 if ((param = gda_parameter_list_find_param (par_list, "symbolid")) == NULL)
3423 g_warning ("param symbolid is NULL from pquery!");
3424 return -1;
3427 gda_value_reset_with_type (value, G_TYPE_INT);
3428 g_value_set_int (value, symbol_referer_id);
3429 gda_parameter_set_value (param, value);
3430 gda_value_free (value);
3432 /* execute the query with parametes just set */
3433 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
3435 return symbol_referer_id;
3440 * @param data Must be filled with some values. It must have num_rows > 0
3441 * @note *CALL THIS BEFORE second_pass_update_heritage ()*
3442 * @note *DO NOT FREE data* inside this function.
3444 static void
3445 sdb_engine_second_pass_update_scope (SymbolDBEngine * dbe, GdaDataModel * data)
3448 * Fill up the scope.
3449 * The case: "my_foo_func_1" is the name of the current tag parsed.
3450 * Suppose we have a namespace MyFooNamespace, under which is declared
3451 * a class MyFooClass. Under that class there are some funcs like
3452 * my_foo_func_1 () etc. ctags will present us this info about
3453 * my_foo_func_1 ():
3454 * "class : MyFooNamespace::MyFooClass"
3455 * but hey! We don't need to know the namespace here, we just want to
3456 * know that my_foo_func_1 is in the scope of MyFooClass. That one will
3457 * then be mapped inside MyFooNamespace, but that's another thing.
3458 * Go on with the parsing then.
3460 gint i;
3462 for (i = 0; i < gda_data_model_get_n_rows (data); i++)
3464 GValue *value;
3466 if ((value =
3467 (GValue *) gda_data_model_get_value_at_col_name (data,
3468 "field_class",
3469 i)) != NULL)
3471 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "class",
3472 value);
3475 if ((value =
3476 (GValue *) gda_data_model_get_value_at_col_name (data,
3477 "field_struct",
3478 i)) != NULL)
3480 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "struct",
3481 value);
3484 if ((value =
3485 (GValue *) gda_data_model_get_value_at_col_name (data,
3486 "field_typeref",
3487 i)) != NULL)
3489 /* this is a "typedef", not a "typeref". */
3490 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "typedef",
3491 value);
3494 if ((value =
3495 (GValue *) gda_data_model_get_value_at_col_name (data,
3496 "field_enum",
3497 i)) != NULL)
3499 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "enum", value);
3502 if ((value =
3503 (GValue *) gda_data_model_get_value_at_col_name (data,
3504 "field_union",
3505 i)) != NULL)
3507 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "union",
3508 value);
3511 if ((value =
3512 (GValue *) gda_data_model_get_value_at_col_name (data,
3513 "field_namespace",
3514 i)) != NULL)
3516 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "namespace",
3517 value);
3524 * @param data Must be filled with some values. It must have num_rows > 0
3525 * @note *CALL THIS AFTER second_pass_update_scope ()*
3527 static void
3528 sdb_engine_second_pass_update_heritage (SymbolDBEngine * dbe,
3529 GdaDataModel * data)
3531 gint i;
3532 SymbolDBEnginePriv *priv;
3534 g_return_if_fail (dbe != NULL);
3536 priv = dbe->priv;
3538 for (i = 0; i < gda_data_model_get_n_rows (data); i++)
3540 const GValue *value;
3541 const gchar *inherits;
3542 gchar *item;
3543 gchar **inherits_list;
3544 gint j;
3546 value = gda_data_model_get_value_at_col_name (data,
3547 "field_inherits", i);
3548 inherits = g_value_get_string (value);
3550 /* there can be multiple inheritance. Check that. */
3551 inherits_list = g_strsplit (inherits, ",", 0);
3553 if (inherits_list != NULL)
3554 DEBUG_PRINT ("inherits %s\n", inherits);
3556 /* retrieve as much info as we can from the items */
3557 for (j = 0; j < g_strv_length (inherits_list); j++)
3559 gchar **namespaces;
3560 gchar *klass_name;
3561 gchar *namespace_name;
3562 gint namespaces_length;
3563 gint base_klass_id;
3564 gint derived_klass_id;
3565 const GValue *value;
3567 item = inherits_list[j];
3568 DEBUG_PRINT ("heritage %s\n", item);
3570 /* A item may have this string form:
3571 * MyFooNamespace1::MyFooNamespace2::MyFooClass
3572 * We should find the field 'MyFooNamespace2' because it's the one
3573 * that is reachable by the scope_id value of the symbol.
3576 namespaces = g_strsplit (item, "::", 0);
3577 namespaces_length = g_strv_length (namespaces);
3579 if (namespaces_length > 1)
3581 /* this is the case in which we have the case with
3582 * namespace + class
3584 namespace_name = g_strdup (namespaces[namespaces_length - 2]);
3585 klass_name = g_strdup (namespaces[namespaces_length - 1]);
3587 else
3589 /* have a last check before setting namespace_name to null.
3590 * check whether the field_namespace is void or not.
3592 const GValue *namespace_value;
3593 const gchar *tmp_namespace;
3594 gchar **tmp_namespace_array = NULL;
3595 gint tmp_namespace_length;
3597 namespace_value =
3598 gda_data_model_get_value_at_col_name (data,
3599 "field_namespace", i);
3600 tmp_namespace = g_value_get_string (namespace_value);
3601 if (tmp_namespace != NULL)
3603 tmp_namespace_array = g_strsplit (tmp_namespace, "::", 0);
3604 tmp_namespace_length = g_strv_length (tmp_namespace_array);
3606 if (tmp_namespace_length > 0)
3607 namespace_name =
3608 g_strdup (tmp_namespace_array
3609 [tmp_namespace_length - 1]);
3610 else
3611 namespace_name = NULL;
3613 else
3615 namespace_name = NULL;
3618 klass_name = g_strdup (namespaces[namespaces_length - 1]);
3620 g_strfreev (tmp_namespace_array);
3623 g_strfreev (namespaces);
3625 /* get the derived_klass_id. It should be the
3626 * symbol_referer_id field into __tmp_heritage_scope table
3628 if ((value = (GValue *) gda_data_model_get_value_at (data,
3629 1, i)) != NULL)
3631 derived_klass_id = g_value_get_int (value);
3633 else
3635 derived_klass_id = 0;
3638 /* ok, search for the symbol_id of the base class */
3639 if (namespace_name == NULL)
3641 GValue *value1;
3643 value1 = gda_value_new (G_TYPE_STRING);
3644 g_value_set_string (value1, klass_name);
3646 if ((base_klass_id =
3647 sdb_engine_get_table_id_by_unique_name (dbe,
3648 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
3649 "klassname",
3650 value1)) < 0)
3652 gda_value_free (value1);
3653 continue;
3655 gda_value_free (value1);
3657 else
3659 /* FIXME:
3660 when Libgda will parse correctly the PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE
3661 query please uncomment this section and let the prepared statements do their
3662 work.
3664 GValue *value1;
3665 GValue *value2;
3667 value1 = gda_value_new (G_TYPE_STRING);
3668 g_value_set_string (value1, klass_name);
3670 value2 = gda_value_new (G_TYPE_STRING);
3671 g_value_set_string (value2, namespace_name);
3673 DEBUG_PRINT ("value1 : %s value2 : %s", klass_name, namespace_name);
3674 if ((base_klass_id =
3675 sdb_engine_get_table_id_by_unique_name2 (dbe,
3676 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
3677 "klassname",
3678 value1,
3679 "namespacename",
3680 value2)) < 0)
3682 gda_value_free (value1);
3683 gda_value_free (value2);
3684 continue;
3686 gda_value_free (value1);
3687 gda_value_free (value2);
3689 GValue *value1;
3690 GdaDataModel *base_data;
3691 gchar *query_str;
3692 query_str =
3693 g_strdup_printf ("SELECT symbol_id FROM symbol JOIN scope ON "
3694 "symbol.scope_id=scope.scope_id JOIN sym_type ON "
3695 "scope.type_id=sym_type.type_id WHERE "
3696 "symbol.name='%s' AND scope.scope_name='%s' AND "
3697 "sym_type.type='namespace'",
3698 klass_name, namespace_name);
3700 if ((base_data =
3701 sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
3702 gda_data_model_get_n_rows (base_data) <= 0 )
3704 g_free (query_str);
3706 if (base_data != NULL)
3707 g_object_unref (base_data);
3709 continue;
3712 value1 = (GValue*)gda_data_model_get_value_at (base_data, 0, 0);
3713 base_klass_id = g_value_get_int (value1);
3714 DEBUG_PRINT ("found base_klass_id %d", base_klass_id );
3715 g_free (query_str);
3717 if (base_data != NULL)
3718 g_object_unref (base_data);
3721 g_free (namespace_name);
3722 g_free (klass_name);
3724 DEBUG_PRINT ("gonna sdb_engine_add_new_heritage with "
3725 "base_klass_id %d, derived_klass_id %d", base_klass_id,
3726 derived_klass_id);
3727 sdb_engine_add_new_heritage (dbe, base_klass_id, derived_klass_id);
3730 g_strfreev (inherits_list);
3735 * Process the temporary table to update the symbols on scope and inheritance
3736 * fields.
3737 * *CALL THIS FUNCTION ONLY AFTER HAVING PARSED ALL THE TAGS ONCE*
3740 static void
3741 sdb_engine_second_pass_do (SymbolDBEngine * dbe)
3743 GdaObject *query_result;
3744 const GdaQuery *query1, *query2, *query3;
3746 /* prepare for scope second scan */
3747 if ((query1 =
3748 sdb_engine_get_query_by_id (dbe,
3749 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE))
3750 == NULL)
3752 g_warning ("query is null");
3753 return;
3756 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3757 gda_query_get_query_type ((GdaQuery *) query1))
3759 g_warning ("non parsed sql error");
3760 return;
3763 /* execute the query */
3764 query_result = gda_query_execute ((GdaQuery *) query1, NULL, FALSE, NULL);
3766 if (!GDA_IS_DATA_MODEL (query_result) ||
3767 gda_data_model_get_n_rows (GDA_DATA_MODEL (query_result)) <= 0)
3769 if (query_result != NULL)
3770 g_object_unref (query_result);
3771 query_result = NULL;
3773 else
3775 sdb_engine_second_pass_update_scope (dbe, GDA_DATA_MODEL (query_result));
3778 if (query_result != NULL)
3779 g_object_unref (query_result);
3781 /* prepare for heritage second scan */
3782 if ((query2 =
3783 sdb_engine_get_query_by_id (dbe,
3784 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS))
3785 == NULL)
3787 g_warning ("query is null");
3788 return;
3791 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3792 gda_query_get_query_type ((GdaQuery *) query2))
3794 g_warning ("non parsed sql error");
3795 return;
3798 /* execute the query */
3799 query_result = gda_query_execute ((GdaQuery *) query2, NULL, FALSE, NULL);
3801 if (!GDA_IS_DATA_MODEL (query_result) ||
3802 gda_data_model_get_n_rows (GDA_DATA_MODEL (query_result)) <= 0)
3804 if (query_result != NULL)
3805 g_object_unref (query_result);
3806 query_result = NULL;
3808 else
3810 sdb_engine_second_pass_update_heritage (dbe, GDA_DATA_MODEL (query_result));
3813 if (query_result != NULL)
3814 g_object_unref (query_result);
3816 /* clean tmp heritage table */
3817 if ((query3 =
3818 sdb_engine_get_query_by_id (dbe,
3819 PREP_QUERY_TMP_HERITAGE_DELETE_ALL))
3820 == NULL)
3822 g_warning ("query is null");
3823 return;
3826 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3827 gda_query_get_query_type ((GdaQuery *) query3))
3829 g_warning ("non parsed sql error");
3830 return;
3833 /* execute the query */
3834 query_result =
3835 gda_query_execute ((GdaQuery *) query3, NULL, FALSE, NULL);
3837 if (query_result != NULL)
3838 g_object_unref (query_result);
3841 /* base_prj_path can be NULL. In that case path info tag_entry will be taken
3842 * as an absolute path.
3843 * fake_file can be used when a buffer updating is being executed. In that
3844 * particular case both base_prj_path and tag_entry->file will be ignored.
3845 * fake_file is real_path of file on disk
3847 static gint
3848 sdb_engine_add_new_symbol (SymbolDBEngine * dbe, tagEntry * tag_entry,
3849 const gchar *base_prj_path, const gchar *fake_file,
3850 gboolean sym_update)
3853 CREATE TABLE symbol (symbol_id integer PRIMARY KEY AUTOINCREMENT,
3854 file_defined_id integer not null REFERENCES file (file_id),
3855 name varchar (256) not null,
3856 file_position integer,
3857 is_file_scope integer,
3858 signature varchar (256),
3859 scope_definition_id integer,
3860 scope_id integer,
3861 type_id integer REFERENCES sym_type (type_id),
3862 kind_id integer REFERENCES sym_kind (sym_kind_id),
3863 access_kind_id integer REFERENCES sym_access (sym_access_id),
3864 implementation_kind_id integer REFERENCES sym_implementation
3865 (sym_impl_id)
3868 SymbolDBEnginePriv *priv;
3869 const GdaQuery *query;
3870 GdaObject *query_result;
3871 GdaParameterList *par_list;
3872 GdaParameter *param;
3873 const gchar *tmp_str;
3874 gint table_id, symbol_id;
3875 gint file_defined_id = 0;
3876 gchar name[256];
3877 gint file_position = 0;
3878 gint is_file_scope = 0;
3879 gchar signature[256];
3880 gint scope_definition_id = 0;
3881 gint scope_id = 0;
3882 gint type_id = 0;
3883 gint kind_id = 0;
3884 gint access_kind_id = 0;
3885 gint implementation_kind_id = 0;
3886 GValue *value, *value1, *value2, *value3;
3887 gboolean sym_was_updated = FALSE;
3889 gint update_flag;
3891 g_return_val_if_fail (dbe != NULL, -1);
3892 priv = dbe->priv;
3894 /* keep it at 0 if sym_update == false */
3895 if (sym_update == FALSE)
3896 update_flag = 0;
3897 else
3898 update_flag = 1;
3900 g_return_val_if_fail (tag_entry != NULL, -1);
3902 value = gda_value_new (G_TYPE_STRING);
3903 if (base_prj_path != NULL)
3905 /* in this case fake_file will be ignored. */
3907 /* we expect here an absolute path */
3908 g_value_set_string (value,
3909 tag_entry->file + strlen (base_prj_path) );
3911 else
3913 /* check whether the fake_file can substitute the tag_entry->file one */
3914 if (fake_file == NULL)
3915 g_value_set_string (value, tag_entry->file);
3916 else
3917 g_value_set_string (value, fake_file);
3920 if ((file_defined_id = sdb_engine_get_table_id_by_unique_name (dbe,
3921 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
3922 "filepath",
3923 value)) < 0)
3925 /* if we arrive here there should be some sync problems between the filenames
3926 * in database and the ones in the ctags files. We trust in db's ones,
3927 * so we'll just return here.
3929 g_warning ("sync problems between db and ctags filenames entries. "
3930 "File was %s (base_path: %s, fake_file: %s, tag_file: %s)",
3931 g_value_get_string (value), base_prj_path, fake_file,
3932 tag_entry->file);
3933 gda_value_free (value);
3934 return -1;
3938 /* parse the entry name */
3939 if (strlen (tag_entry->name) > sizeof (name))
3941 DEBUG_PRINT ("fatal error when inserting symbol, name of symbol is too big.");
3942 gda_value_free (value);
3943 return -1;
3945 else
3947 memset (name, 0, sizeof (name));
3948 memcpy (name, tag_entry->name, strlen (tag_entry->name));
3951 file_position = tag_entry->address.lineNumber;
3952 is_file_scope = tag_entry->fileScope;
3954 memset (signature, 0, sizeof (signature));
3955 if ((tmp_str = tagsField (tag_entry, "signature")) != NULL)
3957 if (strlen (tmp_str) > sizeof (signature))
3959 memcpy (signature, tmp_str, sizeof (signature));
3961 else
3963 memcpy (signature, tmp_str, strlen (tmp_str));
3967 type_id = sdb_engine_add_new_sym_type (dbe, tag_entry);
3970 /* scope_definition_id tells what scope this symbol defines
3971 * this call *MUST BE DONE AFTER* sym_type table population.
3973 scope_definition_id = sdb_engine_add_new_scope_definition (dbe, tag_entry,
3974 type_id);
3976 /* the container scopes can be: union, struct, typeref, class, namespace etc.
3977 * this field will be parse in the second pass.
3979 scope_id = 0;
3981 kind_id = sdb_engine_add_new_sym_kind (dbe, tag_entry);
3983 access_kind_id = sdb_engine_add_new_sym_access (dbe, tag_entry);
3984 implementation_kind_id =
3985 sdb_engine_add_new_sym_implementation (dbe, tag_entry);
3987 /* ok: was the symbol updated [at least on it's type_id/name]?
3988 * There are 3 cases:
3989 * #1. The symbol remain the same [at least on unique index key]. We will
3990 * perform only a simple update.
3991 * #2. The symbol has changed: at least on name/type/file. We will insert a
3992 * new symbol on table 'symbol'. Deletion of old one will take place
3993 * at a second stage, when a delete of all symbols with
3994 * 'tmp_flag = 0' will be done.
3995 * #3. The symbol has been deleted. As above it will be deleted at
3996 * a second stage because of the 'tmp_flag = 0'. Triggers will remove
3997 * also scope_ids and other things.
4000 value1 = gda_value_new (G_TYPE_STRING);
4001 g_value_set_string (value1, name);
4003 value2 = gda_value_new (G_TYPE_INT);
4004 g_value_set_int (value2, file_defined_id);
4006 value3 = gda_value_new (G_TYPE_INT);
4007 g_value_set_int (value3, type_id);
4009 if ((symbol_id = sdb_engine_get_table_id_by_unique_name3 (dbe,
4010 PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY,
4011 "symname", value1,
4012 "filedefid",value2,
4013 "typeid", value3)) <= 0)
4015 /* case 2 and 3 */
4016 sym_was_updated = FALSE;
4018 gda_value_free (value1);
4019 gda_value_free (value2);
4020 gda_value_free (value3);
4022 /* create specific query for a fresh new symbol */
4023 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SYMBOL_NEW))
4024 == NULL)
4026 g_warning ("query is null");
4027 return -1;
4030 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4031 gda_query_get_query_type ((GdaQuery *) query))
4033 g_warning ("non parsed sql error");
4034 gda_value_free (value);
4035 return -1;
4038 if ((par_list =
4039 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4041 g_warning ("par_list is NULL!\n");
4042 gda_value_free (value);
4043 return -1;
4046 /* filedefid parameter */
4047 if ((param =
4048 gda_parameter_list_find_param (par_list, "filedefid")) == NULL)
4050 g_warning ("param filedefid is NULL from pquery!");
4051 gda_value_free (value);
4052 return -1;
4055 gda_value_reset_with_type (value, G_TYPE_INT);
4056 g_value_set_int (value, file_defined_id);
4057 gda_parameter_set_value (param, value);
4059 /* name parameter */
4060 if ((param = gda_parameter_list_find_param (par_list, "name")) == NULL)
4062 g_warning ("param name is NULL from pquery!");
4063 gda_value_free (value);
4064 return -1;
4067 gda_value_reset_with_type (value, G_TYPE_STRING);
4068 g_value_set_string (value, name);
4069 gda_parameter_set_value (param, value);
4071 /* typeid parameter */
4072 if ((param =
4073 gda_parameter_list_find_param (par_list, "typeid")) == NULL)
4075 g_warning ("param typeid is NULL from pquery!");
4076 gda_value_free (value);
4077 return -1;
4080 gda_value_reset_with_type (value, G_TYPE_INT);
4081 g_value_set_int (value, type_id);
4082 gda_parameter_set_value (param, value);
4084 else
4086 /* case 1 */
4087 sym_was_updated = TRUE;
4089 gda_value_free (value1);
4090 gda_value_free (value2);
4091 gda_value_free (value3);
4093 /* create specific query for a fresh new symbol */
4094 if ((query = sdb_engine_get_query_by_id (dbe,
4095 PREP_QUERY_UPDATE_SYMBOL_ALL))
4096 == NULL)
4098 g_warning ("query is null");
4099 return -1;
4102 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4103 gda_query_get_query_type ((GdaQuery *) query))
4105 g_warning ("non parsed sql error");
4106 gda_value_free (value);
4107 return -1;
4110 if ((par_list =
4111 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4113 g_warning ("par_list is NULL!\n");
4114 gda_value_free (value);
4115 return -1;
4118 /* symbolid parameter */
4119 if ((param = gda_parameter_list_find_param (par_list, "symbolid"))
4120 == NULL)
4122 g_warning ("param isfilescope is NULL from pquery!");
4123 gda_value_free (value);
4124 return -1;
4127 gda_value_reset_with_type (value, G_TYPE_INT);
4128 g_value_set_int (value, symbol_id);
4129 gda_parameter_set_value (param, value);
4132 /* common params */
4134 /* fileposition parameter */
4135 if ((param =
4136 gda_parameter_list_find_param (par_list, "fileposition")) == NULL)
4138 g_warning ("param fileposition is NULL from pquery!");
4139 gda_value_free (value);
4140 return -1;
4143 gda_value_reset_with_type (value, G_TYPE_INT);
4144 g_value_set_int (value, file_position);
4145 gda_parameter_set_value (param, value);
4148 /* isfilescope parameter */
4149 if ((param =
4150 gda_parameter_list_find_param (par_list, "isfilescope")) == NULL)
4152 g_warning ("param isfilescope is NULL from pquery!");
4153 gda_value_free (value);
4154 return -1;
4157 gda_value_reset_with_type (value, G_TYPE_INT);
4158 g_value_set_int (value, is_file_scope);
4159 gda_parameter_set_value (param, value);
4161 /* signature parameter */
4162 if ((param = gda_parameter_list_find_param (par_list, "signature")) == NULL)
4164 g_warning ("param signature is NULL from pquery!");
4165 gda_value_free (value);
4166 return -1;
4169 gda_value_reset_with_type (value, G_TYPE_STRING);
4170 g_value_set_string (value, signature);
4171 gda_parameter_set_value (param, value);
4173 /* scopedefinitionid parameter */
4174 if ((param =
4175 gda_parameter_list_find_param (par_list, "scopedefinitionid")) == NULL)
4177 g_warning ("param scopedefinitionid is NULL from pquery!");
4178 gda_value_free (value);
4179 return -1;
4182 gda_value_reset_with_type (value, G_TYPE_INT);
4183 g_value_set_int (value, scope_definition_id);
4184 gda_parameter_set_value (param, value);
4186 /* scopeid parameter */
4187 if ((param = gda_parameter_list_find_param (par_list, "scopeid")) == NULL)
4189 g_warning ("param scopeid is NULL from pquery!");
4190 gda_value_free (value);
4191 return -1;
4194 gda_value_reset_with_type (value, G_TYPE_INT);
4195 g_value_set_int (value, scope_id);
4196 gda_parameter_set_value (param, value);
4198 /* kindid parameter */
4199 if ((param = gda_parameter_list_find_param (par_list, "kindid")) == NULL)
4201 g_warning ("param kindid is NULL from pquery!");
4202 gda_value_free (value);
4203 return -1;
4206 gda_value_reset_with_type (value, G_TYPE_INT);
4207 g_value_set_int (value, kind_id);
4208 gda_parameter_set_value (param, value);
4210 /* accesskindid parameter */
4211 if ((param =
4212 gda_parameter_list_find_param (par_list, "accesskindid")) == NULL)
4214 g_warning ("param accesskindid is NULL from pquery!");
4215 gda_value_free (value);
4216 return -1;
4219 gda_value_reset_with_type (value, G_TYPE_INT);
4220 g_value_set_int (value, access_kind_id);
4221 gda_parameter_set_value (param, value);
4223 /* implementationkindid parameter */
4224 if ((param =
4225 gda_parameter_list_find_param (par_list,
4226 "implementationkindid")) == NULL)
4228 g_warning ("param implementationkindid is NULL from pquery!");
4229 gda_value_free (value);
4230 return -1;
4233 gda_value_reset_with_type (value, G_TYPE_INT);
4234 g_value_set_int (value, implementation_kind_id);
4235 gda_parameter_set_value (param, value);
4237 /* updateflag parameter */
4238 if ((param =
4239 gda_parameter_list_find_param (par_list, "updateflag")) == NULL)
4241 g_warning ("param updateflag is NULL from pquery!");
4242 gda_value_free (value);
4243 return -1;
4246 gda_value_reset_with_type (value, G_TYPE_INT);
4247 g_value_set_int (value, update_flag);
4248 gda_parameter_set_value (param, value);
4249 gda_value_free (value);
4251 /* execute the query with parametes just set */
4252 query_result =
4253 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
4255 if (sym_was_updated == FALSE)
4257 if (query_result != NULL)
4259 table_id = sdb_engine_get_last_insert_id (dbe);
4260 g_object_unref (query_result);
4262 /* This is a wrong place to emit the symbol-updated signal. Infact
4263 * db is in a inconsistent state, e.g. inheritance references are still
4264 * *not* calculated.
4265 * So add the symbol id into a queue that will be parsed once and emitted.
4267 g_async_queue_push (priv->inserted_symbols_id, (gpointer) table_id);
4269 else
4271 table_id = -1;
4274 else
4276 if (query_result != NULL)
4278 table_id = symbol_id;
4279 g_object_unref (query_result);
4281 /* This is a wrong place to emit the symbol-updated signal. Infact
4282 * db is in a inconsistent state, e.g. inheritance references are still
4283 * *not* calculated.
4284 * So add the symbol id into a queue that will be parsed once and emitted.
4286 g_async_queue_push (priv->updated_symbols_id, (gpointer) table_id);
4288 else
4290 table_id = -1;
4294 /* before returning the table_id we have to fill some infoz on temporary tables
4295 * so that in a second pass we can parse also the heritage and scope fields.
4297 if (table_id > 0)
4298 sdb_engine_add_new_tmp_heritage_scope (dbe, tag_entry, table_id);
4299 return table_id;
4304 * Select * from __tmp_removed and emits removed signals.
4306 static void
4307 sdb_engine_detects_removed_ids (SymbolDBEngine *dbe)
4309 const GdaQuery *query, *query2;
4310 GdaObject *query_result;
4311 SymbolDBEnginePriv *priv;
4312 gint num_rows;
4313 gint i;
4314 g_return_if_fail (dbe != NULL);
4316 priv = dbe->priv;
4318 /* ok, now we should read from __tmp_removed all the symbol ids which have
4319 * been removed, and emit a signal
4321 if ((query = sdb_engine_get_query_by_id (dbe,
4322 PREP_QUERY_GET_REMOVED_IDS))
4323 == NULL)
4325 g_warning ("query is null");
4326 return;
4329 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4330 gda_query_get_query_type ((GdaQuery *) query))
4332 g_warning ("non parsed sql error");
4333 return;
4336 query_result = gda_query_execute ((GdaQuery *) query, NULL, FALSE,
4337 NULL);
4339 if (GDA_IS_DATA_MODEL (query_result))
4341 if ((num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (query_result))) <= 0)
4343 DEBUG_PRINT ("sdb_engine_detects_removed_ids (): nothing to remove");
4344 g_object_unref (query_result);
4345 return;
4348 else
4350 if (query_result != NULL)
4351 g_object_unref (query_result);
4352 return;
4355 /* get and parse the results. */
4356 for (i = 0; i < num_rows; i++)
4358 const GValue *val;
4359 gint tmp;
4360 val = gda_data_model_get_value_at (GDA_DATA_MODEL (query_result), 0, i);
4361 tmp = g_value_get_int (val);
4363 DEBUG_PRINT ("EMITTING symbol-removed");
4364 g_async_queue_push (priv->signals_queue, (gpointer)(SYMBOL_REMOVED + 1));
4365 g_async_queue_push (priv->signals_queue, (gpointer)tmp);
4368 g_object_unref (query_result);
4370 /* let's clean the tmp_table */
4371 if ((query2 = sdb_engine_get_query_by_id (dbe,
4372 PREP_QUERY_TMP_REMOVED_DELETE_ALL))
4373 == NULL)
4375 g_warning ("query is null");
4376 return;
4379 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4380 gda_query_get_query_type ((GdaQuery *) query2))
4382 g_warning ("non parsed sql error");
4383 return;
4386 /* bye bye */
4387 query_result =
4388 gda_query_execute ((GdaQuery *) query2, NULL, FALSE, NULL);
4390 if (query_result)
4392 g_object_unref (query_result);
4397 * WARNING: do not use this function thinking that it would do a scan of symbols
4398 * too. Use symbol_db_engine_update_files_symbols () instead. This one will set
4399 * up some things on db, like removing the 'old' files which have not been
4400 * updated.
4402 static gboolean
4403 sdb_engine_update_file (SymbolDBEngine * dbe, const gchar * file_on_db)
4405 const GdaQuery *query;
4406 GdaObject *query_result;
4407 gchar *query_str;
4408 GdaParameterList *par_list;
4409 GdaParameter *param;
4410 GValue *value;
4411 SymbolDBEnginePriv *priv;
4413 g_return_val_if_fail (dbe != NULL, FALSE);
4415 priv = dbe->priv;
4417 if (symbol_db_engine_is_project_opened (dbe, priv->project_name) == FALSE)
4419 g_warning ("project is not opened");
4420 return FALSE;
4423 /* if we're updating symbols we must do some other operations on db
4424 * symbols, like remove the ones which don't have an update_flag = 1
4425 * per updated file.
4428 /* good. Go on with removing of old symbols, marked by a
4429 * update_flag = 0.
4432 /* FIXME: libgda 3.0 doesn't have support for JOIN keyword at all on
4433 * prepared statements.
4434 * Said this we cannot expect to run queries on a really performant
4435 * way.
4438 /* Triggers will take care of updating/deleting connected symbols
4439 * tuples, like sym_kind, sym_type etc */
4440 query_str = g_strdup_printf ("DELETE FROM symbol WHERE "
4441 "file_defined_id = (SELECT file_id FROM file "
4442 "WHERE file_path = \"%s\") AND update_flag = 0",
4443 file_on_db);
4445 sdb_engine_execute_non_select_sql (dbe, query_str);
4446 g_free (query_str);
4448 /* emits removed symbols signals */
4449 sdb_engine_detects_removed_ids (dbe);
4451 /* reset the update_flag to 0 */
4452 query_str = g_strdup_printf ("UPDATE symbol SET update_flag = 0 "
4453 "WHERE file_defined_id = (SELECT file_id FROM file WHERE "
4454 "file_path = \"%s\")", file_on_db);
4456 sdb_engine_execute_non_select_sql (dbe, query_str);
4457 g_free (query_str);
4459 /* last but not least, update the file analize_time */
4460 if ((query = sdb_engine_get_query_by_id (dbe,
4461 PREP_QUERY_UPDATE_FILE_ANALIZE_TIME))
4462 == NULL)
4464 g_warning ("query is null");
4465 return FALSE;
4468 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4469 gda_query_get_query_type ((GdaQuery *) query))
4471 g_warning ("non parsed sql error");
4472 return FALSE;
4475 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4477 g_warning ("par_list is NULL!\n");
4478 return FALSE;
4481 /* filepath parameter */
4482 if ((param = gda_parameter_list_find_param (par_list, "filepath")) == NULL)
4484 g_warning ("param filepath is NULL from pquery!");
4485 return FALSE;
4488 value = gda_value_new (G_TYPE_STRING);
4489 g_value_set_string (value, file_on_db);
4490 gda_parameter_set_value (param, value);
4492 gda_value_free (value);
4493 query_result =
4494 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
4496 if (query_result)
4497 g_object_unref (query_result);
4499 return TRUE;
4503 * @param data is a GPtrArray *files_to_scan
4504 * It will be freed when this callback will be called.
4506 static void
4507 on_scan_update_files_symbols_end (SymbolDBEngine * dbe, GPtrArray* data)
4509 SymbolDBEnginePriv *priv;
4510 GPtrArray *files_to_scan;
4511 gint i;
4513 DEBUG_PRINT ("on_scan_update_files_symbols_end ();");
4515 g_return_if_fail (dbe != NULL);
4516 g_return_if_fail (data != NULL);
4518 priv = dbe->priv;
4519 files_to_scan = (GPtrArray *) data;
4521 for (i = 0; i < files_to_scan->len; i++)
4523 gchar *node = (gchar *) g_ptr_array_index (files_to_scan, i);
4525 /* clean the db from old un-updated with the last update step () */
4526 if (sdb_engine_update_file (dbe, node +
4527 strlen (priv->data_source)) == FALSE)
4529 g_warning ("Error processing file %s", node +
4530 strlen (priv->data_source) );
4531 return;
4533 g_free (node);
4536 g_signal_handlers_disconnect_by_func (dbe, on_scan_update_files_symbols_end,
4537 files_to_scan);
4539 /* free the GPtrArray. */
4540 g_ptr_array_free (files_to_scan, TRUE);
4541 data = files_to_scan = NULL;
4546 * Update symbols of saved files.
4547 * @note WARNING: files_path and it's contents will be freed on
4548 * on_scan_update_files_symbols_end () callback.
4550 gboolean
4551 symbol_db_engine_update_files_symbols (SymbolDBEngine * dbe, const gchar * project,
4552 GPtrArray * files_path,
4553 gboolean update_prj_analize_time)
4555 SymbolDBEnginePriv *priv;
4557 priv = dbe->priv;
4559 DEBUG_PRINT ("symbol_db_engine_update_files_symbols ()");
4560 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
4561 g_return_val_if_fail (project != NULL, FALSE);
4563 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4565 g_warning ("project is not opened");
4566 return FALSE;
4569 /* data will be freed when callback will be called. The signal will be
4570 * disconnected too, don't worry about disconneting it by hand.
4572 g_signal_connect (G_OBJECT (dbe), "scan-end",
4573 G_CALLBACK (on_scan_update_files_symbols_end), files_path);
4575 sdb_engine_scan_files_1 (dbe, files_path, NULL, TRUE);
4577 /* if true, we'll update the project scanning time too.
4578 * warning: project time scanning won't could be set before files one.
4579 * This why we'll fork the process calling sdb_engine_scan_files ()
4581 if (update_prj_analize_time == TRUE)
4583 const GdaQuery *query;
4584 GdaObject *query_result;
4585 GdaParameterList *par_list;
4586 GdaParameter *param;
4587 GValue *value;
4589 /* and the project analize_time */
4590 if ((query = sdb_engine_get_query_by_id (dbe,
4591 PREP_QUERY_UPDATE_PROJECT_ANALIZE_TIME))
4592 == NULL)
4594 g_warning ("query is null");
4595 return FALSE;
4598 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4599 gda_query_get_query_type ((GdaQuery *) query))
4601 g_warning ("non parsed sql error");
4602 return FALSE;
4605 if ((par_list =
4606 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4608 g_warning ("par_list is NULL!\n");
4609 return FALSE;
4612 /* prjname parameter */
4613 if ((param = gda_parameter_list_find_param (par_list, "prjname"))
4614 == NULL)
4616 g_warning ("param prjname is NULL from pquery!");
4617 return FALSE;
4620 value = gda_value_new (G_TYPE_STRING);
4621 g_value_set_string (value, priv->project_name);
4622 gda_parameter_set_value (param, value);
4624 gda_value_free (value);
4626 DEBUG_PRINT ("updating project analize_time");
4627 query_result =
4628 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
4630 if (query_result)
4631 g_object_unref (query_result);
4634 return TRUE;
4637 /* Update symbols of the whole project. It scans all file symbols etc.
4638 * FIXME: libgda does not support nested prepared queries like
4639 * PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME. When it will do please
4640 * remember to update this function.
4642 gboolean
4643 symbol_db_engine_update_project_symbols (SymbolDBEngine *dbe, const gchar *project)
4645 const GdaQuery *query;
4646 GdaParameterList *par_list;
4647 GdaParameter *param;
4648 GValue *value;
4649 GdaObject *query_result;
4650 gint project_id;
4651 gint num_rows = 0;
4652 gint i;
4653 GPtrArray *files_to_scan;
4654 SymbolDBEnginePriv *priv;
4657 g_return_val_if_fail (dbe != NULL, FALSE);
4658 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4660 g_warning ("project is not opened");
4661 return FALSE;
4664 priv = dbe->priv;
4666 value = gda_value_new (G_TYPE_STRING);
4667 g_value_set_string (value, project);
4669 /* get project id */
4670 if ((project_id = sdb_engine_get_table_id_by_unique_name (dbe,
4671 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
4672 "prjname",
4673 value)) <= 0)
4675 gda_value_free (value);
4676 return FALSE;
4679 if ((query = sdb_engine_get_query_by_id (dbe,
4680 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID))
4681 == NULL)
4683 g_warning ("query is null");
4684 gda_value_free (value);
4685 return FALSE;
4688 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4689 gda_query_get_query_type ((GdaQuery *) query))
4691 g_warning ("non parsed sql error");
4692 gda_value_free (value);
4693 return FALSE;
4696 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4698 g_warning ("par_list is NULL!\n");
4699 gda_value_free (value);
4700 return FALSE;
4703 /* prjid parameter */
4704 if ((param = gda_parameter_list_find_param (par_list, "prjid")) == NULL)
4706 g_warning ("param prjname is NULL from pquery!");
4707 return FALSE;
4710 gda_value_reset_with_type (value, G_TYPE_INT);
4711 g_value_set_int (value, project_id);
4712 gda_parameter_set_value (param, value);
4714 /* execute the query with parametes just set */
4715 query_result = gda_query_execute
4716 ((GdaQuery *) query, par_list, FALSE, NULL);
4718 if (!GDA_IS_DATA_MODEL (query_result) ||
4719 (num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (query_result))) <= 0)
4721 g_message ("no rows");
4722 if (query_result != NULL)
4723 g_object_unref (query_result);
4724 query_result = NULL;
4727 /* we don't need it anymore */
4728 gda_value_free (value);
4730 DEBUG_PRINT ("got gda_data_model_get_n_rows (GDA_DATA_MODEL(obj)) %d",
4731 num_rows);
4733 /* initialize the array */
4734 files_to_scan = g_ptr_array_new ();
4736 /* we can now scan each filename entry to check the last modification time. */
4737 for (i = 0; i < num_rows; i++)
4739 const GValue *value, *value1;
4740 const gchar *file_name;
4741 gchar *file_abs_path;
4742 struct tm filetm;
4743 time_t db_file_time;
4744 gchar *date_string;
4745 gchar *abs_vfs_path;
4746 GnomeVFSHandle *handle;
4748 if ((value =
4749 gda_data_model_get_value_at_col_name (GDA_DATA_MODEL (query_result),
4750 "file_path", i)) == NULL)
4752 continue;
4755 /* build abs path. */
4756 file_name = g_value_get_string (value);
4757 if (priv->data_source != NULL)
4759 abs_vfs_path = g_strdup_printf ("file://%s%s", priv->data_source,
4760 file_name);
4761 file_abs_path = g_strdup_printf ("%s%s", priv->data_source,
4762 file_name);
4764 else
4766 abs_vfs_path = g_strdup_printf ("file://%s", file_name);
4767 file_abs_path = g_strdup (file_name);
4770 GnomeVFSURI *uri = gnome_vfs_uri_new (abs_vfs_path);
4771 GnomeVFSFileInfo *file_info = gnome_vfs_file_info_new ();
4773 /* retrieve data/time info */
4774 if (gnome_vfs_open_uri (&handle, uri,
4775 GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_RANDOM) !=
4776 GNOME_VFS_OK)
4778 g_message ("could not open URI %s", abs_vfs_path);
4779 gnome_vfs_uri_unref (uri);
4780 gnome_vfs_file_info_unref (file_info);
4781 g_free (abs_vfs_path);
4782 g_free (file_abs_path);
4783 continue;
4786 if (gnome_vfs_get_file_info_from_handle (handle, file_info,
4787 GNOME_VFS_FILE_INFO_DEFAULT) !=
4788 GNOME_VFS_OK)
4790 g_message ("cannot get file info from handle");
4791 gnome_vfs_close (handle);
4792 gnome_vfs_uri_unref (uri);
4793 gnome_vfs_file_info_unref (file_info);
4794 g_free (file_abs_path);
4795 continue;
4798 if ((value1 =
4799 gda_data_model_get_value_at_col_name (GDA_DATA_MODEL (query_result),
4800 "analize_time", i)) == NULL)
4802 continue;
4805 /* weirdly we have a strange libgda behaviour here too.
4806 * as from ChangeLog GDA_TYPE_TIMESTAMP as SQLite does not impose a
4807 * known format for dates (there is no date datatype).
4808 * We have then to do some hackery to retrieve the date.
4810 date_string = (gchar *) g_value_get_string (value1);
4812 DEBUG_PRINT ("processing for upating symbol %s", file_name);
4813 DEBUG_PRINT ("date_string %s", date_string);
4815 /* fill a struct tm with the date retrieved by the string. */
4816 /* string is something like '2007-04-18 23:51:39' */
4817 memset (&filetm, 0, sizeof (struct tm));
4818 filetm.tm_year = atoi (date_string) - 1900;
4819 date_string += 5;
4820 filetm.tm_mon = atoi (date_string) - 1;
4821 date_string += 3;
4822 filetm.tm_mday = atoi (date_string);
4823 date_string += 3;
4824 filetm.tm_hour = atoi (date_string);
4825 date_string += 3;
4826 filetm.tm_min = atoi (date_string);
4827 date_string += 3;
4828 filetm.tm_sec = atoi (date_string);
4830 /* subtract one hour to the db_file_time. (why this?) */
4831 db_file_time = mktime (&filetm) - 3600;
4833 if (difftime (db_file_time, file_info->mtime) <= 0)
4835 g_message ("to be added! : %s", file_name);
4836 g_ptr_array_add (files_to_scan, file_abs_path);
4839 DEBUG_PRINT ("difftime %f", difftime (db_file_time, file_info->mtime));
4840 DEBUG_PRINT ("db_file_time %d - "
4841 "file_info->mtime %d "
4842 "file_info->ctime %d", db_file_time,
4843 file_info->mtime, file_info->ctime);
4845 gnome_vfs_close (handle);
4846 gnome_vfs_uri_unref (uri);
4847 gnome_vfs_file_info_unref (file_info);
4848 g_free (abs_vfs_path);
4849 /* no need to free file_abs_path, it's been added to files_to_scan */
4852 if (query_result)
4853 g_object_unref (query_result);
4855 if (files_to_scan->len > 0)
4857 /* at the end let's the scanning function do its job */
4858 return symbol_db_engine_update_files_symbols (dbe, project,
4859 files_to_scan, TRUE);
4861 return TRUE;
4865 /* Remove a file, together with its symbols, from a project. */
4866 gboolean
4867 symbol_db_engine_remove_file (SymbolDBEngine * dbe, const gchar * project,
4868 const gchar * file)
4870 gchar *query_str;
4871 SymbolDBEnginePriv *priv;
4873 g_return_val_if_fail (dbe != NULL, FALSE);
4874 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4876 g_warning ("project is not opened");
4877 return FALSE;
4880 priv = dbe->priv;
4882 if (strlen (file) < strlen (priv->data_source))
4884 g_warning ("wrong file");
4885 return FALSE;
4888 /* Triggers will take care of updating/deleting connected symbols
4889 * tuples, like sym_kind, sym_type etc */
4890 query_str = g_strdup_printf ("DELETE FROM file WHERE prj_id "
4891 "= (SELECT project_id FROM project WHERE project_name = '%s') AND "
4892 "file_path = '%s'", project, file + strlen (priv->data_source));
4894 sdb_engine_execute_non_select_sql (dbe, query_str);
4895 g_free (query_str);
4897 /* emits removed symbols signals */
4898 sdb_engine_detects_removed_ids (dbe);
4899 return TRUE;
4903 static void
4904 on_scan_update_buffer_end (SymbolDBEngine * dbe, gpointer data)
4906 SymbolDBEnginePriv *priv;
4907 GPtrArray *files_to_scan;
4908 gint i;
4910 g_return_if_fail (dbe != NULL);
4911 g_return_if_fail (data != NULL);
4913 priv = dbe->priv;
4914 files_to_scan = (GPtrArray *) data;
4916 DEBUG_PRINT ("files_to_scan->len %d", files_to_scan->len);
4918 for (i = 0; i < files_to_scan->len; i++)
4920 gchar *node = (gchar *) g_ptr_array_index (files_to_scan, i);
4922 DEBUG_PRINT ("processing updating for file [on disk] %s, "
4923 "passed to on_scan_update_buffer_end (): %s",
4924 node, node + strlen (priv->data_source));
4926 /* will be emitted removed signals */
4927 if (sdb_engine_update_file (dbe, node+
4928 strlen (priv->data_source)) == FALSE)
4930 g_warning ("Error processing file %s", node);
4931 return;
4933 g_free (node);
4936 g_signal_handlers_disconnect_by_func (dbe, on_scan_update_buffer_end,
4937 files_to_scan);
4939 /* free the GPtrArray. */
4940 DEBUG_PRINT ("free the files_to_scan");
4941 g_ptr_array_free (files_to_scan, TRUE);
4942 data = files_to_scan = NULL;
4943 DEBUG_PRINT ("done");
4946 /* Update symbols of a file by a memory-buffer to perform a real-time updating
4947 * of symbols.
4948 * real_files_list: full path on disk to 'real file' to update. e.g.
4949 * /home/foouser/fooproject/src/main.c
4951 gboolean
4952 symbol_db_engine_update_buffer_symbols (SymbolDBEngine * dbe, const gchar *project,
4953 GPtrArray * real_files_list,
4954 const GPtrArray * text_buffers,
4955 const GPtrArray * buffer_sizes)
4957 SymbolDBEnginePriv *priv;
4958 gint i;
4960 DEBUG_PRINT ("symbol_db_engine_update_buffer_symbols ()");
4962 /* array that'll represent the /dev/shm/anjuta-XYZ files */
4963 GPtrArray *temp_files;
4964 GPtrArray *real_files_on_db;
4966 priv = dbe->priv;
4968 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
4969 g_return_val_if_fail (project != NULL, FALSE);
4970 g_return_val_if_fail (real_files_list != NULL, FALSE);
4971 g_return_val_if_fail (text_buffers != NULL, FALSE);
4972 g_return_val_if_fail (buffer_sizes != NULL, FALSE);
4974 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4976 g_warning ("project is not opened");
4977 return FALSE;
4980 temp_files = g_ptr_array_new();
4981 real_files_on_db = g_ptr_array_new();
4983 /* obtain a GPtrArray with real_files on database */
4984 for (i=0; i < real_files_list->len; i++)
4986 gchar *new_node = (gchar*)g_ptr_array_index (real_files_list, i)
4987 + strlen(priv->data_source);
4988 /* DEBUG_PRINT ("real_file on db: %s", new_node);*/
4989 g_ptr_array_add (real_files_on_db, g_strdup (new_node));
4992 /* create a temporary file for each buffer */
4993 for (i=0; i < real_files_list->len; i++)
4995 FILE *shared_mem_file;
4996 const gchar *temp_buffer;
4997 gint shared_mem_fd;
4998 gint temp_size;
4999 gchar *temp_file;
5000 gchar *base_filename;
5001 const gchar *curr_real_file;
5003 curr_real_file = g_ptr_array_index (real_files_list, i);
5005 /* it's ok to have just the base filename to create the
5006 * target buffer one */
5007 base_filename = g_filename_display_basename (curr_real_file);
5009 temp_file = g_strdup_printf ("/anjuta-%d-%ld-%s", getpid (),
5010 time (NULL), base_filename);
5011 g_free (base_filename);
5013 if ((shared_mem_fd =
5014 shm_open (temp_file, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0)
5016 g_warning ("Error while trying to open a shared memory file. Be"
5017 "sure to have /dev/shm mounted with tmpfs");
5018 return FALSE;
5021 shared_mem_file = fdopen (shared_mem_fd, "w+b");
5023 temp_buffer = g_ptr_array_index (text_buffers, i);
5024 temp_size = (gint)g_ptr_array_index (buffer_sizes, i);
5025 fwrite (temp_buffer, sizeof(gchar), temp_size, shared_mem_file);
5026 fflush (shared_mem_file);
5027 fclose (shared_mem_file);
5029 /* add the temp file to the array. */
5030 g_ptr_array_add (temp_files, g_strdup_printf ("/dev/shm%s", temp_file));
5031 g_free (temp_file);
5035 /* data will be freed when callback will be called. The signal will be
5036 * disconnected too, don't worry about disconneting it by hand.
5038 g_signal_connect (G_OBJECT (dbe), "scan-end",
5039 G_CALLBACK (on_scan_update_buffer_end), real_files_list);
5041 sdb_engine_scan_files_1 (dbe, temp_files, real_files_on_db, TRUE);
5043 /* let's free the temp_files array */
5044 for (i=0; i < temp_files->len; i++)
5045 g_free (g_ptr_array_index (temp_files, i));
5047 g_ptr_array_free (temp_files, TRUE);
5049 /* and the real_files_on_db too */
5050 for (i=0; i < real_files_on_db->len; i++)
5051 g_free (g_ptr_array_index (real_files_on_db, i));
5053 g_ptr_array_free (real_files_on_db, TRUE);
5056 return TRUE;
5059 gboolean
5060 symbol_db_engine_is_locked (SymbolDBEngine * dbe)
5062 SymbolDBEnginePriv *priv;
5064 g_return_val_if_fail (dbe != NULL, FALSE);
5066 priv = dbe->priv;
5067 return priv->scanning_status;
5070 static inline gint
5071 sdb_engine_walk_down_scope_path (SymbolDBEngine *dbe, const GPtrArray* scope_path)
5073 SymbolDBEnginePriv *priv;
5074 gint final_definition_id;
5075 gint scope_path_len;
5076 gint i;
5077 gchar *query_str;
5078 GdaDataModel *data;
5080 g_return_val_if_fail (dbe != NULL, FALSE);
5081 priv = dbe->priv;
5083 scope_path_len = scope_path->len;
5085 /* we'll return if the length is even or minor than 3 */
5086 if (scope_path_len < 3 || scope_path_len % 2 == 0)
5088 g_warning ("bad scope_path.");
5089 return -1;
5092 final_definition_id = 0;
5093 for (i=0; i < scope_path_len -1; i = i + 2)
5095 const GValue *value;
5096 DEBUG_PRINT ("loop final_definition_id %d", final_definition_id);
5098 query_str = g_strdup_printf ("SELECT scope_definition_id FROM symbol "
5099 "WHERE scope_id = '%d' AND scope_definition_id = ("
5100 "SELECT scope.scope_id FROM scope "
5101 "INNER JOIN sym_type ON scope.type_id = sym_type.type_id "
5102 "WHERE sym_type.type = '%s' "
5103 "AND scope.scope_name = '%s'"
5104 ")", final_definition_id, (gchar*)g_ptr_array_index (scope_path, i),
5105 (gchar*)g_ptr_array_index (scope_path, i + 1));
5107 DEBUG_PRINT ("walk down query is %s", query_str);
5109 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5110 gda_data_model_get_n_rows (data) <= 0 )
5112 g_free (query_str);
5113 return -1;
5116 g_free (query_str);
5118 value = gda_data_model_get_value_at (data, 0, 0);
5119 if (G_VALUE_HOLDS (value, G_TYPE_INT))
5121 final_definition_id = g_value_get_int (value);
5122 g_object_unref (data);
5124 else
5126 /* something went wrong. Our symbol cannot be retrieved coz of a
5127 * bad scope path.
5129 final_definition_id = -1;
5130 break;
5134 return final_definition_id;
5137 /* Returns an iterator to the data retrieved from database.
5138 * The iterator, if not null, will contain a list of parent classes for the given
5139 * symbol name.
5140 * namespace_name can be NULL.
5142 SymbolDBEngineIterator *
5143 symbol_db_engine_get_class_parents (SymbolDBEngine *dbe, const gchar *klass_name,
5144 const GPtrArray *scope_path)
5146 SymbolDBEnginePriv *priv;
5147 gchar *query_str;
5148 GdaDataModel *data;
5149 gint final_definition_id;
5151 g_return_val_if_fail (dbe != NULL, FALSE);
5152 priv = dbe->priv;
5154 if (priv->mutex)
5155 g_mutex_lock (priv->mutex);
5157 final_definition_id = -1;
5158 if (scope_path != NULL)
5159 final_definition_id = sdb_engine_walk_down_scope_path (dbe, scope_path);
5161 /* FIXME: as always prepared queries of this complexity gives
5162 GDA_QUERY_TYPE_NON_PARSED_SQL error. */
5163 if (final_definition_id > 0)
5165 query_str = g_strdup_printf("SELECT symbol.symbol_id, symbol.name FROM heritage "
5166 "JOIN symbol ON heritage.symbol_id_base = symbol.symbol_id "
5167 "WHERE symbol_id_derived = ("
5168 "SELECT symbol_id FROM symbol "
5169 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
5170 "WHERE symbol.name = '%s' "
5171 "AND sym_kind.kind_name = 'class' "
5172 "AND symbol.scope_id = '%d'"
5173 ")", klass_name, final_definition_id);
5175 else
5177 query_str = g_strdup_printf("SELECT symbol.symbol_id, symbol.name FROM heritage "
5178 "JOIN symbol ON heritage.symbol_id_base = symbol.symbol_id "
5179 "WHERE symbol_id_derived = ("
5180 "SELECT symbol_id FROM symbol "
5181 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
5182 "WHERE symbol.name = '%s' "
5183 "AND sym_kind.kind_name = 'class' "
5184 ")", klass_name);
5187 DEBUG_PRINT ("get parents query: %s", query_str);
5189 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5190 gda_data_model_get_n_rows (data) <= 0 )
5192 g_free (query_str);
5193 if (priv->mutex)
5194 g_mutex_unlock (priv->mutex);
5195 return NULL;
5198 g_free (query_str);
5200 if (priv->mutex)
5201 g_mutex_unlock (priv->mutex);
5202 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5205 static inline void
5206 sdb_engine_prepare_symbol_info_sql (SymbolDBEngine *dbe, GString *info_data,
5207 GString *join_data, gint sym_info)
5209 if (sym_info & SYMINFO_FILE_PATH ||
5210 sym_info & SYMINFO_LANGUAGE ||
5211 sym_info & SYMINFO_PROJECT_NAME ||
5212 sym_info & SYMINFO_FILE_IGNORE ||
5213 sym_info & SYMINFO_FILE_INCLUDE)
5215 info_data = g_string_append (info_data, ",file.file_path ");
5216 join_data = g_string_append (join_data, "LEFT JOIN file ON "
5217 "symbol.file_defined_id = file.file_id ");
5220 if (sym_info & SYMINFO_LANGUAGE)
5222 info_data = g_string_append (info_data, ",language.language_name ");
5223 join_data = g_string_append (join_data, "LEFT JOIN language ON "
5224 "file.lang_id = language.language_id ");
5227 if (sym_info & SYMINFO_IMPLEMENTATION)
5229 info_data = g_string_append (info_data, ",sym_implementation.implementation_name ");
5230 join_data = g_string_append (join_data, "LEFT JOIN sym_implementation ON "
5231 "symbol.implementation_kind_id = sym_implementation.sym_impl_id ");
5234 if (sym_info & SYMINFO_ACCESS)
5236 info_data = g_string_append (info_data, ",sym_access.access_name ");
5237 join_data = g_string_append (join_data, "LEFT JOIN sym_access ON "
5238 "symbol.access_kind_id = sym_access.access_kind_id ");
5241 if (sym_info & SYMINFO_KIND)
5243 info_data = g_string_append (info_data, ",sym_kind.kind_name ");
5244 join_data = g_string_append (join_data, "LEFT JOIN sym_kind ON "
5245 "symbol.kind_id = sym_kind.sym_kind_id ");
5248 if (sym_info & SYMINFO_TYPE || sym_info & SYMINFO_TYPE_NAME)
5250 info_data = g_string_append (info_data, ",sym_type.type,"
5251 "sym_type.type_name ");
5252 join_data = g_string_append (join_data, "LEFT JOIN sym_type ON "
5253 "symbol.type_id = sym_type.type_id ");
5256 if (sym_info & SYMINFO_PROJECT_NAME ||
5257 sym_info & SYMINFO_FILE_IGNORE ||
5258 sym_info & SYMINFO_FILE_INCLUDE)
5260 info_data = g_string_append (info_data, ",project.project_name ");
5261 join_data = g_string_append (join_data, "LEFT JOIN project ON "
5262 "file.prj_id = project.project_id ");
5265 if (sym_info & SYMINFO_FILE_IGNORE)
5267 info_data = g_string_append (info_data, ",file_ignore.type AS file_ignore_type ");
5268 join_data = g_string_append (join_data, "LEFT JOIN ext_ignore ON "
5269 "ext_ignore.prj_id = project.project_id "
5270 "LEFT JOIN file_ignore ON "
5271 "ext_ignore.file_ign_id = file_ignore.file_ignore_id ");
5274 if (sym_info & SYMINFO_FILE_INCLUDE)
5276 info_data = g_string_append (info_data, ",file_include.type AS file_include_type ");
5277 join_data = g_string_append (join_data, "LEFT JOIN ext_include ON "
5278 "ext_include.prj_id = project.project_id "
5279 "LEFT JOIN file_include ON "
5280 "ext_include.file_incl_id = file_include.file_include_id ");
5283 /* TODO, or better.. TAKE A DECISION
5284 if (sym_info & SYMINFO_WORKSPACE_NAME)
5286 info_data = g_string_append (info_data, ",sym_access.access_name ");
5287 join_data = g_string_append (info_data, "LEFT JOIN sym_kind ON "
5288 "symbol.kind_id = sym_kind.sym_kind_id ");
5293 SymbolDBEngineIterator *
5294 symbol_db_engine_get_global_members (SymbolDBEngine *dbe,
5295 const gchar *kind, gboolean group_them,
5296 gint results_limit, gint results_offset,
5297 gint sym_info)
5299 SymbolDBEnginePriv *priv;
5300 GdaDataModel *data;
5301 GString *info_data;
5302 GString *join_data;
5303 gchar *query_str;
5304 const gchar *group_by_option;
5305 gchar *limit = "";
5306 gboolean limit_free = FALSE;
5307 gchar *offset = "";
5308 gboolean offset_free = FALSE;
5310 g_return_val_if_fail (dbe != NULL, NULL);
5311 priv = dbe->priv;
5313 if (priv->mutex)
5314 g_mutex_lock (priv->mutex);
5316 /* check for an already flagged sym_info with KIND. SYMINFO_KIND on sym_info
5317 * is already contained into the default query infos.
5319 sym_info = sym_info & ~SYMINFO_KIND;
5321 /* info_data contains the stuff after SELECT and befor FROM */
5322 info_data = g_string_new ("");
5324 /* join_data contains the optionals joins to do to retrieve new data on other
5325 * tables.
5327 join_data = g_string_new ("");
5329 /* fill info_data and join data with optional sql */
5330 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5332 if (group_them == TRUE)
5334 group_by_option = "GROUP BY symbol.name";
5336 else
5338 group_by_option = "";
5341 if (results_limit > 0)
5343 limit = g_strdup_printf ("LIMIT %d", results_limit);
5344 limit_free = TRUE;
5347 if (results_offset > 0)
5349 offset = g_strdup_printf ("OFFSET %d", results_offset);
5350 offset_free = TRUE;
5353 if (kind == NULL)
5355 query_str = g_strdup_printf ("SELECT symbol.symbol_id, "
5356 "symbol.name, symbol.file_position, symbol.is_file_scope, "
5357 "symbol.signature, sym_kind.kind_name %s FROM symbol "
5358 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id %s "
5359 "WHERE symbol.scope_id <= 0 %s %s %s", info_data->str, join_data->str,
5360 group_by_option, limit, offset);
5363 else
5365 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5366 "symbol.file_position, "
5367 "symbol.is_file_scope, symbol.signature, sym_kind.kind_name %s FROM symbol "
5368 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id %s "
5369 "WHERE symbol.scope_id <= 0 "
5370 "AND sym_kind.kind_name = '%s' %s %s %s", info_data->str, join_data->str,
5371 kind, group_by_option, limit, offset);
5374 DEBUG_PRINT ("query is %s", query_str);
5375 #if 0
5376 GdaCommand *command;
5377 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
5378 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
5380 if ( (data = gda_connection_execute_select_command (priv->db_connection,
5381 command, NULL, NULL)) == NULL ||
5382 gda_data_model_get_n_rows (data) <= 0 )
5384 gda_command_free (command);
5385 g_free (query_str);
5386 if (priv->mutex)
5387 g_mutex_unlock (priv->mutex);
5388 return NULL;
5391 // gda_data_model_dump (data, stdout);
5392 gda_command_free (command);
5393 #else
5395 if (limit_free)
5396 g_free (limit);
5398 if (offset_free)
5399 g_free (offset);
5401 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5402 gda_data_model_get_n_rows (data) <= 0 )
5404 g_free (query_str);
5405 g_string_free (info_data, FALSE);
5406 g_string_free (join_data, FALSE);
5407 if (priv->mutex)
5408 g_mutex_unlock (priv->mutex);
5409 return NULL;
5411 // gda_data_model_dump (data, stdout);
5412 #endif
5413 g_free (query_str);
5414 g_string_free (info_data, FALSE);
5415 g_string_free (join_data, FALSE);
5417 if (priv->mutex)
5418 g_mutex_unlock (priv->mutex);
5419 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5424 * Sometimes it's useful going to query just with ids [and so integers] to have
5425 * a little speed improvement.
5427 SymbolDBEngineIterator *
5428 symbol_db_engine_get_scope_members_by_symbol_id (SymbolDBEngine *dbe,
5429 gint scope_parent_symbol_id,
5430 gint results_limit,
5431 gint results_offset,
5432 gint sym_info)
5435 select b.* from symbol a, symbol b where a.symbol_id = 348 and
5436 b.scope_id = a.scope_definition_id;
5438 SymbolDBEnginePriv *priv;
5439 gchar *query_str;
5440 GdaDataModel *data;
5441 GString *info_data;
5442 GString *join_data;
5443 gchar *limit = "";
5444 gboolean limit_free = FALSE;
5445 gchar *offset = "";
5446 gboolean offset_free = FALSE;
5448 g_return_val_if_fail (dbe != NULL, NULL);
5449 priv = dbe->priv;
5451 if (priv->mutex)
5452 g_mutex_lock (priv->mutex);
5454 if (scope_parent_symbol_id <= 0)
5456 if (priv->mutex)
5457 g_mutex_unlock (priv->mutex);
5458 return NULL;
5461 /* info_data contains the stuff after SELECT and befor FROM */
5462 info_data = g_string_new ("");
5464 /* join_data contains the optionals joins to do to retrieve new data on other
5465 * tables.
5467 join_data = g_string_new ("");
5469 /* fill info_data and join data with optional sql */
5470 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5472 if (results_limit > 0)
5474 limit = g_strdup_printf ("LIMIT %d", results_limit);
5475 limit_free = TRUE;
5478 if (results_offset > 0)
5480 offset = g_strdup_printf ("OFFSET %d", results_offset);
5481 offset_free = TRUE;
5484 /* ok, beware that we use an 'alias hack' to accomplish compatibility with
5485 * sdb_engine_prepare_symbol_info_sql () function. In particular we called
5486 * the first joining table 'a', the second one 'symbol', where is the info we
5487 * want
5489 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5490 "symbol.file_position, "
5491 "symbol.is_file_scope, symbol.signature %s FROM symbol a, symbol symbol "
5492 "%s WHERE a.symbol_id = '%d' AND symbol.scope_id = a.scope_definition_id "
5493 "AND symbol.scope_id > 0 %s %s", info_data->str, join_data->str,
5494 scope_parent_symbol_id,
5495 limit, offset);
5497 if (limit_free)
5498 g_free (limit);
5500 if (offset_free)
5501 g_free (offset);
5503 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5504 gda_data_model_get_n_rows (data) <= 0 )
5506 g_free (query_str);
5507 if (priv->mutex)
5508 g_mutex_unlock (priv->mutex);
5509 return NULL;
5512 g_free (query_str);
5513 g_string_free (info_data, FALSE);
5514 g_string_free (join_data, FALSE);
5516 if (priv->mutex)
5517 g_mutex_unlock (priv->mutex);
5518 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5521 /* scope_path cannot be NULL.
5522 * scope_path will be something like "scope1_kind", "scope1_name", "scope2_kind",
5523 * "scope2_name", NULL
5525 SymbolDBEngineIterator *
5526 symbol_db_engine_get_scope_members (SymbolDBEngine *dbe,
5527 const GPtrArray* scope_path, gint sym_info)
5530 simple scope
5532 select * from symbol where scope_id = (
5533 select scope.scope_id from scope
5534 inner join sym_type on scope.type_id = sym_type.type_id
5535 where sym_type.type = 'class'
5536 and scope.scope_name = 'MyClass'
5539 select * from symbol where scope_id = (
5540 select scope.scope_id from scope
5541 inner join sym_type on scope.type_id = sym_type.type_id
5542 where sym_type.type = 'struct'
5543 and scope.scope_name = '_faa_1');
5546 es. scope_path = First, namespace, Second, namespace, NULL,
5547 symbol_name = Second_1_class
5549 SymbolDBEnginePriv *priv;
5550 gchar *query_str;
5551 GdaDataModel *data;
5552 gint final_definition_id;
5553 GString *info_data;
5554 GString *join_data;
5556 g_return_val_if_fail (dbe != NULL, NULL);
5557 priv = dbe->priv;
5559 if (priv->mutex)
5560 g_mutex_lock (priv->mutex);
5562 final_definition_id = sdb_engine_walk_down_scope_path (dbe, scope_path);
5564 if (final_definition_id <= 0)
5566 if (priv->mutex)
5567 g_mutex_unlock (priv->mutex);
5568 return NULL;
5571 /* info_data contains the stuff after SELECT and befor FROM */
5572 info_data = g_string_new ("");
5574 /* join_data contains the optionals joins to do to retrieve new data on other
5575 * tables.
5577 join_data = g_string_new ("");
5579 /* fill info_data and join data with optional sql */
5580 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5582 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5583 "symbol.file_position, "
5584 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5585 "%s WHERE scope_id = '%d'", info_data->str, join_data->str,
5586 final_definition_id);
5588 /* DEBUG_PRINT ("DYNAMIC query is %s", query_str);*/
5590 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5591 gda_data_model_get_n_rows (data) <= 0 )
5593 g_free (query_str);
5594 if (priv->mutex)
5595 g_mutex_unlock (priv->mutex);
5596 return NULL;
5599 g_free (query_str);
5600 g_string_free (info_data, FALSE);
5601 g_string_free (join_data, FALSE);
5603 if (priv->mutex)
5604 g_mutex_unlock (priv->mutex);
5605 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5608 /* Returns an iterator to the data retrieved from database.
5609 * It will be possible to get the scope specified by the line of the file.
5611 SymbolDBEngineIterator *
5612 symbol_db_engine_get_current_scope (SymbolDBEngine *dbe, const gchar* filename,
5613 gulong line)
5615 SymbolDBEnginePriv *priv;
5616 gchar *file_escaped;
5617 gchar *query_str;
5618 GdaDataModel *data;
5620 g_return_val_if_fail (dbe != NULL, NULL);
5621 priv = dbe->priv;
5623 if (priv->mutex)
5624 g_mutex_lock (priv->mutex);
5625 file_escaped = g_strescape (filename, NULL);
5627 /* WARNING: probably there can be some problems with escaping file names here.
5628 * They should come already escaped as from project db.
5630 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5631 "symbol.file_position, "
5632 "symbol.is_file_scope, symbol.signature, MIN('%d' - symbol.file_position) "
5633 "FROM symbol "
5634 "JOIN file ON file_defined_id = file_id "
5635 "WHERE file.file_path = \"%s\" "
5636 "AND '%d' - symbol.file_position >= 0", (gint)line, file_escaped,
5637 (gint)line);
5639 DEBUG_PRINT ("current_scope query is %s", query_str);
5641 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5642 gda_data_model_get_n_rows (data) <= 0 )
5644 g_free (query_str);
5645 g_free (file_escaped);
5646 if (priv->mutex)
5647 g_mutex_unlock (priv->mutex);
5648 return NULL;
5651 g_free (query_str);
5652 g_free (file_escaped);
5654 if (priv->mutex)
5655 g_mutex_unlock (priv->mutex);
5656 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5661 * @param file_path Full local file path, e.g. /home/user/foo/file.c
5663 SymbolDBEngineIterator *
5664 symbol_db_engine_get_file_symbols (SymbolDBEngine *dbe,
5665 const gchar *file_path, gint sym_info)
5667 SymbolDBEnginePriv *priv;
5668 gchar *query_str;
5669 GdaDataModel *data;
5670 GString *info_data;
5671 GString *join_data;
5673 g_return_val_if_fail (dbe != NULL, NULL);
5674 g_return_val_if_fail (file_path != NULL, NULL);
5675 priv = dbe->priv;
5676 g_return_val_if_fail (priv->data_source != NULL, NULL);
5678 if (priv->mutex)
5679 g_mutex_lock (priv->mutex);
5680 /* check for an already flagged sym_info with FILE_PATH. SYMINFO_FILE_PATH on
5681 * sym_info is already contained into the default query infos.
5683 sym_info = sym_info & ~SYMINFO_FILE_PATH;
5685 /* info_data contains the stuff after SELECT and befor FROM */
5686 info_data = g_string_new ("");
5688 /* join_data contains the optionals joins to do to retrieve new data on other
5689 * tables.
5691 join_data = g_string_new ("");
5693 /* fill info_data and join data with optional sql */
5694 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5696 /* rember to do a file_path + strlen(priv->data_source): a project relative
5697 * file path
5699 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5700 "symbol.file_position, "
5701 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5702 "JOIN file ON symbol.file_defined_id = file.file_id "
5703 "%s WHERE file.file_path = \"%s\"", info_data->str, join_data->str,
5704 file_path + strlen(priv->data_source));
5706 DEBUG_PRINT ("symbol_db_engine_get_file_symbols (): query is %s", query_str);
5708 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5709 gda_data_model_get_n_rows (data) <= 0 )
5711 g_free (query_str);
5712 if (priv->mutex)
5713 g_mutex_unlock (priv->mutex);
5714 return NULL;
5717 g_free (query_str);
5718 g_string_free (info_data, FALSE);
5719 g_string_free (join_data, FALSE);
5721 if (priv->mutex)
5722 g_mutex_unlock (priv->mutex);
5723 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5727 SymbolDBEngineIterator *
5728 symbol_db_engine_get_symbol_info_by_id (SymbolDBEngine *dbe,
5729 gint sym_id, gint sym_info)
5731 SymbolDBEnginePriv *priv;
5732 gchar *query_str;
5733 GdaDataModel *data;
5734 GString *info_data;
5735 GString *join_data;
5737 g_return_val_if_fail (dbe != NULL, NULL);
5738 priv = dbe->priv;
5740 if (priv->mutex)
5741 g_mutex_lock (priv->mutex);
5743 /* info_data contains the stuff after SELECT and befor FROM */
5744 info_data = g_string_new ("");
5746 /* join_data contains the optionals joins to do to retrieve new data on other
5747 * tables.
5749 join_data = g_string_new ("");
5751 /* fill info_data and join data with optional sql */
5752 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5754 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5755 "symbol.file_position, "
5756 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5757 "%s WHERE symbol.symbol_id = %d", info_data->str, join_data->str,
5758 sym_id);
5760 /* DEBUG_PRINT ("DYNAMIC query is %s", query_str);*/
5762 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5763 gda_data_model_get_n_rows (data) <= 0 )
5765 g_free (query_str);
5766 if (priv->mutex)
5767 g_mutex_unlock (priv->mutex);
5768 return NULL;
5771 g_free (query_str);
5772 g_string_free (info_data, FALSE);
5773 g_string_free (join_data, FALSE);
5775 if (priv->mutex)
5776 g_mutex_unlock (priv->mutex);
5777 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5780 /* user must free the returned value */
5781 gchar*
5782 symbol_db_engine_get_full_local_path (SymbolDBEngine *dbe, const gchar* file)
5784 SymbolDBEnginePriv *priv;
5785 gchar *full_path;
5787 g_return_val_if_fail (dbe != NULL, NULL);
5789 priv = dbe->priv;
5790 full_path = g_strdup_printf ("%s%s", priv->data_source, file);
5791 return full_path;
5794 gchar*
5795 symbol_db_engine_get_file_db_path (SymbolDBEngine *dbe, const gchar* full_local_file_path)
5797 SymbolDBEnginePriv *priv;
5798 gchar *relative_path;
5799 const gchar *tmp;
5800 g_return_val_if_fail (dbe != NULL, NULL);
5802 priv = dbe->priv;
5803 g_return_val_if_fail (priv->data_source != NULL, NULL);
5805 if (strlen (priv->data_source) >= strlen (full_local_file_path))
5807 return NULL;
5810 tmp = full_local_file_path + strlen (priv->data_source);
5811 relative_path = strdup (tmp);
5813 return relative_path;
5817 SymbolDBEngineIterator *
5818 symbol_db_engine_find_symbol_by_name_pattern (SymbolDBEngine *dbe,
5819 const gchar *name, gint sym_info)
5821 SymbolDBEnginePriv *priv;
5822 gchar *query_str;
5823 GdaDataModel *data;
5824 GString *info_data;
5825 GString *join_data;
5827 g_return_val_if_fail (dbe != NULL, NULL);
5828 priv = dbe->priv;
5830 if (priv->mutex)
5831 g_mutex_lock (priv->mutex);
5833 /* info_data contains the stuff after SELECT and befor FROM */
5834 info_data = g_string_new ("");
5836 /* join_data contains the optionals joins to do to retrieve new data on other
5837 * tables.
5839 join_data = g_string_new ("");
5841 /* fill info_data and join data with optional sql */
5842 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5844 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5845 "symbol.file_position, "
5846 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5847 "%s WHERE symbol.name LIKE \"%s%%\"", info_data->str, join_data->str,
5848 name);
5850 /* DEBUG_PRINT ("DYNAMIC query is %s", query_str);*/
5852 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5853 gda_data_model_get_n_rows (data) <= 0 )
5855 g_free (query_str);
5856 if (priv->mutex)
5857 g_mutex_unlock (priv->mutex);
5858 return NULL;
5861 g_free (query_str);
5862 g_string_free (info_data, FALSE);
5863 g_string_free (join_data, FALSE);
5865 if (priv->mutex)
5866 g_mutex_unlock (priv->mutex);
5867 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5870 /**
5871 * No iterator for now. We need the quickest query possible.
5872 * @param db_file Can be NULL. In that case there won't be any check on file.
5874 gint
5875 symbol_db_engine_get_parent_scope_id_by_symbol_id (SymbolDBEngine *dbe,
5876 gint scoped_symbol_id,
5877 const gchar * db_file)
5880 select * from symbol where scope_definition_id = (
5881 select scope_id from symbol where symbol_id = 26
5884 SymbolDBEnginePriv *priv;
5885 gchar *query_str;
5886 GdaDataModel *data;
5887 const GValue* value;
5888 gint res;
5889 gint num_rows;
5891 g_return_val_if_fail (dbe != NULL, -1);
5892 priv = dbe->priv;
5894 if (priv->mutex)
5895 g_mutex_lock (priv->mutex);
5897 if (db_file == NULL)
5899 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.file_defined_id, "
5900 "symbol.file_position, symbol.scope_id "
5901 "FROM symbol "
5902 "WHERE symbol.scope_definition_id = ( "
5903 "SELECT symbol.scope_id FROM symbol WHERE symbol.symbol_id = '%d') "
5904 "AND symbol.scope_definition_id > 0",
5905 scoped_symbol_id);
5907 else
5909 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.file_defined_id, "
5910 "symbol.file_position, symbol.scope_id "
5911 "FROM symbol JOIN file "
5912 "ON symbol.file_defined_id = file.file_id "
5913 "WHERE symbol.scope_definition_id = ( "
5914 "SELECT symbol.scope_id FROM symbol WHERE symbol.symbol_id = '%d') "
5915 "AND symbol.scope_definition_id > 0 "
5916 "AND file.file_path = '%s' ",
5917 scoped_symbol_id,
5918 db_file);
5921 /* DEBUG_PRINT ("symbol_db_engine_get_parent_scope_id_by_symbol_id() query is %s",
5922 query_str);*/
5924 if ( (data = sdb_engine_execute_select_sql (dbe, query_str)) == NULL ||
5925 gda_data_model_get_n_rows (data) <= 0 )
5927 g_free (query_str);
5928 if (priv->mutex)
5929 g_mutex_unlock (priv->mutex);
5930 return -1;
5933 g_free (query_str);
5935 num_rows = gda_data_model_get_n_rows (data);
5937 /* Hey, we can go in trouble here. Imagine this situation:
5938 * We have two namespaces, 'Editor' and 'Entwickler'. Inside
5939 * them there are two classes with the same name, 'Preferences', hence
5940 * the same scope.
5942 * This is how the above query will result:
5944 * 324|31|Preferences|28|0||192|92|276|3|-1|-1|0
5945 * 365|36|Preferences|33|0||192|2|276|3|-1|-1|0
5947 * Say that 92 is 'Editor' scope, and '2' is 'Entwickler'. We're looking for the
5948 * latter, and so we know that the right answer is symbol_id 365.
5949 * 1. We'll store the symbold_id(s) and the scope_id(s) of both 324 and 365.
5950 * 2. We'll query the db to retrieve all the symbols written before our
5951 * scoped_symbol_id in the file where scoped_symbol_id is.
5952 * 3. Compare every symbol's scope_defintion_id retrieved on step 2 against
5953 * all the ones saved at point 1. The first match is our parent_scope symbol_id.
5955 if (num_rows > 1)
5957 gint i;
5958 gchar *detailed_query;
5960 GList *candidate_parents = NULL;
5961 typedef struct _candidate_node {
5962 gint symbol_id;
5963 gint scope_id;
5964 } candidate_node;
5966 GdaDataModel *detailed_data;
5968 for (i=0; i < num_rows; i++)
5970 candidate_node *node;
5971 const GValue *tmp_value, *tmp_value1;
5973 node = g_new0 (candidate_node, 1);
5975 /* get the symbol_id from the former 'data' result set */
5976 tmp_value = gda_data_model_get_value_at (data, 0, i);
5977 node->symbol_id = tmp_value != NULL && G_VALUE_HOLDS_INT (tmp_value)
5978 ? g_value_get_int (tmp_value) : -1;
5980 /* get scope_id */
5981 tmp_value1 = gda_data_model_get_value_at (data, 3, i);
5982 node->scope_id = tmp_value1 != NULL && G_VALUE_HOLDS_INT (tmp_value1)
5983 ? g_value_get_int (tmp_value1) : -1;
5985 candidate_parents = g_list_prepend (candidate_parents, node);
5988 detailed_query = g_strdup_printf ("SELECT symbol.scope_definition_id FROM symbol WHERE "
5989 "file_defined_id = (SELECT file_defined_id FROM symbol WHERE symbol_id = %d) "
5990 "AND file_position < (SELECT file_position FROM symbol WHERE symbol_id = %d) "
5991 "ORDER BY file_position DESC", scoped_symbol_id, scoped_symbol_id);
5993 /* DEBUG_PRINT ("detailed_query %s", detailed_query);*/
5995 /* we should receive just ONE row. If it's > 1 than we have surely an
5996 * error on code.
5998 if ( (detailed_data =
5999 sdb_engine_execute_select_sql (dbe, detailed_query)) == NULL ||
6000 gda_data_model_get_n_rows (detailed_data) < 0)
6002 g_free (detailed_query);
6003 res = -1;
6005 else /* ok we have a good result here */
6007 gint j;
6008 gboolean found = FALSE;
6009 gint parent_scope_definition_id;
6010 gint found_symbol_id = -1;
6011 candidate_node *node = NULL;
6013 g_free (detailed_query);
6015 for (j=0; j < gda_data_model_get_n_rows (detailed_data); j++)
6017 const GValue *tmp_value;
6018 gint k;
6020 tmp_value = gda_data_model_get_value_at (detailed_data, 0, j);
6021 parent_scope_definition_id = tmp_value != NULL && G_VALUE_HOLDS_INT (tmp_value)
6022 ? g_value_get_int (tmp_value) : -1;
6024 /* DEBUG_PRINT ("symbol_db_engine_get_parent_scope_id_by_symbol_id (): "
6025 "testing parent_scope_definition_id %d",
6026 parent_scope_definition_id);*/
6028 for (k = 0; k < g_list_length (candidate_parents); k++)
6030 node = g_list_nth_data (candidate_parents, k);
6031 if (node->scope_id == parent_scope_definition_id)
6033 found = TRUE;
6034 found_symbol_id = node->symbol_id;
6035 break;
6039 if (found)
6040 break;
6043 /* ok, right now we have node and parent_scope_id we searched for */
6044 /* DEBUG_PRINT ("symbol_db_engine_get_parent_scope_id_by_symbol_id (): "
6045 "FOUND parent %d!", found_symbol_id);*/
6046 res = found_symbol_id;
6049 if (detailed_data)
6050 g_object_unref (detailed_data);
6052 for (i=0; i < g_list_length (candidate_parents); i++)
6054 g_free (g_list_nth_data (candidate_parents, i));
6056 g_list_free (candidate_parents);
6058 else
6060 value = gda_data_model_get_value_at (data, 0, 0);
6061 res = value != NULL && G_VALUE_HOLDS_INT (value)
6062 ? g_value_get_int (value) : -1;
6064 g_object_unref (data);
6066 if (priv->mutex)
6067 g_mutex_unlock (priv->mutex);
6068 return res;