/**
 * midgard_replicator_export:
 * @object: #MidgardDBObject instance
 *
 * Given object is not serialized. Its storage record is marked as exported.
 * 
 * @see midgard_object_update() to find out possible error codes returned in case of #MidgardObject failure.
 *
 * Returns: %TRUE on success, %FALSE otherwise.
 */ 
gboolean 
midgard_replicator_export (MidgardDBObject *object) 
{
	g_return_val_if_fail (object != NULL, FALSE);

	MidgardConnection *mgd = MGD_OBJECT_CNC(object);
	g_return_val_if_fail (mgd != NULL, FALSE);

	const gchar *guid = MGD_OBJECT_GUID(object);

	if (guid == NULL){
	
		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_INVALID_PROPERTY_VALUE, "Empty guid value! ");
		return FALSE;
	}

	/* FIXME, invoke update as MidgardDBObject virtual method */
	if (MIDGARD_IS_OBJECT (object)) {
		
		g_signal_emit(object, MIDGARD_OBJECT_GET_CLASS(object)->signal_action_export, 0);
		return _midgard_object_update(MIDGARD_OBJECT(object), OBJECT_UPDATE_EXPORTED, NULL);
	}
	
	return FALSE;
}
Esempio n. 2
0
/**
 * midgard_connection_open_config:
 * @self: [in]newly initialized #MidgardConnection object
 * @config: #MidgardConfig object
 *
 * Opens a #MidgardConnection with the given configuration. 
 *
 * Take a look at midgard_connection_open() wrt #MidgardSchema.
 *
 * If #MidgardConnection is already associated with given config, method returns %TRUE.
 * If associated with another one, %FALSE is returned and MGD_ERR_INTERNAL error is set.
 *
 * Returns: %TRUE on success, %FALSE otherwise
 */
gboolean midgard_connection_open_config(
		MidgardConnection *self, MidgardConfig *config)
{
	g_assert(self != NULL);	
	g_assert(config != NULL);

	MidgardConfig *self_config = self->priv->config;
	gboolean rv = TRUE;

	__SELF_REOPEN (self, rv);
	if (!rv) 
		return rv;

	/* Emulate the same config pointer, as we have copy associated */
	if (self_config 
			&& (g_str_equal (self_config->database, config->database)
				&& g_str_equal (self_config->dbtype, config->dbtype)
				&& g_str_equal (self_config->host, config->host))) {
		return TRUE;
	} else if (self_config) {
		MIDGARD_ERRNO_SET_STRING (self, MGD_ERR_INTERNAL, "Midgard connection already associated with configuration");
		return FALSE;
	}

	self->priv->config = midgard_config_copy (config);

	GHashTable *hash = NULL;

	if(!__midgard_connection_open(self, &hash, TRUE))
		rv = FALSE;

	if(hash)
		g_hash_table_destroy(hash);

	return rv;
}
Esempio n. 3
0
gboolean __midgard_connection_open(
		MidgardConnection *mgd, 
		GHashTable **hashtable, gboolean init_schema)
{
	g_return_val_if_fail(mgd != NULL, FALSE);

	MIDGARD_ERRNO_SET (mgd, MGD_ERR_OK);

	gchar *host, *dbname, *dbuser, *dbpass, *loglevel, *tmpstr;
	guint port = 0;
	gchar *auth = NULL;
	MidgardConfig *config = mgd->priv->config;
	host = config->host;
	dbname = config->database;
	dbuser = config->dbuser;
	dbpass = config->dbpass;
	loglevel = config->loglevel;
	port = config->dbport;
	gboolean enable_threads = config->gdathreads;

	/* Get 30% performance boost for non threaded applications */
	if(!enable_threads) 
		g_setenv("LIBGDA_NO_THREADS", "yes", TRUE);

	/* Initialize libgda */
	gda_init ();

	midgard_connection_set_loglevel(mgd, loglevel, NULL);

	if(config->priv->dbtype == MIDGARD_DB_TYPE_SQLITE) {

		gchar *path = NULL;
		gchar *dbdir = config->dbdir;
		if (!dbdir || *dbdir == '\0') {
			const gchar *sqlite_dir[] = {"data", NULL};
			path = midgard_core_config_build_path(sqlite_dir, NULL, TRUE);
		} else {
			path = g_strdup(dbdir);
		}

		tmpstr = g_strconcat("DB_DIR=", path, ";", "DB_NAME=", dbname, NULL);
		g_free(path);

	} else if (config->priv->dbtype == MIDGARD_DB_TYPE_ORACLE) {

		GString *cnc = g_string_sized_new(100);
		cnc_add_part(cnc, "TNSNAME", dbname, MGD_MYSQL_HOST);
		cnc_add_part(cnc, "HOST", host, MGD_MYSQL_HOST);
		cnc_add_part(cnc, "DB_NAME", dbname, MGD_MYSQL_DATABASE);
		tmpstr = g_string_free(cnc, FALSE);
		cnc = g_string_sized_new(100);
		cnc_add_part(cnc, "USERNAME", dbuser, MGD_MYSQL_USERNAME);
		cnc_add_part(cnc, "PASSWORD", dbpass, MGD_MYSQL_PASSWORD);
		auth = g_string_free(cnc, FALSE);

	} else { 
		
		GString *cnc = g_string_sized_new(100);
		cnc_add_part(cnc, "HOST", host, MGD_MYSQL_HOST);

		if (port > 0) {

			GString *_strp = g_string_new("");
			g_string_append_printf (_strp, "%d", port);
			cnc_add_part (cnc, "PORT", _strp->str, "");
			g_string_free (_strp, TRUE);
		}

		cnc_add_part(cnc, "DB_NAME", dbname, MGD_MYSQL_DATABASE);
		tmpstr = g_string_free(cnc, FALSE);
		GString *auth_str = g_string_sized_new(100);
		cnc_add_part(auth_str, "USERNAME", dbuser, MGD_MYSQL_USERNAME);
		cnc_add_part(auth_str, "PASSWORD", dbpass, MGD_MYSQL_PASSWORD);
		auth = g_string_free(auth_str, FALSE);
	}

	GError *error = NULL;
	GdaConnection *connection = gda_connection_open_from_string(
			config->dbtype, tmpstr, auth, GDA_CONNECTION_OPTIONS_NONE, &error);
	g_free(auth);	

	if(connection == NULL) {

		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_NOT_CONNECTED, 
				" Database [%s]. %s", tmpstr, error->message);

		g_free(tmpstr);

		return FALSE;
	
	} 

	g_free(tmpstr);

	mgd->priv->parser = gda_connection_create_parser (connection);
	if (!mgd->priv->parser)
		mgd->priv->parser = gda_sql_parser_new();
	g_assert (mgd->priv->parser != NULL);

	mgd->priv->connection = connection;
	midgard_core_connection_connect_error_callback (mgd);	

	if(init_schema) {
		
		if(!g_type_from_name("midgard_quota")) {
			
			MidgardSchema *schema = g_object_new(MIDGARD_TYPE_SCHEMA, NULL);
			gchar *path = g_build_path(G_DIR_SEPARATOR_S, config->sharedir, "MidgardObjects.xml", NULL);
			midgard_schema_init(schema, (const gchar *)path);
			g_free(path);
			midgard_schema_read_dir(schema, config->sharedir);
			
			mgd->priv->schema = schema;
		}
	}

	//midgard_connection_set_loglevel(mgd, loglevel, NULL);

	/* Loads available authentication types */
	midgard_core_connection_initialize_auth_types(mgd);

	g_signal_emit (mgd, MIDGARD_CONNECTION_GET_CLASS (mgd)->signal_id_connected, 0);

	return TRUE;
}
Esempio n. 4
0
GList *
midgard_core_qb_set_object_from_query (MidgardQueryBuilder *builder, guint select_type, MidgardObject **nobject)
{
        g_assert(builder != NULL);
 
        guint ret_rows, ret_fields;
	MidgardConnection *mgd = builder->priv->mgd;
      
	gchar *sql = midgard_core_qb_get_sql(
			builder, select_type, 
			midgard_query_builder_get_object_select(builder, select_type));

	GSList *olist = NULL;
	MidgardDBObjectClass *dbklass = MIDGARD_DBOBJECT_CLASS(g_type_class_peek(builder->priv->type));

	if (!dbklass) {

		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_INTERNAL, "Failed to peek MidgardDBObjectClass pointer");
		return NULL;
	}

	if (dbklass->dbpriv->set_from_sql) {

		if (select_type != MQB_SELECT_GUID) {

			olist = dbklass->dbpriv->set_from_sql(mgd, builder->priv->type, ((const gchar *)sql));
			g_free(sql);

			return (GList *)olist;
		}
	}

	GdaDataModel *model = midgard_core_query_get_model(builder->priv->mgd, sql);
	g_free(sql);

	if(!model) 
		return NULL;	

	MidgardObject *object = NULL;
	gint rows, columns;
	const GValue *gvalue = NULL;

	ret_rows = gda_data_model_get_n_rows(model);
	ret_fields =  gda_data_model_get_n_columns(model);

	/* records found , allocate as many objects as many returned rows */ 
	GList *list = NULL;

	if(ret_rows == 0) {
		g_object_unref(model);
		return list;
	}

	/* We count rows only */
	if(select_type == MQB_SELECT_GUID) {
		
		gvalue = midgard_data_model_get_value_at(model, 0, 0);	
	
		if (!gvalue || !G_IS_VALUE (gvalue)) {
			
			g_object_unref (model);
			return 0;
		}

		MidgardTypeHolder *holder = g_new(MidgardTypeHolder, 1);

		GValue val = {0, };
		g_value_init (&val, G_TYPE_INT64);
		g_value_transform (gvalue, &val);

		holder->elements = (guint)g_value_get_int64((GValue*)&val);
		
		list = g_list_append(list, holder);	
		
		g_object_unref(model);
		g_value_unset (&val);

		return list;		
	}

	/* Get every row */
	for (rows = 0; rows < ret_rows; rows++) {
	
		if(!nobject)
			object = g_object_new (builder->priv->type, "connection", mgd, NULL);
		else 
			object = *nobject;

		MGD_OBJECT_IN_STORAGE (object) = TRUE;	
				
		if(dbklass->dbpriv->__set_from_sql != NULL) {
			
			dbklass->dbpriv->__set_from_sql(MIDGARD_DBOBJECT(object), 
					model, rows); 

		} else {
		
			/* Compute number of metadata properties */
			guint n_md_props = 0;
			MidgardMetadata *mklass = (MidgardMetadata *)MGD_DBCLASS_METADATA_CLASS (dbklass);
			if (mklass) 
				n_md_props = g_hash_table_size (MGD_DBCLASS_STORAGE_DATA (mklass)->prophash);

			guint __cols = n_md_props + 1; /* Add one for guid */

			/* we have guid and metadata columns first */
			for (columns = __cols; columns < ret_fields; columns++) {	
				
				gvalue = midgard_data_model_get_value_at(model, columns, rows);
				const gchar *coltitle =
					gda_data_model_get_column_title(model, columns);
				GParamSpec *pspec =
					g_object_class_find_property(G_OBJECT_GET_CLASS(object), coltitle);

				if(G_IS_VALUE(gvalue)) {

					if (!pspec) {
						
						g_warning("Failed to found (unregistered) %s property (%s class)", 
								coltitle, G_OBJECT_TYPE_NAME(object));
						continue;
					}

					if (G_VALUE_TYPE (gvalue) == GDA_TYPE_BINARY
							&& G_TYPE_FUNDAMENTAL (pspec->value_type) == G_TYPE_STRING) {

						gchar *stringified = midgard_core_query_binary_stringify ((GValue *)gvalue);
						g_object_set (G_OBJECT (object), coltitle, stringified, NULL);
				   		g_free (stringified);
					
					} else if (pspec->value_type != G_VALUE_TYPE (gvalue)) {

						GValue _convert = {0, };
						g_value_init (&_convert, pspec->value_type);	
				
						if (g_value_transform (gvalue, &_convert)) {

							/* FIXME, remove workaround once it's fixed in GDA */
							/* https://bugzilla.gnome.org/show_bug.cgi?id=617550 */
							guint dbtype = mgd->priv->config->priv->dbtype;
							if (dbtype == MIDGARD_DB_TYPE_MYSQL && G_VALUE_TYPE (gvalue) == GDA_TYPE_BLOB) {
								gchar *tmp_str = __default_unescape_string (g_value_get_string (&_convert));
								if (tmp_str)
									g_value_take_string (&_convert, tmp_str);
							}

							g_object_set_property (G_OBJECT (object), coltitle, &_convert);
					
						} else {

							g_warning ("Failed to convert %s to %s for %s property",
									G_VALUE_TYPE_NAME (gvalue),
									G_VALUE_TYPE_NAME (&_convert), 
									coltitle);
						}

						g_value_unset (&_convert);

					} else {

						g_object_set_property(G_OBJECT(object), coltitle, gvalue);
					}	
				
				} else if (gda_value_is_null(gvalue)) {			

					switch (pspec->value_type) {

						case G_TYPE_INT:
						case G_TYPE_UINT:
							g_object_set(G_OBJECT(object), coltitle, 0, NULL);
							break;

						case G_TYPE_STRING:
							g_object_set(G_OBJECT(object), coltitle, "", NULL);
							break;

						default:
							g_warning("Found (%s) not a value at %d.%d (%s)", 
									g_type_name(pspec->value_type), 
									columns, rows, 
									gda_data_model_get_column_title(model, columns));
							break;
					}
				}
			}	
		}

		/* Set guid */
		const gchar *guid;
		gvalue = midgard_data_model_get_value_at(model, 0, rows);
		if(G_IS_VALUE(gvalue) && G_VALUE_HOLDS_STRING(gvalue)){
			guid = g_value_get_string(gvalue);   
			g_free((gchar *)MIDGARD_DBOBJECT(object)->dbpriv->guid);
			MIDGARD_DBOBJECT(object)->dbpriv->guid = g_strdup(guid);
		}
		
		/* Set metadata */
		MidgardMetadata *metadata = MGD_DBOBJECT_METADATA (object);
	     	if (metadata) {
			GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(object), "metadata");
			if (pspec)
				__mqb_set_metadata(metadata, model, rows);
		}	

		list = g_list_append(list, G_OBJECT(object));                		
	}

	g_object_unref(model);
	return list;	
}
/**
 * midgard_replicator_import_object:
 * @object: #MidgardDBObject instance
 * @force: toggle to force import
 *
 * Imports given object to underlying storage
 *
 * Cases to return %FALSE:
 * <itemizedlist>
 * <listitem><para>
 * Given guid is NULL or empty string (MGD_ERR_INVALID_PROPERTY_VALUE)
 * </para></listitem>
 * <listitem><para>
 * Object is already imported (MGD_ERR_OBJECT_IMPORTED)
 * </para></listitem>
 * <listitem><para>
 * Object identified is deleted (MGD_ERR_OBJECT_DELETED)
 * </para></listitem>
 * <listitem><para>
 * Object doesn't provide metadata one (MGD_ERR_NO_METADATA)
 * </para></listitem>
 * </itemizedlist>
 *
 * Set @force toggle if you want to import object even if it's already imported or deleted.
 *
 * Returns: %TRUE on success, %FALSE otherwise
 */ 
gboolean 
midgard_replicator_import_object (MidgardDBObject *object, gboolean force)
{	
	MidgardConnection *mgd = MGD_OBJECT_CNC (object);
	const gchar *guid = MGD_OBJECT_GUID (object);

	g_return_val_if_fail (mgd != NULL, FALSE);
	g_return_val_if_fail (g_type_is_a (G_OBJECT_TYPE (object), MIDGARD_TYPE_DBOBJECT), FALSE);

	MIDGARD_ERRNO_SET(object->dbpriv->mgd, MGD_ERR_OK);
	gboolean ret_val = FALSE;

	if (guid == NULL || (guid && *guid == '\0')) {		
		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_INVALID_PROPERTY_VALUE, "NULL or empty guid");
		return ret_val;
	}

	MidgardMetadata *dbmetadata = NULL;
	MidgardMetadata *metadata = MGD_DBOBJECT_METADATA (object);
	if (!metadata) {
		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_NO_METADATA, "Metadata class not available.");
		return ret_val;
	}

	g_signal_emit(object, MIDGARD_OBJECT_GET_CLASS(object)->signal_action_import, 0);

	/* Get object from database */
	MidgardQueryBuilder *builder = midgard_query_builder_new(mgd, G_OBJECT_TYPE_NAME(object));
	if(!builder)
		return FALSE;

	GValue pval = {0, };
	/* Add guid constraint */
	g_value_init(&pval,G_TYPE_STRING);
	g_object_get_property(G_OBJECT(object), "guid", &pval);
	midgard_query_builder_add_constraint(builder, "guid", "=", &pval);
	g_value_unset(&pval);
	
	/* Get db object which is "elder" than imported one */
	/*
	g_value_init(&pval,G_TYPE_STRING);
	g_object_get_property(G_OBJECT(object->metadata), "revised", &pval);
	midgard_query_builder_add_constraint(builder, 
			"metadata.revised", "<", &pval);
	g_value_unset(&pval);
	*/

	/* Get deleted or undeleted object */
	midgard_query_builder_include_deleted (builder);

	guint n_objects;
	GObject **_dbobjects = midgard_query_builder_execute (builder, &n_objects);
	MidgardObject *dbobject;

	if (!_dbobjects){
	
		g_object_unref (G_OBJECT (builder));
		
		if ((mgd->errnum == MGD_ERR_OBJECT_PURGED) && force) {

			/* we need to delete repligard entry here 
			 * In any other case we need to change core's API a bit
			 * and make create method more complicated with 
			 * additional needless cases */

			GString *sql = g_string_new ("DELETE from repligard WHERE ");
			g_string_append_printf (sql,
					"typename = '%s' AND guid = '%s' ",
					G_OBJECT_TYPE_NAME (object),
					MGD_OBJECT_GUID (object));
			midgard_core_query_execute (MGD_OBJECT_CNC (object), sql->str, TRUE);
			g_string_free (sql, TRUE);
			
			ret_val =  _midgard_object_create (MIDGARD_OBJECT (object), MGD_OBJECT_GUID (object), OBJECT_UPDATE_IMPORTED);		
			return ret_val;
		}

		if (mgd->errnum == MGD_ERR_NOT_EXISTS || mgd->errnum == MGD_ERR_OK) {

			ret_val =  _midgard_object_create (MIDGARD_OBJECT(object), MGD_OBJECT_GUID(object), OBJECT_UPDATE_IMPORTED);
			return ret_val;
		}

	} else {

		gchar *updated, *dbupdated;
		dbobject = (MidgardObject *)_dbobjects[0];
		g_free (_dbobjects);

		GValue updated_timestamp = {0, };
		g_value_init (&updated_timestamp, MGD_TYPE_TIMESTAMP);
		GValue dbupdated_timestamp = {0, };
		g_value_init (&dbupdated_timestamp, MGD_TYPE_TIMESTAMP);
		
		metadata = MGD_DBOBJECT_METADATA (object);
		dbmetadata = MGD_DBOBJECT_METADATA (dbobject);

		/* Compare revised datetimes. We must know if imported 
		 * object is newer than that one which exists in database */
		g_object_get_property (G_OBJECT (metadata), "revised", &updated_timestamp);
		g_object_get_property (G_OBJECT (dbmetadata), "revised", &dbupdated_timestamp);

		updated = midgard_timestamp_get_string_from_value ((const GValue *)&updated_timestamp);
		dbupdated = midgard_timestamp_get_string_from_value ((const GValue *)&dbupdated_timestamp);

		g_value_unset (&updated_timestamp);
		g_value_unset (&dbupdated_timestamp);

		/* We can use g_ascii_strcasecmp as it type cast every single 
		 * pointer to integer and unsigned char returning substract result */		
		gint datecmp;
	
	     	if (updated == NULL) {

			g_warning ("Trying to import ivalid object. metadata.revised property holds NULL (Object: %s)", 
					MGD_OBJECT_GUID (object));

			if (dbupdated)
				g_free (dbupdated);

			g_object_unref (dbobject);

			return FALSE;
		}

		if (dbupdated == NULL) {

			g_warning ("Trying to import object for invalid object stored in database. metadata.revised property holds NULL (Database object:%s)", MGD_OBJECT_GUID (object));

			if (updated)
				g_free (updated);

			g_object_unref (dbobject);

			return FALSE;
		}

		if (force) {

			datecmp = -1;
		
		} else {
			
			datecmp = g_ascii_strcasecmp ((const gchar *)dbupdated, (const gchar *)updated);
		}

		g_free(updated);
		g_free(dbupdated);

		gboolean deleted;
		gboolean ret;

		if (datecmp > 0 || datecmp == 0) {
			
			/* Database object is more recent or exactly the same */	
			g_object_unref (dbobject);	
			MIDGARD_ERRNO_SET (mgd, MGD_ERR_OBJECT_IMPORTED);
	
			return FALSE;

		} else if (datecmp < 0) {
			
			/* Database object is elder */	
			
			/* DELETE */
			g_object_get (G_OBJECT (metadata), "deleted", &deleted, NULL);
			/* Imported object is marked as deleted , so 
			 * * we delete object from database */
			if (deleted) {

				ret = midgard_object_delete (dbobject, FALSE);
				g_object_unref (dbobject);
				return ret;
			}

			/* UPDATE */
		
			MidgardMetadata *db_metadata = MGD_DBOBJECT_METADATA (dbobject);

			/* Check if dbobject is deleted */
			g_object_get (db_metadata, "deleted", &deleted, NULL);

			guint undelete;
			g_object_get (G_OBJECT (metadata), "deleted", &undelete, NULL);

			if ((deleted && !undelete)) {
				midgard_schema_object_factory_object_undelete (mgd, MGD_OBJECT_GUID (dbobject));
				goto _update_object;
			}

			if (deleted && !force) {
				
				MIDGARD_ERRNO_SET (mgd, MGD_ERR_OBJECT_DELETED);
				g_object_unref (dbobject);
				return FALSE;
			}

			_update_object:
			ret = _midgard_object_update (MIDGARD_OBJECT (object), OBJECT_UPDATE_IMPORTED, NULL);
			g_object_unref (dbobject);
			return ret;
		}		
	}

	return FALSE;
}
/**
 * midgard_replicator_export_by_guid:
 * @mgd: #MidgardConnection instance
 * @guid: guid which identifies object to be exported
 *
 * Marks object's storage record as exported.
 *
 * Cases to return %FALSE:
 * <itemizedlist>
 * <listitem><para>
 * Given guid is NULL or empty string (MGD_ERR_INVALID_PROPERTY_VALUE)
 * </para></listitem>
 * <listitem><para>
 * Object identified by given guid doesn't exist (MGD_ERR_NOT_EXISTS)
 * </para></listitem>
 * <listitem><para>
 * Object identified by given guid is purged (MGD_ERR_OBJECT_PURGED)
 * </para></listitem>
 * <listitem><para>
 * Internal storage error (MGD_ERR_INTERNAL)
 * </para></listitem>
 * </itemizedlist>
 *
 * Returns: %TRUE on success, %FALSE otherwise
 */ 
gboolean 
midgard_replicator_export_by_guid (MidgardConnection *mgd, const gchar *guid)
{
	g_return_val_if_fail (mgd != NULL, FALSE);

	if(guid == NULL || (guid && (*guid == '\0'))) {
		MIDGARD_ERRNO_SET_STRING (mgd, MGD_ERR_INVALID_PROPERTY_VALUE, "Empty or NULL guid given");
		return FALSE;
	}

	MIDGARD_ERRNO_SET(mgd, MGD_ERR_OK);

	MidgardDBObject *repligard = NULL;
	GError *error = NULL;
	GValue gval = {0, };
	g_value_init (&gval, G_TYPE_STRING);
	g_value_set_string (&gval, guid);
	midgard_core_query_get_object (mgd, g_type_name (MIDGARD_TYPE_REPLIGARD), &repligard, FALSE, &error, "guid", &gval, NULL);
	g_value_unset (&gval);

	if (error) {
		MIDGARD_ERRNO_SET_STRING (mgd, error->code, "%s", error->message);
		g_clear_error (&error);
		if (repligard)
			g_object_unref (G_OBJECT (repligard));
		return FALSE;
	}

	guint action;
	gchar *classname;
	g_object_get (repligard, 
			"action", &action,
			"type", &classname, NULL);
	g_object_unref (repligard);

	MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS_BY_NAME(classname);

	if(klass == NULL) {
		g_warning("Failed to get class pointer for '%s', an object identified with '%s'", classname, guid);
		MIDGARD_ERRNO_SET(mgd, MGD_ERR_INTERNAL);
		g_free (classname);
		return FALSE;
	}

	g_free (classname);

	const gchar *table = midgard_core_class_get_table(MIDGARD_DBOBJECT_CLASS(klass)); 
	GValue tval = {0, };
	gchar *timeupdated;
	gint qr;
	GString *sql = NULL;

	switch(action) {
		
		case MGD_OBJECT_ACTION_PURGE:
			MIDGARD_ERRNO_SET(mgd, MGD_ERR_OBJECT_PURGED);
			return FALSE;
			break;

		default:
			sql = g_string_new ("UPDATE ");
			g_string_append_printf(sql, "%s SET ", table);

			midgard_timestamp_new_current (&tval);
			timeupdated = midgard_timestamp_get_string_from_value (&tval);
			
			g_string_append_printf(sql, "metadata_exported='%s' WHERE guid = '%s' ", 
					timeupdated, guid);

			qr = midgard_core_query_execute(mgd, sql->str, TRUE);
			g_string_free(sql, TRUE);

			g_value_unset (&tval);
			g_free(timeupdated);

			if (qr == 0) {
				MIDGARD_ERRNO_SET(mgd, MGD_ERR_INTERNAL);
				return FALSE;
			}

			return TRUE;

			break;
	}

	return FALSE;
}