00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021 #include <stdlib.h>
00022 #include "midgard/midgard_type.h"
00023 #include "midgard/midgard_object.h"
00024 #include "midgard/midgard_metadata.h"
00025 #include "midgard/query.h"
00026 #include "midgard/midgard_legacy.h"
00027
00028 #include "midgard/query_builder.h"
00029 #include "midgard/midgard_timestamp.h"
00030 #include "midgard/midgard_datatypes.h"
00031 #include "midgard/midgard_quota.h"
00032 #include "schema.h"
00033 #include "midgard_mysql.h"
00034 #include "midgard/midgard_reflection_property.h"
00035 #include "midgard/midgard_error.h"
00036 #include "midgard_core_object.h"
00037 #include "midgard_core_object_class.h"
00038
00039 GType _midgard_attachment_type = 0;
00040
00041 enum {
00042 MIDGARD_PROPERTY_NULL = 0,
00043 MIDGARD_PROPERTY_GUID,
00044 MIDGARD_PROPERTY_SITEGROUP,
00045 MIDGARD_PROPERTY_METADATA
00046 };
00047
00048 typedef enum {
00049 OBJECT_UPDATE_NONE = 0,
00050 OBJECT_UPDATE_EXPORTED,
00051 OBJECT_UPDATE_IMPORTED
00052 } _ObjectActionUpdate;
00053
00054 static GParamSpec **_midgard_object_class_paramspec()
00055 {
00056
00057
00058
00059
00060
00061
00062
00063 GParamSpec **params = g_malloc(sizeof(GParamSpec*)*5);
00064 params[0] = g_param_spec_string ("guid", "", "GUID",
00065 " ", G_PARAM_READWRITE);
00066 params[1] = g_param_spec_uint ("sitegroup", "",
00067 "Sitegroup which object belongs to. Only for old objects",
00068 0, G_MAXUINT32, 0, G_PARAM_READWRITE);
00069 params[2] = g_param_spec_object ("metadata", "",
00070 "Property with Midgard metadata object",
00071 G_TYPE_OBJECT, G_PARAM_READWRITE);
00072 params[3] = g_param_spec_string ("action", "", "What was done with object",
00073 " ", G_PARAM_READWRITE);
00074 params[4] = NULL;
00075
00076 return params;
00077 }
00078
00079
00080 static void
00081 _object_instance_init(GTypeInstance *instance, gpointer g_class)
00082 {
00083 GType own_type = G_TYPE_FROM_INSTANCE(instance);
00084 MgdSchemaTypeAttr *priv = G_TYPE_INSTANCE_GET_PRIVATE (instance, own_type, MgdSchemaTypeAttr);
00085
00086 MgdObject *self = (MgdObject *) instance;
00087
00088 self->private = g_new0(MidgardTypePrivate, 1);
00089 self->private->guid = NULL;
00090 self->private->sg = -1;
00091 self->private->action = NULL;
00092 self->private->exported = NULL;
00093 self->private->imported = NULL;
00094
00095
00096 self->metadata = (MidgardMetadata *) g_object_new(MIDGARD_TYPE_METADATA, NULL);
00097
00098
00099
00100
00101 self->private->parameters = NULL;
00102 self->private->_params = NULL;
00103
00104 priv->base_index = 1;
00105
00106 guint propn;
00107 GParamSpec **props =
00108 g_object_class_list_properties(g_type_class_peek(own_type), &propn);
00109 g_free(props);
00110
00111 priv->num_properties = propn;
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 priv->properties =
00123 priv->num_properties ? g_new0 (MgdSchemaPropertyAttr*, priv->num_properties) : NULL;
00124 if (priv->properties) {
00125 guint idx;
00126 for (idx = 0; idx < priv->num_properties; idx++) {
00127 priv->properties[idx] = g_new0 (MgdSchemaPropertyAttr, 1);
00128 }
00129 }
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #define G_MIDGARD_LOOP_HIERARCHY_START \
00142 do { \
00143 \
00144 priv = G_TYPE_INSTANCE_GET_PRIVATE (object, current_type, MgdSchemaTypeAttr); \
00145
00146 #define G_MIDGARD_LOOP_HIERARCHY_STOP \
00147 current_type = g_type_parent(current_type); \
00148 } while (current_type != G_TYPE_OBJECT);
00149
00150
00151
00152
00153 static void
00154 _object_set_property (GObject *object, guint prop_id,
00155 const GValue *value, GParamSpec *pspec)
00156 {
00157 gint prop_id_local = 0;
00158 MgdSchemaTypeAttr *priv;
00159 GType current_type = G_TYPE_FROM_INSTANCE(object);
00160 MgdObject *self = (MgdObject *) object;
00161 MgdSchemaPropertyAttr *prop;
00162
00163 switch(prop_id) {
00164
00165 case MIDGARD_PROPERTY_GUID:
00166 g_free ((gchar *)self->private->guid);
00167 self->private->guid = g_value_dup_string (value);
00168 break;
00169
00170 case MIDGARD_PROPERTY_SITEGROUP:
00171 self->private->sg = g_value_get_uint(value);
00172 break;
00173
00174 case MIDGARD_PROPERTY_METADATA:
00175 self->metadata = g_value_get_object (value);
00176 break;
00177
00178 default:
00179 G_MIDGARD_LOOP_HIERARCHY_START
00180 prop_id_local = prop_id - priv->base_index - 1;
00181 if ((prop_id_local >= 0) && (prop_id_local < priv->num_properties)) {
00182 if (priv->num_properties) {
00183 prop = priv->properties[prop_id_local];
00184 if (!G_IS_VALUE(&prop->value)) {
00185 g_value_init(&prop->value, G_VALUE_TYPE(value));
00186
00187 }
00188 g_value_copy(value, &prop->value);
00189 }
00190 return;
00191 }
00192 G_MIDGARD_LOOP_HIERARCHY_STOP
00193 }
00194 }
00195
00196
00197 static void
00198 _object_get_property (GObject *object, guint prop_id,
00199 GValue *value, GParamSpec *pspec)
00200 {
00201 gint prop_id_local = 0;
00202 MgdSchemaTypeAttr *priv;
00203 GType current_type = G_TYPE_FROM_INSTANCE(object);
00204 MgdObject *self = (MgdObject *) object;
00205
00206 switch(prop_id) {
00207
00208 case MIDGARD_PROPERTY_GUID:
00209 g_value_set_string (value, self->private->guid);
00210 break;
00211
00212 case MIDGARD_PROPERTY_SITEGROUP:
00213 g_value_set_uint (value, (guint)self->private->sg);
00214 break;
00215
00216 case MIDGARD_PROPERTY_METADATA:
00217 g_value_set_object(value,
00218 (MidgardMetadata *) self->metadata);
00219 break;
00220
00221 default:
00222 G_MIDGARD_LOOP_HIERARCHY_START
00223 prop_id_local = prop_id - priv->base_index - 1;
00224 if ((prop_id_local >= 0) && (
00225 prop_id_local < priv->num_properties)) {
00226 if (priv->num_properties) {
00227 if (priv->properties && G_IS_VALUE(
00228 &priv->properties[prop_id_local]->value)) {
00229 g_value_copy(&priv->properties[prop_id_local]->value,
00230 value);
00231 }
00232 }
00233 return;
00234 }
00235 G_MIDGARD_LOOP_HIERARCHY_STOP
00236 }
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 static void _object_finalize (GObject *object)
00250 {
00251 guint idx;
00252 MgdSchemaTypeAttr *priv;
00253
00254 if(object == NULL)
00255 return;
00256
00257 MgdObject *self = (MgdObject *)object;
00258
00259
00260 g_free((gchar *)self->private->guid);
00261 g_free((gchar *)self->private->action);
00262 g_free(self->private->exported);
00263 g_free(self->private->imported);
00264
00265
00266 if(self->private->parameters != NULL) {
00267
00268 GSList *_param = self->private->parameters;
00269 for (; _param; _param = _param->next) {
00270 g_object_unref(_param->data);
00271 }
00272 g_slist_free(_param);
00273 }
00274
00275 if(self->private->_params != NULL)
00276 g_hash_table_destroy(self->private->_params);
00277
00278 g_free(self->private);
00279
00280
00281 g_object_run_dispose(G_OBJECT(self->metadata));
00282 g_object_unref(self->metadata);
00283
00284 GType current_type = G_TYPE_FROM_INSTANCE(object);
00285
00286 G_MIDGARD_LOOP_HIERARCHY_START
00287 for (idx = 0; idx < priv->num_properties; idx++) {
00288 if (priv->properties[idx]) {
00289 if (G_IS_VALUE(&priv->properties[idx]->value)) {
00290 g_value_unset(&priv->properties[idx]->value);
00291 }
00292 g_free (priv->properties[idx]);
00293 priv->properties[idx] = NULL;
00294 }
00295 }
00296 if (priv->properties) {
00297 g_free (priv->properties);
00298 priv->properties = NULL;
00299 }
00300 G_MIDGARD_LOOP_HIERARCHY_STOP
00301
00302
00303 {
00304 GObjectClass *parent_class = g_type_class_ref (current_type);
00305 if (parent_class->finalize) {
00306 parent_class->finalize (object);
00307 }
00308 g_type_class_unref (parent_class);
00309 }
00310 }
00311
00312 static GHashTable *_build_create_or_update_query(MgdObject *object)
00313 {
00314 GParamSpec **props;
00315 guint propn, i;
00316 GValue pval = {0,};
00317 GHashTable *sqls = midgard_hash_strings_new();
00318 gchar **table, *sqlset = "", *sqlsetf = "";
00319 const gchar *nick, *strval;
00320 GString *tmpsql;
00321 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(object);
00322 const gchar *primary_property = midgard_object_class_get_primary_property(klass);
00323
00324 if(( props = g_object_class_list_properties(
00325 G_OBJECT_GET_CLASS(G_OBJECT(object)), &propn)) == NULL)
00326 return NULL;
00327
00328 g_hash_table_insert(sqls, g_strdup(
00329 midgard_object_class_get_table(
00330 MIDGARD_OBJECT_GET_CLASS(object))), g_strdup(sqlset));
00331
00332 for (i = 0; i < propn; i++) {
00333
00334 nick = g_param_spec_get_nick (props[i]);
00335
00336 if ((strlen(nick)) > 0) {
00337
00338 table = g_strsplit_set(nick, ".", 0);
00339 g_value_init(&pval,props[i]->value_type);
00340 g_object_get_property(G_OBJECT(object), (gchar*)props[i]->name, &pval);
00341
00342 if ((sqlsetf = g_hash_table_lookup(sqls, table[0])) == NULL) {
00343 sqlset = g_strdup("");
00344 g_hash_table_insert(sqls, g_strdup(table[0]), sqlset);
00345 }
00346
00347 tmpsql = g_string_new(sqlsetf);
00348
00349 switch (props[i]->value_type) {
00350
00351 case MGD_TYPE_STRING:
00352 strval = g_value_get_string(&pval);
00353 if(strval == NULL)
00354 strval = "";
00355 guint length = strlen(strval);
00356 gchar *escaped = g_new(gchar, 2 * length + 1);
00357 mysql_real_escape_string(
00358 object->mgd->msql->mysql,
00359 escaped, strval, length);
00360 g_string_append_printf(tmpsql,
00361 "%s='%s', ",
00362 table[1],
00363 escaped);
00364 g_free(escaped);
00365 break;
00366
00367
00368 case MGD_TYPE_UINT:
00369
00370 if(!g_str_equal(props[i]->name, primary_property)) {
00371 g_string_append_printf(tmpsql,
00372 "%s=%d, ",
00373 table[1],
00374 g_value_get_uint(&pval));
00375 }
00376 break;
00377
00378 case MGD_TYPE_INT:
00379 if(!g_str_equal(props[i]->name, primary_property)) {
00380 g_string_append_printf(tmpsql,
00381 "%s=%d, ",
00382 table[1],
00383 g_value_get_int(&pval));
00384 }
00385 break;
00386
00387 case MGD_TYPE_FLOAT:
00388 g_string_append_printf(tmpsql,
00389 "%s=%f, ",
00390 table[1],
00391 g_value_get_float(&pval));
00392 break;
00393
00394 case MGD_TYPE_BOOLEAN:
00395 g_string_append_printf(tmpsql,
00396 "%s=%d, ",
00397 table[1],
00398 g_value_get_boolean(&pval));
00399 break;
00400 }
00401
00402 g_hash_table_insert(sqls, g_strdup(table[0]), g_string_free(tmpsql, FALSE));
00403 g_value_unset(&pval);
00404 g_strfreev(table);
00405 }
00406 }
00407
00408 g_free(props);
00409 return sqls;
00410 }
00411
00412 void _insert_records(gpointer key, gpointer value, gpointer userdata)
00413 {
00414 gchar *table = (gchar *) key;
00415 gchar *sql = (gchar *) value;
00416 MgdSchemaTypeQuery *query;
00417 gint qr, rid;
00418 guint object_sitegroup;
00419 MgdObject *object = (MgdObject *) userdata;
00420
00421
00422 g_object_get(G_OBJECT(object), "sitegroup", &object_sitegroup, NULL);
00423 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(object);
00424
00425 if(!g_str_equal(midgard_object_class_get_table(klass), table)){
00426 query = g_hash_table_lookup(klass->data->tables, table);
00427 if (query->use_lang) {
00428
00429
00430
00431 }
00432
00433 GString *fquery = g_string_new("INSERT INTO ");
00434 g_string_append_printf(fquery,
00435 "%s SET %s sitegroup=%d",
00436 table,
00437 sql,
00438 object_sitegroup);
00439 gchar *tmpstr = g_string_free(fquery, FALSE);
00440
00441 qr = mysql_query(object->mgd->msql->mysql, tmpstr);
00442 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", tmpstr);
00443
00444 if (qr != 0) {
00445 g_warning("query failed: %s \n %s",
00446 tmpstr,
00447 mysql_error(object->mgd->msql->mysql));
00448 } else {
00449
00450
00451
00452 if ((query->use_lang == 1) && (qr == 0)) {
00453 rid = mysql_insert_id(object->mgd->msql->mysql);
00454 gchar *guid = midgard_guid_new(object->mgd);
00455 fquery = g_string_new("INSERT INTO repligard ");
00456 g_string_append_printf(fquery,
00457 "(realm,guid,id,changed,action,sitegroup)"
00458 " VALUES ('%s', '%s', %d , NULL, 'create', %d)",
00459 table, guid, rid, object_sitegroup);
00460 gchar *rtmpstr = g_string_free(fquery, FALSE);
00461 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", rtmpstr);
00462 qr = mysql_query(object->mgd->msql->mysql, rtmpstr);
00463 if (qr != 0)
00464 g_warning("query failed: %s \n %s",
00465 rtmpstr,
00466 mysql_error(object->mgd->msql->mysql));
00467 g_free(guid);
00468 g_free(rtmpstr);
00469 }
00470 }
00471 g_free(tmpstr);
00472 }
00473 }
00474
00475 void _update_records(gpointer key, gpointer value, gpointer userdata)
00476 {
00477 gchar *table = (gchar *) key;
00478 gchar *sql = (gchar *) value, *tmpstr = NULL;
00479 const gchar *otable;
00480 MgdSchemaTypeQuery *query;
00481 gint qr, doins = 0;
00482 gpointer rid;
00483 GString *where;
00484 MgdObject *object = (MgdObject *) userdata;
00485 guint object_sitegroup, id;
00486
00487 g_object_get(G_OBJECT(object), "sitegroup",
00488 &object_sitegroup, NULL);
00489 g_object_get(G_OBJECT(object), "id",
00490 &id, NULL);
00491
00492 otable = midgard_object_class_get_table(
00493 MIDGARD_OBJECT_GET_CLASS(object));
00494
00495 if(!g_str_equal(otable, table)){
00496
00497 query = g_hash_table_lookup(object->data->tables, table);
00498 if(!query)
00499 return;
00500
00501 if (query->use_lang) {
00502 where = g_string_new(" sid=");
00503 g_string_append_printf(where,
00504 "%d AND lang=%d",
00505 id, mgd_lang(object->mgd));
00506 tmpstr = g_string_free(where, FALSE);
00507 rid = midgard_query_field_get(object->mgd,
00508 "id",
00509 table,
00510 (const gchar*)tmpstr);
00511 g_free(tmpstr);
00512
00513 if(rid != NULL) {
00514 id = (guint) atoi(rid);
00515 where = g_string_new("UPDATE ");
00516 g_string_append_printf(where,
00517 "%s SET %s sitegroup=%d "
00518 "WHERE id=%d AND sitegroup=%d",
00519 table, sql, object_sitegroup,
00520 id, object_sitegroup);
00521 } else {
00522 where = g_string_new("INSERT INTO ");
00523 g_string_append_printf(where,
00524 "%s SET %s sitegroup=%d",
00525 table, sql,
00526 object_sitegroup);
00527 doins = 1;
00528 }
00529 } else {
00530
00531 where = g_string_new("UPDATE ");
00532 g_string_append_printf(where,
00533 "%s SET %s, sitegroup=%d",
00534 table, sql, object_sitegroup);
00535 }
00536
00537 tmpstr = g_string_free(where, FALSE);
00538 qr = mysql_query(object->mgd->msql->mysql, tmpstr);
00539
00540 if (query->use_lang && qr == 1 && doins == 1) {
00541 rid = midgard_query_field_get(object->mgd,
00542 "id",
00543 table,
00544 tmpstr);
00545 if(rid != NULL)
00546 id = (guint) atoi(rid);
00547 }
00548 g_free(tmpstr);
00549 if (qr) {
00550
00551 if (query->use_lang == 1)
00552 UPDATE_REPLIGARD(object->mgd, table, id);
00553 }
00554 }
00555 }
00556
00557
00558 gboolean _object_in_tree(MgdObject *object)
00559 {
00560 guint n_objects = 0;
00561 GParamSpec *name_prop, *up_prop, *primary;
00562 GValue pval = {0,}, fval = {0,};
00563
00564 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(object);
00565 const gchar *primary_prop = midgard_object_class_get_primary_property(klass);
00566 const gchar *upname = midgard_object_class_get_parent_property(klass);
00567 if(upname == NULL)
00568 upname = midgard_object_class_get_up_property(klass);
00569
00570 if(upname == NULL)
00571 return FALSE;
00572
00573 up_prop = g_object_class_find_property(
00574 G_OBJECT_GET_CLASS(G_OBJECT(object)), upname);
00575 name_prop = g_object_class_find_property(
00576 G_OBJECT_GET_CLASS(G_OBJECT(object)), "name");
00577
00578 if((name_prop == NULL) || (up_prop == NULL))
00579 return FALSE;
00580
00581 MidgardQueryBuilder *builder =
00582 midgard_query_builder_new(object->mgd,
00583 G_OBJECT_TYPE_NAME(object));
00584
00585 g_value_init(&pval,up_prop->value_type);
00586 g_object_get_property(G_OBJECT(object), upname, &pval);
00587 midgard_query_builder_add_constraint(builder,
00588 upname,
00589 "=", &pval);
00590 g_value_unset(&pval);
00591
00592
00593 g_value_init(&pval,name_prop->value_type);
00594 g_object_get_property(G_OBJECT(object), "name", &pval);
00595
00596 const gchar *tmpstr = g_value_get_string(&pval);
00597 if(!tmpstr)
00598 tmpstr = "";
00599 if(g_str_equal(tmpstr, "")){
00600 g_object_unref(builder);
00601 g_value_unset(&pval);
00602 return FALSE;
00603 }
00604 midgard_query_builder_add_constraint(builder,
00605 "name",
00606 "=", &pval);
00607 g_value_unset(&pval);
00608
00609 GObject **ret_object =
00610 midgard_query_builder_execute(
00611 builder, &n_objects);
00612
00613
00614 if(n_objects < 1){
00615 g_object_unref(G_OBJECT(builder));
00616 return FALSE;
00617 }
00618
00619
00620
00621 primary = g_object_class_find_property(
00622 G_OBJECT_GET_CLASS(G_OBJECT(ret_object[0])), primary_prop);
00623
00624 gboolean duplicate = TRUE;
00625 g_value_init(&fval, primary->value_type);
00626 g_object_get_property(G_OBJECT(ret_object[0]), primary_prop, &fval);
00627
00628 g_value_init(&pval, primary->value_type);
00629 g_object_get_property(G_OBJECT(object), primary_prop, &pval);
00630
00631 switch(primary->value_type){
00632
00633 case G_TYPE_UINT:
00634 if(g_value_get_uint(&fval) == g_value_get_uint(&pval))
00635 duplicate = FALSE;
00636 break;
00637
00638 case G_TYPE_STRING:
00639 if(g_str_equal(g_value_get_string(&fval),
00640 g_value_get_string(&pval)))
00641 duplicate = FALSE;
00642 break;
00643 }
00644
00645 g_object_unref(ret_object[0]);
00646 g_object_unref(builder);
00647
00648 if(duplicate)
00649 return TRUE;
00650
00651
00652
00653
00654
00655
00656
00657
00658 return FALSE;
00659 }
00660
00661 gboolean _midgard_object_update(MgdObject *gobj,
00662 _ObjectActionUpdate replicate)
00663 {
00664 g_assert(gobj != NULL);
00665 g_assert(gobj->mgd != NULL);
00666
00667 gchar *sqlsetf = "", *fquery = "";
00668 guint qr, oid, id = 0;
00669 GHashTable *sqls;
00670 const gchar *table;
00671 guint object_sitegroup , current_sitegroup;
00672
00673 if(!_midgard_core_object_is_valid(gobj))
00674 return FALSE;
00675
00676 MIDGARD_ERRNO_SET(gobj->mgd, MGD_ERR_OK);
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 if (gobj->data == NULL) {
00687 MIDGARD_ERRNO_SET(gobj->mgd, MGD_ERR_INTERNAL);
00688 return FALSE;
00689 }
00690 table = midgard_object_class_get_table(MIDGARD_OBJECT_GET_CLASS(gobj));
00691
00692 if(table == NULL) {
00693
00694 g_warning("Object '%s' has no table defined!", gobj->cname);
00695 MIDGARD_ERRNO_SET(gobj->mgd, MGD_ERR_INTERNAL);
00696 return FALSE;
00697 }
00698
00699 current_sitegroup = mgd_sitegroup(gobj->mgd);
00700 g_object_get(G_OBJECT(gobj), "sitegroup", &object_sitegroup, NULL);
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 if((current_sitegroup > 0) && (object_sitegroup > 0) &&
00715 (current_sitegroup != object_sitegroup))
00716 g_object_set(G_OBJECT(gobj), "sitegroup",
00717 mgd_sitegroup(gobj->mgd) , NULL);
00718
00719
00720 if(_object_in_tree(gobj)) {
00721 MIDGARD_ERRNO_SET(gobj->mgd, MGD_ERR_DUPLICATE);
00722 return FALSE;
00723 }
00724
00725
00726 g_object_get((GObject *) gobj, "id", &oid , NULL);
00727
00728
00729 if (gobj->data->use_lang) {
00730 g_object_set((GObject *) gobj, "sid", oid , NULL);
00731 g_object_set((GObject *) gobj, "lang", mgd_lang(gobj->mgd), NULL);
00732 }
00733
00734 sqls = _build_create_or_update_query(gobj);
00735 sqlsetf = g_hash_table_lookup(sqls, gobj->data->table);
00736
00737 GString *sql = g_string_new("UPDATE ");
00738 g_string_append_printf(sql,
00739 "%s SET %s ",
00740 table, sqlsetf);
00741
00742
00743 gchar *person_guid ;
00744 MgdObject *person = (MgdObject *)gobj->mgd->person;
00745 if(person){
00746 if(G_IS_OBJECT(G_OBJECT(person)))
00747 g_object_get(G_OBJECT(person), "guid", &person_guid, NULL);
00748 }else {
00749
00750 person_guid = g_strdup("");
00751 }
00752
00753 GValue tval = {0, };
00754 g_value_init(&tval, midgard_timestamp_get_type());
00755 midgard_timestamp_set_time(&tval, time(NULL));
00756 gchar *timeupdated = midgard_timestamp_dup_string(&tval);
00757
00758
00759
00760
00761 gchar *revised_time;
00762 gint revision_count = gobj->metadata->private->revision;
00763
00764 if(replicate == OBJECT_UPDATE_IMPORTED){
00765 revised_time = gobj->metadata->private->revised;
00766 } else {
00767 revised_time = timeupdated;
00768 revision_count++;
00769 }
00770
00771 switch(replicate){
00772
00773 case OBJECT_UPDATE_NONE:
00774
00775
00776
00777
00778
00779
00780 g_string_append_printf(sql,
00781 "metadata_revisor='%s', metadata_revised='%s',"
00782 "metadata_revision=%d ",
00783 person_guid, revised_time, revision_count);
00784
00785 gchar *metasql = midgard_metadata_get_sql(gobj->metadata);
00786 g_string_append_printf(sql, " %s ", metasql);
00787 g_free(metasql);
00788
00789 g_object_set(G_OBJECT(gobj->metadata),
00790 "revisor", person_guid,
00791 "revised", timeupdated,
00792 "revision", revision_count,
00793 NULL);
00794
00795 g_free(person_guid);
00796 g_free(timeupdated);
00797 break;
00798
00799 case OBJECT_UPDATE_EXPORTED:
00800 g_string_append_printf(sql,
00801 "metadata_exported='%s'",
00802 timeupdated);
00803 g_free(gobj->private->exported);
00804 gobj->private->exported = g_strdup(timeupdated);
00805 g_object_set(G_OBJECT(gobj->metadata),
00806 "exported", timeupdated,
00807 NULL);
00808 break;
00809
00810 case OBJECT_UPDATE_IMPORTED:
00811 g_string_append_printf(sql,
00812 "metadata_imported='%s'"
00813 ",metadata_exported='%s'"
00814 ",metadata_revisor='%s' "
00815 ",metadata_revised='%s' "
00816 ",metadata_revision=%d "
00817 ",metadata_creator='%s' ",
00818 timeupdated,
00819 gobj->metadata->private->exported,
00820 gobj->metadata->private->revisor,
00821 revised_time,
00822 revision_count,
00823 gobj->metadata->private->creator);
00824
00825 g_free(gobj->private->imported);
00826 gobj->private->imported = g_strdup(timeupdated);
00827
00828
00829
00830
00831
00832 break;
00833 }
00834
00835
00836
00837
00838 GValue pval = {0, };
00839 const gchar *pprop = midgard_object_class_get_primary_property(
00840 MIDGARD_OBJECT_GET_CLASS(gobj));
00841
00842 GParamSpec *propval = g_object_class_find_property(
00843 G_OBJECT_GET_CLASS(G_OBJECT(gobj)), pprop);
00844
00845 g_value_init(&pval, propval->value_type);
00846 switch(propval->value_type){
00847
00848 case G_TYPE_STRING:
00849
00850 g_object_get(G_OBJECT(gobj), "id", &id, NULL);
00851 if(gobj->private->guid == NULL)
00852 g_critical("Object's guid is NULL. Can not update");
00853 g_string_append_printf(sql,
00854 " WHERE %s = '%s'", pprop, gobj->private->guid);
00855 break;
00856
00857 case G_TYPE_UINT:
00858 g_object_get_property(G_OBJECT(gobj), pprop, &pval);
00859 g_string_append_printf(sql,
00860 " WHERE %s = %d", pprop, g_value_get_uint(&pval));
00861 id = g_value_get_uint(&pval);
00862 if(id == 0)
00863 g_warning("Object's ID is 0. Can not update");
00864 break;
00865 }
00866 g_value_unset(&pval);
00867
00868
00869 if(!mgd_isroot(gobj->mgd)){
00870 g_string_append_printf(sql,
00871 " AND %s.sitegroup = %d",
00872 table,
00873 object_sitegroup);
00874 }
00875
00876 guint object_size;
00877 g_object_get(G_OBJECT(gobj->metadata), "size", &object_size, NULL);
00878 fquery = g_string_free(sql, FALSE);
00879 if(midgard_quota_size_is_reached(gobj, object_size)){
00880 MIDGARD_ERRNO_SET(gobj->mgd, MGD_ERR_QUOTA);
00881 g_free(fquery);
00882 return FALSE;
00883 }
00884
00885
00886 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", fquery);
00887 qr = mysql_query(gobj->mgd->msql->mysql, fquery);
00888 g_free(fquery);
00889
00890 if (qr != 0) {
00891 g_warning("query failed: %s",
00892 mysql_error(gobj->mgd->msql->mysql));
00893 MIDGARD_ERRNO_SET(gobj->mgd, MGD_ERR_INTERNAL);
00894 return FALSE;
00895 } else {
00896 midgard_quota_update(gobj);
00897
00898
00899
00900
00901 if(id > 0){
00902 sql = g_string_new("UPDATE repligard SET changed=NULL,action='update',");
00903 g_string_append_printf(sql,
00904 "typename='%s' WHERE guid='%s' AND realm='%s'",
00905 G_OBJECT_TYPE_NAME(gobj),
00906 gobj->private->guid,
00907 table);
00908 fquery = g_string_free(sql, FALSE);
00909 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", fquery);
00910 mysql_query(gobj->mgd->msql->mysql, fquery);
00911 g_free(fquery);
00912
00913 }
00914 }
00915
00916
00917 g_hash_table_foreach(sqls, _update_records, gobj);
00918 g_hash_table_destroy(sqls);
00919 MIDGARD_ERRNO_SET(gobj->mgd, MGD_ERR_OK);
00920
00921 return TRUE;
00922 }
00923
00924 gboolean midgard_object_update(MgdObject *self)
00925 {
00926 return _midgard_object_update(self, OBJECT_UPDATE_NONE);
00927 }
00928
00929
00930
00931 gboolean _midgard_object_create(MgdObject *object, const gchar *create_guid)
00932 {
00933 gchar *sqlsetf = "", *fquery;
00934 guint qr, rid, object_sitegroup;
00935 GHashTable *sqls;
00936 GString *query;
00937 const gchar *table;
00938
00939 if (object->data == NULL)
00940 return FALSE;
00941
00942 if(!_midgard_core_object_is_valid(object))
00943 return FALSE;
00944 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_OK);
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 if((table = midgard_object_class_get_table(MIDGARD_OBJECT_GET_CLASS(object))) == NULL) {
00955
00956 g_warning("Object '%s' has no table or storage defined!",
00957 object->cname);
00958 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_NOT_EXISTS);
00959 return FALSE;
00960 }
00961
00962
00963 if(!mgd_isroot(object->mgd)) {
00964 g_object_set(G_OBJECT(object), "sitegroup",
00965 midgard_sitegroup_get_id(object->mgd) , NULL);
00966 }
00967
00968
00969 g_object_get(G_OBJECT(object), "sitegroup", &object_sitegroup, NULL);
00970
00971
00972
00973
00974
00975
00976 if(_object_in_tree(object)) {
00977 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_DUPLICATE);
00978 return FALSE;
00979 }
00980
00981
00982 gchar *guid;
00983 if(create_guid == NULL)
00984 guid = midgard_guid_new(object->mgd);
00985 else
00986 guid = g_strdup(create_guid);
00987
00988 g_object_set(G_OBJECT(object), "guid", guid , NULL);
00989
00990 sqls = _build_create_or_update_query(object);
00991 sqlsetf = g_hash_table_lookup(sqls, object->data->table);
00992
00993
00994 query = g_string_new("INSERT INTO ");
00995 g_string_append_printf(query,
00996 "%s SET %s guid='%s',",
00997 table, sqlsetf, guid);
00998
00999
01000 if(!mgd_isroot(object->mgd))
01001 object_sitegroup = midgard_sitegroup_get_id(object->mgd);
01002
01003 g_string_append_printf(query,
01004 "sitegroup=%d,", object_sitegroup);
01005
01006 g_hash_table_destroy(sqls);
01007
01008
01009
01010
01011 gchar *person_guid ;
01012 MgdObject *person = (MgdObject *)object->mgd->person;
01013 if(person){
01014 if(G_IS_OBJECT(G_OBJECT(person)))
01015 g_object_get(G_OBJECT(person), "guid", &person_guid, NULL);
01016 } else {
01017
01018 person_guid = g_strdup("");
01019 }
01020
01021
01022 GValue tval = {0, };
01023 time_t utctime = time(NULL);
01024 g_value_init(&tval, MIDGARD_TYPE_TIMESTAMP);
01025 midgard_timestamp_set_time(&tval, utctime);
01026 gchar *timecreated = midgard_timestamp_dup_string(&tval);
01027 g_value_unset(&tval);
01028 guint object_size;
01029 g_object_get(G_OBJECT(object->metadata), "size", &object_size, NULL);
01030 g_string_append_printf(query,
01031 "metadata_creator='%s', metadata_created='%s', "
01032 "metadata_revised='%s', metadata_revision=0, "
01033 "metadata_revisor='%s', metadata_size=%d ",
01034 person_guid, timecreated,
01035 timecreated, person_guid,
01036 object_size);
01037
01038
01039 g_object_set(G_OBJECT(object->metadata),
01040 "creator", person_guid,
01041 "created", timecreated,
01042 "revised", timecreated,
01043 "revision", 0,
01044 "revisor", person_guid,
01045 "published", timecreated,
01046 NULL);
01047
01048 gchar *metasql = midgard_metadata_get_sql(object->metadata);
01049 g_string_append_printf(query, " %s ", metasql);
01050
01051 g_free(metasql);
01052 g_free(timecreated);
01053 g_free(person_guid);
01054
01055
01056 fquery = g_string_free(query, FALSE);
01057
01058 if(!midgard_quota_create(object)){
01059 g_free(fquery);
01060 return FALSE;
01061 }
01062 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", fquery);
01063
01064 qr = mysql_query(object->mgd->msql->mysql, fquery);
01065 g_free(fquery);
01066
01067 if (qr != 0) {
01068 g_warning("\n\n QUERY FAILED: %s \n\n", mysql_error(object->mgd->msql->mysql));
01069 g_free(guid);
01070 g_object_set(G_OBJECT(object), "guid", "" , NULL);
01071 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_NOT_EXISTS);
01072 return FALSE;
01073 } else {
01074
01075 if ((rid = mysql_insert_id(object->mgd->msql->mysql))){
01076 g_object_set(G_OBJECT(object), "id", rid, NULL);
01077 midgard_quota_update(object);
01078 query = g_string_new("INSERT INTO repligard SET ");
01079 g_string_append_printf(query,
01080 "realm='%s', guid='%s', changed=NULL, "
01081 "action='create', typename='%s', id=%d, "
01082 " sitegroup=%d, object_action = %d ",
01083 table, guid, object->cname, rid,
01084 object_sitegroup,
01085 MGD_OBJECT_ACTION_NONE);
01086
01087 g_free(guid);
01088 fquery = g_string_free(query, FALSE);
01089 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", fquery);
01090 qr = mysql_query(object->mgd->msql->mysql, fquery);
01091 g_free(fquery);
01092
01093 if (qr != 0) {
01094 g_warning("query failed: %s", mysql_error(object->mgd->msql->mysql));
01095 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_INTERNAL);
01096 }
01097
01098
01099 if (g_object_class_find_property(
01100 G_OBJECT_GET_CLASS(G_OBJECT(object)), "sid") != NULL)
01101 g_object_set(G_OBJECT(object), "sid", rid, NULL);
01102
01103 if (g_object_class_find_property(
01104 G_OBJECT_GET_CLASS(G_OBJECT(object)), "lang") != NULL)
01105 g_object_set(G_OBJECT(object),
01106 "lang", midgard_lang_get(object->mgd), NULL);
01107
01108 sqls = _build_create_or_update_query(object);
01109 g_hash_table_foreach(sqls, _insert_records, object);
01110
01111 g_hash_table_destroy(sqls);
01112 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Object %s created with id=%d",
01113 object->cname, rid);
01114 return TRUE;
01115 }
01116 }
01117 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_INTERNAL);
01118 return FALSE;
01119 }
01120
01121 gboolean midgard_object_create(MgdObject *object)
01122 {
01123 return _midgard_object_create(object, NULL);
01124 }
01125
01126
01127
01128 void _object_copy_properties(GObject *src, GObject *dest)
01129 {
01130 g_assert(src != NULL && dest != NULL);
01131
01132 guint nprop, i;
01133 GValue pval = {0, };
01134 GValue doval = {0, };
01135 GParamSpec **props = g_object_class_list_properties(
01136 G_OBJECT_GET_CLASS(src),
01137 &nprop);
01138
01139 for(i = 0; i <+ nprop; i++){
01140
01141 g_value_init(&pval, props[i]->value_type);
01142
01143 if(props[i]->value_type == G_TYPE_OBJECT){
01144
01145 g_object_get_property(src,
01146 props[i]->name,
01147 &pval);
01148
01149 g_value_init(&doval, props[i]->value_type);
01150 g_object_get_property(dest,
01151 props[i]->name,
01152 &doval);
01153
01154 _object_copy_properties(
01155 G_OBJECT(g_value_get_object(&pval)),
01156 G_OBJECT(g_value_get_object(&doval))
01157 );
01158 g_value_unset(&doval);
01159
01160 } else {
01161
01162 g_object_get_property(G_OBJECT(src),
01163 props[i]->name,
01164 &pval);
01165 g_object_set_property(G_OBJECT(dest),
01166 props[i]->name,
01167 &pval);
01168 }
01169
01170 g_value_unset(&pval);
01171 }
01172
01173 g_free(props);
01174 }
01175
01176
01177
01178 gboolean midgard_object_get_by_id(MgdObject *object)
01179 {
01180 g_assert(object != NULL);
01181 g_assert(object->mgd != NULL);
01182
01183
01184 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_OK);
01185
01186 guint n_objects = 0;
01187 GParamSpec *prop;
01188 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(object);
01189
01190
01191 prop = g_object_class_find_property(
01192 (GObjectClass*)klass,
01193 "id");
01194 if(prop == NULL){
01195 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_INTERNAL);
01196 g_warning("Primary property id not found for object's klass '%s'",
01197 G_OBJECT_TYPE_NAME(object));
01198 return FALSE;
01199 }
01200
01201
01202 g_assert((prop->value_type == G_TYPE_UINT));
01203
01204
01205 MidgardQueryBuilder *builder =
01206 midgard_query_builder_new(object->mgd,
01207 G_OBJECT_TYPE_NAME(object));
01208
01209 if(!builder) {
01210 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_INTERNAL);
01211 g_warning("Invalid query builder configuration (%s)",
01212 G_OBJECT_TYPE_NAME(object));
01213 return FALSE;
01214 }
01215
01216
01217 GValue pval = {0,};
01218 g_value_init(&pval,prop->value_type);
01219 g_object_get_property(G_OBJECT(object), "id", &pval);
01220 if (midgard_query_builder_add_constraint(builder,
01221 "id",
01222 "=", &pval)) {
01223
01224 GObject **ret_object = midgard_query_builder_execute(
01225 builder, &n_objects);
01226
01227 g_value_unset(&pval);
01228 g_object_unref(G_OBJECT(builder));
01229
01230 if(n_objects < 1) {
01231 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_NOT_EXISTS);
01232 return FALSE;
01233 }
01234
01235 _object_copy_properties(ret_object[0],
01236 G_OBJECT(object));
01237
01238 g_object_unref(ret_object[0]);
01239 g_free(ret_object);
01240
01241 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_OK);
01242 return TRUE;
01243 }
01244 return FALSE;
01245 }
01246
01247 GObject **midgard_object_find(MgdObject *object, guint *n_objects)
01248 {
01249 GParamSpec **props;
01250 guint propn, i;
01251 GValue pval = {0,};
01252
01253 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_OK);
01254
01255 props = g_object_class_list_properties(
01256 G_OBJECT_CLASS(MIDGARD_OBJECT_GET_CLASS(object)), &propn);
01257 if(!props){
01258 g_warning("No properties found for %s class!",
01259 object->cname);
01260 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_INTERNAL);
01261 return NULL;
01262 }
01263
01264 MidgardQueryBuilder *builder =
01265 midgard_query_builder_new(object->mgd, object->cname);
01266 if(!builder){
01267 MIDGARD_ERRNO_SET(object->mgd, MGD_ERR_INTERNAL);
01268 return NULL;
01269 }
01270
01271 for(i = 0; i < propn; i++) {
01272 g_value_init(&pval,props[i]->value_type);
01273 g_object_get_property(G_OBJECT(object), props[i]->name, &pval);
01274 switch (props[i]->value_type) {
01275
01276 case G_TYPE_STRING:
01277 if(g_value_get_string(&pval))
01278 midgard_query_builder_add_constraint(builder,
01279 props[i]->name, "=", &pval);
01280 break;
01281
01282 case G_TYPE_UINT:
01283 if(g_value_get_uint(&pval))
01284 midgard_query_builder_add_constraint(builder,
01285 props[i]->name, "=", &pval);
01286 break;
01287
01288 case G_TYPE_INT:
01289 if(g_value_get_int(&pval))
01290 midgard_query_builder_add_constraint(builder,
01291 props[i]->name, "=", &pval);
01292 break;
01293
01294 case G_TYPE_FLOAT:
01295 if(g_value_get_float(&pval))
01296 midgard_query_builder_add