2007-10-13 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / plugins / symbol-db / symbol-db-engine.c
blobedd733bf8052789e1f950d6ce18edc9b9c591a49
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"
131 enum {
132 DO_UPDATE_SYMS = 1,
133 DONT_UPDATE_SYMS,
134 DONT_FAKE_UPDATE_SYMS,
135 END_UPDATE_GROUP_SYMS
138 typedef enum
140 PREP_QUERY_WORKSPACE_NEW = 0,
141 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
142 PREP_QUERY_PROJECT_NEW,
143 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
144 PREP_QUERY_UPDATE_PROJECT_ANALIZE_TIME,
145 PREP_QUERY_FILE_NEW,
146 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
147 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME,
148 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID,
149 PREP_QUERY_UPDATE_FILE_ANALIZE_TIME,
150 PREP_QUERY_LANGUAGE_NEW,
151 PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
152 PREP_QUERY_SYM_TYPE_NEW,
153 PREP_QUERY_GET_SYM_TYPE_ID,
154 PREP_QUERY_SYM_KIND_NEW,
155 PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
156 PREP_QUERY_SYM_ACCESS_NEW,
157 PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
158 PREP_QUERY_SYM_IMPLEMENTATION_NEW,
159 PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
160 PREP_QUERY_HERITAGE_NEW,
161 PREP_QUERY_SCOPE_NEW,
162 PREP_QUERY_GET_SCOPE_ID,
163 PREP_QUERY_TMP_HERITAGE_NEW,
164 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE,
165 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS,
166 PREP_QUERY_TMP_HERITAGE_DELETE_ALL,
167 PREP_QUERY_SYMBOL_NEW,
168 PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
169 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
170 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
171 PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID,
172 PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY,
173 PREP_QUERY_UPDATE_SYMBOL_ALL,
174 PREP_QUERY_GET_REMOVED_IDS,
175 PREP_QUERY_TMP_REMOVED_DELETE_ALL,
176 PREP_QUERY_COUNT
177 } query_type;
180 typedef struct _query_node
182 query_type query_id;
183 gchar *query_str;
184 GdaQuery *query;
186 } query_node;
189 /* *MUST* respect query_type enum order. */
190 /* FIXME: Libgda does not yet support 'LIMIT' keyword. This can be used to
191 * speed up some select(s). Please upgrade them as soon as the library support
192 * it.
194 static query_node query_list[PREP_QUERY_COUNT] = {
195 /* -- workspace -- */
197 PREP_QUERY_WORKSPACE_NEW,
198 "INSERT INTO workspace (workspace_name, analize_time) "
199 "VALUES (## /* name:'wsname' type:gchararray */,"
200 "datetime ('now', 'localtime'))",
201 NULL
204 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
205 "SELECT workspace_id FROM workspace WHERE workspace_name = ## /* name:'wsname' "
206 "type:gchararray */",
207 NULL
209 /* -- project -- */
211 PREP_QUERY_PROJECT_NEW,
212 "INSERT INTO project (project_name, wrkspace_id, analize_time) "
213 "VALUES (## /* name:'prjname' type:gchararray */,"
214 "## /* name:'wsid' type:gint */, datetime ('now', 'localtime'))",
215 NULL
218 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
219 "SELECT project_id FROM project WHERE project_name = ## /* name:'prjname' "
220 "type:gchararray */",
221 NULL
224 PREP_QUERY_UPDATE_PROJECT_ANALIZE_TIME,
225 "UPDATE project SET analize_time = datetime('now', 'localtime') WHERE "
226 "project_name = ## /* name:'prjname' type:gchararray */",
227 NULL
229 /* -- file -- */
231 PREP_QUERY_FILE_NEW,
232 "INSERT INTO file (file_path, prj_id, lang_id, analize_time) VALUES ("
233 "## /* name:'filepath' type:gchararray */, ## /* name:'prjid' "
234 "type:gint */, ## /* name:'langid' type:gint */, "
235 "datetime ('now', 'localtime'))",
236 NULL
239 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
240 "SELECT file_id FROM file WHERE file_path = ## /* name:'filepath' "
241 "type:gchararray */",
242 NULL
245 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME,
246 "SELECT * FROM file WHERE prj_id = (SELECT project_id FROM project "
247 "WHERE project_name = ## /* name:'prjname' type:gchararray */)",
248 NULL
251 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID,
252 "SELECT * FROM file WHERE prj_id = ## /* name:'prjid' type:gint */",
254 "SELECT * FROM file JOIN project on project_id = prj_id WHERE "\
255 "project.name = ## /* name:'prjname' type:gchararray * /",
257 NULL
260 PREP_QUERY_UPDATE_FILE_ANALIZE_TIME,
261 "UPDATE file SET analize_time = datetime('now', 'localtime') WHERE "
262 "file_path = ## /* name:'filepath' type:gchararray */",
263 NULL},
264 /* -- language -- */
266 PREP_QUERY_LANGUAGE_NEW,
267 "INSERT INTO language (language_name) VALUES (## /* name:'langname' "
268 "type:gchararray */)",
269 NULL
272 PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
273 "SELECT language_id FROM language WHERE language_name = ## /* name:'langname' "
274 "type:gchararray */",
275 NULL
277 /* -- sym type -- */
279 PREP_QUERY_SYM_TYPE_NEW,
280 "INSERT INTO sym_type (type, type_name) VALUES (## /* name:'type' "
281 "type:gchararray */, ## /* name:'typename' type:gchararray */)",
282 NULL
285 PREP_QUERY_GET_SYM_TYPE_ID,
286 "SELECT type_id FROM sym_type WHERE type = ## /* name:'type' "
287 "type:gchararray */ AND type_name = ## /* name:'typename' "
288 "type:gchararray */",
289 NULL
291 /* -- sym kind -- */
293 PREP_QUERY_SYM_KIND_NEW,
294 "INSERT INTO sym_kind (kind_name) VALUES(## /* name:'kindname' "
295 "type:gchararray */)",
296 NULL
299 PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
300 "SELECT sym_kind_id FROM sym_kind WHERE kind_name = ## /* "
301 "name:'kindname' type:gchararray */",
302 NULL
304 /* -- sym access -- */
306 PREP_QUERY_SYM_ACCESS_NEW,
307 "INSERT INTO sym_access (access_name) VALUES(## /* name:'accesskind' "
308 "type:gchararray */)",
309 NULL
312 PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
313 "SELECT access_kind_id FROM sym_access WHERE access_name = ## /* "
314 "name:'accesskind' type:gchararray */",
315 NULL
317 /* -- sym implementation -- */
319 PREP_QUERY_SYM_IMPLEMENTATION_NEW,
320 "INSERT INTO sym_implementation (implementation_name) VALUES(## /* name:'implekind' "
321 "type:gchararray */)",
322 NULL
325 PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
326 "SELECT sym_impl_id FROM sym_implementation WHERE kind = ## /* "
327 "name:'implekind' type:gchararray */",
328 NULL
330 /* -- heritage -- */
332 PREP_QUERY_HERITAGE_NEW,
333 "INSERT INTO heritage (symbol_id_base, symbol_id_derived) VALUES(## /* "
334 "name:'symbase' type:gint */, ## /* name:'symderived' type:gint */)",
335 NULL
337 /* -- scope -- */
339 PREP_QUERY_SCOPE_NEW,
340 "INSERT INTO scope (scope, type_id) VALUES(## /* name:'scope' "
341 "type:gchararray */, ## /* name:'typeid' type:gint */)",
342 NULL
345 PREP_QUERY_GET_SCOPE_ID,
346 "SELECT scope_id FROM scope WHERE scope = ## /* name:'scope' "
347 "type:gchararray */ AND type_id = ## /* name:'typeid' type:gint */",
348 NULL
350 /* -- tmp heritage -- */
352 PREP_QUERY_TMP_HERITAGE_NEW,
353 "INSERT INTO __tmp_heritage_scope (symbol_referer_id, field_inherits, "
354 "field_struct, field_typeref, field_enum, field_union, "
355 "field_class, field_namespace) VALUES (## /* name:'symreferid' "
356 "type:gint */, ## /* name:'finherits' type:gchararray */, ## /* "
357 "name:'fstruct' type:gchararray */, ## /* name:'ftyperef' "
358 "type:gchararray */, ## /* name:'fenum' type:gchararray */, ## /* "
359 "name:'funion' type:gchararray */, ## /* name:'fclass' type:gchararray "
360 "*/, ## /* name:'fnamespace' type:gchararray */)",
361 NULL
364 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE,
365 "SELECT * FROM __tmp_heritage_scope",
366 NULL
369 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS,
370 "SELECT * FROM __tmp_heritage_scope WHERE field_inherits != ''",
371 NULL
374 PREP_QUERY_TMP_HERITAGE_DELETE_ALL,
375 "DELETE FROM __tmp_heritage_scope",
376 NULL
378 /* -- symbol -- */
380 PREP_QUERY_SYMBOL_NEW,
381 "INSERT INTO symbol (file_defined_id, name, file_position, "
382 "is_file_scope, signature, scope_definition_id, scope_id, type_id, "
383 "kind_id, access_kind_id, implementation_kind_id, update_flag) VALUES("
384 "## /* name:'filedefid' type:gint */, ## /* name:'name' "
385 "type:gchararray */, ## /* name:'fileposition' type:gint */, ## /* "
386 "name:'isfilescope' type:gint */, ## /* name:'signature' "
387 "type:gchararray */,## /* name:'scopedefinitionid' type:gint */, ## "
388 "/* name:'scopeid' type:gint */,## /* name:'typeid' type:gint */, ## "
389 "/* name:'kindid' type:gint */,## /* name:'accesskindid' type:gint */, "
390 "## /* name:'implementationkindid' type:gint */, ## /* "
391 "name:'updateflag' type:gint */)",
392 NULL
395 PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
396 "SELECT scope_definition_id FROM symbol JOIN sym_type ON symbol.type_id"
397 "= sym_type.type_id WHERE sym_type.type = ## /* name:'tokenname' "
398 "type:gchararray */ AND sym_type.type_name = ## /* name:'objectname' "
399 "type:gchararray */",
400 NULL
403 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
404 "SELECT symbol_id FROM symbol JOIN sym_type ON symbol.type_id = "
405 "sym_type.type_id WHERE scope_id=0 AND sym_type.type='class' AND "
406 "name = ## /* name:'klassname' type:gchararray */",
407 NULL
410 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
411 "SELECT symbol_id FROM symbol JOIN scope ON symbol.scope_id = "
412 "scope.scope_id JOIN sym_type ON scope.type_id = sym_type.type_id "
413 "WHERE symbol.name = /* name:'klassname' type:gchararray */ AND "
414 "scope.scope = /* name:'namespacename' type:gchararray */ AND "
415 "sym_type.type='namespace'",
416 NULL
419 PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID,
420 "UPDATE symbol SET scope_id = ## /* name:'scopeid' type:gint */ "
421 "WHERE symbol_id = ## /* name:'symbolid' type:gint */",
422 NULL
425 PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY,
426 "SELECT symbol_id FROM symbol WHERE name = ## /* name:'symname' "
427 "type:gchararray */ AND file_defined_id = ## /* name:'filedefid' "
428 "type:gint */ AND type_id = ## /* name:'typeid' type:gint */",
429 NULL
432 PREP_QUERY_UPDATE_SYMBOL_ALL,
433 "UPDATE symbol SET is_file_scope = ## /* name:'isfilescope' type:gint "
434 "*/, signature = ## /* name:'signature' type:gchararray */, "
435 "scope_definition_id = ## /* name:'scopedefinitionid' type:gint */, "
436 "scope_id = ## /* name:'scopeid' type:gint */, kind_id = "
437 "## /* name:'kindid' type:gint */, access_kind_id = ## /* name:"
438 "'accesskindid' type:gint */, implementation_kind_id = ## /* name:"
439 "'implementationkindid' type:gint */, update_flag = ## /* name:"
440 "'updateflag' type:gint */ WHERE symbol_id = ## /* name:'symbolid' type:"
441 "gint */",
442 NULL
444 /* -- tmp_removed -- */
446 PREP_QUERY_GET_REMOVED_IDS,
447 "SELECT symbol_removed_id FROM __tmp_removed",
448 NULL
451 PREP_QUERY_TMP_REMOVED_DELETE_ALL,
452 "DELETE FROM __tmp_removed",
453 NULL
458 /* this is a special case which is not doable with a prepared query. */
459 static GdaCommand *last_insert_id_cmd = NULL;
461 typedef void (SymbolDBEngineCallback) (SymbolDBEngine * dbe,
462 gpointer user_data);
464 enum
466 SCAN_END,
467 SYMBOL_INSERTED,
468 SYMBOL_UPDATED,
469 SYMBOL_REMOVED,
470 LAST_SIGNAL
473 static unsigned int signals[LAST_SIGNAL] = { 0 };
476 struct _SymbolDBEnginePriv
478 GdaConnection *db_connection;
479 GdaClient *gda_client;
480 GdaDict *dict;
481 gchar *dsn_name;
482 gchar *project_name;
483 gchar *data_source;
485 GAsyncQueue *scan_queue;
487 GAsyncQueue *updated_symbols_id;
488 GAsyncQueue *inserted_symbols_id;
490 gchar *shared_mem_str;
491 FILE *shared_mem_file;
492 gint shared_mem_fd;
493 AnjutaLauncher *ctags_launcher;
494 gboolean scanning_status;
495 gboolean force_sym_update;
498 static GObjectClass *parent_class = NULL;
501 static void sdb_engine_second_pass_do (SymbolDBEngine * dbe);
502 static gint
503 sdb_engine_add_new_symbol (SymbolDBEngine * dbe, tagEntry * tag_entry,
504 gchar * base_prj_path, gchar * fake_file,
505 gboolean sym_update);
509 * Use this as little as you can. Prepared statements are quicker.
511 static void inline
512 sdb_engine_execute_non_select_sql (SymbolDBEngine * dbe, const gchar * buffer)
514 SymbolDBEnginePriv *priv;
515 GdaCommand *command;
517 priv = dbe->priv;
519 command = gda_command_new (buffer, GDA_COMMAND_TYPE_SQL,
520 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
521 gda_connection_execute_non_select_command (priv->db_connection,
522 command, NULL, NULL);
523 gda_command_free (command);
527 * Will test the opened project within the dbe plugin and the passed one.
529 gboolean inline
530 symbol_db_engine_is_project_opened (SymbolDBEngine *dbe, const gchar* project_name)
532 SymbolDBEnginePriv *priv;
534 g_return_val_if_fail (dbe != NULL, FALSE);
535 priv = dbe->priv;
537 if (priv->project_name == NULL)
538 return FALSE;
540 return strcmp (project_name, priv->project_name) == 0 ? TRUE : FALSE;
544 * Use a proxy to return an already present or a fresh new prepared query
545 * from static 'query_list'. We should perform actions in the fastest way, because
546 * these queries are time-critical.
549 static inline const GdaQuery *
550 sdb_engine_get_query_by_id (SymbolDBEngine * dbe, query_type query_id)
552 query_node *node;
553 SymbolDBEnginePriv *priv;
555 priv = dbe->priv;
557 /* no way: if connection is NULL we will break here. There must be
558 * a connection established to db before using this function */
559 g_return_val_if_fail (priv->db_connection != NULL, NULL);
561 node = &query_list[query_id];
563 /* check for a null dict into priv struct */
564 if (priv->dict == NULL)
566 priv->dict = gda_dict_new ();
567 gda_dict_set_connection (priv->dict, priv->db_connection);
570 if (node->query == NULL)
572 DEBUG_PRINT ("generating new query.... %d", query_id);
573 /* create a new GdaQuery */
574 node->query =
575 gda_query_new_from_sql (priv->dict, node->query_str, NULL);
578 return node->query;
581 static inline gint
582 sdb_engine_get_last_insert_id (SymbolDBEngine * dbe)
584 GdaDataModel *data;
585 const GValue *num;
586 gint table_id;
587 SymbolDBEnginePriv *priv;
589 priv = dbe->priv;
591 /* check whether we have already initialized it or not. */
592 if (last_insert_id_cmd == NULL)
594 DEBUG_PRINT ("creating new command...");
595 last_insert_id_cmd = gda_command_new ("SELECT last_insert_rowid()",
596 GDA_COMMAND_TYPE_SQL,
597 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
600 if ((data = gda_connection_execute_select_command (priv->db_connection,
601 last_insert_id_cmd, NULL,
602 NULL)) == NULL
603 || gda_data_model_get_n_rows (data) <= 0)
605 return -1;
608 num = gda_data_model_get_value_at (data, 0, 0);
609 if (G_VALUE_HOLDS (num, G_TYPE_INT))
610 table_id = g_value_get_int (num);
611 else
612 return -1;
614 g_object_unref (data);
615 return table_id;
619 * Clear the static cached queries data. You should call this function when closing/
620 * destroying SymbolDBEngine object.
621 * priv->dict is also destroyed.
623 static void
624 sdb_engine_free_cached_queries (SymbolDBEngine * dbe)
626 gint i;
627 query_node *node;
628 SymbolDBEnginePriv *priv;
630 priv = dbe->priv;
632 for (i = 0; i < PREP_QUERY_COUNT; i++)
634 node = &query_list[i];
636 if (node->query != NULL)
638 g_object_unref ((gpointer) node->query);
639 node->query = NULL;
643 /* destroys also dict */
644 g_object_unref (priv->dict);
647 static gboolean
648 sdb_engine_disconnect_from_db (SymbolDBEngine * dbe)
650 SymbolDBEnginePriv *priv;
652 g_return_val_if_fail (dbe != NULL, FALSE);
653 priv = dbe->priv;
655 if (priv->gda_client)
657 gda_client_close_all_connections (priv->gda_client);
658 g_object_unref (priv->gda_client);
660 priv->gda_client = NULL;
661 priv->db_connection = NULL;
663 g_free (priv->data_source);
664 priv->data_source = NULL;
666 g_free (priv->dsn_name);
667 priv->dsn_name = NULL;
669 if (priv->dict)
671 g_object_unref (priv->dict);
672 priv->dict = NULL;
676 return TRUE;
679 static GTimer *sym_timer_DEBUG = NULL;
682 * If base_prj_path != NULL then fake_file will not be parsed. Else
683 * if fake_file is != NULL we claim and assert that tags contents which are
684 * scanned belong to the fake_file in the project.
685 * More: the fake_file refers to just one single file and cannot be used
686 * for multiple fake_files.
688 static void
689 sdb_engine_populate_db_by_tags (SymbolDBEngine * dbe, FILE* fd,
690 gchar * base_prj_path, gchar * fake_file_on_db,
691 gboolean force_sym_update)
693 tagFile *tag_file;
694 tagFileInfo tag_file_info;
695 tagEntry tag_entry;
697 SymbolDBEnginePriv *priv;
699 g_return_if_fail (dbe != NULL);
701 priv = dbe->priv;
703 g_return_if_fail (priv->db_connection != NULL);
704 g_return_if_fail (fd != NULL);
706 if (priv->updated_symbols_id == NULL)
707 priv->updated_symbols_id = g_async_queue_new ();
709 if (priv->inserted_symbols_id == NULL)
710 priv->inserted_symbols_id = g_async_queue_new ();
712 DEBUG_PRINT ("sdb_engine_populate_db_by_tags ()");
713 if ((tag_file = tagsOpen_1 (fd, &tag_file_info)) == NULL)
714 g_warning ("error in opening ctags file");
716 gda_connection_begin_transaction (priv->db_connection, "fixme", 0, NULL);
718 if (sym_timer_DEBUG == NULL)
719 sym_timer_DEBUG = g_timer_new ();
720 else
721 g_timer_reset (sym_timer_DEBUG);
722 gint tags_total_DEBUG = 0;
724 while (tagsNext (tag_file, &tag_entry) != TagFailure)
726 sdb_engine_add_new_symbol (dbe, &tag_entry, fake_file_on_db == NULL ?
727 base_prj_path : NULL, fake_file_on_db,
728 force_sym_update);
730 tags_total_DEBUG ++;
733 gdouble elapsed_DEBUG = g_timer_elapsed (sym_timer_DEBUG, NULL);
734 DEBUG_PRINT ("elapsed: %f for (%d) [%f per symbol]", elapsed_DEBUG,
735 tags_total_DEBUG, elapsed_DEBUG / tags_total_DEBUG);
737 gda_connection_commit_transaction (priv->db_connection, "fixme", NULL);
740 static void
741 sdb_engine_ctags_output_callback_1 (AnjutaLauncher * launcher,
742 AnjutaLauncherOutputType output_type,
743 const gchar * chars, gpointer user_data)
745 gint len_chars;
746 gint remaining_chars;
747 gint len_marker;
748 gchar *chars_ptr;
749 SymbolDBEnginePriv *priv;
750 SymbolDBEngine *dbe;
752 g_return_if_fail (user_data != NULL);
753 g_return_if_fail (chars != NULL);
755 dbe = (SymbolDBEngine*)user_data;
756 priv = dbe->priv;
758 chars_ptr = (gchar*)chars;
760 remaining_chars = len_chars = strlen (chars);
761 len_marker = strlen (CTAGS_MARKER);
763 /* DEBUG_PRINT ("gotta %s", chars_ptr);*/
765 if ( len_chars >= len_marker )
767 gchar *marker_ptr = NULL;
768 gint tmp_str_length = 0;
770 /* is it an end file marker? */
771 marker_ptr = strstr (chars_ptr, CTAGS_MARKER);
773 do {
774 if (marker_ptr != NULL)
776 gint scan_flag;
777 gchar *real_file;
778 DEBUG_PRINT ("found marker!");
780 /* set the length of the string parsed */
781 tmp_str_length = marker_ptr - chars_ptr;
783 /*DEBUG_PRINT ("program output [new version]: ==>%s<==", chars_ptr);*/
784 /* write to shm_file all the chars_ptr received without the marker ones */
785 fwrite (chars_ptr, sizeof(gchar), tmp_str_length, priv->shared_mem_file);
787 chars_ptr = marker_ptr + len_marker;
788 remaining_chars -= (tmp_str_length + len_marker);
789 fflush (priv->shared_mem_file);
791 /* get the scan flag from the queue. We need it to know whether
792 * an update of symbols must be done or not */
793 scan_flag = (int)g_async_queue_try_pop (priv->scan_queue);
794 real_file = g_async_queue_try_pop (priv->scan_queue);
796 /* and now call the populating function */
797 sdb_engine_populate_db_by_tags (dbe, priv->shared_mem_file,
798 priv->data_source,
799 (int)real_file == DONT_FAKE_UPDATE_SYMS ? NULL : real_file,
800 scan_flag == DO_UPDATE_SYMS ? TRUE : FALSE);
802 /* don't forget to free the real_life, if it's a char */
803 if ((int)real_file != DONT_FAKE_UPDATE_SYMS)
804 g_free (real_file);
806 /* check also if, together with an end file marker, we have an
807 * end group-of-files end marker.
809 if ((strcmp (marker_ptr + len_marker, CTAGS_MARKER) == 0) ||
810 ftell (priv->shared_mem_file) <= 0)
812 gint tmp_inserted;
813 gint tmp_updated;
815 /* proceed with second passes */
816 DEBUG_PRINT ("FOUND end-of-group-files marker.\n"
817 "go on with sdb_engine_second_pass_do ()");
818 sdb_engine_second_pass_do (dbe);
820 chars_ptr += len_marker;
821 remaining_chars -= len_marker;
824 /* Here we are. It's the right time to notify the listeners
825 * about out fresh new inserted/updated symbols...
826 * Go on by emitting them.
828 while ((tmp_inserted = (int)
829 g_async_queue_try_pop (priv->inserted_symbols_id)) > 0)
831 g_signal_emit (dbe, signals[SYMBOL_INSERTED], 0, tmp_inserted);
834 while ((tmp_updated = (int)
835 g_async_queue_try_pop (priv->updated_symbols_id)) > 0)
837 g_signal_emit (dbe, signals[SYMBOL_UPDATED], 0, tmp_updated);
840 /* emit signal. The end of files-group can be cannot be
841 * determined by the caller. This is the only way.
843 DEBUG_PRINT ("EMITTING scan-end");
844 g_signal_emit (dbe, signals[SCAN_END], 0);
847 /* truncate the file to 0 length */
848 ftruncate (priv->shared_mem_fd, 0);
850 else
852 /* marker_ptr is NULL here. We should then exit the loop. */
853 /* write to shm_file all the chars received */
854 fwrite (chars_ptr, sizeof(gchar), remaining_chars,
855 priv->shared_mem_file);
857 fflush (priv->shared_mem_file);
858 break;
861 /* found out a new marker */
862 marker_ptr = strstr (marker_ptr + len_marker, CTAGS_MARKER);
863 } while (remaining_chars + len_marker < len_chars);
865 else
867 DEBUG_PRINT ("no len_chars > len_marker");
871 static void
872 on_scan_files_end_1 (AnjutaLauncher * launcher, int child_pid,
873 int exit_status, gulong time_taken_in_seconds,
874 gpointer data)
876 DEBUG_PRINT ("ctags ended");
880 /* Scans with ctags and produce an output 'tags' file [shared memory file]
881 * containing language symbols. This function will call ctags
882 * executale and then sdb_engine_populate_db_by_tags () when it'll detect some
883 * output.
884 * Please note the files_list/real_files_list parameter:
885 * this version of sdb_engine_scan_files_1 () let you scan for text buffer(s) that
886 * will be claimed as buffers for the real files.
887 * 1. simple mode: files_list represents the real files on disk and so we don't
888 * need real_files_list, which will be NULL.
889 * 2. advanced mode: files_list represents temporary flushing of buffers on disk, i.e.
890 * /tmp/anjuta_XYZ.cxx. real_files_list is the representation of those files on
891 * database. On the above example we can have anjuta_XYZ.cxx mapped as /src/main.c
892 * on db. In this mode files_list and real_files_list must have the same size.
895 /* server mode version */
896 static gboolean
897 sdb_engine_scan_files_1 (SymbolDBEngine * dbe, const GPtrArray * files_list,
898 const GPtrArray *real_files_list, gboolean symbols_update)
900 SymbolDBEnginePriv *priv;
901 gint i;
903 g_return_val_if_fail (dbe != NULL, FALSE);
904 g_return_val_if_fail (files_list != NULL, FALSE);
906 if (files_list->len == 0)
907 return FALSE;
909 /* start process in server mode */
910 priv = dbe->priv;
912 if (real_files_list != NULL && (files_list->len != real_files_list->len))
914 g_warning ("no matched size between real_files_list and files_list");
915 return FALSE;
918 /* if ctags_launcher isn't initialized, then do it now. */
919 if (priv->ctags_launcher == NULL)
921 gchar *exe_string;
923 DEBUG_PRINT ("creating anjuta_launcher");
924 priv->ctags_launcher = anjuta_launcher_new ();
926 g_signal_connect (G_OBJECT (priv->ctags_launcher), "child-exited",
927 G_CALLBACK (on_scan_files_end_1), NULL);
929 exe_string = g_strdup_printf ("%s --fields=afmiKlnsStz "
930 "--filter=yes --filter-terminator='"CTAGS_MARKER"'",
931 CTAGS_PATH);
933 anjuta_launcher_execute (priv->ctags_launcher,
934 exe_string, sdb_engine_ctags_output_callback_1,
935 dbe);
936 g_free (exe_string);
939 /* what about the scan_queue? is it initialized? It will contain mainly
940 * ints that refers to the force_update status.
942 if (priv->scan_queue == NULL)
944 priv->scan_queue = g_async_queue_new ();
947 /* create the shared memory file */
948 if (priv->shared_mem_file == 0)
950 gchar *temp_file;
951 temp_file = g_strdup_printf ("/anjuta-%d_%ld.tags", getpid (),
952 time (NULL));
954 priv->shared_mem_str = temp_file;
956 if ((priv->shared_mem_fd =
957 shm_open (temp_file, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0)
959 g_warning ("Error while trying to open a shared memory file. Be"
960 "sure to have /dev/shm mounted with tmpfs");
963 priv->shared_mem_file = fdopen (priv->shared_mem_fd, "a+b");
964 DEBUG_PRINT ("temp_file %s", temp_file);
966 /* no need to free temp_file. It will be freed on plugin finalize */
969 priv->scanning_status = TRUE;
971 DEBUG_PRINT ("files_list->len %d", files_list->len);
973 for (i = 0; i < files_list->len; i++)
975 gchar *node = (gchar *) g_ptr_array_index (files_list, i);
977 if (g_file_test (node, G_FILE_TEST_EXISTS) == FALSE)
979 g_warning ("File %s not scanned because it does not exist", node);
980 continue;
982 DEBUG_PRINT ("anjuta_launcher_send_stdin %s", node);
983 anjuta_launcher_send_stdin (priv->ctags_launcher, node);
984 anjuta_launcher_send_stdin (priv->ctags_launcher, "\n");
986 if (symbols_update == TRUE)
987 g_async_queue_push (priv->scan_queue, (gpointer) DO_UPDATE_SYMS);
988 else
989 g_async_queue_push (priv->scan_queue, (gpointer) DONT_UPDATE_SYMS);
991 /* don't forget to add the real_files if the caller provided a list for
992 * them! */
993 if (real_files_list != NULL)
995 g_async_queue_push (priv->scan_queue,
996 (gpointer)g_strdup (
997 g_ptr_array_index (real_files_list, i)));
999 else
1001 /* else add a DONT_FAKE_UPDATE_SYMS marker, just to noty that this is
1002 * not a fake file scan
1004 g_async_queue_push (priv->scan_queue, (gpointer) DONT_FAKE_UPDATE_SYMS);
1008 /* hack to let ctags output a marker. We will then process it into the
1009 * output callback function */
1010 anjuta_launcher_send_stdin (priv->ctags_launcher, "/dev/null\n");
1012 priv->scanning_status = FALSE;
1014 return TRUE;
1019 static void
1020 sdb_engine_init (SymbolDBEngine * object)
1022 SymbolDBEngine *sdbe;
1024 sdbe = SYMBOL_DB_ENGINE (object);
1025 sdbe->priv = g_new0 (SymbolDBEnginePriv, 1);
1027 /* initialize some priv data */
1028 sdbe->priv->gda_client = NULL;
1029 sdbe->priv->db_connection = NULL;
1030 sdbe->priv->dsn_name = NULL;
1031 sdbe->priv->project_name = NULL;
1032 sdbe->priv->data_source = NULL;
1034 sdbe->priv->scan_queue = NULL;
1035 sdbe->priv->updated_symbols_id = NULL;
1036 sdbe->priv->inserted_symbols_id = NULL;
1037 sdbe->priv->shared_mem_file = NULL;
1038 sdbe->priv->shared_mem_fd = 0;
1039 sdbe->priv->shared_mem_str = NULL;
1040 sdbe->priv->scanning_status = FALSE;
1041 sdbe->priv->force_sym_update = FALSE;
1043 /* Initialize gda library. */
1044 gda_init ("AnjutaGda", NULL, 0, NULL);
1046 /* create Anjuta Launcher instance. It will be used for tags parsing. */
1047 sdbe->priv->ctags_launcher = NULL;
1050 static void
1051 sdb_engine_finalize (GObject * object)
1053 SymbolDBEngine *dbe;
1054 SymbolDBEnginePriv *priv;
1056 dbe = SYMBOL_DB_ENGINE (object);
1057 priv = dbe->priv;
1059 sdb_engine_disconnect_from_db (dbe);
1060 sdb_engine_free_cached_queries (dbe);
1062 g_free (priv->project_name);
1064 if (priv->scan_queue)
1066 g_async_queue_unref (priv->scan_queue);
1067 priv->scan_queue = NULL;
1070 if (priv->updated_symbols_id)
1072 g_async_queue_unref (priv->updated_symbols_id);
1073 priv->updated_symbols_id = NULL;
1077 if (priv->inserted_symbols_id)
1079 g_async_queue_unref (priv->inserted_symbols_id);
1080 priv->inserted_symbols_id = NULL;
1083 if (priv->shared_mem_file)
1085 fclose (priv->shared_mem_file);
1086 priv->shared_mem_file = NULL;
1090 if (priv->shared_mem_str)
1092 shm_unlink (priv->shared_mem_str);
1093 g_free (priv->shared_mem_str);
1094 priv->shared_mem_str = NULL;
1097 if (priv->ctags_launcher)
1099 anjuta_launcher_signal (priv->ctags_launcher, SIGINT);
1100 g_object_unref (priv->ctags_launcher);
1103 G_OBJECT_CLASS (parent_class)->finalize (object);
1106 static void
1107 sdb_engine_class_init (SymbolDBEngineClass * klass)
1109 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1110 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
1112 object_class->finalize = sdb_engine_finalize;
1114 signals[SCAN_END]
1115 = g_signal_new ("scan-end",
1116 G_OBJECT_CLASS_TYPE (object_class),
1117 G_SIGNAL_RUN_FIRST,
1118 G_STRUCT_OFFSET (SymbolDBEngineClass, scan_end),
1119 NULL, NULL,
1120 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
1122 signals[SYMBOL_INSERTED]
1123 = g_signal_new ("symbol-inserted",
1124 G_OBJECT_CLASS_TYPE (object_class),
1125 G_SIGNAL_RUN_FIRST,
1126 G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_inserted),
1127 NULL, NULL,
1128 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
1130 G_TYPE_INT);
1132 signals[SYMBOL_UPDATED]
1133 = g_signal_new ("symbol-updated",
1134 G_OBJECT_CLASS_TYPE (object_class),
1135 G_SIGNAL_RUN_FIRST,
1136 G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_updated),
1137 NULL, NULL,
1138 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
1140 G_TYPE_INT);
1142 signals[SYMBOL_REMOVED]
1143 = g_signal_new ("symbol-removed",
1144 G_OBJECT_CLASS_TYPE (object_class),
1145 G_SIGNAL_RUN_FIRST,
1146 G_STRUCT_OFFSET (SymbolDBEngineClass, symbol_removed),
1147 NULL, NULL,
1148 g_cclosure_marshal_VOID__INT, G_TYPE_NONE,
1150 G_TYPE_INT);
1154 GType
1155 sdb_engine_get_type (void)
1157 static GType our_type = 0;
1159 if (our_type == 0)
1161 static const GTypeInfo our_info = {
1162 sizeof (SymbolDBEngineClass), /* class_size */
1163 (GBaseInitFunc) NULL, /* base_init */
1164 (GBaseFinalizeFunc) NULL, /* base_finalize */
1165 (GClassInitFunc) sdb_engine_class_init, /* class_init */
1166 (GClassFinalizeFunc) NULL, /* class_finalize */
1167 NULL /* class_data */ ,
1168 sizeof (SymbolDBEngine), /* instance_size */
1169 0, /* n_preallocs */
1170 (GInstanceInitFunc) sdb_engine_init, /* instance_init */
1171 NULL /* value_table */
1174 our_type = g_type_register_static (G_TYPE_OBJECT, "SymbolDBEngine",
1175 &our_info, 0);
1178 return our_type;
1181 SymbolDBEngine *
1182 symbol_db_engine_new (void)
1184 SymbolDBEngine *sdbe;
1186 sdbe = g_object_new (SYMBOL_TYPE_DB_ENGINE, NULL);
1187 return sdbe;
1190 /* Will create priv->db_connection, priv->gda_client.
1191 * Connect to database identified by data_source.
1192 * Usually data_source is defined also into priv. We let it here as parameter
1193 * because it is required and cannot be null.
1195 static gboolean
1196 sdb_engine_connect_to_db (SymbolDBEngine * dbe, const gchar * data_source)
1198 SymbolDBEnginePriv *priv;
1200 g_return_val_if_fail (dbe != NULL, FALSE);
1201 priv = dbe->priv;
1203 if (priv->db_connection != NULL)
1205 /* if it's the case that the connection isn't NULL, we
1206 * should notify the user
1207 * and return FALSE. It's his task to disconnect and retry to connect */
1208 g_warning ("connection is already established. Please disconnect "
1209 "and then try to reconnect.");
1210 return FALSE;
1213 /* create new client */
1214 priv->gda_client = gda_client_new ();
1216 /* establish a connection. If the sqlite file does not exist it will
1217 * be created
1219 priv->db_connection
1220 = gda_client_open_connection (priv->gda_client, data_source,
1221 "", "",
1222 GDA_CONNECTION_OPTIONS_READ_ONLY, NULL);
1224 if (!GDA_IS_CONNECTION (priv->db_connection))
1226 g_warning ("could not open connection to %s\n", data_source);
1227 return FALSE;
1230 g_message ("connected to database %s", data_source);
1231 return TRUE;
1236 * Creates required tables for the database to work.
1237 * @param tables_sql_file File containing sql code.
1239 static gboolean
1240 sdb_engine_create_db_tables (SymbolDBEngine * dbe, gchar * tables_sql_file)
1242 GError *err;
1243 GdaCommand *command;
1244 SymbolDBEnginePriv *priv;
1245 gchar *contents;
1246 gsize size;
1248 g_return_val_if_fail (tables_sql_file != NULL, FALSE);
1250 priv = dbe->priv;
1252 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
1254 /* read the contents of the file */
1255 if (g_file_get_contents (tables_sql_file, &contents, &size, &err) == FALSE)
1257 g_warning ("Something went wrong while trying to read %s",
1258 tables_sql_file);
1260 if (err != NULL)
1261 g_message ("%s", err->message);
1262 return FALSE;
1265 command = gda_command_new (contents, GDA_COMMAND_TYPE_SQL,
1266 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
1267 gda_connection_execute_non_select_command (priv->db_connection, command,
1268 NULL, NULL);
1269 gda_command_free (command);
1271 g_free (contents);
1272 return TRUE;
1276 * Check if the database already exists into the prj_directory
1278 gboolean
1279 symbol_db_engine_db_exists (SymbolDBEngine * dbe, gchar * prj_directory)
1281 SymbolDBEnginePriv *priv;
1283 g_return_val_if_fail (prj_directory != NULL, FALSE);
1285 priv = dbe->priv;
1287 /* check whether the db filename already exists.*/
1288 gchar *tmp_file = g_strdup_printf ("%s/%s.db", prj_directory,
1289 ANJUTA_DB_FILE);
1291 if (g_file_test (tmp_file, G_FILE_TEST_EXISTS) == FALSE)
1293 DEBUG_PRINT ("db %s does not exist", tmp_file);
1294 g_free (tmp_file);
1295 return FALSE;
1297 g_free (tmp_file);
1299 DEBUG_PRINT ("db %s does exist", tmp_file);
1300 return TRUE;
1304 * Open or create a new database at given directory.
1306 gboolean
1307 symbol_db_engine_open_db (SymbolDBEngine * dbe, gchar * prj_directory)
1309 SymbolDBEnginePriv *priv;
1310 /* Connection data */
1311 gchar *dsn_name;
1312 gboolean needs_tables_creation = FALSE;
1314 g_return_val_if_fail (prj_directory != NULL, FALSE);
1316 priv = dbe->priv;
1318 /* check whether the db filename already exists. If it's not the case
1319 * create the tables for the database. */
1320 gchar *tmp_file = g_strdup_printf ("%s/%s.db", prj_directory,
1321 ANJUTA_DB_FILE);
1323 if (g_file_test (tmp_file, G_FILE_TEST_EXISTS) == FALSE)
1325 needs_tables_creation = TRUE;
1327 g_free (tmp_file);
1330 priv->data_source = g_strdup (prj_directory);
1332 dsn_name = g_strdup_printf ("DB_DIR=%s;DB_NAME=%s", prj_directory,
1333 ANJUTA_DB_FILE);
1335 if (gda_config_save_data_source (priv->data_source, "SQLite",
1336 dsn_name, "Anjuta Project",
1337 "", "", FALSE) == FALSE)
1339 return FALSE;
1342 /* store the dsn name into Priv data. We can avoid to free it here coz it will
1343 * used later again. */
1344 priv->dsn_name = dsn_name;
1346 DEBUG_PRINT ("opening/connecting to database...");
1347 sdb_engine_connect_to_db (dbe, priv->data_source);
1349 if (needs_tables_creation == TRUE)
1351 DEBUG_PRINT ("creating tables: it needs tables...");
1352 sdb_engine_create_db_tables (dbe, TABLES_SQL);
1355 return TRUE;
1359 * @return -1 on error. Otherwise the id of table
1361 static gint
1362 sdb_engine_get_table_id_by_unique_name (SymbolDBEngine * dbe, query_type qtype,
1363 gchar * param_key,
1364 const GValue * param_value)
1366 const GdaQuery *query;
1367 GdaParameterList *par_list;
1368 GdaParameter *param;
1369 const GValue *num;
1370 gint table_id;
1372 /* get prepared query */
1373 if ((query = sdb_engine_get_query_by_id (dbe, qtype)) == NULL)
1375 g_warning ("query is null");
1376 return -1;
1379 if (GDA_QUERY_TYPE_NON_PARSED_SQL
1380 == gda_query_get_query_type ((GdaQuery *) query))
1382 g_warning ("sdb_engine_get_table_id_by_unique_name: non parsed "
1383 "sql error");
1384 return -1;
1387 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1389 g_warning ("par_list is NULL!\n");
1390 return -1;
1393 if ((param = gda_parameter_list_find_param (par_list, param_key)) == NULL)
1395 g_warning ("sdb_engine_get_table_id_by_unique_name: param is NULL "
1396 "from pquery!\n");
1397 return -1;
1400 gda_parameter_set_value (param, param_value);
1402 /* execute the query with parametes just set */
1403 GObject *obj =
1404 G_OBJECT (gda_query_execute ((GdaQuery *) query, par_list, FALSE,
1405 NULL));
1407 if (!GDA_IS_DATA_MODEL (obj) ||
1408 gda_data_model_get_n_rows (GDA_DATA_MODEL (obj)) <= 0)
1410 /* DEBUG_PRINT ("could not retrieve table id by unique name [par %s]",
1411 param_key);*/
1413 if (obj != NULL)
1414 g_object_unref (obj);
1415 return -1;
1418 /* get and parse the results. */
1419 num = gda_data_model_get_value_at (GDA_DATA_MODEL (obj), 0, 0);
1421 table_id = g_value_get_int (num);
1422 g_object_unref (obj);
1423 return table_id;
1427 * This is the same as sdb_engine_get_table_id_by_unique_name () but for two
1428 * unique parameters. This should be the quickest way. Surely quicker than
1429 * use g_strdup_printf () with a va_list for example.
1430 * @return -1 on error. Otherwise the id of table
1433 static gint
1434 sdb_engine_get_table_id_by_unique_name2 (SymbolDBEngine * dbe, query_type qtype,
1435 gchar * param_key1,
1436 const GValue * value1,
1437 gchar * param_key2,
1438 const GValue * value2)
1440 const GdaQuery *query;
1441 GdaParameterList *par_list;
1442 GdaParameter *param;
1443 const GValue *num;
1444 gint table_id;
1446 /* get prepared query */
1447 if ((query = sdb_engine_get_query_by_id (dbe, qtype)) == NULL)
1449 g_warning ("query is null");
1450 return -1;
1453 if (GDA_QUERY_TYPE_NON_PARSED_SQL
1454 == gda_query_get_query_type ((GdaQuery *) query))
1456 g_warning
1457 ("sdb_engine_get_table_id_by_unique_name2: non parsed sql error");
1458 return -1;
1461 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1463 g_warning ("par_list is NULL!\n");
1464 return -1;
1467 /* look for and set the first parameter */
1468 if ((param = gda_parameter_list_find_param (par_list, param_key1)) == NULL)
1470 g_warning ("sdb_engine_get_table_id_by_unique_name2: "
1471 "param is NULL from pquery! [par1: %s] [par2: %s]\n",
1472 param_key1, param_key2);
1473 return -1;
1476 gda_parameter_set_value (param, value1);
1478 /* ...and the second one */
1479 if ((param = gda_parameter_list_find_param (par_list, param_key2)) == NULL)
1481 g_warning ("param is NULL from pquery!\n");
1482 return -1;
1485 gda_parameter_set_value (param, value2);
1487 /* execute the query with parametes just set */
1488 GObject *obj =
1489 G_OBJECT (gda_query_execute ((GdaQuery *) query, par_list, FALSE,
1490 NULL));
1492 if (!GDA_IS_DATA_MODEL (obj) ||
1493 gda_data_model_get_n_rows (GDA_DATA_MODEL (obj)) <= 0)
1496 if (obj != NULL)
1497 g_object_unref (obj);
1498 return -1;
1501 /* get and parse the results. */
1502 num = gda_data_model_get_value_at (GDA_DATA_MODEL (obj), 0, 0);
1504 table_id = g_value_get_int (num);
1505 g_object_unref (obj);
1506 return table_id;
1509 static gint
1510 sdb_engine_get_table_id_by_unique_name3 (SymbolDBEngine * dbe, query_type qtype,
1511 gchar * param_key1,
1512 const GValue * value1,
1513 gchar * param_key2,
1514 const GValue * value2,
1515 gchar * param_key3,
1516 const GValue * value3)
1518 const GdaQuery *query;
1519 GdaParameterList *par_list;
1520 GdaParameter *param;
1521 const GValue *num;
1522 gint table_id;
1524 /* get prepared query */
1525 if ((query = sdb_engine_get_query_by_id (dbe, qtype)) == NULL)
1527 g_warning ("query is null");
1528 return -1;
1531 if (GDA_QUERY_TYPE_NON_PARSED_SQL
1532 == gda_query_get_query_type ((GdaQuery *) query))
1534 g_warning
1535 ("sdb_engine_get_table_id_by_unique_name2: non parsed sql error");
1536 return -1;
1539 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1541 g_warning ("par_list is NULL!\n");
1542 return -1;
1545 /* look for and set the first parameter */
1546 if ((param = gda_parameter_list_find_param (par_list, param_key1)) == NULL)
1548 g_warning ("sdb_engine_get_table_id_by_unique_name2: "
1549 "param is NULL from pquery! [par1: %s] [par2: %s]\n",
1550 param_key1, param_key2);
1551 return -1;
1554 gda_parameter_set_value (param, value1);
1556 /* ...and the second one */
1557 if ((param = gda_parameter_list_find_param (par_list, param_key2)) == NULL)
1559 g_warning ("param is NULL from pquery!\n");
1560 return -1;
1563 gda_parameter_set_value (param, value2);
1565 /* ...and the third one */
1566 if ((param = gda_parameter_list_find_param (par_list, param_key3)) == NULL)
1568 g_warning ("param is NULL from pquery!\n");
1569 return -1;
1572 gda_parameter_set_value (param, value3);
1575 /* execute the query with parametes just set */
1576 GObject *obj =
1577 G_OBJECT (gda_query_execute ((GdaQuery *) query, par_list, FALSE,
1578 NULL));
1580 if (!GDA_IS_DATA_MODEL (obj) ||
1581 gda_data_model_get_n_rows (GDA_DATA_MODEL (obj)) <= 0)
1584 if (obj != NULL)
1585 g_object_unref (obj);
1586 return -1;
1589 /* get and parse the results. */
1590 num = gda_data_model_get_value_at (GDA_DATA_MODEL (obj), 0, 0);
1592 table_id = g_value_get_int (num);
1593 g_object_unref (obj);
1594 return table_id;
1598 gboolean
1599 symbol_db_engine_add_new_workspace (SymbolDBEngine * dbe,
1600 gchar * workspace_name)
1603 CREATE TABLE workspace (workspace_id integer PRIMARY KEY AUTOINCREMENT,
1604 workspace_name varchar (50) not null unique,
1605 analize_time DATE
1608 const GdaQuery *query;
1609 GdaParameterList *par_list;
1610 GdaParameter *param;
1611 GValue *value;
1612 SymbolDBEnginePriv *priv;
1614 priv = dbe->priv;
1616 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
1618 if ((query =
1619 sdb_engine_get_query_by_id (dbe, PREP_QUERY_WORKSPACE_NEW)) == NULL)
1621 g_warning ("query is null");
1622 return FALSE;
1625 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
1626 gda_query_get_query_type ((GdaQuery *) query))
1628 g_warning ("non parsed sql error");
1629 return FALSE;
1632 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1634 g_warning ("par_list is NULL!\n");
1635 return FALSE;
1638 if ((param = gda_parameter_list_find_param (par_list, "wsname")) == NULL)
1640 g_warning ("param is NULL from pquery!\n");
1641 return FALSE;
1644 value = gda_value_new (G_TYPE_STRING);
1645 g_value_set_string (value, workspace_name);
1647 gda_parameter_set_value (param, value);
1649 /* execute the query with parametes just set */
1650 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
1651 gda_value_free (value);
1653 return TRUE;
1657 * Return the name of the opened project.
1658 * NULL on error. Returned string must be freed by caller.
1660 gchar*
1661 symbol_db_engine_get_opened_project_name (SymbolDBEngine * dbe)
1663 SymbolDBEnginePriv *priv;
1664 g_return_val_if_fail (dbe != NULL, NULL);
1665 priv = dbe->priv;
1667 g_return_val_if_fail (priv->db_connection != NULL, NULL);
1669 return g_strdup (priv->project_name);
1673 * Open a new project.
1674 * It will test if project was correctly created.
1676 gboolean
1677 symbol_db_engine_open_project (SymbolDBEngine * dbe, /*gchar* workspace, */
1678 const gchar * project_name)
1680 GValue *value;
1681 SymbolDBEnginePriv *priv;
1682 gint prj_id;
1684 priv = dbe->priv;
1686 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
1687 if (symbol_db_engine_is_project_opened (dbe, project_name) == TRUE) {
1688 g_warning ("project already opened, %s (priv %s)", project_name,
1689 priv->project_name);
1690 return FALSE;
1693 value = gda_value_new (G_TYPE_STRING);
1694 g_value_set_string (value, project_name);
1696 /* test the existence of the project in db */
1697 if ((prj_id = sdb_engine_get_table_id_by_unique_name (dbe,
1698 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
1699 "prjname",
1700 value)) <= 0)
1702 gda_value_free (value);
1703 return FALSE;
1706 gda_value_free (value);
1708 /* open the project... */
1709 priv->project_name = g_strdup (project_name);
1711 return TRUE;
1715 gboolean
1716 symbol_db_engine_close_project (SymbolDBEngine *dbe, gchar* project_name)
1718 SymbolDBEnginePriv *priv;
1720 priv = dbe->priv;
1722 g_free (priv->project_name);
1723 priv->project_name = NULL;
1725 return sdb_engine_disconnect_from_db (dbe);
1730 * @param workspace Can be NULL. In that case a default workspace will be created,
1731 * and project will depend on that.
1732 * @param project Project name. Must NOT be NULL.
1734 // FIXME: file_include file_ignore
1735 gboolean
1736 symbol_db_engine_add_new_project (SymbolDBEngine * dbe, gchar * workspace,
1737 gchar * project)
1740 CREATE TABLE project (project_id integer PRIMARY KEY AUTOINCREMENT,
1741 project_name varchar (50) not null unique,
1742 wrkspace_id integer REFERENCES workspace (workspace_id),
1743 analize_time DATE
1746 const GdaQuery *query;
1747 GdaParameterList *par_list;
1748 GdaParameter *param;
1749 GValue *value;
1750 gchar *workspace_name;
1751 gint wks_id;
1752 SymbolDBEnginePriv *priv;
1754 g_return_val_if_fail (dbe != NULL, FALSE);
1756 priv = dbe->priv;
1758 if (symbol_db_engine_is_project_opened (dbe, project) == TRUE)
1760 g_warning ("You have an already opened project. Cannot continue.");
1761 return FALSE;
1764 if (workspace == NULL)
1766 workspace_name = "anjuta_workspace_default";
1768 DEBUG_PRINT ("adding default workspace...");
1769 if (symbol_db_engine_add_new_workspace (dbe, workspace_name) == FALSE)
1771 DEBUG_PRINT ("Project cannot be added because a default workspace "
1772 "cannot be created");
1773 return FALSE;
1776 else
1778 workspace_name = workspace;
1781 value = gda_value_new (G_TYPE_STRING);
1782 g_value_set_string (value, workspace_name);
1784 /* get workspace id */
1785 if ((wks_id = sdb_engine_get_table_id_by_unique_name (dbe,
1786 PREP_QUERY_GET_WORKSPACE_ID_BY_UNIQUE_NAME,
1787 "wsname",
1788 value)) <= 0)
1790 DEBUG_PRINT ("no workspace id");
1791 gda_value_free (value);
1792 return FALSE;
1795 /* insert new project */
1796 if ((query =
1797 sdb_engine_get_query_by_id (dbe, PREP_QUERY_PROJECT_NEW)) == NULL)
1799 g_warning ("query is null");
1800 gda_value_free (value);
1801 return FALSE;
1804 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
1805 gda_query_get_query_type ((GdaQuery *) query))
1807 g_warning ("non parsed sql error");
1808 gda_value_free (value);
1809 return FALSE;
1812 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1814 g_warning ("par_list is NULL!\n");
1815 gda_value_free (value);
1816 return FALSE;
1819 if ((param = gda_parameter_list_find_param (par_list, "prjname")) == NULL)
1821 g_warning ("param prjname is NULL from pquery!");
1822 gda_value_free (value);
1823 return FALSE;
1826 gda_value_reset_with_type (value, G_TYPE_STRING);
1827 g_value_set_string (value, project);
1828 gda_parameter_set_value (param, value);
1830 if ((param = gda_parameter_list_find_param (par_list, "wsid")) == NULL)
1832 g_warning ("param is NULL from pquery!");
1833 return FALSE;
1836 gda_value_reset_with_type (value, G_TYPE_INT);
1837 g_value_set_int (value, wks_id);
1839 gda_parameter_set_value (param, value);
1841 /* execute the query with parametes just set */
1842 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
1843 gda_value_free (value);
1845 return TRUE;
1849 static gint
1850 sdb_engine_add_new_language (SymbolDBEngine * dbe, const gchar *language)
1853 CREATE TABLE language (language_id integer PRIMARY KEY AUTOINCREMENT,
1854 language_name varchar (50) not null unique);
1856 gint table_id;
1857 GValue *value;
1859 g_return_val_if_fail (language != NULL, -1);
1861 value = gda_value_new (G_TYPE_STRING);
1862 g_value_set_string (value, language);
1864 /* check for an already existing table with language "name". */
1865 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
1866 PREP_QUERY_GET_LANGUAGE_ID_BY_UNIQUE_NAME,
1867 "langname",
1868 value)) < 0)
1871 /* insert a new entry on db */
1872 const GdaQuery *query;
1873 GdaParameterList *par_list;
1874 GdaParameter *param;
1875 GValue *value;
1877 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_LANGUAGE_NEW))
1878 == NULL)
1880 g_warning ("query is null");
1881 return FALSE;
1884 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
1885 gda_query_get_query_type ((GdaQuery *) query))
1887 g_warning ("non parsed sql error");
1888 return FALSE;
1891 if ((par_list =
1892 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1894 g_warning ("par_list is NULL!\n");
1895 return FALSE;
1898 if ((param =
1899 gda_parameter_list_find_param (par_list, "langname")) == NULL)
1901 g_warning ("param langname is NULL from pquery!");
1902 return FALSE;
1905 value = gda_value_new (G_TYPE_STRING);
1906 g_value_set_string (value, language);
1908 gda_parameter_set_value (param, value);
1909 gda_value_free (value);
1910 /* execute the query with parametes just set */
1911 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
1913 table_id = sdb_engine_get_last_insert_id (dbe);
1915 gda_value_free (value);
1916 return table_id;
1920 /* Add a file to project.
1921 * This function requires an opened db, i.e. calling before
1922 * symbol_db_engine_open_db ()
1923 * filepath: referes to a full file path.
1924 * WARNING: we suppose that project is already opened.
1926 static gboolean
1927 sdb_engine_add_new_file (SymbolDBEngine * dbe, const gchar * project,
1928 const gchar * filepath, const gchar * language)
1931 CREATE TABLE file (file_id integer PRIMARY KEY AUTOINCREMENT,
1932 file_path TEXT not null unique,
1933 prj_id integer REFERENCES project (projec_id),
1934 lang_id integer REFERENCES language (language_id),
1935 analize_time DATE
1938 SymbolDBEnginePriv *priv;
1939 gint project_id;
1940 gint language_id;
1941 gint file_id;
1942 GValue *value;
1944 priv = dbe->priv;
1946 value = gda_value_new (G_TYPE_STRING);
1947 g_value_set_string (value, project);
1949 /* check for an already existing table with project "project". */
1950 if ((project_id = sdb_engine_get_table_id_by_unique_name (dbe,
1951 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
1952 "prjname",
1953 value)) < 0)
1955 g_warning ("no project with that name exists");
1956 gda_value_free (value);
1957 return FALSE;
1960 gda_value_free (value);
1961 value = gda_value_new (G_TYPE_STRING);
1962 /* we're gonna set the file relative to the project folder, not the full one.
1963 * e.g.: we have a file on disk: "/tmp/foo/src/file.c" and a datasource located on
1964 * "/tmp/foo". The entry on db will be "src/file.c"
1966 g_value_set_string (value, filepath + strlen(priv->data_source));
1968 if ((file_id = sdb_engine_get_table_id_by_unique_name (dbe,
1969 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
1970 "filepath",
1971 value)) < 0)
1973 /* insert a new entry on db */
1974 const GdaQuery *query;
1975 GdaParameterList *par_list;
1976 GdaParameter *param;
1977 GValue *value;
1979 language_id = sdb_engine_add_new_language (dbe, language);
1981 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_FILE_NEW))
1982 == NULL)
1984 g_warning ("query is null");
1985 return FALSE;
1988 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
1989 gda_query_get_query_type ((GdaQuery *) query))
1991 g_warning ("non parsed sql error");
1992 return FALSE;
1995 if ((par_list =
1996 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
1998 g_warning ("par_list is NULL!\n");
1999 return FALSE;
2002 /* filepath parameter */
2003 if ((param =
2004 gda_parameter_list_find_param (par_list, "filepath")) == NULL)
2006 g_warning ("param filepath is NULL from pquery!");
2007 return FALSE;
2010 value = gda_value_new (G_TYPE_STRING);
2011 /* relative filepath */
2012 g_value_set_string (value, filepath + strlen(priv->data_source));
2013 gda_parameter_set_value (param, value);
2015 /* project id parameter */
2016 if ((param = gda_parameter_list_find_param (par_list, "prjid")) == NULL)
2018 g_warning ("param prjid is NULL from pquery!");
2019 return FALSE;
2022 gda_value_reset_with_type (value, G_TYPE_INT);
2023 g_value_set_int (value, project_id);
2024 gda_parameter_set_value (param, value);
2026 /* language id parameter */
2027 if ((param =
2028 gda_parameter_list_find_param (par_list, "langid")) == NULL)
2030 g_warning ("param langid is NULL from pquery!");
2031 return FALSE;
2034 gda_value_reset_with_type (value, G_TYPE_INT);
2035 g_value_set_int (value, language_id);
2036 gda_parameter_set_value (param, value);
2037 gda_value_free (value);
2039 /* execute the query with parametes just set */
2040 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2042 gda_value_free (value);
2044 return TRUE;
2048 static void
2049 sdb_prepare_executing_commands (SymbolDBEngine *dbe)
2051 GdaCommand *command;
2052 SymbolDBEnginePriv *priv;
2053 priv = dbe->priv;
2055 command = gda_command_new ("PRAGMA page_size = 4096", GDA_COMMAND_TYPE_SQL,
2056 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2057 gda_connection_execute_non_select_command (priv->db_connection,
2058 command, NULL, NULL);
2059 gda_command_free (command);
2061 command = gda_command_new ("PRAGMA cache_size = 10000", GDA_COMMAND_TYPE_SQL,
2062 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2063 gda_connection_execute_non_select_command (priv->db_connection,
2064 command, NULL, NULL);
2065 gda_command_free (command);
2067 command = gda_command_new ("PRAGMA synchronous = OFF", GDA_COMMAND_TYPE_SQL,
2068 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2069 gda_connection_execute_non_select_command (priv->db_connection,
2070 command, NULL, NULL);
2071 gda_command_free (command);
2073 command = gda_command_new ("PRAGMA temp_store = MEMORY", GDA_COMMAND_TYPE_SQL,
2074 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
2075 gda_connection_execute_non_select_command (priv->db_connection,
2076 command, NULL, NULL);
2077 gda_command_free (command);
2082 gboolean
2083 symbol_db_engine_add_new_files (SymbolDBEngine * dbe, const gchar * project,
2084 const GPtrArray * files_path, const gchar * language,
2085 gboolean scan_symbols)
2087 gint i;
2088 SymbolDBEnginePriv *priv;
2090 g_return_val_if_fail (dbe != NULL, FALSE);
2091 priv = dbe->priv;
2093 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
2094 g_return_val_if_fail (project != NULL, FALSE);
2096 /* FIXME try this... */
2097 //sdb_prepare_executing_commands (dbe);
2100 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
2102 g_warning ("your project isn't opened, %s (priv %s)", project,
2103 priv->project_name);
2104 return FALSE;
2107 for (i = 0; i < files_path->len; i++)
2109 gchar *node = (gchar *) g_ptr_array_index (files_path, i);
2111 /* test the existance of node file */
2112 if (g_file_test (node, G_FILE_TEST_EXISTS) == FALSE)
2114 g_warning ("File %s doesn't exist", node);
2115 continue;
2118 /* DEBUG_PRINT ("gonna adding symbols for %s", node);*/
2120 if (sdb_engine_add_new_file (dbe, project, node, language) == FALSE)
2122 g_warning ("Error processing file %s", node);
2123 return FALSE;
2128 /* perform the scan of files. It will spawn a fork() process with
2129 * AnjutaLauncher and ctags in server mode. After the ctags cmd has been
2130 * executed, the populating process'll take place.
2132 if (scan_symbols)
2133 return sdb_engine_scan_files_1 (dbe, files_path, NULL, FALSE);
2135 return TRUE;
2139 static gint
2140 sdb_engine_add_new_sym_type (SymbolDBEngine * dbe, tagEntry * tag_entry)
2143 CREATE TABLE sym_type (type_id integer PRIMARY KEY AUTOINCREMENT,
2144 type varchar (256) not null ,
2145 type_name varchar (256) not null ,
2146 unique (type, type_name)
2149 const gchar *type;
2150 const gchar *type_name;
2151 gint table_id;
2152 GValue *value1, *value2;
2154 g_return_val_if_fail (tag_entry != NULL, -1);
2156 type = tag_entry->kind;
2157 type_name = tag_entry->name;
2159 value1 = gda_value_new (G_TYPE_STRING);
2160 g_value_set_string (value1, type);
2162 value2 = gda_value_new (G_TYPE_STRING);
2163 g_value_set_string (value2, type_name);
2165 if ((table_id = sdb_engine_get_table_id_by_unique_name2 (dbe,
2166 PREP_QUERY_GET_SYM_TYPE_ID,
2167 "type", value1,
2168 "typename",
2169 value2)) < 0)
2171 const GdaQuery *query;
2172 GdaParameterList *par_list;
2173 GdaParameter *param;
2174 GValue *value;
2176 /* it does not exist. Create a new tuple. */
2177 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SYM_TYPE_NEW))
2178 == NULL)
2180 g_warning ("query is null");
2181 return -1;
2184 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2185 gda_query_get_query_type ((GdaQuery *) query))
2187 g_warning ("non parsed sql error");
2188 return -1;
2191 if ((par_list =
2192 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2194 g_warning ("par_list is NULL!\n");
2195 return -1;
2198 /* type parameter */
2199 if ((param = gda_parameter_list_find_param (par_list, "type")) == NULL)
2201 g_warning ("param type is NULL from pquery!");
2202 return -1;
2205 value = gda_value_new (G_TYPE_STRING);
2206 g_value_set_string (value, type);
2207 gda_parameter_set_value (param, value);
2209 /* type_name parameter */
2210 if ((param =
2211 gda_parameter_list_find_param (par_list, "typename")) == NULL)
2213 g_warning ("param typename is NULL from pquery!");
2214 return -1;
2217 gda_value_reset_with_type (value, G_TYPE_STRING);
2218 g_value_set_string (value, type_name);
2219 gda_parameter_set_value (param, value);
2220 gda_value_free (value);
2222 /* execute the query with parametes just set */
2223 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2225 table_id = sdb_engine_get_last_insert_id (dbe);
2228 gda_value_free (value1);
2229 gda_value_free (value2);
2231 return table_id;
2234 static gint
2235 sdb_engine_add_new_sym_kind (SymbolDBEngine * dbe, tagEntry * tag_entry)
2238 CREATE TABLE sym_kind (sym_kind_id integer PRIMARY KEY AUTOINCREMENT,
2239 kind_name varchar (50) not null unique
2242 const gchar *kind_name;
2243 gint table_id;
2244 GValue *value;
2246 g_return_val_if_fail (tag_entry != NULL, -1);
2248 kind_name = tag_entry->kind;
2250 /* no kind associated with current tag */
2251 if (kind_name == NULL)
2252 return -1;
2254 value = gda_value_new (G_TYPE_STRING);
2255 g_value_set_string (value, kind_name);
2257 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
2258 PREP_QUERY_GET_SYM_KIND_BY_UNIQUE_NAME,
2259 "kindname",
2260 value)) < 0)
2262 const GdaQuery *query;
2263 GdaParameterList *par_list;
2264 GdaParameter *param;
2265 GValue *value;
2267 /* not found. Go on with inserting */
2268 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SYM_KIND_NEW))
2269 == NULL)
2271 g_warning ("query is null");
2272 return -1;
2275 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2276 gda_query_get_query_type ((GdaQuery *) query))
2278 g_warning ("non parsed sql error");
2279 return -1;
2282 if ((par_list =
2283 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2285 g_warning ("par_list is NULL!\n");
2286 return -1;
2289 /* kindname parameter */
2290 if ((param =
2291 gda_parameter_list_find_param (par_list, "kindname")) == NULL)
2293 g_warning ("param kindname is NULL from pquery!");
2294 return -1;
2297 value = gda_value_new (G_TYPE_STRING);
2298 g_value_set_string (value, kind_name);
2299 gda_parameter_set_value (param, value);
2300 gda_value_free (value);
2302 /* execute the query with parametes just set */
2303 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2305 table_id = sdb_engine_get_last_insert_id (dbe);
2307 gda_value_free (value);
2308 return table_id;
2311 static gint
2312 sdb_engine_add_new_sym_access (SymbolDBEngine * dbe, tagEntry * tag_entry)
2315 CREATE TABLE sym_access (access_kind_id integer PRIMARY KEY AUTOINCREMENT,
2316 access_name varchar (50) not null unique
2319 const gchar *access;
2320 gint table_id;
2321 GValue *value;
2323 g_return_val_if_fail (tag_entry != NULL, -1);
2325 if ((access = tagsField (tag_entry, "access")) == NULL)
2327 /* no access associated with current tag */
2328 return -1;
2331 value = gda_value_new (G_TYPE_STRING);
2332 g_value_set_string (value, access);
2334 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
2335 PREP_QUERY_GET_SYM_ACCESS_BY_UNIQUE_NAME,
2336 "accesskind",
2337 value)) < 0)
2339 const GdaQuery *query;
2340 GdaParameterList *par_list;
2341 GdaParameter *param;
2342 GValue *value;
2344 /* not found. Go on with inserting */
2345 if ((query =
2346 sdb_engine_get_query_by_id (dbe,
2347 PREP_QUERY_SYM_ACCESS_NEW)) == NULL)
2349 g_warning ("query is null");
2350 return -1;
2353 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2354 gda_query_get_query_type ((GdaQuery *) query))
2356 g_warning ("non parsed sql error");
2357 return -1;
2360 if ((par_list =
2361 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2363 g_warning ("par_list is NULL!\n");
2364 return -1;
2367 /* accesskind parameter */
2368 if ((param =
2369 gda_parameter_list_find_param (par_list, "accesskind")) == NULL)
2371 g_warning ("param accesskind is NULL from pquery!");
2372 return -1;
2375 value = gda_value_new (G_TYPE_STRING);
2376 g_value_set_string (value, access);
2377 gda_parameter_set_value (param, value);
2378 gda_value_free (value);
2380 /* execute the query with parametes just set */
2381 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2383 table_id = sdb_engine_get_last_insert_id (dbe);
2385 gda_value_free (value);
2386 return table_id;
2389 static gint
2390 sdb_engine_add_new_sym_implementation (SymbolDBEngine * dbe,
2391 tagEntry * tag_entry)
2394 CREATE TABLE sym_implementation (sym_impl_id integer PRIMARY KEY AUTOINCREMENT,
2395 implementation_name varchar (50) not null unique
2398 const gchar *implementation;
2399 gint table_id;
2400 GValue *value;
2402 g_return_val_if_fail (tag_entry != NULL, -1);
2404 if ((implementation = tagsField (tag_entry, "implementation")) == NULL)
2406 /* no implementation associated with current tag */
2407 return -1;
2410 value = gda_value_new (G_TYPE_STRING);
2411 g_value_set_string (value, implementation);
2413 if ((table_id = sdb_engine_get_table_id_by_unique_name (dbe,
2414 PREP_QUERY_GET_SYM_IMPLEMENTATION_BY_UNIQUE_NAME,
2415 "implekind",
2416 value)) < 0)
2418 const GdaQuery *query;
2419 GdaParameterList *par_list;
2420 GdaParameter *param;
2421 GValue *value;
2423 /* not found. Go on with inserting */
2424 if ((query =
2425 sdb_engine_get_query_by_id (dbe,
2426 PREP_QUERY_SYM_IMPLEMENTATION_NEW)) ==
2427 NULL)
2429 g_warning ("query is null");
2430 return -1;
2433 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2434 gda_query_get_query_type ((GdaQuery *) query))
2436 g_warning ("non parsed sql error");
2437 return -1;
2440 if ((par_list =
2441 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2443 g_warning ("par_list is NULL!\n");
2444 return -1;
2447 /* implekind parameter */
2448 if ((param =
2449 gda_parameter_list_find_param (par_list, "implekind")) == NULL)
2451 g_warning ("param implekind is NULL from pquery!");
2452 return -1;
2455 value = gda_value_new (G_TYPE_STRING);
2456 g_value_set_string (value, implementation);
2457 gda_parameter_set_value (param, value);
2458 gda_value_free (value);
2460 /* execute the query with parametes just set */
2461 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2463 table_id = sdb_engine_get_last_insert_id (dbe);
2465 gda_value_free (value);
2466 return table_id;
2470 static void
2471 sdb_engine_add_new_heritage (SymbolDBEngine * dbe, gint base_symbol_id,
2472 gint derived_symbol_id)
2475 CREATE TABLE heritage (symbol_id_base integer REFERENCES symbol (symbol_id),
2476 symbol_id_derived integer REFERENCES symbol (symbol_id),
2477 PRIMARY KEY (symbol_id_base, symbol_id_derived)
2480 const GdaQuery *query;
2481 GdaParameterList *par_list;
2482 GdaParameter *param;
2483 GValue *value;
2485 g_return_if_fail (base_symbol_id > 0);
2486 g_return_if_fail (derived_symbol_id > 0);
2488 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_HERITAGE_NEW))
2489 == NULL)
2491 g_warning ("query is null");
2492 return;
2495 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2496 gda_query_get_query_type ((GdaQuery *) query))
2498 g_warning ("non parsed sql error");
2499 return;
2502 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2504 g_warning ("par_list is NULL!\n");
2505 return;
2508 /* symbase parameter */
2509 if ((param = gda_parameter_list_find_param (par_list, "symbase")) == NULL)
2511 g_warning ("param symbase is NULL from pquery!");
2512 return;
2515 value = gda_value_new (G_TYPE_INT);
2516 g_value_set_int (value, base_symbol_id);
2517 gda_parameter_set_value (param, value);
2519 /* symderived id parameter */
2520 if ((param =
2521 gda_parameter_list_find_param (par_list, "symderived")) == NULL)
2523 g_warning ("param symderived is NULL from pquery!");
2524 return;
2527 gda_value_reset_with_type (value, G_TYPE_INT);
2528 g_value_set_int (value, derived_symbol_id);
2529 gda_parameter_set_value (param, value);
2530 gda_value_free (value);
2532 /* execute the query with parametes just set */
2533 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2537 static gint
2538 sdb_engine_add_new_scope_definition (SymbolDBEngine * dbe, tagEntry * tag_entry)
2541 CREATE TABLE scope (scope_id integer PRIMARY KEY AUTOINCREMENT,
2542 scope varchar(256) not null,
2543 type_id integer REFERENCES sym_type (type_id),
2544 unique (scope, type_id)
2547 const gchar *scope;
2548 GValue *value1, *value2;
2549 gint type_table_id, table_id;
2551 g_return_val_if_fail (tag_entry != NULL, -1);
2552 g_return_val_if_fail (tag_entry->kind != NULL, -1);
2554 /* This symbol will define a scope which name is tag_entry->name
2555 * For example if we get a tag MyFoo with kind "namespace", it will define
2556 * the "MyFoo" scope, which type is "namespace MyFoo"
2558 scope = tag_entry->name;
2560 /* filter out 'variable' and 'member' kinds. They define no scope. */
2561 if (strcmp (tag_entry->kind, "variable") == 0 ||
2562 strcmp (tag_entry->kind, "member") == 0)
2564 return -1;
2567 value1 = gda_value_new (G_TYPE_STRING);
2568 g_value_set_string (value1, tag_entry->kind);
2570 value2 = gda_value_new (G_TYPE_STRING);
2571 g_value_set_string (value2, scope);
2573 /* search for type_id on sym_type table */
2574 if ((type_table_id = sdb_engine_get_table_id_by_unique_name2 (dbe,
2575 PREP_QUERY_GET_SYM_TYPE_ID,
2576 "type",
2577 value1,
2578 "typename",
2579 value2)) < 0)
2581 /* no type has been found. */
2582 gda_value_free (value1);
2583 gda_value_free (value2);
2585 return -1;
2588 /* let's check for an already present scope table with scope and type_id infos. */
2589 gda_value_reset_with_type (value1, G_TYPE_STRING);
2590 g_value_set_string (value1, scope);
2592 gda_value_reset_with_type (value2, G_TYPE_INT);
2593 g_value_set_int (value2, type_table_id);
2595 if ((table_id = sdb_engine_get_table_id_by_unique_name2 (dbe,
2596 PREP_QUERY_GET_SCOPE_ID,
2597 "scope", value1,
2598 "typeid",
2599 value2)) < 0)
2601 /* no luck. A table with the pair scope and type_id is not present.
2602 * ok, let's insert out new scope table.
2604 const GdaQuery *query;
2605 GdaParameterList *par_list;
2606 GdaParameter *param;
2607 GValue *value;
2609 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SCOPE_NEW))
2610 == NULL)
2612 g_warning ("query is null");
2613 return -1;
2616 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2617 gda_query_get_query_type ((GdaQuery *) query))
2619 g_warning ("non parsed sql error");
2620 return -1;
2623 if ((par_list =
2624 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2626 g_warning ("par_list is NULL!\n");
2627 return -1;
2630 /* scope parameter */
2631 if ((param = gda_parameter_list_find_param (par_list, "scope")) == NULL)
2633 g_warning ("param scope is NULL from pquery!");
2634 return -1;
2637 value = gda_value_new (G_TYPE_STRING);
2638 g_value_set_string (value, scope);
2639 gda_parameter_set_value (param, value);
2641 /* typeid parameter */
2642 if ((param =
2643 gda_parameter_list_find_param (par_list, "typeid")) == NULL)
2645 g_warning ("param typeid is NULL from pquery!");
2646 return -1;
2649 gda_value_reset_with_type (value, G_TYPE_INT);
2650 g_value_set_int (value, type_table_id);
2651 gda_parameter_set_value (param, value);
2652 gda_value_free (value);
2654 /* execute the query with parametes just set */
2655 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2657 table_id = sdb_engine_get_last_insert_id (dbe);
2660 gda_value_free (value1);
2661 gda_value_free (value2);
2662 return table_id;
2666 * Saves the tagEntry info for a second pass parsing.
2667 * Usually we don't know all the symbol at the first scan of the tags. We need
2668 * a second one. These tuples are created for that purpose.
2670 * @return the table_id of the inserted tuple. -1 on error.
2672 static gint
2673 sdb_engine_add_new_tmp_heritage_scope (SymbolDBEngine * dbe,
2674 tagEntry * tag_entry,
2675 gint symbol_referer_id)
2678 CREATE TABLE __tmp_heritage_scope (tmp_heritage_scope_id integer PRIMARY KEY
2679 AUTOINCREMENT,
2680 symbol_referer_id integer not null,
2681 field_inherits varchar(256) not null,
2682 field_struct varchar(256),
2683 field_typeref varchar(256),
2684 field_enum varchar(256),
2685 field_union varchar(256),
2686 field_class varchar(256),
2687 field_namespace varchar(256)
2690 const GdaQuery *query;
2691 GdaParameterList *par_list;
2692 GdaParameter *param;
2693 gint table_id;
2694 GValue *value;
2695 const gchar *field_inherits, *field_struct, *field_typeref,
2696 *field_enum, *field_union, *field_class, *field_namespace;
2697 gboolean good_tag;
2699 g_return_val_if_fail (tag_entry != NULL, -1);
2701 /* init the flag */
2702 good_tag = FALSE;
2704 if ((field_inherits = tagsField (tag_entry, "inherits")) == NULL)
2706 field_inherits = "";
2708 else
2709 good_tag = TRUE;
2711 if ((field_struct = tagsField (tag_entry, "struct")) == NULL)
2713 field_struct = "";
2715 else
2716 good_tag = TRUE;
2718 if ((field_typeref = tagsField (tag_entry, "typeref")) == NULL)
2720 field_typeref = "";
2722 else
2723 good_tag = TRUE;
2725 if ((field_enum = tagsField (tag_entry, "enum")) == NULL)
2727 field_enum = "";
2729 else
2730 good_tag = TRUE;
2732 if ((field_union = tagsField (tag_entry, "union")) == NULL)
2734 field_union = "";
2736 else
2737 good_tag = TRUE;
2739 if ((field_class = tagsField (tag_entry, "class")) == NULL)
2741 field_class = "";
2743 else
2744 good_tag = TRUE;
2746 if ((field_namespace = tagsField (tag_entry, "namespace")) == NULL)
2748 field_namespace = "";
2750 else
2751 good_tag = TRUE;
2753 if (!good_tag)
2754 return -1;
2757 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_TMP_HERITAGE_NEW))
2758 == NULL)
2760 g_warning ("query is null");
2761 return -1;
2764 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
2765 gda_query_get_query_type ((GdaQuery *) query))
2767 g_warning ("non parsed sql error");
2768 return -1;
2771 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2773 g_warning ("par_list is NULL!\n");
2774 return -1;
2777 /* symreferid parameter */
2778 if ((param =
2779 gda_parameter_list_find_param (par_list, "symreferid")) == NULL)
2781 g_warning ("param symreferid is NULL from pquery!");
2782 return -1;
2785 value = gda_value_new (G_TYPE_INT);
2786 g_value_set_int (value, symbol_referer_id);
2787 gda_parameter_set_value (param, value);
2789 /* finherits parameter */
2790 if ((param = gda_parameter_list_find_param (par_list, "finherits")) == NULL)
2792 g_warning ("param finherits is NULL from pquery!");
2793 return -1;
2796 gda_value_reset_with_type (value, G_TYPE_STRING);
2797 g_value_set_string (value, field_inherits);
2798 gda_parameter_set_value (param, value);
2800 /* fstruct parameter */
2801 if ((param = gda_parameter_list_find_param (par_list, "fstruct")) == NULL)
2803 g_warning ("param fstruct is NULL from pquery!");
2804 return -1;
2807 gda_value_reset_with_type (value, G_TYPE_STRING);
2808 g_value_set_string (value, field_struct);
2809 gda_parameter_set_value (param, value);
2811 /* ftyperef parameter */
2812 if ((param = gda_parameter_list_find_param (par_list, "ftyperef")) == NULL)
2814 g_warning ("param ftyperef is NULL from pquery!");
2815 return -1;
2818 gda_value_reset_with_type (value, G_TYPE_STRING);
2819 g_value_set_string (value, field_typeref);
2820 gda_parameter_set_value (param, value);
2822 /* fenum parameter */
2823 if ((param = gda_parameter_list_find_param (par_list, "fenum")) == NULL)
2825 g_warning ("param fenum is NULL from pquery!");
2826 return -1;
2829 gda_value_reset_with_type (value, G_TYPE_STRING);
2830 g_value_set_string (value, field_enum);
2831 gda_parameter_set_value (param, value);
2833 /* funion parameter */
2834 if ((param = gda_parameter_list_find_param (par_list, "funion")) == NULL)
2836 g_warning ("param funion is NULL from pquery!");
2837 return -1;
2840 gda_value_reset_with_type (value, G_TYPE_STRING);
2841 g_value_set_string (value, field_union);
2842 gda_parameter_set_value (param, value);
2844 /* fclass parameter */
2845 if ((param = gda_parameter_list_find_param (par_list, "fclass")) == NULL)
2847 g_warning ("param fclass is NULL from pquery!");
2848 return -1;
2851 gda_value_reset_with_type (value, G_TYPE_STRING);
2852 g_value_set_string (value, field_class);
2853 gda_parameter_set_value (param, value);
2855 /* fnamespace parameter */
2856 if ((param =
2857 gda_parameter_list_find_param (par_list, "fnamespace")) == NULL)
2859 g_warning ("param fnamespace is NULL from pquery!");
2860 return -1;
2863 gda_value_reset_with_type (value, G_TYPE_STRING);
2864 g_value_set_string (value, field_namespace);
2865 gda_parameter_set_value (param, value);
2866 gda_value_free (value);
2869 /* execute the query with parametes just set */
2870 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
2872 table_id = sdb_engine_get_last_insert_id (dbe);
2873 return table_id;
2876 static gboolean
2877 sdb_engine_second_pass_update_scope_1 (SymbolDBEngine * dbe,
2878 GdaDataModel * data, gint data_row,
2879 gchar * token_name,
2880 const GValue * token_value)
2882 gint scope_id;
2883 GValue *value1, *value2, *value;
2884 const GValue *value_id2;
2885 gint symbol_id;
2886 const gchar *tmp_str;
2887 gchar **tmp_str_splitted;
2888 gint tmp_str_splitted_length;
2889 gchar *object_name = NULL;
2890 gboolean free_token_name = FALSE;
2891 const GdaQuery *query;
2892 GdaParameterList *par_list;
2893 GdaParameter *param;
2895 g_return_val_if_fail (G_VALUE_HOLDS_STRING (token_value), FALSE);
2897 tmp_str = g_value_get_string (token_value);
2899 /* we don't need empty strings */
2900 if (strcmp (tmp_str, "") == 0)
2901 return FALSE;
2903 /* we could have something like "First::Second::Third::Fourth" as tmp_str, so
2904 * take only the lastscope, in this case 'Fourth'.
2906 tmp_str_splitted = g_strsplit (tmp_str, ":", 0);
2907 tmp_str_splitted_length = g_strv_length (tmp_str_splitted);
2909 if (tmp_str_splitted_length > 0)
2911 /* handle special typedef case. Usually we have something like struct:my_foo.
2912 * splitting we have [0]-> struct [1]-> my_foo
2914 if (strcmp (token_name, "typedef") == 0)
2916 free_token_name = TRUE;
2917 token_name = g_strdup (tmp_str_splitted[0]);
2920 object_name = g_strdup (tmp_str_splitted[tmp_str_splitted_length - 1]);
2922 else
2924 g_strfreev (tmp_str_splitted);
2925 return FALSE;
2928 g_strfreev (tmp_str_splitted);
2930 /* DEBUG_PRINT ("2nd pass scope: got %s %s (from %s)", token_name, object_name,
2931 * tmp_str);
2934 value1 = gda_value_new (G_TYPE_STRING);
2935 g_value_set_string (value1, token_name);
2937 value2 = gda_value_new (G_TYPE_STRING);
2938 g_value_set_string (value2, object_name);
2940 if ((scope_id = sdb_engine_get_table_id_by_unique_name2 (dbe,
2941 PREP_QUERY_GET_SYMBOL_SCOPE_DEFINITION_ID,
2942 "tokenname",
2943 value1,
2944 "objectname",
2945 value2)) < 0)
2947 if (free_token_name)
2948 g_free (token_name);
2950 gda_value_free (value1);
2951 gda_value_free (value2);
2952 return FALSE;
2954 gda_value_free (value1);
2955 gda_value_free (value2);
2957 if (free_token_name)
2958 g_free (token_name);
2960 /* if we reach this point we should have a good scope_id.
2961 * Go on with symbol updating.
2963 value_id2 = gda_data_model_get_value_at_col_name (data, "symbol_referer_id",
2964 data_row);
2965 symbol_id = g_value_get_int (value_id2);
2967 if ((query = sdb_engine_get_query_by_id (dbe,
2968 PREP_QUERY_UPDATE_SYMBOL_SCOPE_ID))
2969 == NULL)
2971 g_warning ("query is null");
2972 return FALSE;
2975 if (GDA_QUERY_TYPE_NON_PARSED_SQL
2976 == gda_query_get_query_type ((GdaQuery *) query))
2978 g_warning ("non parsed sql error");
2979 return FALSE;
2982 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
2984 g_warning ("par_list is NULL!\n");
2985 return FALSE;
2988 /* scopeid parameter */
2989 if ((param = gda_parameter_list_find_param (par_list, "scopeid")) == NULL)
2991 g_warning ("param scopeid is NULL from pquery!");
2992 return FALSE;
2995 value = gda_value_new (G_TYPE_INT);
2996 g_value_set_int (value, scope_id);
2997 gda_parameter_set_value (param, value);
2999 /* symbolid parameter */
3000 if ((param = gda_parameter_list_find_param (par_list, "symbolid")) == NULL)
3002 g_warning ("param symbolid is NULL from pquery!");
3003 return FALSE;
3006 gda_value_reset_with_type (value, G_TYPE_INT);
3007 g_value_set_int (value, symbol_id);
3008 gda_parameter_set_value (param, value);
3009 gda_value_free (value);
3011 /* execute the query with parametes just set */
3012 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
3014 return TRUE;
3019 * @param data Must be filled with some values. It must have num_rows > 0
3020 * @note *CALL THIS BEFORE second_pass_update_heritage ()*
3021 * @note *DO NOT FREE data* inside this function.
3023 static void
3024 sdb_engine_second_pass_update_scope (SymbolDBEngine * dbe, GdaDataModel * data)
3027 * Fill up the scope.
3028 * The case: "my_foo_func_1" is the name of the current tag parsed.
3029 * Suppose we have a namespace MyFooNamespace, under which is declared
3030 * a class MyFooClass. Under that class there are some funcs like
3031 * my_foo_func_1 () etc. ctags will present us this info about
3032 * my_foo_func_1 ():
3033 * "class : MyFooNamespace::MyFooClass"
3034 * but hey! We don't need to know the namespace here, we just want to
3035 * know that my_foo_func_1 is in the scope of MyFooClass. That one will
3036 * then be mapped inside MyFooNamespace, but that's another thing.
3037 * Go on with the parsing then.
3039 gint i;
3041 for (i = 0; i < gda_data_model_get_n_rows (data); i++)
3043 GValue *value;
3045 if ((value =
3046 (GValue *) gda_data_model_get_value_at_col_name (data,
3047 "field_class",
3048 i)) != NULL)
3050 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "class",
3051 value);
3054 if ((value =
3055 (GValue *) gda_data_model_get_value_at_col_name (data,
3056 "field_struct",
3057 i)) != NULL)
3059 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "struct",
3060 value);
3063 if ((value =
3064 (GValue *) gda_data_model_get_value_at_col_name (data,
3065 "field_typeref",
3066 i)) != NULL)
3068 /* this is a "typedef", not a "typeref". */
3069 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "typedef",
3070 value);
3073 if ((value =
3074 (GValue *) gda_data_model_get_value_at_col_name (data,
3075 "field_enum",
3076 i)) != NULL)
3078 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "enum", value);
3081 if ((value =
3082 (GValue *) gda_data_model_get_value_at_col_name (data,
3083 "field_union",
3084 i)) != NULL)
3086 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "union",
3087 value);
3090 if ((value =
3091 (GValue *) gda_data_model_get_value_at_col_name (data,
3092 "field_namespace",
3093 i)) != NULL)
3095 sdb_engine_second_pass_update_scope_1 (dbe, data, i, "namespace",
3096 value);
3103 * @param data Must be filled with some values. It must have num_rows > 0
3104 * @note *CALL THIS AFTER second_pass_update_scope ()*
3106 static void
3107 sdb_engine_second_pass_update_heritage (SymbolDBEngine * dbe,
3108 GdaDataModel * data)
3110 gint i;
3111 SymbolDBEnginePriv *priv;
3113 g_return_if_fail (dbe != NULL);
3115 priv = dbe->priv;
3117 for (i = 0; i < gda_data_model_get_n_rows (data); i++)
3119 const GValue *value;
3120 const gchar *inherits;
3121 gchar *item;
3122 gchar **inherits_list;
3123 gint j;
3125 value = gda_data_model_get_value_at_col_name (data,
3126 "field_inherits", i);
3127 inherits = g_value_get_string (value);
3129 /* there can be multiple inheritance. Check that. */
3130 inherits_list = g_strsplit (inherits, ",", 0);
3132 if (inherits_list != NULL)
3133 DEBUG_PRINT ("inherits %s\n", inherits);
3135 /* retrieve as much info as we can from the items */
3136 for (j = 0; j < g_strv_length (inherits_list); j++)
3138 gchar **namespaces;
3139 gchar *klass_name;
3140 gchar *namespace_name;
3141 gint namespaces_length;
3142 gint base_klass_id;
3143 gint derived_klass_id;
3144 const GValue *value;
3146 item = inherits_list[j];
3147 DEBUG_PRINT ("heritage %s\n", item);
3149 /* A item may have this string form:
3150 * MyFooNamespace1::MyFooNamespace2::MyFooClass
3151 * We should find the field 'MyFooNamespace2' because it's the one
3152 * that is reachable by the scope_id value of the symbol.
3155 namespaces = g_strsplit (item, "::", 0);
3156 namespaces_length = g_strv_length (namespaces);
3158 if (namespaces_length > 1)
3160 /* this is the case in which we have the case with
3161 * namespace + class
3163 namespace_name = g_strdup (namespaces[namespaces_length - 2]);
3164 klass_name = g_strdup (namespaces[namespaces_length - 1]);
3166 else
3168 /* have a last check before setting namespace_name to null.
3169 * check whether the field_namespace is void or not.
3171 const GValue *namespace_value;
3172 const gchar *tmp_namespace;
3173 gchar **tmp_namespace_array = NULL;
3174 gint tmp_namespace_length;
3176 namespace_value =
3177 gda_data_model_get_value_at_col_name (data,
3178 "field_namespace", i);
3179 tmp_namespace = g_value_get_string (namespace_value);
3180 if (tmp_namespace != NULL)
3182 tmp_namespace_array = g_strsplit (tmp_namespace, "::", 0);
3183 tmp_namespace_length = g_strv_length (tmp_namespace_array);
3185 if (tmp_namespace_length > 0)
3186 namespace_name =
3187 g_strdup (tmp_namespace_array
3188 [tmp_namespace_length - 1]);
3189 else
3190 namespace_name = NULL;
3192 else
3194 namespace_name = NULL;
3197 klass_name = g_strdup (namespaces[namespaces_length - 1]);
3199 g_strfreev (tmp_namespace_array);
3202 g_strfreev (namespaces);
3204 /* get the derived_klass_id. It should be the
3205 * symbol_referer_id field into __tmp_heritage_scope table
3207 if ((value = (GValue *) gda_data_model_get_value_at (data,
3208 1, i)) != NULL)
3210 derived_klass_id = g_value_get_int (value);
3212 else
3214 derived_klass_id = 0;
3217 /* ok, search for the symbol_id of the base class */
3218 if (namespace_name == NULL)
3220 GValue *value1;
3222 value1 = gda_value_new (G_TYPE_STRING);
3223 g_value_set_string (value1, klass_name);
3225 if ((base_klass_id =
3226 sdb_engine_get_table_id_by_unique_name (dbe,
3227 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME,
3228 "klassname",
3229 value1)) < 0)
3231 gda_value_free (value1);
3232 continue;
3234 gda_value_free (value1);
3236 else
3238 /* FIXME:
3239 when Libgda will parse correctly the PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE
3240 query please uncomment this section and let the prepared statements do their
3241 work.
3242 GValue *value1;
3243 GValue *value2;
3245 value1 = gda_value_new (G_TYPE_STRING);
3246 g_value_set_string (value1, klass_name);
3248 value2 = gda_value_new (G_TYPE_STRING);
3249 g_value_set_string (value2, namespace_name);
3251 DEBUG_PRINT ("value1 : %s value2 : %s", klass_name, namespace_name);
3252 if ((base_klass_id =
3253 sdb_engine_get_table_id_by_unique_name2 (dbe,
3254 PREP_QUERY_GET_SYMBOL_ID_BY_CLASS_NAME_AND_NAMESPACE,
3255 "klassname",
3256 value1,
3257 "namespacename",
3258 value2)) < 0)
3260 gda_value_free (value1);
3261 gda_value_free (value2);
3262 continue;
3264 gda_value_free (value1);
3265 gda_value_free (value2);
3267 GValue *value1;
3268 GdaCommand *command;
3269 GdaDataModel *base_data;
3270 gchar *query_str;
3271 query_str =
3272 g_strdup_printf ("SELECT symbol_id FROM symbol JOIN scope ON "
3273 "symbol.scope_id=scope.scope_id JOIN sym_type ON "
3274 "scope.type_id=sym_type.type_id WHERE "
3275 "symbol.name='%s' AND scope.scope='%s' AND "
3276 "sym_type.type='namespace'",
3277 klass_name, namespace_name);
3279 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
3280 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
3282 if ( (base_data =
3283 gda_connection_execute_select_command (priv->db_connection,
3284 command, NULL,
3285 NULL)) == NULL ||
3286 gda_data_model_get_n_rows (base_data) <= 0 )
3288 gda_command_free (command);
3289 g_free (query_str);
3291 if (base_data != NULL)
3292 g_object_unref (base_data);
3294 continue;
3297 value1 = (GValue*)gda_data_model_get_value_at (base_data, 0, 0);
3298 base_klass_id = g_value_get_int (value1);
3299 DEBUG_PRINT ("found base_klass_id %d", base_klass_id );
3300 gda_command_free (command);
3301 g_free (query_str);
3303 if (base_data != NULL)
3304 g_object_unref (base_data);
3307 g_free (namespace_name);
3308 g_free (klass_name);
3310 DEBUG_PRINT ("gonna sdb_engine_add_new_heritage with "
3311 "base_klass_id %d, derived_klass_id %d", base_klass_id,
3312 derived_klass_id);
3313 sdb_engine_add_new_heritage (dbe, base_klass_id, derived_klass_id);
3316 g_strfreev (inherits_list);
3321 * Process the temporary table to update the symbols on scope and inheritance
3322 * fields.
3323 * *CALL THIS FUNCTION ONLY AFTER HAVING PARSED ALL THE TAGS ONCE*
3326 static void
3327 sdb_engine_second_pass_do (SymbolDBEngine * dbe)
3329 GObject *obj;
3330 const GdaQuery *query1, *query2, *query3;
3332 /* prepare for scope second scan */
3333 if ((query1 =
3334 sdb_engine_get_query_by_id (dbe,
3335 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE))
3336 == NULL)
3338 g_warning ("query is null");
3339 return;
3342 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3343 gda_query_get_query_type ((GdaQuery *) query1))
3345 g_warning ("non parsed sql error");
3346 return;
3349 /* execute the query */
3350 obj = G_OBJECT (gda_query_execute ((GdaQuery *) query1, NULL, FALSE, NULL));
3352 if (!GDA_IS_DATA_MODEL (obj) ||
3353 gda_data_model_get_n_rows (GDA_DATA_MODEL (obj)) <= 0)
3356 if (obj != NULL)
3357 g_object_unref (obj);
3358 obj = NULL;
3360 else
3362 sdb_engine_second_pass_update_scope (dbe, GDA_DATA_MODEL (obj));
3365 if (obj != NULL)
3366 g_object_unref (obj);
3368 /* prepare for heritage second scan */
3369 if ((query2 =
3370 sdb_engine_get_query_by_id (dbe,
3371 PREP_QUERY_GET_ALL_FROM_TMP_HERITAGE_WITH_INHERITS))
3372 == NULL)
3374 g_warning ("query is null");
3375 return;
3378 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3379 gda_query_get_query_type ((GdaQuery *) query2))
3381 g_warning ("non parsed sql error");
3382 return;
3385 /* execute the query */
3386 obj = G_OBJECT (gda_query_execute ((GdaQuery *) query2, NULL, FALSE, NULL));
3388 if (!GDA_IS_DATA_MODEL (obj) ||
3389 gda_data_model_get_n_rows (GDA_DATA_MODEL (obj)) <= 0)
3391 if (obj != NULL)
3392 g_object_unref (obj);
3393 obj = NULL;
3395 else
3397 sdb_engine_second_pass_update_heritage (dbe, GDA_DATA_MODEL (obj));
3400 if (obj != NULL)
3401 g_object_unref (obj);
3404 /* clean tmp heritage table */
3405 if ((query3 =
3406 sdb_engine_get_query_by_id (dbe,
3407 PREP_QUERY_TMP_HERITAGE_DELETE_ALL))
3408 == NULL)
3410 g_warning ("query is null");
3411 return;
3414 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3415 gda_query_get_query_type ((GdaQuery *) query3))
3417 g_warning ("non parsed sql error");
3418 return;
3421 /* execute the query */
3422 gda_query_execute ((GdaQuery *) query3, NULL, FALSE, NULL);
3425 /* base_prj_path can be NULL. In that case path info tag_entry will be taken
3426 * as an absolute path.
3427 * fake_file can be used when a buffer updating is being executed. In that
3428 * particular case both base_prj_path and tag_entry->file will be ignored.
3429 * fake_file is real_path of file on disk
3431 static gint
3432 sdb_engine_add_new_symbol (SymbolDBEngine * dbe, tagEntry * tag_entry,
3433 gchar * base_prj_path, gchar * fake_file,
3434 gboolean sym_update)
3437 CREATE TABLE symbol (symbol_id integer PRIMARY KEY AUTOINCREMENT,
3438 file_defined_id integer not null REFERENCES file (file_id),
3439 name varchar (256) not null,
3440 file_position integer,
3441 is_file_scope integer,
3442 signature varchar (256),
3443 scope_definition_id integer,
3444 scope_id integer,
3445 type_id integer REFERENCES sym_type (type_id),
3446 kind_id integer REFERENCES sym_kind (sym_kind_id),
3447 access_kind_id integer REFERENCES sym_access (sym_access_id),
3448 implementation_kind_id integer REFERENCES sym_implementation
3449 (sym_impl_id)
3452 SymbolDBEnginePriv *priv;
3453 const GdaQuery *query;
3454 GdaParameterList *par_list;
3455 GdaParameter *param;
3456 const gchar *tmp_str;
3457 gint table_id, symbol_id;
3458 gint file_defined_id = 0;
3459 gchar name[256];
3460 gint file_position = 0;
3461 gint is_file_scope = 0;
3462 gchar signature[256];
3463 gint scope_definition_id = 0;
3464 gint scope_id = 0;
3465 gint type_id = 0;
3466 gint kind_id = 0;
3467 gint access_kind_id = 0;
3468 gint implementation_kind_id = 0;
3469 GValue *value, *value1, *value2, *value3;
3470 gboolean sym_was_updated = FALSE;
3472 gint update_flag;
3474 g_return_val_if_fail (dbe != NULL, -1);
3475 priv = dbe->priv;
3477 /* keep it at 0 if sym_update == false */
3478 if (sym_update == FALSE)
3479 update_flag = 0;
3480 else
3481 update_flag = 1;
3483 g_return_val_if_fail (tag_entry != NULL, -1);
3485 value = gda_value_new (G_TYPE_STRING);
3486 if (base_prj_path != NULL)
3488 /* in this case fake_file will be ignored. */
3490 /* we expect here an absolute path */
3491 g_value_set_string (value,
3492 tag_entry->file + strlen (base_prj_path) );
3494 else
3496 /* check whether the fake_file can substitute the tag_entry->file one */
3497 if (fake_file == NULL)
3498 g_value_set_string (value, tag_entry->file);
3499 else
3500 g_value_set_string (value, fake_file);
3503 if ((file_defined_id = sdb_engine_get_table_id_by_unique_name (dbe,
3504 PREP_QUERY_GET_FILE_ID_BY_UNIQUE_NAME,
3505 "filepath",
3506 value)) < 0)
3508 /* if we arrive here there should be some sync problems between the filenames
3509 * in database and the ones in the ctags files. We trust in db's ones,
3510 * so we'll just return here.
3512 g_warning ("sync problems between db and ctags filenames entries. "
3513 "File was %s (base_path: %s, fake_file: %s, tag_file: %s)",
3514 g_value_get_string (value), base_prj_path, fake_file,
3515 tag_entry->file);
3516 gda_value_free (value);
3517 return -1;
3521 /* parse the entry name */
3522 if (strlen (tag_entry->name) > sizeof (name))
3524 printf
3525 ("fatal error when inserting symbol, name of symbol is too big.\n");
3526 gda_value_free (value);
3527 return -1;
3529 else
3531 memset (name, 0, sizeof (name));
3532 memcpy (name, tag_entry->name, strlen (tag_entry->name));
3535 file_position = tag_entry->address.lineNumber;
3536 is_file_scope = tag_entry->fileScope;
3538 memset (signature, 0, sizeof (signature));
3539 if ((tmp_str = tagsField (tag_entry, "signature")) != NULL)
3541 if (strlen (tmp_str) > sizeof (signature))
3543 memcpy (signature, tmp_str, sizeof (signature));
3545 else
3547 memcpy (signature, tmp_str, strlen (tmp_str));
3551 type_id = sdb_engine_add_new_sym_type (dbe, tag_entry);
3554 /* scope_definition_id tells what scope this symbol defines
3555 * this call *MUST BE DONE AFTER* sym_type table population.
3557 scope_definition_id = sdb_engine_add_new_scope_definition (dbe, tag_entry);
3559 /* the container scopes can be: union, struct, typeref, class, namespace etc.
3560 * this field will be parse in the second pass.
3562 scope_id = 0;
3564 kind_id = sdb_engine_add_new_sym_kind (dbe, tag_entry);
3566 access_kind_id = sdb_engine_add_new_sym_access (dbe, tag_entry);
3567 implementation_kind_id =
3568 sdb_engine_add_new_sym_implementation (dbe, tag_entry);
3570 /* ok: was the symbol updated [at least on it's type_id/name]?
3571 * There are 3 cases:
3572 * #1. The symbol remain the same [at least on unique index key]. We will
3573 * perform only a simple update.
3574 * #2. The symbol has changed: at least on name/type/file. We will insert a
3575 * new symbol on table 'symbol'. Deletion of old one will take place
3576 * at a second stage, when a delete of all symbols with
3577 * 'tmp_flag = 0' will be done.
3578 * #3. The symbol has been deleted. As above it will be deleted at
3579 * a second stage because of the 'tmp_flag = 0'. Triggers will remove
3580 * also scope_ids and other things.
3583 value1 = gda_value_new (G_TYPE_STRING);
3584 g_value_set_string (value1, name);
3586 value2 = gda_value_new (G_TYPE_INT);
3587 g_value_set_int (value2, file_defined_id);
3589 value3 = gda_value_new (G_TYPE_INT);
3590 g_value_set_int (value3, type_id);
3592 if ((symbol_id = sdb_engine_get_table_id_by_unique_name3 (dbe,
3593 PREP_QUERY_GET_SYMBOL_ID_BY_UNIQUE_INDEX_KEY,
3594 "symname", value1,
3595 "filedefid",value2,
3596 "typeid", value3)) <= 0)
3598 /* case 2 and 3 */
3599 /* DEBUG_PRINT ("inserting new symbol: %s", name);*/
3600 sym_was_updated = FALSE;
3602 gda_value_free (value1);
3603 gda_value_free (value2);
3604 gda_value_free (value3);
3606 /* create specific query for a fresh new symbol */
3607 if ((query = sdb_engine_get_query_by_id (dbe, PREP_QUERY_SYMBOL_NEW))
3608 == NULL)
3610 g_warning ("query is null");
3611 return -1;
3614 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3615 gda_query_get_query_type ((GdaQuery *) query))
3617 g_warning ("non parsed sql error");
3618 gda_value_free (value);
3619 return -1;
3622 if ((par_list =
3623 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
3625 g_warning ("par_list is NULL!\n");
3626 gda_value_free (value);
3627 return -1;
3630 /* filedefid parameter */
3631 if ((param =
3632 gda_parameter_list_find_param (par_list, "filedefid")) == NULL)
3634 g_warning ("param filedefid is NULL from pquery!");
3635 gda_value_free (value);
3636 return -1;
3639 gda_value_reset_with_type (value, G_TYPE_INT);
3640 g_value_set_int (value, file_defined_id);
3641 gda_parameter_set_value (param, value);
3643 /* name parameter */
3644 if ((param = gda_parameter_list_find_param (par_list, "name")) == NULL)
3646 g_warning ("param name is NULL from pquery!");
3647 gda_value_free (value);
3648 return -1;
3651 gda_value_reset_with_type (value, G_TYPE_STRING);
3652 g_value_set_string (value, name);
3653 gda_parameter_set_value (param, value);
3655 /* fileposition parameter */
3656 if ((param =
3657 gda_parameter_list_find_param (par_list, "fileposition")) == NULL)
3659 g_warning ("param fileposition is NULL from pquery!");
3660 gda_value_free (value);
3661 return -1;
3664 gda_value_reset_with_type (value, G_TYPE_INT);
3665 g_value_set_int (value, file_position);
3666 gda_parameter_set_value (param, value);
3669 /* typeid parameter */
3670 if ((param =
3671 gda_parameter_list_find_param (par_list, "typeid")) == NULL)
3673 g_warning ("param typeid is NULL from pquery!");
3674 gda_value_free (value);
3675 return -1;
3678 gda_value_reset_with_type (value, G_TYPE_INT);
3679 g_value_set_int (value, type_id);
3680 gda_parameter_set_value (param, value);
3682 else
3684 /* case 1 */
3685 /* DEBUG_PRINT ("updating symbol: %s", name);*/
3686 sym_was_updated = TRUE;
3688 gda_value_free (value1);
3689 gda_value_free (value2);
3690 gda_value_free (value3);
3692 /* create specific query for a fresh new symbol */
3693 if ((query = sdb_engine_get_query_by_id (dbe,
3694 PREP_QUERY_UPDATE_SYMBOL_ALL))
3695 == NULL)
3697 g_warning ("query is null");
3698 return -1;
3701 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3702 gda_query_get_query_type ((GdaQuery *) query))
3704 g_warning ("non parsed sql error");
3705 gda_value_free (value);
3706 return -1;
3709 if ((par_list =
3710 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
3712 g_warning ("par_list is NULL!\n");
3713 gda_value_free (value);
3714 return -1;
3717 /* isfilescope parameter */
3718 if ((param = gda_parameter_list_find_param (par_list, "symbolid"))
3719 == NULL)
3721 g_warning ("param isfilescope is NULL from pquery!");
3722 gda_value_free (value);
3723 return -1;
3726 gda_value_reset_with_type (value, G_TYPE_INT);
3727 g_value_set_int (value, symbol_id);
3728 gda_parameter_set_value (param, value);
3731 /* common params */
3733 /* isfilescope parameter */
3734 if ((param =
3735 gda_parameter_list_find_param (par_list, "isfilescope")) == NULL)
3737 g_warning ("param isfilescope is NULL from pquery!");
3738 gda_value_free (value);
3739 return -1;
3742 gda_value_reset_with_type (value, G_TYPE_INT);
3743 g_value_set_int (value, is_file_scope);
3744 gda_parameter_set_value (param, value);
3746 /* signature parameter */
3747 if ((param = gda_parameter_list_find_param (par_list, "signature")) == NULL)
3749 g_warning ("param signature is NULL from pquery!");
3750 gda_value_free (value);
3751 return -1;
3754 gda_value_reset_with_type (value, G_TYPE_STRING);
3755 g_value_set_string (value, signature);
3756 gda_parameter_set_value (param, value);
3758 /* scopedefinitionid parameter */
3759 if ((param =
3760 gda_parameter_list_find_param (par_list, "scopedefinitionid")) == NULL)
3762 g_warning ("param scopedefinitionid is NULL from pquery!");
3763 gda_value_free (value);
3764 return -1;
3767 gda_value_reset_with_type (value, G_TYPE_INT);
3768 g_value_set_int (value, scope_definition_id);
3769 gda_parameter_set_value (param, value);
3771 /* scopeid parameter */
3772 if ((param = gda_parameter_list_find_param (par_list, "scopeid")) == NULL)
3774 g_warning ("param scopeid is NULL from pquery!");
3775 gda_value_free (value);
3776 return -1;
3779 gda_value_reset_with_type (value, G_TYPE_INT);
3780 g_value_set_int (value, scope_id);
3781 gda_parameter_set_value (param, value);
3783 /* kindid parameter */
3784 if ((param = gda_parameter_list_find_param (par_list, "kindid")) == NULL)
3786 g_warning ("param kindid is NULL from pquery!");
3787 gda_value_free (value);
3788 return -1;
3791 gda_value_reset_with_type (value, G_TYPE_INT);
3792 g_value_set_int (value, kind_id);
3793 gda_parameter_set_value (param, value);
3795 /* accesskindid parameter */
3796 if ((param =
3797 gda_parameter_list_find_param (par_list, "accesskindid")) == NULL)
3799 g_warning ("param accesskindid is NULL from pquery!");
3800 gda_value_free (value);
3801 return -1;
3804 gda_value_reset_with_type (value, G_TYPE_INT);
3805 g_value_set_int (value, access_kind_id);
3806 gda_parameter_set_value (param, value);
3808 /* implementationkindid parameter */
3809 if ((param =
3810 gda_parameter_list_find_param (par_list,
3811 "implementationkindid")) == NULL)
3813 g_warning ("param implementationkindid is NULL from pquery!");
3814 gda_value_free (value);
3815 return -1;
3818 gda_value_reset_with_type (value, G_TYPE_INT);
3819 g_value_set_int (value, implementation_kind_id);
3820 gda_parameter_set_value (param, value);
3822 /* updateflag parameter */
3823 if ((param =
3824 gda_parameter_list_find_param (par_list, "updateflag")) == NULL)
3826 g_warning ("param updateflag is NULL from pquery!");
3827 gda_value_free (value);
3828 return -1;
3831 gda_value_reset_with_type (value, G_TYPE_INT);
3832 g_value_set_int (value, update_flag);
3833 gda_parameter_set_value (param, value);
3834 gda_value_free (value);
3836 /* execute the query with parametes just set */
3837 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
3839 if (sym_was_updated == FALSE)
3841 table_id = sdb_engine_get_last_insert_id (dbe);
3843 /* This is a wrong place to emit the symbol-updated signal. Infact
3844 * db is in a inconsistent state, e.g. inheritance references are still
3845 * *not* calculated.
3846 * So add the symbol id into a queue that will be parsed once and emitted.
3848 /* g_signal_emit (dbe, signals[SYMBOL_INSERTED], 0, table_id); */
3849 g_async_queue_push (priv->inserted_symbols_id, (gpointer) table_id);
3851 else
3853 table_id = symbol_id;
3855 /* This is a wrong place to emit the symbol-updated signal. Infact
3856 * db is in a inconsistent state, e.g. inheritance references are still
3857 * *not* calculated.
3858 * So add the symbol id into a queue that will be parsed once and emitted.
3860 /* g_signal_emit (dbe, signals[SYMBOL_UPDATED], 0, table_id); */
3861 g_async_queue_push (priv->updated_symbols_id, (gpointer) table_id);
3864 /* before returning the table_id we have to fill some infoz on temporary tables
3865 * so that in a second pass we can parse also the heritage and scope fields.
3867 sdb_engine_add_new_tmp_heritage_scope (dbe, tag_entry, table_id);
3869 return table_id;
3874 * Select * from __tmp_removed and emits removed signals.
3876 static void
3877 sdb_engine_detects_removed_ids (SymbolDBEngine *dbe)
3879 const GdaQuery *query, *query2;
3880 SymbolDBEnginePriv *priv;
3881 GObject *obj;
3882 gint num_rows;
3883 gint i;
3884 g_return_if_fail (dbe != NULL);
3886 priv = dbe->priv;
3888 /* ok, now we should read from __tmp_removed all the symbol ids which have
3889 * been removed, and emit a signal
3891 if ((query = sdb_engine_get_query_by_id (dbe,
3892 PREP_QUERY_GET_REMOVED_IDS))
3893 == NULL)
3895 g_warning ("query is null");
3896 return;
3899 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3900 gda_query_get_query_type ((GdaQuery *) query))
3902 g_warning ("non parsed sql error");
3903 return;
3906 obj = G_OBJECT (gda_query_execute ((GdaQuery *) query, NULL, FALSE,
3907 NULL));
3909 if (GDA_IS_DATA_MODEL (obj))
3911 if ((num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (obj))) <= 0)
3913 g_object_unref (obj);
3914 return;
3917 else
3919 if (obj != NULL)
3920 g_object_unref (obj);
3921 return;
3924 /* get and parse the results. */
3925 for (i = 0; i < num_rows; i++)
3927 const GValue *val;
3928 gint tmp;
3929 val = gda_data_model_get_value_at (GDA_DATA_MODEL (obj), 0, i);
3930 tmp = g_value_get_int (val);
3932 g_signal_emit (dbe, signals[SYMBOL_REMOVED], 0, tmp);
3935 g_object_unref (obj);
3937 /* let's clean the tmp_table */
3938 if ((query2 = sdb_engine_get_query_by_id (dbe,
3939 PREP_QUERY_TMP_REMOVED_DELETE_ALL))
3940 == NULL)
3942 g_warning ("query is null");
3943 return;
3946 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
3947 gda_query_get_query_type ((GdaQuery *) query2))
3949 g_warning ("non parsed sql error");
3950 return;
3953 /* bye bye */
3954 gda_query_execute ((GdaQuery *) query2, NULL, FALSE, NULL);
3959 * WARNING: do not use this function thinking that it would do a scan of symbols
3960 * too. Use symbol_db_engine_update_files_symbols () instead. This one will set
3961 * up some things on db, like removing the 'old' files which have not been
3962 * updated.
3964 static gboolean
3965 sdb_engine_update_file (SymbolDBEngine * dbe, const gchar * file_on_db)
3967 const GdaQuery *query;
3968 gchar *query_str;
3969 GdaParameterList *par_list;
3970 GdaParameter *param;
3971 GValue *value;
3972 SymbolDBEnginePriv *priv;
3974 g_return_val_if_fail (dbe != NULL, FALSE);
3976 priv = dbe->priv;
3978 if (symbol_db_engine_is_project_opened (dbe, priv->project_name) == FALSE)
3980 g_warning ("project is not opened");
3981 return FALSE;
3985 /* if we're updating symbols we must do some other operations on db
3986 * symbols, like remove the ones which don't have an update_flag = 1
3987 * per updated file.
3990 /* good. Go on with removing of old symbols, marked by a
3991 * update_flag = 0.
3994 /* FIXME: libgda 3.0 doesn't have support for JOIN keyword at all on
3995 * prepared statements.
3996 * Said this we cannot expect to run queries on a really performant
3997 * way.
4000 /* Triggers will take care of updating/deleting connected symbols
4001 * tuples, like sym_kind, sym_type etc */
4002 query_str = g_strdup_printf ("DELETE FROM symbol WHERE "
4003 "file_defined_id = (SELECT file_id FROM file "
4004 "WHERE file_path = \"%s\") AND update_flag = 0",
4005 file_on_db);
4007 sdb_engine_execute_non_select_sql (dbe, query_str);
4008 g_free (query_str);
4010 /* emits removed symbols signals */
4011 sdb_engine_detects_removed_ids (dbe);
4013 /* reset the update_flag to 0 */
4014 query_str = g_strdup_printf ("UPDATE symbol SET update_flag = 0 "
4015 "WHERE file_defined_id = (SELECT file_id FROM file WHERE "
4016 "file_path = \"%s\")", file_on_db);
4018 sdb_engine_execute_non_select_sql (dbe, query_str);
4019 g_free (query_str);
4021 /* last but not least, update the file analize_time */
4022 if ((query = sdb_engine_get_query_by_id (dbe,
4023 PREP_QUERY_UPDATE_FILE_ANALIZE_TIME))
4024 == NULL)
4026 g_warning ("query is null");
4027 return FALSE;
4030 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4031 gda_query_get_query_type ((GdaQuery *) query))
4033 g_warning ("non parsed sql error");
4034 return FALSE;
4037 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4039 g_warning ("par_list is NULL!\n");
4040 return FALSE;
4043 /* filepath parameter */
4044 if ((param = gda_parameter_list_find_param (par_list, "filepath")) == NULL)
4046 g_warning ("param filepath is NULL from pquery!");
4047 return FALSE;
4050 value = gda_value_new (G_TYPE_STRING);
4051 g_value_set_string (value, file_on_db);
4052 gda_parameter_set_value (param, value);
4054 gda_value_free (value);
4055 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
4057 return TRUE;
4061 * @param data is a GPtrArray *files_to_scan
4062 * It will be freed when this callback will be called.
4064 static void
4065 on_scan_update_files_symbols_end (SymbolDBEngine * dbe, GPtrArray* data)
4067 SymbolDBEnginePriv *priv;
4068 GPtrArray *files_to_scan;
4069 gint i;
4071 DEBUG_PRINT ("on_scan_update_files_symbols_end ();");
4073 g_return_if_fail (dbe != NULL);
4074 g_return_if_fail (data != NULL);
4076 priv = dbe->priv;
4077 files_to_scan = (GPtrArray *) data;
4079 DEBUG_PRINT ("files_to_scan->len %d", files_to_scan->len);
4081 for (i = 0; i < files_to_scan->len; i++)
4083 gchar *node = (gchar *) g_ptr_array_index (files_to_scan, i);
4085 /* DEBUG_PRINT ("processing updating node: %s, data_source: %s", node,
4086 priv->data_source);
4087 DEBUG_PRINT ("processing updating for file %s", node +
4088 strlen (priv->data_source));*/
4090 /* clean the db from old un-updated with the last update step () */
4091 if (sdb_engine_update_file (dbe, node +
4092 strlen (priv->data_source)) == FALSE)
4094 g_warning ("Error processing file %s", node +
4095 strlen (priv->data_source) );
4096 return;
4098 g_free (node);
4101 g_signal_handlers_disconnect_by_func (dbe, on_scan_update_files_symbols_end,
4102 files_to_scan);
4104 /* free the GPtrArray. */
4105 DEBUG_PRINT ("free the files_to_scan");
4106 g_ptr_array_free (files_to_scan, TRUE);
4107 data = files_to_scan = NULL;
4108 DEBUG_PRINT ("done");
4112 /* Update symbols of saved files.
4113 * WARNING: files_path and it's contents will be freed on
4114 * on_scan_update_files_symbols_end () callback.
4116 gboolean
4117 symbol_db_engine_update_files_symbols (SymbolDBEngine * dbe, gchar * project,
4118 GPtrArray * files_path /*,
4119 * gchar *language */ ,
4120 gboolean update_prj_analize_time)
4122 SymbolDBEnginePriv *priv;
4124 priv = dbe->priv;
4126 DEBUG_PRINT ("symbol_db_engine_update_files_symbols ()");
4127 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
4128 g_return_val_if_fail (project != NULL, FALSE);
4130 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4132 g_warning ("project is not opened");
4133 return FALSE;
4136 /* data will be freed when callback will be called. The signal will be
4137 * disconnected too, don't worry about disconneting it by hand.
4139 g_signal_connect (G_OBJECT (dbe), "scan-end",
4140 G_CALLBACK (on_scan_update_files_symbols_end), files_path);
4142 sdb_engine_scan_files_1 (dbe, files_path, NULL, TRUE);
4144 /* if true, we'll update the project scanning time too.
4145 * warning: project time scanning won't could be set before files one.
4146 * This why we'll fork the process calling sdb_engine_scan_files ()
4148 if (update_prj_analize_time == TRUE)
4150 const GdaQuery *query;
4151 GdaParameterList *par_list;
4152 GdaParameter *param;
4153 GValue *value;
4155 /* and the project analize_time */
4156 if ((query = sdb_engine_get_query_by_id (dbe,
4157 PREP_QUERY_UPDATE_PROJECT_ANALIZE_TIME))
4158 == NULL)
4160 g_warning ("query is null");
4161 return FALSE;
4164 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4165 gda_query_get_query_type ((GdaQuery *) query))
4167 g_warning ("non parsed sql error");
4168 return FALSE;
4171 if ((par_list =
4172 gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4174 g_warning ("par_list is NULL!\n");
4175 return FALSE;
4178 /* prjname parameter */
4179 if ((param = gda_parameter_list_find_param (par_list, "prjname"))
4180 == NULL)
4182 g_warning ("param prjname is NULL from pquery!");
4183 return FALSE;
4186 value = gda_value_new (G_TYPE_STRING);
4187 g_value_set_string (value, priv->project_name);
4188 gda_parameter_set_value (param, value);
4190 gda_value_free (value);
4192 DEBUG_PRINT ("updating project analize_time");
4193 gda_query_execute ((GdaQuery *) query, par_list, FALSE, NULL);
4196 return TRUE;
4199 /* Update symbols of the whole project. It scans all file symbols etc.
4200 * FIXME: libgda does not support nested prepared queries like
4201 * PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_NAME. When it will do please
4202 * remember to update this function.
4204 gboolean
4205 symbol_db_engine_update_project_symbols (SymbolDBEngine * dbe, gchar * project /*,
4206 * gboolean force */ )
4208 const GdaQuery *query;
4209 GdaParameterList *par_list;
4210 GdaParameter *param;
4211 GValue *value;
4212 GObject *obj;
4213 gint project_id;
4214 gint num_rows = 0;
4215 gint i;
4216 GPtrArray *files_to_scan;
4217 SymbolDBEnginePriv *priv;
4220 g_return_val_if_fail (dbe != NULL, FALSE);
4221 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4223 g_warning ("project is not opened");
4224 return FALSE;
4227 priv = dbe->priv;
4229 value = gda_value_new (G_TYPE_STRING);
4230 g_value_set_string (value, project);
4232 /* get project id */
4233 if ((project_id = sdb_engine_get_table_id_by_unique_name (dbe,
4234 PREP_QUERY_GET_PROJECT_ID_BY_UNIQUE_NAME,
4235 "prjname",
4236 value)) <= 0)
4238 gda_value_free (value);
4239 return FALSE;
4242 if ((query = sdb_engine_get_query_by_id (dbe,
4243 PREP_QUERY_GET_ALL_FROM_FILE_BY_PROJECT_ID))
4244 == NULL)
4246 g_warning ("query is null");
4247 gda_value_free (value);
4248 return FALSE;
4251 if (GDA_QUERY_TYPE_NON_PARSED_SQL ==
4252 gda_query_get_query_type ((GdaQuery *) query))
4254 g_warning ("non parsed sql error");
4255 gda_value_free (value);
4256 return FALSE;
4259 if ((par_list = gda_query_get_parameter_list ((GdaQuery *) query)) == NULL)
4261 g_warning ("par_list is NULL!\n");
4262 gda_value_free (value);
4263 return FALSE;
4266 /* prjid parameter */
4267 if ((param = gda_parameter_list_find_param (par_list, "prjid")) == NULL)
4269 g_warning ("param prjname is NULL from pquery!");
4270 return FALSE;
4273 gda_value_reset_with_type (value, G_TYPE_INT);
4274 g_value_set_int (value, project_id);
4275 gda_parameter_set_value (param, value);
4277 /* execute the query with parametes just set */
4278 obj =
4279 G_OBJECT (gda_query_execute
4280 ((GdaQuery *) query, par_list, FALSE, NULL));
4282 if (!GDA_IS_DATA_MODEL (obj) ||
4283 (num_rows = gda_data_model_get_n_rows (GDA_DATA_MODEL (obj))) <= 0)
4286 g_message ("no rows");
4287 if (obj != NULL)
4288 g_object_unref (obj);
4289 obj = NULL;
4292 /* we don't need it anymore */
4293 gda_value_free (value);
4295 g_message ("got gda_data_model_get_n_rows (GDA_DATA_MODEL(obj)) %d",
4296 num_rows);
4298 /* initialize the array */
4299 files_to_scan = g_ptr_array_new ();
4301 /* we can now scan each filename entry to check the last modification time. */
4302 for (i = 0; i < num_rows; i++)
4304 const GValue *value, *value1;
4305 const gchar *file_name;
4306 gchar *file_abs_path;
4307 struct tm filetm;
4308 time_t db_file_time;
4309 gchar *date_string;
4310 gchar *abs_vfs_path;
4311 GnomeVFSHandle *handle;
4313 if ((value =
4314 gda_data_model_get_value_at_col_name (GDA_DATA_MODEL (obj),
4315 "file_path", i)) == NULL)
4317 continue;
4320 /* build abs path. */
4321 file_name = g_value_get_string (value);
4322 if (priv->data_source != NULL)
4324 abs_vfs_path = g_strdup_printf ("file://%s%s", priv->data_source,
4325 file_name);
4326 file_abs_path = g_strdup_printf ("%s%s", priv->data_source,
4327 file_name);
4329 else
4331 abs_vfs_path = g_strdup_printf ("file://%s", file_name);
4332 file_abs_path = g_strdup (file_name);
4335 GnomeVFSURI *uri = gnome_vfs_uri_new (abs_vfs_path);
4336 GnomeVFSFileInfo *file_info = gnome_vfs_file_info_new ();
4338 /* retrieve data/time info */
4339 if (gnome_vfs_open_uri (&handle, uri,
4340 GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_RANDOM) !=
4341 GNOME_VFS_OK)
4343 g_message ("could not open URI %s", abs_vfs_path);
4344 gnome_vfs_uri_unref (uri);
4345 gnome_vfs_file_info_unref (file_info);
4346 g_free (abs_vfs_path);
4347 g_free (file_abs_path);
4348 continue;
4351 if (gnome_vfs_get_file_info_from_handle (handle, file_info,
4352 GNOME_VFS_FILE_INFO_DEFAULT) !=
4353 GNOME_VFS_OK)
4355 g_message ("cannot get file info from handle");
4356 gnome_vfs_close (handle);
4357 gnome_vfs_uri_unref (uri);
4358 gnome_vfs_file_info_unref (file_info);
4359 g_free (file_abs_path);
4360 continue;
4363 if ((value1 =
4364 gda_data_model_get_value_at_col_name (GDA_DATA_MODEL (obj),
4365 "analize_time", i)) == NULL)
4367 continue;
4370 /* weirdly we have a strange libgda behaviour here too.
4371 * as from ChangeLog GDA_TYPE_TIMESTAMP as SQLite does not impose a
4372 * known format for dates (there is no date datatype).
4373 * We have then to do some hackery to retrieve the date.
4375 date_string = (gchar *) g_value_get_string (value1);
4377 DEBUG_PRINT ("processing for upating symbol %s", file_name);
4378 DEBUG_PRINT ("date_string %s", date_string);
4380 /* fill a struct tm with the date retrieved by the string. */
4381 /* string is something like '2007-04-18 23:51:39' */
4382 memset (&filetm, 0, sizeof (struct tm));
4383 filetm.tm_year = atoi (date_string) - 1900;
4384 date_string += 5;
4385 filetm.tm_mon = atoi (date_string) - 1;
4386 date_string += 3;
4387 filetm.tm_mday = atoi (date_string);
4388 date_string += 3;
4389 filetm.tm_hour = atoi (date_string);
4390 date_string += 3;
4391 filetm.tm_min = atoi (date_string);
4392 date_string += 3;
4393 filetm.tm_sec = atoi (date_string);
4395 /* subtract one hour to the db_file_time. (why this?) */
4396 db_file_time = mktime (&filetm) - 3600;
4398 if (difftime (db_file_time, file_info->mtime) <= 0)
4400 g_message ("to be added! : %s", file_name);
4401 g_ptr_array_add (files_to_scan, file_abs_path);
4404 DEBUG_PRINT ("difftime %f", difftime (db_file_time, file_info->mtime));
4405 DEBUG_PRINT ("db_file_time %d - "
4406 "file_info->mtime %d "
4407 "file_info->ctime %d", db_file_time,
4408 file_info->mtime, file_info->ctime);
4410 gnome_vfs_close (handle);
4411 gnome_vfs_uri_unref (uri);
4412 gnome_vfs_file_info_unref (file_info);
4413 g_free (abs_vfs_path);
4414 /* no need to free file_abs_path, it's been added to files_to_scan */
4417 if (files_to_scan->len > 0)
4419 /* at the end let's the scanning function do its job */
4420 return symbol_db_engine_update_files_symbols (dbe, project,
4421 files_to_scan, TRUE);
4423 return TRUE;
4427 /* Remove a file, together with its symbols, from a project. */
4428 gboolean
4429 symbol_db_engine_remove_file (SymbolDBEngine * dbe, const gchar * project,
4430 const gchar * file)
4432 gchar *query_str;
4433 SymbolDBEnginePriv *priv;
4435 g_return_val_if_fail (dbe != NULL, FALSE);
4436 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4438 g_warning ("project is not opened");
4439 return FALSE;
4442 priv = dbe->priv;
4444 if (strlen (file) < strlen (priv->data_source))
4446 g_warning ("wrong file");
4447 return FALSE;
4450 /* Triggers will take care of updating/deleting connected symbols
4451 * tuples, like sym_kind, sym_type etc */
4452 query_str = g_strdup_printf ("DELETE FROM file WHERE prj_id "
4453 "= (SELECT project_id FROM project WHERE project_name = '%s') AND "
4454 "file_path = '%s'", project, file + strlen (priv->data_source));
4456 /* DEBUG_PRINT ("symbol_db_engine_remove_file () : %s", query_str);*/
4457 sdb_engine_execute_non_select_sql (dbe, query_str);
4458 g_free (query_str);
4460 /* emits removed symbols signals */
4461 sdb_engine_detects_removed_ids (dbe);
4462 return TRUE;
4466 static void
4467 on_scan_update_buffer_end (SymbolDBEngine * dbe, gpointer data)
4469 SymbolDBEnginePriv *priv;
4470 GPtrArray *files_to_scan;
4471 gint i;
4473 g_return_if_fail (dbe != NULL);
4474 g_return_if_fail (data != NULL);
4476 priv = dbe->priv;
4477 files_to_scan = (GPtrArray *) data;
4479 DEBUG_PRINT ("files_to_scan->len %d", files_to_scan->len);
4481 for (i = 0; i < files_to_scan->len; i++)
4483 gchar *node = (gchar *) g_ptr_array_index (files_to_scan, i);
4485 DEBUG_PRINT ("processing updating for file [on disk] %s, "
4486 "passed to on_scan_update_buffer_end (): %s",
4487 node, node + strlen (priv->data_source));
4489 if (sdb_engine_update_file (dbe, node+
4490 strlen (priv->data_source)) == FALSE)
4492 g_warning ("Error processing file %s", node);
4493 return;
4495 g_free (node);
4498 g_signal_handlers_disconnect_by_func (dbe, on_scan_update_buffer_end,
4499 files_to_scan);
4501 /* free the GPtrArray. */
4502 DEBUG_PRINT ("free the files_to_scan");
4503 g_ptr_array_free (files_to_scan, TRUE);
4504 data = files_to_scan = NULL;
4505 DEBUG_PRINT ("done");
4508 /* Update symbols of a file by a memory-buffer to perform a real-time updating
4509 * of symbols.
4510 * real_files_list: full path on disk to 'real file' to update. e.g.
4511 * /home/foouser/fooproject/src/main.c
4513 gboolean
4514 symbol_db_engine_update_buffer_symbols (SymbolDBEngine * dbe, gchar * project,
4515 GPtrArray * real_files_list,
4516 const GPtrArray * text_buffers,
4517 const GPtrArray * buffer_sizes)
4519 SymbolDBEnginePriv *priv;
4520 gint i;
4522 DEBUG_PRINT ("symbol_db_engine_update_buffer_symbols ()");
4524 /* array that'll represent the /dev/shm/anjuta-XYZ files */
4525 GPtrArray *temp_files;
4526 GPtrArray *real_files_on_db;
4528 priv = dbe->priv;
4530 g_return_val_if_fail (priv->db_connection != NULL, FALSE);
4531 g_return_val_if_fail (project != NULL, FALSE);
4532 g_return_val_if_fail (real_files_list != NULL, FALSE);
4533 g_return_val_if_fail (text_buffers != NULL, FALSE);
4534 g_return_val_if_fail (buffer_sizes != NULL, FALSE);
4536 if (symbol_db_engine_is_project_opened (dbe, project) == FALSE)
4538 g_warning ("project is not opened");
4539 return FALSE;
4542 temp_files = g_ptr_array_new();
4543 real_files_on_db = g_ptr_array_new();
4545 /* obtain a GPtrArray with real_files on database */
4546 for (i=0; i < real_files_list->len; i++)
4548 gchar *new_node = (gchar*)g_ptr_array_index (real_files_list, i)
4549 + strlen(priv->data_source);
4550 DEBUG_PRINT ("real_file on db: %s", new_node);
4551 g_ptr_array_add (real_files_on_db, g_strdup (new_node));
4554 /* create a temporary file for each buffer */
4555 for (i=0; i < real_files_list->len; i++)
4557 FILE *shared_mem_file;
4558 const gchar *temp_buffer;
4559 gint shared_mem_fd;
4560 gint temp_size;
4561 gchar *temp_file;
4562 gchar *base_filename;
4563 const gchar *curr_real_file;
4565 curr_real_file = g_ptr_array_index (real_files_list, i);
4567 /* it's ok to have just the base filename to create the
4568 * target buffer one */
4569 base_filename = g_filename_display_basename (curr_real_file);
4571 temp_file = g_strdup_printf ("/anjuta-%d-%ld-%s", getpid (),
4572 time (NULL), base_filename);
4573 g_free (base_filename);
4575 DEBUG_PRINT ("my temp file is %s", temp_file);
4576 if ((shared_mem_fd =
4577 shm_open (temp_file, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0)
4579 g_warning ("Error while trying to open a shared memory file. Be"
4580 "sure to have /dev/shm mounted with tmpfs");
4581 return FALSE;
4584 shared_mem_file = fdopen (shared_mem_fd, "w+b");
4586 DEBUG_PRINT ("temp_file %s", temp_file);
4588 temp_buffer = g_ptr_array_index (text_buffers, i);
4589 temp_size = (gint)g_ptr_array_index (buffer_sizes, i);
4590 fwrite (temp_buffer, sizeof(gchar), temp_size, shared_mem_file);
4591 fflush (shared_mem_file);
4592 fclose (shared_mem_file);
4594 /* add the temp file to the array. */
4595 g_ptr_array_add (temp_files, g_strdup_printf ("/dev/shm%s", temp_file));
4596 g_free (temp_file);
4600 /* data will be freed when callback will be called. The signal will be
4601 * disconnected too, don't worry about disconneting it by hand.
4603 g_signal_connect (G_OBJECT (dbe), "scan-end",
4604 G_CALLBACK (on_scan_update_buffer_end), real_files_list);
4606 sdb_engine_scan_files_1 (dbe, temp_files, real_files_on_db, TRUE);
4608 /* let's free the temp_files array */
4609 for (i=0; i < temp_files->len; i++)
4610 g_free (g_ptr_array_index (temp_files, i));
4612 g_ptr_array_free (temp_files, TRUE);
4614 /* and the real_files_on_db too */
4615 for (i=0; i < real_files_on_db->len; i++)
4616 g_free (g_ptr_array_index (real_files_on_db, i));
4618 g_ptr_array_free (real_files_on_db, TRUE);
4621 return TRUE;
4624 gboolean
4625 symbol_db_engine_is_locked (SymbolDBEngine * dbe)
4627 SymbolDBEnginePriv *priv;
4629 g_return_val_if_fail (dbe != NULL, FALSE);
4631 priv = dbe->priv;
4632 return priv->scanning_status;
4635 static inline gint
4636 sdb_engine_walk_down_scope_path (SymbolDBEngine *dbe, const GPtrArray* scope_path)
4638 SymbolDBEnginePriv *priv;
4639 gint final_definition_id;
4640 gint scope_path_len;
4641 gint i;
4642 gchar *query_str;
4643 GdaCommand *command;
4644 GdaDataModel *data;
4646 g_return_val_if_fail (dbe != NULL, FALSE);
4647 priv = dbe->priv;
4649 scope_path_len = scope_path->len;
4651 /* we'll return if the length is even or minor than 3 */
4652 if (scope_path_len < 3 || scope_path_len % 2 == 0)
4654 g_warning ("bad scope_path.");
4655 return -1;
4658 final_definition_id = 0;
4659 for (i=0; i < scope_path_len -1; i = i + 2)
4661 const GValue *value;
4662 DEBUG_PRINT ("loop final_definition_id %d", final_definition_id);
4664 query_str = g_strdup_printf ("SELECT scope_definition_id FROM symbol "
4665 "WHERE scope_id = '%d' AND scope_definition_id = ("
4666 "SELECT scope.scope_id FROM scope "
4667 "INNER JOIN sym_type ON scope.type_id = sym_type.type_id "
4668 "WHERE sym_type.type = '%s' "
4669 "AND scope.scope = '%s'"
4670 ")", final_definition_id, (gchar*)g_ptr_array_index (scope_path, i),
4671 (gchar*)g_ptr_array_index (scope_path, i + 1));
4673 DEBUG_PRINT ("walk down query is %s", query_str);
4674 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
4675 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
4677 if ( (data = gda_connection_execute_select_command (priv->db_connection,
4678 command, NULL, NULL)) == NULL ||
4679 gda_data_model_get_n_rows (data) <= 0 )
4681 gda_command_free (command);
4682 g_free (query_str);
4683 return -1;
4686 gda_command_free (command);
4687 g_free (query_str);
4689 value = gda_data_model_get_value_at (data, 0, 0);
4690 if (G_VALUE_HOLDS (value, G_TYPE_INT))
4692 final_definition_id = g_value_get_int (value);
4693 g_object_unref (data);
4695 else
4697 /* something went wrong. Our symbol cannot be retrieved coz of a
4698 * bad scope path.
4700 final_definition_id = -1;
4701 break;
4705 return final_definition_id;
4708 /* Returns an iterator to the data retrieved from database.
4709 * The iterator, if not null, will contain a list of parent classes for the given
4710 * symbol name.
4711 * namespace_name can be NULL.
4713 SymbolDBEngineIterator *
4714 symbol_db_engine_get_class_parents (SymbolDBEngine *dbe, gchar *klass_name,
4715 const GPtrArray *scope_path)
4717 SymbolDBEnginePriv *priv;
4718 gchar *query_str;
4719 GdaCommand *command;
4720 GdaDataModel *data;
4721 gint final_definition_id;
4723 g_return_val_if_fail (dbe != NULL, FALSE);
4724 priv = dbe->priv;
4726 final_definition_id = -1;
4727 if (scope_path != NULL)
4728 final_definition_id = sdb_engine_walk_down_scope_path (dbe, scope_path);
4730 /* FIXME: as always prepared queries of this complexity gives
4731 GDA_QUERY_TYPE_NON_PARSED_SQL error. */
4732 if (final_definition_id > 0)
4734 query_str = g_strdup_printf("SELECT symbol.symbol_id, symbol.name FROM heritage "
4735 "JOIN symbol ON heritage.symbol_id_base = symbol.symbol_id "
4736 "WHERE symbol_id_derived = ("
4737 "SELECT symbol_id FROM symbol "
4738 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
4739 "WHERE symbol.name = '%s' "
4740 "AND sym_kind.kind_name = 'class' "
4741 "AND symbol.scope_id = '%d'"
4742 ")", klass_name, final_definition_id);
4744 else
4746 query_str = g_strdup_printf("SELECT symbol.symbol_id, symbol.name FROM heritage "
4747 "JOIN symbol ON heritage.symbol_id_base = symbol.symbol_id "
4748 "WHERE symbol_id_derived = ("
4749 "SELECT symbol_id FROM symbol "
4750 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id "
4751 "WHERE symbol.name = '%s' "
4752 "AND sym_kind.kind_name = 'class' "
4753 ")", klass_name);
4756 DEBUG_PRINT ("get parents query: %s", query_str);
4757 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
4758 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
4760 if ( (data = gda_connection_execute_select_command (priv->db_connection,
4761 command, NULL, NULL)) == NULL ||
4762 gda_data_model_get_n_rows (data) <= 0 )
4764 gda_command_free (command);
4765 g_free (query_str);
4766 return NULL;
4769 gda_command_free (command);
4770 g_free (query_str);
4772 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
4775 static inline void
4776 sdb_engine_prepare_symbol_info_sql (SymbolDBEngine *dbe, GString *info_data,
4777 GString *join_data, gint sym_info)
4779 if (sym_info & SYMINFO_FILE_PATH ||
4780 sym_info & SYMINFO_LANGUAGE ||
4781 sym_info & SYMINFO_PROJECT_NAME ||
4782 sym_info & SYMINFO_FILE_IGNORE ||
4783 sym_info & SYMINFO_FILE_INCLUDE)
4785 info_data = g_string_append (info_data, ",file.file_path ");
4786 join_data = g_string_append (join_data, "LEFT JOIN file ON "
4787 "symbol.file_defined_id = file.file_id ");
4790 if (sym_info & SYMINFO_LANGUAGE)
4792 info_data = g_string_append (info_data, ",language.language_name ");
4793 join_data = g_string_append (join_data, "LEFT JOIN language ON "
4794 "file.lang_id = language.language_id ");
4797 if (sym_info & SYMINFO_IMPLEMENTATION)
4799 info_data = g_string_append (info_data, ",sym_implementation.implementation_name ");
4800 join_data = g_string_append (join_data, "LEFT JOIN sym_implementation ON "
4801 "symbol.implementation_kind_id = sym_implementation.sym_impl_id ");
4804 if (sym_info & SYMINFO_ACCESS)
4806 info_data = g_string_append (info_data, ",sym_access.access_name ");
4807 join_data = g_string_append (join_data, "LEFT JOIN sym_access ON "
4808 "symbol.access_kind_id = sym_access.access_kind_id ");
4811 if (sym_info & SYMINFO_KIND)
4813 info_data = g_string_append (info_data, ",sym_kind.kind_name ");
4814 join_data = g_string_append (join_data, "LEFT JOIN sym_kind ON "
4815 "symbol.kind_id = sym_kind.sym_kind_id ");
4818 if (sym_info & SYMINFO_TYPE || sym_info & SYMINFO_TYPE_NAME)
4820 info_data = g_string_append (info_data, ",sym_type.type,"
4821 "sym_type.type_name ");
4822 join_data = g_string_append (join_data, "LEFT JOIN sym_type ON "
4823 "symbol.type_id = sym_type.type_id ");
4826 if (sym_info & SYMINFO_PROJECT_NAME ||
4827 sym_info & SYMINFO_FILE_IGNORE ||
4828 sym_info & SYMINFO_FILE_INCLUDE)
4830 info_data = g_string_append (info_data, ",project.project_name ");
4831 join_data = g_string_append (join_data, "LEFT JOIN project ON "
4832 "file.prj_id = project.project_id ");
4835 if (sym_info & SYMINFO_FILE_IGNORE)
4837 info_data = g_string_append (info_data, ",file_ignore.type AS file_ignore_type ");
4838 join_data = g_string_append (join_data, "LEFT JOIN ext_ignore ON "
4839 "ext_ignore.prj_id = project.project_id "
4840 "LEFT JOIN file_ignore ON "
4841 "ext_ignore.file_ign_id = file_ignore.file_ignore_id ");
4844 if (sym_info & SYMINFO_FILE_INCLUDE)
4846 info_data = g_string_append (info_data, ",file_include.type AS file_include_type ");
4847 join_data = g_string_append (join_data, "LEFT JOIN ext_include ON "
4848 "ext_include.prj_id = project.project_id "
4849 "LEFT JOIN file_include ON "
4850 "ext_include.file_incl_id = file_include.file_include_id ");
4853 /* TODO, or better.. TAKE A DECISION
4854 if (sym_info & SYMINFO_WORKSPACE_NAME)
4856 info_data = g_string_append (info_data, ",sym_access.access_name ");
4857 join_data = g_string_append (info_data, "LEFT JOIN sym_kind ON "
4858 "symbol.kind_id = sym_kind.sym_kind_id ");
4864 * kind can be NULL. In that case we'll return all the kinds of symbols found
4865 * at root level [global level].
4867 SymbolDBEngineIterator *
4868 symbol_db_engine_get_global_members (SymbolDBEngine *dbe,
4869 const gchar *kind, gint sym_info)
4871 SymbolDBEnginePriv *priv;
4872 GdaCommand *command;
4873 GdaDataModel *data;
4874 GString *info_data;
4875 GString *join_data;
4876 gchar *query_str;
4878 g_return_val_if_fail (dbe != NULL, NULL);
4879 priv = dbe->priv;
4881 /* check for an already flagged sym_info with KIND. SYMINFO_KIND on sym_info
4882 * is already contained into the default query infos.
4884 sym_info = sym_info & ~SYMINFO_KIND;
4886 /* info_data contains the stuff after SELECT and befor FROM */
4887 info_data = g_string_new ("");
4889 /* join_data contains the optionals joins to do to retrieve new data on other
4890 * tables.
4892 join_data = g_string_new ("");
4894 /* fill info_data and join data with optional sql */
4895 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
4897 if (kind == NULL)
4899 query_str = g_strdup_printf ("SELECT symbol.symbol_id, "
4900 "symbol.name, symbol.file_position, symbol.is_file_scope, "
4901 "symbol.signature, sym_kind.kind_name %s FROM symbol "
4902 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id %s "
4903 "WHERE scope_id <= 0", info_data->str, join_data->str);
4905 else
4907 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
4908 "symbol.file_position, "
4909 "symbol.is_file_scope, symbol.signature %s FROM symbol "
4910 "JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id %s "
4911 "WHERE scope_id <= 0 "
4912 "AND sym_kind.kind_name = '%s'", info_data->str, join_data->str,
4913 kind);
4916 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
4917 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
4919 /* DEBUG_PRINT ("query is %s", query_str);*/
4920 if ( (data = gda_connection_execute_select_command (priv->db_connection,
4921 command, NULL, NULL)) == NULL ||
4922 gda_data_model_get_n_rows (data) <= 0 )
4924 gda_command_free (command);
4925 g_free (query_str);
4926 g_string_free (info_data, FALSE);
4927 g_string_free (join_data, FALSE);
4928 return NULL;
4931 gda_command_free (command);
4932 g_free (query_str);
4933 g_string_free (info_data, FALSE);
4934 g_string_free (join_data, FALSE);
4936 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
4942 * Sometimes it's useful going to query just with ids [and so integers] to have
4943 * a little speed improvement.
4945 SymbolDBEngineIterator *
4946 symbol_db_engine_get_scope_members_by_symbol_id (SymbolDBEngine *dbe,
4947 gint scope_parent_symbol_id, gint sym_info)
4950 select b.* from symbol a, symbol b where a.symbol_id = 348 and
4951 b.scope_id = a.scope_definition_id;
4953 SymbolDBEnginePriv *priv;
4954 gchar *query_str;
4955 GdaCommand *command;
4956 GdaDataModel *data;
4957 GString *info_data;
4958 GString *join_data;
4960 g_return_val_if_fail (dbe != NULL, NULL);
4961 priv = dbe->priv;
4963 if (scope_parent_symbol_id <= 0)
4964 return NULL;
4966 /* info_data contains the stuff after SELECT and befor FROM */
4967 info_data = g_string_new ("");
4969 /* join_data contains the optionals joins to do to retrieve new data on other
4970 * tables.
4972 join_data = g_string_new ("");
4974 /* fill info_data and join data with optional sql */
4975 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
4977 /* ok, beware that we use an 'alias hack' to accomplish compatibility with
4978 * sdb_engine_prepare_symbol_info_sql () function. In particular we called
4979 * the first joining table 'a', the second one 'symbol', where is the info we
4980 * want
4982 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
4983 "symbol.file_position, "
4984 "symbol.is_file_scope, symbol.signature %s FROM symbol a, symbol symbol "
4985 "%s WHERE a.symbol_id = '%d' AND symbol.scope_id = a.scope_definition_id "
4986 "AND symbol.scope_id > 0", info_data->str, join_data->str,
4987 scope_parent_symbol_id);
4989 /* DEBUG_PRINT ("DYNAMIC query is %s", query_str);*/
4990 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
4991 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
4993 if ( (data = gda_connection_execute_select_command (priv->db_connection,
4994 command, NULL, NULL)) == NULL ||
4995 gda_data_model_get_n_rows (data) <= 0 )
4997 gda_command_free (command);
4998 g_free (query_str);
4999 return NULL;
5002 gda_command_free (command);
5003 g_free (query_str);
5004 g_string_free (info_data, FALSE);
5005 g_string_free (join_data, FALSE);
5007 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5010 /* scope_path cannot be NULL.
5011 * scope_path will be something like "scope1_kind", "scope1_name", "scope2_kind",
5012 * "scope2_name", NULL
5014 SymbolDBEngineIterator *
5015 symbol_db_engine_get_scope_members (SymbolDBEngine *dbe,
5016 const GPtrArray* scope_path, gint sym_info)
5019 simple scope
5021 select * from symbol where scope_id = (
5022 select scope.scope_id from scope
5023 inner join sym_type on scope.type_id = sym_type.type_id
5024 where sym_type.type = 'class'
5025 and scope.scope = 'MyClass'
5028 select * from symbol where scope_id = (
5029 select scope.scope_id from scope
5030 inner join sym_type on scope.type_id = sym_type.type_id
5031 where sym_type.type = 'struct'
5032 and scope.scope = '_faa_1');
5035 es. scope_path = First, namespace, Second, namespace, NULL,
5036 symbol_name = Second_1_class
5038 SymbolDBEnginePriv *priv;
5039 gchar *query_str;
5040 GdaCommand *command;
5041 GdaDataModel *data;
5042 gint final_definition_id;
5043 GString *info_data;
5044 GString *join_data;
5046 g_return_val_if_fail (dbe != NULL, NULL);
5047 priv = dbe->priv;
5049 final_definition_id = sdb_engine_walk_down_scope_path (dbe, scope_path);
5051 if (final_definition_id <= 0)
5053 return NULL;
5056 /* info_data contains the stuff after SELECT and befor FROM */
5057 info_data = g_string_new ("");
5059 /* join_data contains the optionals joins to do to retrieve new data on other
5060 * tables.
5062 join_data = g_string_new ("");
5064 /* fill info_data and join data with optional sql */
5065 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5067 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5068 "symbol.file_position, "
5069 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5070 "%s WHERE scope_id = '%d'", info_data->str, join_data->str,
5071 final_definition_id);
5073 /* DEBUG_PRINT ("DYNAMIC query is %s", query_str);*/
5074 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
5075 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
5077 if ( (data = gda_connection_execute_select_command (priv->db_connection,
5078 command, NULL, NULL)) == NULL ||
5079 gda_data_model_get_n_rows (data) <= 0 )
5081 gda_command_free (command);
5082 g_free (query_str);
5083 return NULL;
5086 gda_command_free (command);
5087 g_free (query_str);
5088 g_string_free (info_data, FALSE);
5089 g_string_free (join_data, FALSE);
5091 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5094 /* Returns an iterator to the data retrieved from database.
5095 * It will be possible to get the scope specified by the line of the file.
5097 SymbolDBEngineIterator *
5098 symbol_db_engine_get_current_scope (SymbolDBEngine *dbe, const gchar* filename,
5099 gulong line)
5101 SymbolDBEnginePriv *priv;
5102 gchar *file_escaped;
5103 gchar *query_str;
5104 GdaCommand *command;
5105 GdaDataModel *data;
5107 g_return_val_if_fail (dbe != NULL, NULL);
5108 priv = dbe->priv;
5111 file_escaped = g_strescape (filename, NULL);
5113 /* WARNING: probably there can be some problems with escaping file names here.
5114 * They should come already escaped as from project db.
5116 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5117 "symbol.file_position, "
5118 "symbol.is_file_scope, symbol.signature, MIN('%d' - symbol.file_position) "
5119 "FROM symbol "
5120 "JOIN file ON file_defined_id = file_id "
5121 "WHERE file.file_path = \"%s\" "
5122 "AND '%d' - symbol.file_position >= 0", (gint)line, file_escaped,
5123 (gint)line);
5125 DEBUG_PRINT ("current_scope query is %s", query_str);
5127 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
5128 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
5130 if ( (data = gda_connection_execute_select_command (priv->db_connection,
5131 command, NULL, NULL)) == NULL ||
5132 gda_data_model_get_n_rows (data) <= 0 )
5134 gda_command_free (command);
5135 g_free (query_str);
5136 g_free (file_escaped);
5137 return NULL;
5140 gda_command_free (command);
5141 g_free (query_str);
5142 g_free (file_escaped);
5143 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5148 * Filepath: full local file path, e.g. /home/user/foo/file.c
5150 SymbolDBEngineIterator *
5151 symbol_db_engine_get_file_symbols (SymbolDBEngine *dbe,
5152 const gchar *file_path, gint sym_info)
5154 SymbolDBEnginePriv *priv;
5155 gchar *query_str;
5156 GdaCommand *command;
5157 GdaDataModel *data;
5158 GString *info_data;
5159 GString *join_data;
5161 g_return_val_if_fail (dbe != NULL, NULL);
5162 g_return_val_if_fail (file_path != NULL, NULL);
5163 priv = dbe->priv;
5165 g_return_val_if_fail (priv->data_source != NULL, NULL);
5167 /* check for an already flagged sym_info with FILE_PATH. SYMINFO_FILE_PATH on
5168 * sym_info is already contained into the default query infos.
5170 sym_info = sym_info & ~SYMINFO_FILE_PATH;
5172 /* info_data contains the stuff after SELECT and befor FROM */
5173 info_data = g_string_new ("");
5175 /* join_data contains the optionals joins to do to retrieve new data on other
5176 * tables.
5178 join_data = g_string_new ("");
5180 /* fill info_data and join data with optional sql */
5181 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5183 /* rember to do a file_path + strlen(priv->data_source): a project relative
5184 * file path
5186 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5187 "symbol.file_position, "
5188 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5189 "JOIN file ON symbol.file_defined_id = file.file_id "
5190 "%s WHERE file.file_path = \"%s\"", info_data->str, join_data->str,
5191 file_path + strlen(priv->data_source));
5193 DEBUG_PRINT ("DYNAMIC query [file symbols] is %s", query_str);
5194 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
5195 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
5197 if ( (data = gda_connection_execute_select_command (priv->db_connection,
5198 command, NULL, NULL)) == NULL ||
5199 gda_data_model_get_n_rows (data) <= 0 )
5201 gda_command_free (command);
5202 g_free (query_str);
5203 return NULL;
5206 gda_command_free (command);
5207 g_free (query_str);
5208 g_string_free (info_data, FALSE);
5209 g_string_free (join_data, FALSE);
5211 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5215 SymbolDBEngineIterator *
5216 symbol_db_engine_get_symbol_info_by_id (SymbolDBEngine *dbe,
5217 gint sym_id, gint sym_info)
5219 SymbolDBEnginePriv *priv;
5220 gchar *query_str;
5221 GdaCommand *command;
5222 GdaDataModel *data;
5223 GString *info_data;
5224 GString *join_data;
5226 g_return_val_if_fail (dbe != NULL, NULL);
5227 priv = dbe->priv;
5229 /* info_data contains the stuff after SELECT and befor FROM */
5230 info_data = g_string_new ("");
5232 /* join_data contains the optionals joins to do to retrieve new data on other
5233 * tables.
5235 join_data = g_string_new ("");
5237 /* fill info_data and join data with optional sql */
5238 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5240 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5241 "symbol.file_position, "
5242 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5243 "%s WHERE symbol.symbol_id = %d", info_data->str, join_data->str,
5244 sym_id);
5246 /* DEBUG_PRINT ("DYNAMIC query is %s", query_str);*/
5247 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
5248 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
5250 if ( (data = gda_connection_execute_select_command (priv->db_connection,
5251 command, NULL, NULL)) == NULL ||
5252 gda_data_model_get_n_rows (data) <= 0 )
5254 gda_command_free (command);
5255 g_free (query_str);
5256 return NULL;
5259 gda_command_free (command);
5260 g_free (query_str);
5261 g_string_free (info_data, FALSE);
5262 g_string_free (join_data, FALSE);
5264 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5268 /* user must free the returned value */
5269 gchar*
5270 symbol_db_engine_get_full_local_path (SymbolDBEngine *dbe, const gchar* file)
5272 SymbolDBEnginePriv *priv;
5273 gchar *full_path;
5275 g_return_val_if_fail (dbe != NULL, NULL);
5277 priv = dbe->priv;
5278 /* DEBUG_PRINT ("joining %s with %s", priv->data_source, file);*/
5279 full_path = g_strdup_printf ("%s%s", priv->data_source, file);
5280 return full_path;
5284 SymbolDBEngineIterator *
5285 symbol_db_engine_find_symbol_by_name_pattern (SymbolDBEngine *dbe,
5286 const gchar *name, gint sym_info)
5288 SymbolDBEnginePriv *priv;
5289 gchar *query_str;
5290 GdaCommand *command;
5291 GdaDataModel *data;
5292 GString *info_data;
5293 GString *join_data;
5295 g_return_val_if_fail (dbe != NULL, NULL);
5296 priv = dbe->priv;
5298 /* info_data contains the stuff after SELECT and befor FROM */
5299 info_data = g_string_new ("");
5301 /* join_data contains the optionals joins to do to retrieve new data on other
5302 * tables.
5304 join_data = g_string_new ("");
5306 /* fill info_data and join data with optional sql */
5307 sdb_engine_prepare_symbol_info_sql (dbe, info_data, join_data, sym_info);
5309 query_str = g_strdup_printf ("SELECT symbol.symbol_id, symbol.name, "
5310 "symbol.file_position, "
5311 "symbol.is_file_scope, symbol.signature %s FROM symbol "
5312 "%s WHERE symbol.name LIKE \"%s%%\"", info_data->str, join_data->str,
5313 name);
5315 /* DEBUG_PRINT ("DYNAMIC query is %s", query_str);*/
5316 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
5317 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
5319 if ( (data = gda_connection_execute_select_command (priv->db_connection,
5320 command, NULL, NULL)) == NULL ||
5321 gda_data_model_get_n_rows (data) <= 0 )
5323 gda_command_free (command);
5324 g_free (query_str);
5325 return NULL;
5328 gda_command_free (command);
5329 g_free (query_str);
5330 g_string_free (info_data, FALSE);
5331 g_string_free (join_data, FALSE);
5333 return (SymbolDBEngineIterator *)symbol_db_engine_iterator_new (data);
5336 /* No iterator for now. We need the quickest query possible. */
5337 gint
5338 symbol_db_engine_get_parent_scope_id_by_symbol_id (SymbolDBEngine *dbe,
5339 gint scoped_symbol_id)
5342 select * from symbol where scope_definition_id = (
5343 select scope_id from symbol where symbol_id = 26
5347 /* again we're without prepared queries support from libgda... hope
5348 * you guys implement that asap..!
5350 SymbolDBEnginePriv *priv;
5351 gchar *query_str;
5352 GdaCommand *command;
5353 GdaDataModel *data;
5354 const GValue* value;
5356 g_return_val_if_fail (dbe != NULL, -1);
5357 priv = dbe->priv;
5359 query_str = g_strdup_printf ("SELECT symbol.symbol_id FROM symbol "
5360 "WHERE symbol.scope_definition_id = ( "
5361 "SELECT symbol.scope_id FROM symbol WHERE symbol.symbol_id = '%d')",
5362 scoped_symbol_id);
5364 DEBUG_PRINT ("symbol_db_engine_get_parent_scope_id_by_symbol_id() query is %s",
5365 query_str);
5366 command = gda_command_new (query_str, GDA_COMMAND_TYPE_SQL,
5367 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
5369 if ( (data = gda_connection_execute_select_command (priv->db_connection,
5370 command, NULL, NULL)) == NULL ||
5371 gda_data_model_get_n_rows (data) <= 0 )
5373 gda_command_free (command);
5374 g_free (query_str);
5375 DEBUG_PRINT ("BAILING OUT");
5376 return -1;
5379 gda_command_free (command);
5380 g_free (query_str);
5382 value = gda_data_model_get_value_at (data, 0, 0);
5383 gint res = value != NULL && G_VALUE_HOLDS_INT (value)
5384 ? g_value_get_int (value) : -1;
5385 g_object_unref (data);
5387 return res;