Commit adbcdade authored by Mikael Ottela's avatar Mikael Ottela

Abstraction layer to sqlite aggregate function-creation, new version of...

Abstraction layer to sqlite aggregate function-creation, new version of GROUP_CONCAT and some minor fixes

svn path=/trunk/; revision=2985
parent 28fd71f5
2009-02-26 Mikael Ottela <mikael.ottela@ixonos.com>
* src/libtracker-data/tracker-data-backup.c: Fixed some compilation
errors.
* src/libtracker-data/tracker-data-search.c: Minor fix to
concatenation dbus method.
* src/libtracker-db/tracker-db-interface-sqlite.c
* src/libtracker-db/tracker-db-interface-sqlite.h: Added
abstraction layer to sqlite aggregate function creation.
* src/libtracker-db/tracker-db-manager.c: Added a redefined version of
GROUP_CONCAT aggregate function.
2009-02-26 Carlos Garnacho <carlos@imendio.com>
* src/trackerd/tracker-daemon.c (tracker_daemon_get_status): Do not
......
......@@ -98,10 +98,10 @@ restore_backup_triple (gpointer user_data,
(gchar *)triple->predicate,
(gchar *)triple->object);
(data.func) ((const gchar *) triple->subject,
(const gchar *) triple->predicate,
(const gchar *) triple->object,
data->user_data);
(data->func) ((const gchar *) triple->subject,
(const gchar *) triple->predicate,
(const gchar *) triple->object,
data->user_data);
}
#endif /* HAVE_RAPTOR */
......@@ -160,10 +160,10 @@ tracker_data_backup_restore (const gchar *turtle_filename,
if (!g_file_test (turtle_filename, G_FILE_TEST_EXISTS)) {
g_set_error (error, 0, 0,
"Turtle file does not exist");
return;
return FALSE;
}
tracker_turtle_process (backup_file,
tracker_turtle_process (turtle_filename,
"/",
(TurtleTripleCallback) restore_backup_triple,
&data);
......
......@@ -1315,7 +1315,7 @@ tracker_data_search_get_unique_values_with_concat_count_and_sum (const gchar
g_string_free (sql_group, TRUE);
g_set_error (error, TRACKER_DBUS_ERROR, 0,
"Cannot sum '%s': this metadata type is not text",
"Cannot concatenate '%s': this metadata type is not text",
sum_field);
return NULL;
}
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Tracker - Sqlite implementation
* Copyright (C) 2008 Nokia
*
......@@ -24,6 +25,7 @@
typedef struct TrackerDBInterfaceSqlitePrivate TrackerDBInterfaceSqlitePrivate;
typedef struct SqliteFunctionData SqliteFunctionData;
typedef struct SqliteAggregateData SqliteAggregateData;
struct TrackerDBInterfaceSqlitePrivate {
gchar *filename;
......@@ -33,6 +35,7 @@ struct TrackerDBInterfaceSqlitePrivate {
GHashTable *procedures;
GSList *function_data;
GSList *aggregate_data;
guint in_transaction : 1;
guint ro : 1;
......@@ -43,6 +46,14 @@ struct SqliteFunctionData {
TrackerDBFunc func;
};
struct SqliteAggregateData {
TrackerDBInterface *interface;
guint context_size;
TrackerDBFuncStep step;
TrackerDBFuncFinal final;
};
static void tracker_db_interface_sqlite_iface_init (TrackerDBInterfaceIface *iface);
enum {
......@@ -59,7 +70,7 @@ G_DEFINE_TYPE_WITH_CODE (TrackerDBInterfaceSqlite, tracker_db_interface_sqlite,
void
tracker_db_interface_sqlite_enable_shared_cache (void)
{
sqlite3_enable_shared_cache (1);
sqlite3_enable_shared_cache (1);
}
static GObject *
......@@ -162,6 +173,9 @@ tracker_db_interface_sqlite_finalize (GObject *object)
g_slist_foreach (priv->function_data, (GFunc) g_free, NULL);
g_slist_free (priv->function_data);
g_slist_foreach (priv->aggregate_data, (GFunc) g_free, NULL);
g_slist_free (priv->aggregate_data);
sqlite3_close (priv->db);
g_message ("Closed sqlite3 database:'%s'", priv->filename);
......@@ -346,6 +360,114 @@ internal_sqlite3_function (sqlite3_context *context,
g_free (values);
}
static void
internal_sqlite3_aggregate_step (sqlite3_context *context,
int argc,
sqlite3_value *argv[])
{
SqliteAggregateData *data;
void *aggregate_context;
GValue *values;
GByteArray *blob_array;
gint i;
data = (SqliteAggregateData *) sqlite3_user_data (context);
values = g_new0 (GValue, argc);
/* Transform the arguments */
for (i = 0; i < argc; i++) {
switch (sqlite3_value_type (argv[i])) {
case SQLITE_TEXT:
g_value_init (&values[i], G_TYPE_STRING);
g_value_set_string (&values[i], (gchar *) sqlite3_value_text (argv[i]));
break;
case SQLITE_INTEGER:
g_value_init (&values[i], G_TYPE_INT);
g_value_set_int (&values[i], sqlite3_value_int (argv[i]));
break;
case SQLITE_FLOAT:
g_value_init (&values[i], G_TYPE_DOUBLE);
g_value_set_double (&values[i], sqlite3_value_double (argv[i]));
break;
case SQLITE_BLOB: {
gconstpointer blob;
gint size;
blob = sqlite3_value_blob (argv[i]);
size = sqlite3_value_bytes (argv[i]);
blob_array = g_byte_array_sized_new (size);
g_byte_array_append (blob_array, blob, size);
g_value_init (&values[i], TRACKER_TYPE_DB_BLOB);
g_value_take_boxed (&values[i], blob_array);
break;
}
default:
g_critical ("Unknown sqlite3 database value type:%d",
sqlite3_value_type (argv[i]));
}
}
aggregate_context = sqlite3_aggregate_context(context, data->context_size);
/* Call the function */
data->step (data->interface, aggregate_context, argc, values);
/* Now free all this mess */
for (i = 0; i < argc; i++) {
g_value_unset (&values[i]);
}
g_free (values);
}
static void
internal_sqlite3_aggregate_final (sqlite3_context *context)
{
SqliteAggregateData *data;
void *aggregate_context;
GValue result;
GByteArray *blob_array;
data = (SqliteAggregateData *) sqlite3_user_data (context);
aggregate_context = sqlite3_aggregate_context(context, 0);
/* Call the function */
result = data->final (data->interface, aggregate_context);
/* And return something appropriate to the context */
if (G_VALUE_HOLDS_INT (&result)) {
sqlite3_result_int (context, g_value_get_int (&result));
} else if (G_VALUE_HOLDS_DOUBLE (&result)) {
sqlite3_result_double (context, g_value_get_double (&result));
} else if (G_VALUE_HOLDS_STRING (&result)) {
sqlite3_result_text (context,
g_value_dup_string (&result),
-1, g_free);
} else if (G_VALUE_HOLDS (&result, TRACKER_TYPE_DB_BLOB)) {
blob_array = g_value_get_boxed (&result);
sqlite3_result_blob (context,
g_memdup (blob_array->data, blob_array->len),
blob_array->len,
g_free);
} else if (G_VALUE_HOLDS (&result, G_TYPE_INVALID)) {
sqlite3_result_null (context);
} else {
g_critical ("Sqlite3 returned type not managed:'%s'",
G_VALUE_TYPE_NAME (&result));
sqlite3_result_null (context);
}
/* Now free all this mess */
if (! G_VALUE_HOLDS (&result, G_TYPE_INVALID)) {
g_value_unset (&result);
}
}
static void
tracker_db_interface_sqlite_set_procedure_table (TrackerDBInterface *db_interface,
GHashTable *procedure_table)
......@@ -642,6 +764,32 @@ tracker_db_interface_sqlite_create_function (TrackerDBInterface *interface,
sqlite3_create_function (priv->db, name, n_args, SQLITE_ANY, data, &internal_sqlite3_function, NULL, NULL);
}
void
tracker_db_interface_sqlite_create_aggregate (TrackerDBInterface *interface,
const gchar *name,
TrackerDBFuncStep step,
gint n_args,
TrackerDBFuncFinal final,
guint context_size)
{
SqliteAggregateData *data;
TrackerDBInterfaceSqlitePrivate *priv;
priv = TRACKER_DB_INTERFACE_SQLITE_GET_PRIVATE (interface);
data = g_new0 (SqliteAggregateData, 1);
data->interface = interface;
data->context_size = context_size;
data->step = step;
data->final = final;
priv->aggregate_data = g_slist_prepend (priv->aggregate_data, data);
sqlite3_create_function (priv->db, name, n_args, SQLITE_ANY, data, NULL,
&internal_sqlite3_aggregate_step,
&internal_sqlite3_aggregate_final);
}
gboolean
tracker_db_interface_sqlite_set_collation_function (TrackerDBInterfaceSqlite *interface,
const gchar *name,
......
......@@ -42,6 +42,14 @@ typedef GValue (* TrackerDBFunc) (TrackerDBInterface *interface,
gint argc,
GValue argv[]);
typedef void (* TrackerDBFuncStep) (TrackerDBInterface *interface,
void *aggregate_context,
gint argc,
GValue argv[]);
typedef GValue (* TrackerDBFuncFinal) (TrackerDBInterface *interface,
void *aggregate_context);
struct TrackerDBInterfaceSqlite {
GObject parent_instance;
};
......@@ -59,6 +67,12 @@ void tracker_db_interface_sqlite_create_function (TrackerDBInterface *in
const gchar *name,
TrackerDBFunc func,
gint n_args);
void tracker_db_interface_sqlite_create_aggregate (TrackerDBInterface *interface,
const gchar *name,
TrackerDBFuncStep step,
gint n_args,
TrackerDBFuncFinal final,
guint context_size);
gboolean tracker_db_interface_sqlite_set_collation_function (TrackerDBInterfaceSqlite *interface,
const gchar *name,
TrackerDBCollationFunc func);
......
......@@ -79,6 +79,10 @@ typedef struct {
guint64 mtime;
} TrackerDBDefinition;
typedef struct {
GString *string; /* The string we are accumulating */
} AggregateData;
static TrackerDBDefinition dbs[] = {
{ TRACKER_DB_UNKNOWN,
TRACKER_DB_LOCATION_USER_DATA_DIR,
......@@ -1325,6 +1329,41 @@ function_regexp (TrackerDBInterface *interface,
return result;
}
static void
function_group_concat_step (TrackerDBInterface *interface,
void *aggregate_context,
gint argc,
GValue values[])
{
AggregateData *p = (AggregateData *)aggregate_context;
g_assert (argc==1);
if (!p->string) {
p->string = g_string_new ("");
} else {
p->string = g_string_append (p->string, "|");
}
p->string = g_string_append (p->string, g_value_get_string (&values[0]));
}
static GValue
function_group_concat_final (TrackerDBInterface *interface,
void *aggregate_context)
{
GValue result = { 0, };
AggregateData *p = (AggregateData *)aggregate_context;
g_value_init (&result, G_TYPE_STRING);
g_value_set_string (&result, p->string->str);
g_string_free (p->string, TRUE);
return result;
}
static GValue
function_get_service_name (TrackerDBInterface *interface,
gint argc,
......@@ -1697,6 +1736,14 @@ db_set_params (TrackerDBInterface *iface,
"replace",
function_replace,
3);
tracker_db_interface_sqlite_create_aggregate (iface,
"group_concat",
function_group_concat_step,
1,
function_group_concat_final,
sizeof(AggregateData));
tracker_db_interface_sqlite_create_function (iface,
"CollateKey",
function_collate_key,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment