[tracker/wip/carlosg/update-perf: 29/72] libtracker-sparql: Add function to get GValue array from a TrackerDBStatement




commit d34f5e2ca482640784a1bc523ce2ec6766b73af0
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun May 22 14:15:36 2022 +0200

    libtracker-sparql: Add function to get GValue array from a TrackerDBStatement
    
    All of our SELECT queries performed from the update machinery return a single
    column. Add a simple function that can handle returning an array of GValues
    for those cases, so we avoid the TrackerDBCursor GObject creation hot paths.

 .../core/tracker-db-interface-sqlite.c             | 113 +++++++++++++++++++++
 .../core/tracker-db-interface-sqlite.h             |   4 +
 2 files changed, 117 insertions(+)
---
diff --git a/src/libtracker-sparql/core/tracker-db-interface-sqlite.c 
b/src/libtracker-sparql/core/tracker-db-interface-sqlite.c
index 56dc573c6..1cc1269e2 100644
--- a/src/libtracker-sparql/core/tracker-db-interface-sqlite.c
+++ b/src/libtracker-sparql/core/tracker-db-interface-sqlite.c
@@ -3724,6 +3724,119 @@ tracker_db_statement_execute (TrackerDBStatement  *stmt,
        tracker_db_statement_sqlite_release (stmt);
 }
 
+GArray *
+tracker_db_statement_get_values (TrackerDBStatement   *stmt,
+                                 TrackerPropertyType   type,
+                                 GError              **error)
+{
+       gint result = SQLITE_OK;
+       GArray *values;
+
+       tracker_db_interface_lock (stmt->db_interface);
+       tracker_db_interface_ref_use (stmt->db_interface);
+       tracker_db_statement_sqlite_grab (stmt);
+
+#ifdef G_ENABLE_DEBUG
+        if (TRACKER_DEBUG_CHECK (SQL_STATEMENTS)) {
+               gchar *full_query;
+
+               full_query = sqlite3_expanded_sql (stmt->stmt);
+
+               if (full_query) {
+                       g_message ("Executing query: '%s'", full_query);
+                       sqlite3_free (full_query);
+               } else {
+                       g_message ("Executing query: '%s'",
+                                  sqlite3_sql (stmt->stmt));
+               }
+        }
+#endif
+
+       values = g_array_new (FALSE, TRUE, sizeof (GValue));
+       g_array_set_clear_func (values, (GDestroyNotify) g_value_unset);
+
+       while (TRUE) {
+               GError *inner_error = NULL;
+               GDateTime *datetime;
+               GValue gvalue = G_VALUE_INIT;
+
+               result = stmt_step (stmt->stmt);
+
+               if (result == SQLITE_DONE) {
+                       break;
+               } else if (result != SQLITE_ROW) {
+                       g_set_error (error,
+                                    TRACKER_DB_INTERFACE_ERROR,
+                                    TRACKER_DB_QUERY_ERROR,
+                                    "%s", sqlite3_errmsg (stmt->db_interface->db));
+                       g_clear_pointer (&values, g_array_unref);
+                       break;
+               }
+
+               if (sqlite3_column_type (stmt->stmt, 0) == SQLITE_NULL)
+                       continue;
+
+               switch (type) {
+               case TRACKER_PROPERTY_TYPE_UNKNOWN:
+               case TRACKER_PROPERTY_TYPE_STRING:
+                       g_value_init (&gvalue, G_TYPE_STRING);
+                       g_value_set_string (&gvalue, (gchar *) sqlite3_column_text (stmt->stmt, 0));
+                       break;
+               case TRACKER_PROPERTY_TYPE_LANGSTRING: {
+                       sqlite3_value *val = sqlite3_column_value (stmt->stmt, 0);
+                       gchar *text;
+
+                       text = g_strdup ((const gchar *) sqlite3_value_text (val));
+
+                       g_value_init (&gvalue, G_TYPE_BYTES);
+                       g_value_take_boxed (&gvalue,
+                                           g_bytes_new_with_free_func (text,
+                                                                       sqlite3_value_bytes (val),
+                                                                       g_free, text));
+                       break;
+               }
+               case TRACKER_PROPERTY_TYPE_DOUBLE:
+                       g_value_init (&gvalue, G_TYPE_DOUBLE);
+                       g_value_set_double (&gvalue, sqlite3_column_double (stmt->stmt, 0));
+                       break;
+               case TRACKER_PROPERTY_TYPE_BOOLEAN:
+               case TRACKER_PROPERTY_TYPE_INTEGER:
+               case TRACKER_PROPERTY_TYPE_RESOURCE:
+                       g_value_init (&gvalue, G_TYPE_INT64);
+                       g_value_set_int64 (&gvalue, sqlite3_column_int64 (stmt->stmt, 0));
+                       break;
+               case TRACKER_PROPERTY_TYPE_DATE:
+               case TRACKER_PROPERTY_TYPE_DATETIME:
+                       if (sqlite3_column_type (stmt->stmt, 0) == SQLITE_INTEGER) {
+                               datetime = g_date_time_new_from_unix_utc (sqlite3_column_int64 (stmt->stmt, 
0));
+                       } else {
+                               datetime = tracker_date_new_from_iso8601 ((const gchar *) sqlite3_column_text 
(stmt->stmt, 0),
+                                                                         &inner_error);
+                               if (!datetime)
+                                       break;
+                       }
+
+                       g_value_init (&gvalue, G_TYPE_DATE_TIME);
+                       g_value_take_boxed (&gvalue, datetime);
+                       break;
+               }
+
+               if (inner_error) {
+                       g_propagate_error (error, inner_error);
+                       g_clear_pointer (&values, g_array_unref);
+                       break;
+               }
+
+               g_array_append_val (values, gvalue);
+       }
+
+       tracker_db_statement_sqlite_release (stmt);
+       tracker_db_interface_unref_use (stmt->db_interface);
+       tracker_db_interface_unlock (stmt->db_interface);
+
+       return values;
+}
+
 TrackerDBCursor *
 tracker_db_statement_start_cursor (TrackerDBStatement  *stmt,
                                    GError             **error)
diff --git a/src/libtracker-sparql/core/tracker-db-interface-sqlite.h 
b/src/libtracker-sparql/core/tracker-db-interface-sqlite.h
index fedd27df3..265919045 100644
--- a/src/libtracker-sparql/core/tracker-db-interface-sqlite.h
+++ b/src/libtracker-sparql/core/tracker-db-interface-sqlite.h
@@ -94,6 +94,10 @@ gssize              tracker_db_interface_sqlite_release_memory         (TrackerD
 void                tracker_db_interface_ref_use   (TrackerDBInterface *db_interface);
 gboolean            tracker_db_interface_unref_use (TrackerDBInterface *db_interface);
 
+GArray * tracker_db_statement_get_values (TrackerDBStatement   *stmt,
+                                          TrackerPropertyType   type,
+                                          GError              **error);
+
 G_END_DECLS
 
 #endif /* __LIBTRACKER_DB_INTERFACE_SQLITE_H__ */


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