1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Naba Kumar 2010 <naba@gnome.org>
5 * Copyright (C) Massimo Cora' 2011 <maxcvs@email.it>
7 * anjuta is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * anjuta is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <libgda/gda-statement.h>
24 #include <libanjuta/anjuta-debug.h>
25 #include <libanjuta/interfaces/ianjuta-symbol-query.h>
26 #include "symbol-db-engine.h"
27 #include "symbol-db-query.h"
28 #include "symbol-db-query-result.h"
30 #define SYMBOL_DB_QUERY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
31 SYMBOL_DB_TYPE_QUERY, SymbolDBQueryPriv))
33 /* Class properties */
47 PROP_DB_ENGINE_SYSTEM
,
48 PROP_DB_ENGINE_PROJECT
,
49 PROP_DB_ENGINE_SELECTED
,
53 struct _SymbolDBQueryPriv
{
57 IAnjutaSymbolQueryName name
;
58 IAnjutaSymbolQueryMode mode
;
59 IAnjutaSymbolField fields
[IANJUTA_SYMBOL_FIELD_END
];
60 IAnjutaSymbolType filters
;
61 IAnjutaSymbolQueryFileScope file_scope
;
62 IAnjutaSymbolField group_by
;
63 IAnjutaSymbolField order_by
;
65 SymbolDBEngine
*dbe_system
;
66 SymbolDBEngine
*dbe_project
;
67 /* a reference to dbe_system or dbe_project */
68 SymbolDBEngine
*dbe_selected
;
69 GHashTable
*session_packages
;
73 GdaHolder
*param_pattern
, *param_file_path
, *param_limit
, *param_offset
;
74 GdaHolder
*param_file_line
, *param_id
;
77 gboolean query_queued
;
78 GAsyncQueue
*async_result_queue
;
81 gint async_cancel_count
;
82 gint async_result_count
;
85 /* Enumerated list of DB tables used in queries */
88 SDB_QUERY_TABLE_SYMBOL
,
90 SDB_QUERY_TABLE_IMPLEMENTATION
,
91 SDB_QUERY_TABLE_ACCESS
,
93 SDB_QUERY_TABLE_PROJECT
,
97 /* This array must map to each table enumerated above */
98 static gchar
*table_joins
[] =
101 "LEFT JOIN file ON symbol.file_defined_id = file.file_id",
102 "LEFT JOIN sym_implementation ON symbol.implementation_kind_id = sym_implementation.sym_impl_id",
103 "LEFT JOIN sym_access ON symbol.access_kind_id = sym_access.access_kind_id",
104 "LEFT JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id",
105 "LEFT JOIN file ON symbol.file_defined_id = file.file_id \
106 LEFT JOIN project ON file.prj_id = project.project_id",
109 /* Spec to associate a coloum to its table */
116 /* Association of all columns to its tables.
117 * This table must map to each IAnjutaSymbolField value
119 SdbQueryFieldSpec field_specs
[] = {
120 {"symbol.symbol_id ", SDB_QUERY_TABLE_SYMBOL
},
121 {"symbol.name ", SDB_QUERY_TABLE_SYMBOL
},
122 {"symbol.file_position ", SDB_QUERY_TABLE_SYMBOL
},
123 {"symbol.scope_definition_id ", SDB_QUERY_TABLE_SYMBOL
},
124 {"symbol.is_file_scope ", SDB_QUERY_TABLE_SYMBOL
},
125 {"symbol.signature ", SDB_QUERY_TABLE_SYMBOL
},
126 {"symbol.returntype ", SDB_QUERY_TABLE_SYMBOL
},
127 {"symbol.type_type ", SDB_QUERY_TABLE_SYMBOL
},
128 {"symbol.type_name ", SDB_QUERY_TABLE_SYMBOL
},
129 {"file.file_path ", SDB_QUERY_TABLE_FILE
},
130 {"project.project_name ", SDB_QUERY_TABLE_PROJECT
},
131 {"project.project_version ", SDB_QUERY_TABLE_PROJECT
},
132 {"sym_implementation.implementation_name ", SDB_QUERY_TABLE_IMPLEMENTATION
},
133 {"sym_access.access_name ", SDB_QUERY_TABLE_ACCESS
},
134 {"sym_kind.kind_name ", SDB_QUERY_TABLE_KIND
},
135 {"sym_kind.is_container ", SDB_QUERY_TABLE_KIND
}
138 /* FIXME: This maps to the bit position of IAnjutaSymbolType enum. This can
139 * easily get out of hand if IAnjutaSymbolType enum value and this is not
140 * associated more concretely through DB. To do it properly, get this list
141 * from database directly instead of hardcoding here.
143 static gchar
* kind_names
[] =
169 static void ianjuta_symbol_query_iface_init (IAnjutaSymbolQueryIface
*iface
);
171 G_DEFINE_TYPE_WITH_CODE (SymbolDBQuery
, sdb_query
, G_TYPE_OBJECT
,
172 G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_SYMBOL_QUERY
,
173 ianjuta_symbol_query_iface_init
));
175 * sdb_query_build_sql_head:
176 * @query: The query object
177 * @sql: The string where sql statement will be constructed.
179 * This creates SQL header like "SELECT ... FROM symbol LEFT JOIN ... WHERE ".
180 * It goes through the list of fields specified for the query and constructs
181 * the SELECT part. At the same time, also adds the necessary table joins
182 * needed for the columns.
185 sdb_query_build_sql_head (SymbolDBQuery
*query
, GString
*sql
)
189 gboolean tables_joined
[SDB_QUERY_TABLE_MAX
];
190 SymbolDBQueryPriv
*priv
;
191 IAnjutaSymbolField
*field_ptr
;
192 gboolean first_field
= TRUE
;
194 g_return_if_fail (SYMBOL_DB_IS_QUERY (query
));
195 g_return_if_fail (sql
!= NULL
);
197 priv
= SYMBOL_DB_QUERY (query
)->priv
;
198 g_return_if_fail (priv
->fields
!= 0);
200 /* Ensure the lookup tables are in order */
201 g_assert (G_N_ELEMENTS (table_joins
) == SDB_QUERY_TABLE_MAX
);
202 g_assert (G_N_ELEMENTS (field_specs
) == IANJUTA_SYMBOL_FIELD_END
);
204 /* Initialize table joins state to FALSE */
205 for (i
= 0; i
< SDB_QUERY_TABLE_MAX
; i
++)
206 tables_joined
[i
] = FALSE
;
208 /* "symbol" table is in-built, so skip it */
209 tables_joined
[SDB_QUERY_TABLE_SYMBOL
] = TRUE
;
211 g_string_assign (sql
, "SELECT ");
212 sql_joins
= g_string_sized_new (512);
214 /* For each field, construct the coloumns list and the necessary joins */
215 field_ptr
= priv
->fields
;
216 while (*field_ptr
!= IANJUTA_SYMBOL_FIELD_END
)
221 g_string_append (sql
, ", ");
223 g_string_append (sql
, field_specs
[*field_ptr
].column
);
224 if (tables_joined
[field_specs
[*field_ptr
].table
] == FALSE
)
226 g_string_append (sql_joins
,
227 table_joins
[field_specs
[*field_ptr
].table
]);
228 g_string_append (sql_joins
, " ");
229 tables_joined
[field_specs
[*field_ptr
].table
] = TRUE
;
233 g_string_append (sql
, " FROM symbol ");
234 g_string_append (sql
, sql_joins
->str
);
235 g_string_append (sql
, " WHERE ");
236 g_string_free (sql_joins
, TRUE
);
240 * sdb_query_build_sql_kind_filter:
242 * @sql: The string where filter SQL code is appended.
244 * Constructs the necessary sql conditional to filter the resultset to
245 * only those set to filtered symbol types. It will add a subquery to
246 * achieve this filter.
249 sdb_query_build_sql_kind_filter (SymbolDBQuery
*query
, GString
*sql
)
251 gboolean first
= TRUE
;
253 IAnjutaSymbolType filters
;
254 SymbolDBQueryPriv
*priv
;
256 g_return_if_fail (SYMBOL_DB_IS_QUERY (query
));
257 g_return_if_fail (sql
!= NULL
);
259 priv
= SYMBOL_DB_QUERY (query
)->priv
;
261 /* For each filter, identified by bit shifting filters mask, create
262 * SQL subquery to select only those symbol types.
264 filters
= priv
->filters
;
267 g_string_append (sql
, "AND (symbol.kind_id IN (SELECT sym_kind_id FROM sym_kind WHERE kind_name IN (");
273 if (first
) first
= FALSE
;
274 else g_string_append (sql
, ", ");
275 g_string_append (sql
, "'");
276 g_string_append (sql
, kind_names
[bit_count
]);
277 g_string_append (sql
, "'");
281 g_string_append (sql
, "))) ");
286 * sdb_query_add_field:
288 * @field: The field to add.
290 * Adds @field to current list of fields if it isn't already there.
291 * It is used to add additional required fields for some queries which the
292 * user may not have set himself.
295 sdb_query_add_field (SymbolDBQuery
*query
, IAnjutaSymbolField field
)
299 /* Iterate until the given field is found in the list, otherwise add it */
300 while (query
->priv
->fields
[idx
] != IANJUTA_SYMBOL_FIELD_END
)
302 if (query
->priv
->fields
[idx
] == field
)
306 query
->priv
->fields
[idx
] = field
;
307 query
->priv
->fields
[idx
+ 1] = IANJUTA_SYMBOL_FIELD_END
;
311 sdb_query_is_field_set (SymbolDBQuery
*query
, IAnjutaSymbolField field
)
315 for (i
= 0; i
< IANJUTA_SYMBOL_FIELD_END
; i
++)
317 if (query
->priv
->fields
[i
] == field
)
329 * Resets the query to unprepared status.
332 sdb_query_reset (SymbolDBQuery
*query
)
334 if (query
->priv
->stmt
)
335 g_object_unref (query
->priv
->stmt
);
336 query
->priv
->stmt
= NULL
;
337 g_free (query
->priv
->sql_stmt
);
338 query
->priv
->sql_stmt
= NULL
;
345 * Updates the SQL query based on latest set paramenters. Usually called
346 * after some parameter influencing the SQL contruct is changed. It will
347 * also attempt to compile the resulting SQL statement if possible, otherwise
348 * defer it for later when for database connection is established.
351 sdb_query_update (SymbolDBQuery
*query
)
353 const gchar
*condition
;
355 SymbolDBQueryPriv
*priv
;
357 g_return_if_fail (SYMBOL_DB_IS_QUERY (query
));
358 priv
= SYMBOL_DB_QUERY (query
)->priv
;
360 /* Prepare select conditions */
363 case IANJUTA_SYMBOL_QUERY_SEARCH
:
364 condition
= " (symbol.name LIKE ## /* name:'pattern' type:gchararray */) ";
366 case IANJUTA_SYMBOL_QUERY_SEARCH_ALL
:
367 condition
= "1 = 1 ";
369 case IANJUTA_SYMBOL_QUERY_SEARCH_FILE
:
371 (symbol.name LIKE ## /* name:'pattern' type:gchararray */) AND \
372 (symbol.file_defined_id IN \
376 WHERE file_path = ## /* name:'filepath' type:gchararray */ \
379 sdb_query_add_field (query
, IANJUTA_SYMBOL_FIELD_FILE_PATH
);
381 case IANJUTA_SYMBOL_QUERY_SEARCH_IN_SCOPE
:
383 (symbol.name LIKE ## /* name:'pattern' type:gchararray */ \
384 AND symbol.scope_id = \
386 SELECT scope_definition_id \
388 WHERE symbol_id = ## /* name:'symbolid' type:gint */ \
391 case IANJUTA_SYMBOL_QUERY_SEARCH_ID
:
392 condition
= "(symbol.symbol_id = ## /* name:'symbolid' type:gint */)";
394 case IANJUTA_SYMBOL_QUERY_SEARCH_MEMBERS
:
396 "(symbol.scope_id IN \
398 SELECT symbol.scope_definition_id \
400 WHERE symbol.symbol_id = ## /* name:'symbolid' type:gint */ \
402 AND symbol.scope_id > 0) ORDER BY symbol.name ";
404 case IANJUTA_SYMBOL_QUERY_SEARCH_CLASS_PARENTS
:
406 "(symbol.symbol_id IN \
408 SELECT heritage.symbol_id_base \
410 WHERE heritage.symbol_id_derived = ## /* name:'symbolid' type:gint */ \
413 case IANJUTA_SYMBOL_QUERY_SEARCH_SCOPE
:
415 "(file.file_path = ## /* name:'filepath' type:gchararray */ \
416 AND symbol.file_position <= ## /* name:'fileline' type:gint */) \
417 ORDER BY symbol.file_position DESC ";
418 sdb_query_add_field (query
, IANJUTA_SYMBOL_FIELD_FILE_PATH
);
419 g_object_set (query
, "limit", 1, NULL
);
421 case IANJUTA_SYMBOL_QUERY_SEARCH_PARENT_SCOPE
:
423 "(symbol.scope_definition_id IN \
425 SELECT symbol.scope_id \
427 WHERE symbol.symbol_id = ## /* name:'symbolid' type:gint */ \
429 g_object_set (query
, "limit", 1, NULL
);
431 case IANJUTA_SYMBOL_QUERY_SEARCH_PARENT_SCOPE_FILE
:
433 "(symbol.scope_definition_id IN \
435 SELECT symbol.scope_id \
437 WHERE symbol.symbol_id = ## /* name:'symbolid' type:gint */ \
438 ) AND file.file_path = ## /* name:'filepath' type:gchararray */) ";
439 sdb_query_add_field (query
, IANJUTA_SYMBOL_FIELD_FILE_PATH
);
440 g_object_set (query
, "limit", 1, NULL
);
443 g_warning ("Invalid query kind");
444 g_warn_if_reached ();
448 /* Build SQL statement */
449 sql
= g_string_new_len ("", 1024);
451 /* Add head of the SQL statement */
452 sdb_query_build_sql_head (query
, sql
);
454 /* Add condition of the SQL statement */
455 g_string_append (sql
, condition
);
457 /* Add symbol type filters of the SQL statement */
458 sdb_query_build_sql_kind_filter (query
, sql
);
460 /* Add filter for file scope */
461 switch (priv
->file_scope
)
463 case IANJUTA_SYMBOL_QUERY_SEARCH_FS_IGNORE
:
465 case IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE
:
466 g_string_append (sql
, "AND (symbol.is_file_scope = 1) ");
468 case IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC
:
469 g_string_append (sql
, "AND (symbol.is_file_scope = 0) ");
472 g_warn_if_reached ();
475 /* Group by clause */
476 if (priv
->group_by
!= IANJUTA_SYMBOL_FIELD_END
)
477 g_string_append_printf (sql
, "GROUP BY %s ", field_specs
[priv
->group_by
].column
);
479 /* Order by clause */
480 if (priv
->order_by
!= IANJUTA_SYMBOL_FIELD_END
)
481 g_string_append_printf (sql
, "ORDER BY %s ", field_specs
[priv
->order_by
].column
);
483 /* Add tail of the SQL statement */
484 g_string_append (sql
, "LIMIT ## /* name:'limit' type:gint */ ");
485 g_string_append (sql
, "OFFSET ## /* name:'offset' type:gint */ ");
487 /* Prepare statement */
488 g_free (priv
->sql_stmt
);
489 priv
->sql_stmt
= sql
->str
;
491 g_object_unref (priv
->stmt
);
493 /* If database is not connected, defer the statement compilation for later,
494 * otherwise compile it now.
496 if (symbol_db_engine_is_connected (priv
->dbe_selected
))
497 priv
->stmt
= symbol_db_engine_get_statement (priv
->dbe_selected
, sql
->str
);
500 g_string_free (sql
, FALSE
);
504 * sdb_query_execute_real:
507 * Executes the query for real. If for some reason, the SQL statement wasn't
508 * compiled before, it will be compiled now. Subsequent invocation would not
509 * require recompilation, unless some parameters involved in SQL contruct has
512 * Returns: Result set iterator.
514 static SymbolDBQueryResult
*
515 sdb_query_execute_real (SymbolDBQuery
*query
)
517 GdaDataModel
*data_model
;
518 SymbolDBQueryPriv
*priv
= query
->priv
;
520 if (!symbol_db_engine_is_connected (priv
->dbe_selected
))
522 g_warning ("Attempt to make a query when database is not connected");
523 return GINT_TO_POINTER (-1);
525 if (symbol_db_engine_is_scanning (priv
->dbe_selected
))
526 return GINT_TO_POINTER (-1);
529 sdb_query_update (query
);
530 else if (!priv
->stmt
)
531 priv
->stmt
= symbol_db_engine_get_statement (priv
->dbe_selected
,
533 data_model
= symbol_db_engine_execute_select (priv
->dbe_selected
,
537 if (!data_model
) return GINT_TO_POINTER (-1);
538 return symbol_db_query_result_new (data_model
,
540 symbol_db_engine_get_type_conversion_hash (priv
->dbe_selected
),
541 symbol_db_engine_get_project_directory (priv
->dbe_selected
));
545 sdb_query_handle_result (SymbolDBQuery
*query
, SymbolDBQueryResult
*result
)
547 if (GPOINTER_TO_INT (result
) == -1)
549 g_warning ("Error in executing query");
550 g_signal_emit_by_name (query
, "async-result", NULL
);
554 if (symbol_db_query_result_is_empty (result
))
556 g_signal_emit_by_name (query
, "async-result", NULL
);
560 g_signal_emit_by_name (query
, "async-result", result
);
563 g_object_unref (result
);
568 * The callback from async command. Reduces the currently pending async
569 * command invocation counts. If there are no more pending canceled commands
570 * anymore, then emits the "async-result" signal (because its not covered by
571 * the cancelation), otherwise, it reduces cancelable commands count.
574 on_sdb_query_async_poll (gpointer data
)
576 SymbolDBQueryResult
*result
;
577 SymbolDBQuery
*query
= SYMBOL_DB_QUERY (data
);
579 while ((result
= g_async_queue_try_pop (query
->priv
->async_result_queue
)))
581 query
->priv
->async_result_count
++;
582 if (query
->priv
->async_result_count
> query
->priv
->async_cancel_count
)
584 sdb_query_handle_result (query
, result
);
587 if (query
->priv
->async_result_count
< query
->priv
->async_run_count
)
588 return TRUE
; /* More results coming */
589 query
->priv
->async_poll_id
= 0;
590 return FALSE
; /* No more results coming */
594 * sdb_query_async_run:
595 * @command: The command.
597 * Implementation of anjuta_command_run(). Runs the async command, presumably
598 * from a different thread, and emits the data-arrived signal on command object.
601 sdb_query_async_run (gpointer data
)
604 SymbolDBQuery
*query
= SYMBOL_DB_QUERY (data
);
605 SymbolDBQueryPriv
*priv
= query
->priv
;
607 g_async_queue_ref (priv
->async_result_queue
);
608 queue
= priv
->async_result_queue
;
609 g_async_queue_push (queue
, sdb_query_execute_real (query
));
610 g_async_queue_unref (queue
);
612 g_object_unref (query
);
618 * @command: The async command.
620 * Implementation of anjuta_command_cancel().
621 * Cancels any currently executing async commands. Puts the currently pending
622 * async invocation count into pending cancel count, which will be eventually
623 * counted down to 0 without emitting "async-result" signal. Also, clears
624 * any pending query queue (for queued mode).
627 sdb_query_async_cancel (IAnjutaSymbolQuery
*query
, GError
**err
)
629 SymbolDBQueryPriv
*priv
;
631 g_return_if_fail (SYMBOL_DB_IS_QUERY (query
));
632 priv
= SYMBOL_DB_QUERY (query
)->priv
;
634 g_return_if_fail (priv
->mode
!= IANJUTA_SYMBOL_QUERY_MODE_SYNC
);
635 priv
->async_cancel_count
= priv
->async_run_count
;
636 priv
->query_queued
= FALSE
;
639 /* When the DB is connected, any pending SQL statement will be compiled */
641 on_sdb_query_dbe_connected (SymbolDBEngine
*dbe
, SymbolDBQuery
*query
)
643 g_return_if_fail (SYMBOL_DB_IS_QUERY (query
));
645 if (!query
->priv
->stmt
&& query
->priv
->sql_stmt
)
648 symbol_db_engine_get_statement (query
->priv
->dbe_selected
,
649 query
->priv
->sql_stmt
);
654 on_sdb_query_dbe_disconnected (SymbolDBEngine
*dbe
, SymbolDBQuery
*query
)
658 /* The callback for DB scan-end. Any queued query will be executed here */
660 on_sdb_query_dbe_scan_end (SymbolDBEngine
*dbe
, gint something
,
661 SymbolDBQuery
*query
)
663 g_return_if_fail (SYMBOL_DB_IS_QUERY (query
));
665 if (query
->priv
->mode
== IANJUTA_SYMBOL_QUERY_MODE_QUEUED
&&
666 query
->priv
->query_queued
&&
667 !symbol_db_engine_is_scanning (query
->priv
->dbe_selected
))
669 sdb_query_handle_result (query
, sdb_query_execute_real (query
));
670 query
->priv
->query_queued
= FALSE
;
678 * Executes the query. If the query is in sync mode, the query is executed
679 * immediately. If the query is in async mode, an async command is started
680 * and pending async count increased. If the query is in queued mode, the
681 * query is executed immediately if the DB is not busy scanning, otherwise,
682 * it is defered until the DB is done scanning (at which point "async-result"
685 * Returns: The resultset iterator for sync or successful queued queries,
686 * otherwise returns NULL for async or unsuccessful queued queries (their
687 * results will be delivered via "async-result" signal).
689 static IAnjutaIterable
*
690 sdb_query_execute (SymbolDBQuery
*query
)
692 SymbolDBQueryResult
*result
;
693 switch (query
->priv
->mode
)
695 case IANJUTA_SYMBOL_QUERY_MODE_SYNC
:
696 result
= sdb_query_execute_real (query
);
698 if (GPOINTER_TO_INT (result
) == -1) /* Error trap */
701 /* Empty resultset is useless for us. Return NULL instead */
702 if (result
== NULL
|| symbol_db_query_result_is_empty (result
))
705 g_object_unref (result
);
708 return IANJUTA_ITERABLE (result
);
709 case IANJUTA_SYMBOL_QUERY_MODE_ASYNC
:
710 query
->priv
->async_run_count
++;
711 if (query
->priv
->async_poll_id
== 0)
713 query
->priv
->async_poll_id
=
714 g_idle_add (on_sdb_query_async_poll
, query
);
716 g_thread_new ("SymbolDBQuery Thread", sdb_query_async_run
,
717 g_object_ref (query
));
719 case IANJUTA_SYMBOL_QUERY_MODE_QUEUED
:
720 query
->priv
->query_queued
= TRUE
;
722 /* FIXME: shoudn't be called with g_idle_add ? */
723 on_sdb_query_dbe_scan_end (NULL
, 0, query
);
726 g_warn_if_reached ();
732 sdb_query_init (SymbolDBQuery
*query
)
734 SymbolDBQueryPriv
*priv
;
736 GSList
*param_holders
= NULL
;
738 priv
= query
->priv
= SYMBOL_DB_QUERY_GET_PRIVATE(query
);
740 /* By default only ID and Name fields are enabled */
741 priv
->fields
[0] = IANJUTA_SYMBOL_FIELD_ID
;
742 priv
->fields
[1] = IANJUTA_SYMBOL_FIELD_NAME
;
743 priv
->fields
[2] = IANJUTA_SYMBOL_FIELD_END
;
745 priv
->group_by
= IANJUTA_SYMBOL_FIELD_END
;
746 priv
->order_by
= IANJUTA_SYMBOL_FIELD_END
;
748 /* Prepare sql parameter holders */
749 param
= priv
->param_pattern
= gda_holder_new_string ("pattern", "");
750 param_holders
= g_slist_prepend (param_holders
, param
);
752 param
= priv
->param_file_path
= gda_holder_new_string ("filepath", "");
753 param_holders
= g_slist_prepend (param_holders
, param
);
755 param
= priv
->param_limit
= gda_holder_new_int ("limit", INT_MAX
);
756 param_holders
= g_slist_prepend (param_holders
, param
);
758 param
= priv
->param_offset
= gda_holder_new_int ("offset", 0);
759 param_holders
= g_slist_prepend (param_holders
, param
);
761 param
= priv
->param_id
= gda_holder_new_int ("symbolid", 0);
762 param_holders
= g_slist_prepend (param_holders
, param
);
764 param
= priv
->param_file_line
= gda_holder_new_int ("fileline", 0);
765 param_holders
= g_slist_prepend (param_holders
, param
);
767 priv
->params
= gda_set_new (param_holders
);
768 g_slist_free (param_holders
);
770 /* Prepare async signals */
771 priv
->async_run_count
= 0;
772 priv
->async_cancel_count
= 0;
773 priv
->async_result_count
= 0;
774 priv
->query_queued
= FALSE
;
776 priv
->async_result_queue
= g_async_queue_new ();
780 sdb_query_dispose (GObject
*object
)
782 SymbolDBQueryPriv
*priv
;
784 priv
= SYMBOL_DB_QUERY (object
)->priv
;
785 if (priv
->dbe_selected
)
787 g_signal_handlers_disconnect_by_func (priv
->dbe_selected
,
788 on_sdb_query_dbe_scan_end
,
790 g_signal_handlers_disconnect_by_func (priv
->dbe_selected
,
791 on_sdb_query_dbe_connected
,
793 g_signal_handlers_disconnect_by_func (priv
->dbe_selected
,
794 on_sdb_query_dbe_disconnected
,
796 /* no need to unref dbe_selected */
797 priv
->dbe_selected
= NULL
;
799 if (priv
->dbe_system
)
801 g_object_unref (priv
->dbe_system
);
802 priv
->dbe_system
= NULL
;
804 if (priv
->dbe_project
)
806 g_object_unref (priv
->dbe_project
);
807 priv
->dbe_project
= NULL
;
811 g_object_unref (priv
->stmt
);
816 g_object_unref (priv
->params
);
819 if (priv
->async_result_queue
)
821 g_async_queue_unref (priv
->async_result_queue
);
822 priv
->async_result_queue
= NULL
;
824 if (priv
->async_poll_id
)
826 g_warning ("There are still running async threads!");
827 g_source_remove (priv
->async_poll_id
);
829 G_OBJECT_CLASS (sdb_query_parent_class
)->dispose (object
);
833 sdb_query_finalize (GObject
*object
)
835 SymbolDBQueryPriv
*priv
;
837 priv
= SYMBOL_DB_QUERY (object
)->priv
;
838 g_free (priv
->sql_stmt
);
839 G_OBJECT_CLASS (sdb_query_parent_class
)->finalize (object
);
843 sdb_query_set_property (GObject
*object
, guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
845 SymbolDBQuery
*query
;
846 SymbolDBQueryPriv
*priv
;
848 g_return_if_fail (SYMBOL_DB_IS_QUERY (object
));
849 query
= SYMBOL_DB_QUERY (object
);
854 case PROP_QUERY_NAME
:
855 priv
->name
= g_value_get_enum (value
);
856 sdb_query_reset (query
);
858 case PROP_QUERY_MODE
:
859 priv
->mode
= g_value_get_enum (value
);
862 priv
->filters
= g_value_get_int (value
);
863 sdb_query_reset (query
);
865 case PROP_FILE_SCOPE
:
866 priv
->file_scope
= g_value_get_enum (value
);
867 sdb_query_reset (query
);
870 gda_holder_set_value (priv
->param_limit
, value
, NULL
);
873 gda_holder_set_value (priv
->param_offset
, value
, NULL
);
876 priv
->group_by
= g_value_get_enum (value
);
877 sdb_query_reset (query
);
880 priv
->group_by
= g_value_get_enum (value
);
881 sdb_query_reset (query
);
883 case PROP_DB_ENGINE_SYSTEM
:
884 g_assert (priv
->dbe_system
== NULL
);
885 priv
->dbe_system
= g_value_get_object (value
);
887 case PROP_DB_ENGINE_PROJECT
:
888 g_assert (priv
->dbe_project
== NULL
);
889 priv
->dbe_project
= g_value_get_object (value
);
892 g_assert (priv
->dbe_project
!= NULL
);
893 g_assert (priv
->dbe_system
!= NULL
);
894 g_assert (priv
->dbe_selected
== NULL
);
895 switch (g_value_get_enum (value
))
897 case IANJUTA_SYMBOL_QUERY_DB_PROJECT
:
898 priv
->dbe_selected
= priv
->dbe_project
;
900 case IANJUTA_SYMBOL_QUERY_DB_SYSTEM
:
901 priv
->dbe_selected
= priv
->dbe_system
;
904 g_object_ref (priv
->dbe_project
);
905 g_object_ref (priv
->dbe_system
);
907 g_signal_connect (priv
->dbe_selected
, "scan-end",
908 G_CALLBACK (on_sdb_query_dbe_scan_end
), query
);
909 g_signal_connect (priv
->dbe_selected
, "db-connected",
910 G_CALLBACK (on_sdb_query_dbe_connected
), query
);
911 g_signal_connect (priv
->dbe_selected
, "db-disconnected",
912 G_CALLBACK (on_sdb_query_dbe_disconnected
), query
);
914 case PROP_SESSION_PACKAGES
:
915 priv
->session_packages
= g_value_get_pointer (value
);
918 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
924 sdb_query_get_property (GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
926 SymbolDBQueryPriv
*priv
;
928 g_return_if_fail (SYMBOL_DB_IS_QUERY (object
));
929 priv
= SYMBOL_DB_QUERY (object
)->priv
;
933 case PROP_QUERY_NAME
:
934 g_value_set_enum (value
, priv
->name
);
936 case PROP_QUERY_MODE
:
937 g_value_set_enum (value
, priv
->mode
);
940 g_value_set_int (value
, priv
->filters
);
942 case PROP_FILE_SCOPE
:
943 g_value_set_enum (value
, priv
->file_scope
);
946 g_value_set_object (value
, priv
->stmt
);
949 g_value_copy (gda_holder_get_value (priv
->param_limit
), value
);
952 g_value_copy (gda_holder_get_value (priv
->param_offset
), value
);
955 g_value_set_enum (value
, priv
->group_by
);
958 g_value_set_enum (value
, priv
->order_by
);
960 case PROP_DB_ENGINE_SYSTEM
:
961 g_value_set_object (value
, priv
->dbe_system
);
963 case PROP_DB_ENGINE_PROJECT
:
964 g_value_set_object (value
, priv
->dbe_project
);
966 case PROP_DB_ENGINE_SELECTED
:
967 g_value_set_object (value
, priv
->dbe_selected
);
970 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
976 sdb_query_class_init (SymbolDBQueryClass
*klass
)
978 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
980 g_type_class_add_private (klass
, sizeof (SymbolDBQueryPriv
));
982 object_class
->finalize
= sdb_query_finalize
;
983 object_class
->dispose
= sdb_query_dispose
;
984 object_class
->set_property
= sdb_query_set_property
;
985 object_class
->get_property
= sdb_query_get_property
;
987 g_object_class_install_property (object_class
,
988 PROP_DB_ENGINE_SYSTEM
,
989 g_param_spec_object ("db-engine-system",
991 "The System SymbolDBEngine",
992 SYMBOL_TYPE_DB_ENGINE
,
995 G_PARAM_CONSTRUCT_ONLY
));
996 g_object_class_install_property (object_class
,
997 PROP_DB_ENGINE_PROJECT
,
998 g_param_spec_object ("db-engine-project",
1000 "The Project SymbolDBEngine",
1001 SYMBOL_TYPE_DB_ENGINE
,
1004 G_PARAM_CONSTRUCT_ONLY
));
1006 g_object_class_install_property (object_class
,
1008 g_param_spec_enum ("query-name",
1011 IANJUTA_TYPE_SYMBOL_QUERY_NAME
,
1012 IANJUTA_SYMBOL_QUERY_SEARCH
,
1015 G_PARAM_CONSTRUCT_ONLY
));
1016 g_object_class_install_property (object_class
,
1018 g_param_spec_enum ("query-db",
1020 "The query database",
1021 IANJUTA_TYPE_SYMBOL_QUERY_DB
,
1022 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1024 G_PARAM_CONSTRUCT_ONLY
));
1025 g_object_class_install_property (object_class
,
1027 g_param_spec_enum ("query-mode",
1030 IANJUTA_TYPE_SYMBOL_QUERY_MODE
,
1031 IANJUTA_SYMBOL_QUERY_MODE_SYNC
,
1034 g_object_class_install_property (object_class
,
1036 g_param_spec_int ("filters",
1037 "Symbol type filters",
1038 "The symbol type filters",
1039 IANJUTA_SYMBOL_TYPE_NONE
,
1040 IANJUTA_SYMBOL_TYPE_MAX
,
1041 IANJUTA_SYMBOL_TYPE_NONE
,
1044 g_object_class_install_property (object_class
,
1046 g_param_spec_enum ("file-scope",
1048 "The file scope search",
1049 IANJUTA_TYPE_SYMBOL_QUERY_FILE_SCOPE
,
1050 IANJUTA_SYMBOL_QUERY_SEARCH_FS_IGNORE
,
1053 g_object_class_install_property (object_class
,
1055 g_param_spec_object ("statement",
1057 "The compiled query statement",
1061 g_object_class_install_property (object_class
,
1063 g_param_spec_int ("limit",
1065 "Limit to resultset",
1066 0, INT_MAX
, INT_MAX
,
1070 g_object_class_install_property (object_class
,
1072 g_param_spec_int ("offset",
1074 "Offset of begining of resultset",
1078 g_object_class_install_property (object_class
,
1080 g_param_spec_enum ("group-by",
1082 "Group by given field",
1083 IANJUTA_TYPE_SYMBOL_FIELD
,
1084 IANJUTA_SYMBOL_FIELD_END
,
1087 g_object_class_install_property (object_class
,
1089 g_param_spec_enum ("order-by",
1091 "Query order by given field",
1092 IANJUTA_TYPE_SYMBOL_FIELD
,
1093 IANJUTA_SYMBOL_FIELD_END
,
1097 g_object_class_install_property (object_class
,
1098 PROP_DB_ENGINE_SELECTED
,
1099 g_param_spec_object ("db-engine-selected",
1100 "Selected DB Engine",
1101 "The selected SymbolDBEngine",
1102 SYMBOL_TYPE_DB_ENGINE
,
1105 g_object_class_install_property (object_class
,
1106 PROP_SESSION_PACKAGES
,
1107 g_param_spec_pointer ("session-packages",
1109 "The session packages",
1113 // FIXMEPROP_SESSION_PACKAGES
1116 /* IAnjutaSymbolQuery implementation */
1119 sdb_query_set_fields (IAnjutaSymbolQuery
*query
, gint n_fields
,
1120 IAnjutaSymbolField
*fields
, GError
**err
)
1123 SymbolDBQueryPriv
*priv
;
1125 g_return_if_fail (SYMBOL_DB_IS_QUERY (query
));
1127 priv
= SYMBOL_DB_QUERY (query
)->priv
;
1129 /* Transfer the given list of column fields to internal array */
1130 for (i
= 0; i
< n_fields
; i
++)
1131 priv
->fields
[i
] = fields
[i
];
1132 priv
->fields
[i
] = IANJUTA_SYMBOL_FIELD_END
;
1133 sdb_query_reset (SYMBOL_DB_QUERY (query
));
1137 sdb_query_set_mode (IAnjutaSymbolQuery
*query
, IAnjutaSymbolQueryMode mode
,
1140 g_object_set (query
, "query-mode", mode
, NULL
);
1144 sdb_query_set_filters (IAnjutaSymbolQuery
*query
, IAnjutaSymbolType filters
,
1145 gboolean include_types
, GError
**err
)
1147 g_object_set (query
, "filters", filters
, NULL
);
1148 /* FIXME: include_types */
1152 sdb_query_set_limit (IAnjutaSymbolQuery
*query
, gint limit
, GError
**err
)
1154 g_object_set (query
, "limit", limit
, NULL
);
1158 sdb_query_set_offset (IAnjutaSymbolQuery
*query
, gint offset
, GError
**err
)
1160 g_object_set (query
, "offset", offset
, NULL
);
1164 sdb_query_set_group_by (IAnjutaSymbolQuery
*query
, IAnjutaSymbolField field
, GError
**err
)
1166 g_object_set (query
, "group-by", field
, NULL
);
1170 sdb_query_set_order_by (IAnjutaSymbolQuery
*query
, IAnjutaSymbolField field
, GError
**err
)
1172 g_object_set (query
, "order-by", field
, NULL
);
1176 sdb_query_set_file_scope (IAnjutaSymbolQuery
*query
,
1177 IAnjutaSymbolQueryFileScope file_scope
,
1180 g_object_set (query
, "file-scope", file_scope
, NULL
);
1183 /* Search queries */
1186 static IAnjutaIterable
*
1187 sdb_query_search (IAnjutaSymbolQuery
*query
, const gchar
*search_string
,
1190 SDB_QUERY_SEARCH_HEADER
;
1191 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH
, NULL
);
1192 SDB_PARAM_SET_STATIC_STRING (priv
->param_pattern
, search_string
);
1193 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1196 static IAnjutaIterable
*
1197 sdb_query_search_all (IAnjutaSymbolQuery
*query
, GError
**error
)
1199 SDB_QUERY_SEARCH_HEADER
;
1200 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_ALL
, NULL
);
1201 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1204 static IAnjutaIterable
*
1205 sdb_query_search_file (IAnjutaSymbolQuery
*query
, const gchar
*search_string
,
1206 const GFile
*file
, GError
**error
)
1208 const gchar
*rel_file_path
;
1209 gchar
*abs_file_path
;
1210 SDB_QUERY_SEARCH_HEADER
;
1211 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_FILE
, NULL
);
1213 abs_file_path
= g_file_get_path ((GFile
*)file
);
1214 rel_file_path
= symbol_db_util_get_file_db_path (priv
->dbe_selected
, abs_file_path
);
1216 SDB_PARAM_SET_STATIC_STRING (priv
->param_pattern
, search_string
);
1217 SDB_PARAM_SET_STATIC_STRING (priv
->param_file_path
, rel_file_path
);
1218 g_free (abs_file_path
);
1219 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1222 static IAnjutaIterable
*
1223 sdb_query_search_in_scope (IAnjutaSymbolQuery
*query
, const gchar
*search_string
,
1224 IAnjutaSymbol
*scope
, GError
**error
)
1226 SDB_QUERY_SEARCH_HEADER
;
1227 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_IN_SCOPE
, NULL
);
1228 SDB_PARAM_SET_STATIC_STRING (priv
->param_pattern
, search_string
);
1229 SDB_PARAM_SET_INT (priv
->param_id
, ianjuta_symbol_get_int (scope
, IANJUTA_SYMBOL_FIELD_ID
, NULL
));
1230 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1233 static IAnjutaIterable
*
1234 sdb_query_search_id (IAnjutaSymbolQuery
*query
, gint symbol_id
,
1237 SDB_QUERY_SEARCH_HEADER
;
1238 g_return_val_if_fail (symbol_id
> 0, NULL
);
1239 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_ID
, NULL
);
1241 SDB_PARAM_SET_INT (priv
->param_id
, symbol_id
);
1242 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1245 static IAnjutaIterable
*
1246 sdb_query_search_members (IAnjutaSymbolQuery
*query
, IAnjutaSymbol
*symbol
,
1249 SDB_QUERY_SEARCH_HEADER
;
1250 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_MEMBERS
, NULL
);
1252 SDB_PARAM_SET_INT (priv
->param_id
, ianjuta_symbol_get_int (symbol
, IANJUTA_SYMBOL_FIELD_ID
, NULL
));
1253 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1256 static IAnjutaIterable
*
1257 sdb_query_search_class_parents (IAnjutaSymbolQuery
*query
, IAnjutaSymbol
*symbol
,
1260 SDB_QUERY_SEARCH_HEADER
;
1261 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_CLASS_PARENTS
, NULL
);
1263 SDB_PARAM_SET_INT (priv
->param_id
, ianjuta_symbol_get_int (symbol
, IANJUTA_SYMBOL_FIELD_ID
, NULL
));
1264 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1267 static IAnjutaIterable
*
1268 sdb_query_search_scope (IAnjutaSymbolQuery
*query
, const gchar
*file_path
,
1269 gint file_line
, GError
**error
)
1271 const gchar
*db_relative_path
;
1272 SDB_QUERY_SEARCH_HEADER
;
1273 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_SCOPE
, NULL
);
1275 db_relative_path
= symbol_db_util_get_file_db_path (priv
->dbe_selected
, file_path
);
1276 if (db_relative_path
== NULL
)
1279 SDB_PARAM_SET_INT (priv
->param_file_line
, file_line
);
1280 SDB_PARAM_SET_STATIC_STRING (priv
->param_file_path
, db_relative_path
);
1281 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1284 static IAnjutaIterable
*
1285 sdb_query_search_parent_scope (IAnjutaSymbolQuery
*query
, IAnjutaSymbol
*symbol
,
1288 SDB_QUERY_SEARCH_HEADER
;
1289 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_PARENT_SCOPE
, NULL
);
1291 SDB_PARAM_SET_INT (priv
->param_id
, ianjuta_symbol_get_int (symbol
, IANJUTA_SYMBOL_FIELD_ID
, NULL
));
1292 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1295 static IAnjutaIterable
*
1296 sdb_query_search_parent_scope_file (IAnjutaSymbolQuery
*query
, IAnjutaSymbol
*symbol
,
1297 const gchar
*file_path
, GError
**error
)
1299 const gchar
*db_relative_path
;
1300 SDB_QUERY_SEARCH_HEADER
;
1301 g_return_val_if_fail (priv
->name
== IANJUTA_SYMBOL_QUERY_SEARCH_PARENT_SCOPE_FILE
, NULL
);
1303 db_relative_path
= symbol_db_util_get_file_db_path (priv
->dbe_selected
, file_path
);
1304 if (db_relative_path
== NULL
)
1307 SDB_PARAM_SET_INT (priv
->param_id
, ianjuta_symbol_get_int (symbol
, IANJUTA_SYMBOL_FIELD_ID
, NULL
));
1308 SDB_PARAM_SET_STATIC_STRING (priv
->param_file_path
, db_relative_path
);
1309 return sdb_query_execute (SYMBOL_DB_QUERY (query
));
1313 ianjuta_symbol_query_iface_init (IAnjutaSymbolQueryIface
*iface
)
1315 iface
->set_fields
= sdb_query_set_fields
;
1316 iface
->set_mode
= sdb_query_set_mode
;
1317 iface
->set_filters
= sdb_query_set_filters
;
1318 iface
->set_file_scope
= sdb_query_set_file_scope
;
1319 iface
->set_limit
= sdb_query_set_limit
;
1320 iface
->set_offset
= sdb_query_set_offset
;
1321 iface
->set_group_by
= sdb_query_set_group_by
;
1322 iface
->set_order_by
= sdb_query_set_order_by
;
1323 iface
->cancel
= sdb_query_async_cancel
;
1324 iface
->search
= sdb_query_search
;
1325 iface
->search_all
= sdb_query_search_all
;
1326 iface
->search_file
= sdb_query_search_file
;
1327 iface
->search_in_scope
= sdb_query_search_in_scope
;
1328 iface
->search_id
= sdb_query_search_id
;
1329 iface
->search_members
= sdb_query_search_members
;
1330 iface
->search_class_parents
= sdb_query_search_class_parents
;
1331 iface
->search_scope
= sdb_query_search_scope
;
1332 iface
->search_parent_scope
= sdb_query_search_parent_scope
;
1333 iface
->search_parent_scope_file
= sdb_query_search_parent_scope_file
;
1337 symbol_db_query_new (SymbolDBEngine
*system_db_engine
,
1338 SymbolDBEngine
*project_db_engine
,
1339 IAnjutaSymbolQueryName name
,
1340 IAnjutaSymbolQueryDb db
,
1341 GHashTable
*session_packages
)
1343 return g_object_new (SYMBOL_DB_TYPE_QUERY
,
1344 "db-engine-system", system_db_engine
,
1345 "db-engine-project", project_db_engine
,
1348 "session-packages", session_packages
,