00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <config.h>
00020 #include "midgard/midgard_schema.h"
00021 #include <glib/gprintf.h>
00022 #include "midgard/midgard_legacy.h"
00023 #include "midgard/midgard_object.h"
00024 #include "schema.h"
00025 #include "midgard/midgard_object_property.h"
00026 #include "midgard/midgard_reflection_property.h"
00027 #include "midgard_mysql.h"
00028
00029
00030 #define _DQS 512
00031
00032 gint midgard_query_execute(midgard *mgd, gchar *sql, gpointer user_data)
00033 {
00034 g_assert(mgd->msql->mysql != NULL);
00035
00036 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", sql);
00037
00038 gint sq = mysql_query(mgd->msql->mysql, sql);
00039 g_free(sql);
00040
00041 if (sq != 0) {
00042 g_warning("query failed: %s", mysql_error(mgd->msql->mysql));
00043 return -1;
00044 }
00045 return mysql_affected_rows(mgd->msql->mysql);
00046 }
00047
00048 GList *midgard_query_get_single_row(gchar *sql, MgdObject *object)
00049 {
00050
00051 g_assert(sql);
00052 g_assert(object);
00053 g_assert(object->mgd);
00054
00055 midgard *mgd = object->mgd;
00056 GParamSpec *prop;
00057
00058 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", sql);
00059
00060 gint sq = mysql_query(mgd->msql->mysql, sql);
00061 g_free(sql);
00062
00063 if (sq != 0) {
00064 g_warning("query failed: %s", mysql_error(mgd->msql->mysql));
00065 return NULL;
00066 }
00067
00068 guint retf, i;
00069
00070 MYSQL_RES *results = mysql_store_result(mgd->msql->mysql);
00071 if (!results)
00072 return NULL;
00073 if ((retf = mysql_num_fields(results)) == 0) {
00074 mysql_free_result(results);
00075 return NULL;
00076 }
00077
00078 MYSQL_ROW row = mysql_fetch_row(results);
00079 MYSQL_FIELD *field;
00080
00081 if(!row){
00082 mysql_free_result(results);
00083 return NULL;
00084 }
00085
00086 GList *list = NULL;
00087
00088 for(i = 0; i < retf; i++){
00089
00090 if (row[i] == NULL)
00091 row[i] = "";
00092
00093 field = mysql_fetch_field_direct(results, i);
00094 prop = g_object_class_find_property(
00095 (GObjectClass *)object->klass, field->name);
00096
00097 if(prop != NULL) {
00098
00099 switch (prop->value_type) {
00100
00101
00102
00103
00104
00105
00106
00107 default:
00108 list = g_list_prepend(list, g_strdup((gchar *)row[i]));
00109 break;
00110 }
00111
00112 } else {
00113
00114 list = g_list_prepend(list, g_strdup((gchar *)row[i]));
00115 }
00116 }
00117
00118 list = g_list_reverse(list);
00119 mysql_free_result(results);
00120
00121 return list;
00122
00123 }
00124
00125 gboolean midgard_object_set_from_query(gchar *sql, MgdObject *object) {
00126
00127 g_assert(sql);
00128 g_assert(object);
00129 g_assert(object->mgd);
00130
00131 midgard *mgd = object->mgd;
00132 GParamSpec *prop;
00133 GValue pval = {0,};
00134
00135 GString *nsql = g_string_new("");
00136 g_string_append(nsql, sql);
00137 g_string_append_printf(nsql,
00138 "AND %s.sitegroup IN (0, %d)",
00139 midgard_object_class_get_table(MIDGARD_OBJECT_GET_CLASS(object)),
00140 midgard_sitegroup_get_id(object->mgd)
00141 );
00142
00143
00144 if (mgd_isroot(mgd))
00145 g_string_append(nsql, " AND 1=1");
00146
00147 gchar *query = g_string_free(nsql, FALSE);
00148
00149 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", query);
00150
00151 gint sq = mysql_query(mgd->msql->mysql, query);
00152 g_free(query);
00153 g_free(sql);
00154
00155 if (sq != 0) {
00156 g_warning("query failed: %s", mysql_error(mgd->msql->mysql));
00157 return FALSE;
00158 }
00159
00160 guint ret_fields, i;
00161
00162 MYSQL_RES *results = mysql_store_result(mgd->msql->mysql);
00163
00164 if (!results)
00165 return FALSE;
00166
00167 if ((ret_fields = mysql_num_fields(results)) == 0) {
00168 mysql_free_result(results);
00169 return FALSE;
00170 }
00171
00172 if (mysql_num_rows(results) == 0) {
00173
00174 mysql_free_result(results);
00175 return FALSE;
00176 }
00177
00178
00179 MYSQL_ROW row = mysql_fetch_row(results);
00180 MYSQL_FIELD *field;
00181
00182 for(i = 0; i < ret_fields; i++){
00183
00184 if (row[i] == NULL)
00185 row[i] = "";
00186
00187 field = mysql_fetch_field_direct(results, i);
00188
00189 if ((prop = g_object_class_find_property((GObjectClass *)object->klass,
00190 field->name)) != NULL ) {
00191
00192 g_value_init(&pval,prop->value_type);
00193
00194 switch (prop->value_type) {
00195
00196 case G_TYPE_STRING:
00197 g_value_set_string(&pval, (gchar *)row[i]);
00198 break;
00199
00200 case G_TYPE_UINT:
00201 g_value_set_uint(&pval, atoi(row[i]));
00202 break;
00203
00204 case G_TYPE_INT:
00205 g_value_set_int(&pval, atoi(row[i]));
00206 break;
00207
00208 case G_TYPE_CHAR:
00209 g_value_set_string(&pval, row[i]);
00210 break;
00211
00212 case G_TYPE_LONG:
00213 g_value_set_long(&pval, atol(row[i]));
00214 break;
00215
00216 case G_TYPE_FLOAT:
00217 g_value_set_float(&pval, g_ascii_strtod(row[i], NULL));
00218 break;
00219
00220 case G_TYPE_BOOLEAN:
00221 g_value_set_boolean(&pval, atoi(row[i]));
00222 break;
00223
00224 default:
00225 break;
00226 }
00227 g_object_set_property(G_OBJECT(object), field->name, &pval);
00228 g_value_unset(&pval);
00229 }
00230 }
00231
00232 mysql_free_result(results);
00233 return TRUE;
00234 }
00235
00236 gboolean midgard_object_update_storage(MgdObject *object)
00237 {
00238 g_assert(object != NULL);
00239
00240 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(object);
00241 const gchar *table = midgard_object_class_get_table(klass);
00242 const gchar *primary_property =
00243 midgard_object_class_get_primary_property(klass);
00244 if(table == NULL)
00245 return FALSE;
00246
00247 guint propn;
00248 gint i;
00249 GType prop_type;
00250 gchar **real_field = NULL;
00251 MgdSchemaPropertyAttr *prop_attr;
00252 GParamSpec **props =
00253 g_object_class_list_properties(
00254 G_OBJECT_CLASS(klass), &propn);
00255 MidgardReflectionProperty *mrp =
00256 midgard_reflection_property_new(klass);
00257
00258 for(i = 0 ; i < propn; i++){
00259 prop_type =
00260 midgard_reflection_property_get_midgard_type(
00261 mrp, props[i]->name);
00262 prop_attr = g_hash_table_lookup(
00263 klass->data->prophash, props[i]->name);
00264
00265 const gchar *nick = g_param_spec_get_nick (props[i]);
00266 if ((strlen(nick)) < 1)
00267 continue;
00268
00269 real_field = g_strsplit(nick, ".", 2);
00270
00271 GString *alter_cmd = g_string_new("ALTER TABLE ");
00272 g_string_append_printf(
00273 alter_cmd,
00274 " %s MODIFY ",
00275 real_field[0]);
00276
00277
00278 if((prop_attr != NULL) && (prop_attr->dbtype != NULL)) {
00279 g_string_append_printf(
00280 alter_cmd, "%s %s ",
00281 real_field[1],
00282 prop_attr->dbtype
00283 );
00284 } else {
00285
00286 if(prop_type == MGD_TYPE_STRING){
00287 g_string_append_printf(
00288 alter_cmd,
00289 "%s varchar(255) NOT NULL "
00290 "default ''",
00291 real_field[1]);
00292
00293 } else if(prop_type == MGD_TYPE_LONGTEXT){
00294 g_string_append_printf(
00295 alter_cmd,
00296 "%s longtext NOT NULL "
00297 "default ''",
00298 real_field[1]);
00299
00300 } else if(prop_type == MGD_TYPE_INT
00301 || prop_type == MGD_TYPE_UINT){
00302 g_string_append_printf(
00303 alter_cmd,
00304 "%s int(11) NOT NULL ",
00305 real_field[1]);
00306 if(g_str_equal(props[i]->name, primary_property))
00307 g_string_append(alter_cmd,
00308 "auto_increment");
00309 else
00310 g_string_append(alter_cmd,
00311 "default 0");
00312
00313 } else if(prop_type == MGD_TYPE_FLOAT) {
00314 g_string_append_printf(
00315 alter_cmd,
00316 "%s FLOAT NOT NULL "
00317 "default '0.0000'",
00318 real_field[1]);
00319
00320 } else if(prop_type == MGD_TYPE_BOOLEAN) {
00321 g_string_append_printf(
00322 alter_cmd,
00323 "%s BOOLEAN NOT NULL "
00324 "default 0",
00325 real_field[1]);
00326
00327 } else if(prop_type == MGD_TYPE_TIMESTAMP) {
00328 g_string_append_printf(
00329 alter_cmd,
00330 "%s datetime NOT NULL "
00331 "default '0000-00-00 00:00:00'",
00332 real_field[1]);
00333
00334 } else if(prop_type == MGD_TYPE_GUID){
00335 g_string_append_printf(
00336 alter_cmd,
00337 "%s varchar(80) NOT NULL "
00338 "default ''",
00339 real_field[1]);
00340 } else {
00341 g_string_append_printf(
00342 alter_cmd,
00343 "%s varchar(255) NOT NULL "
00344 "default ''",
00345 real_field[1]);
00346 }
00347 }
00348
00349 gint rv = midgard_query_execute(object->mgd,
00350 g_string_free(alter_cmd, FALSE), NULL);
00351 g_strfreev(real_field);
00352 if(rv < 0){
00353 g_free(props);
00354 return FALSE;
00355 }
00356 }
00357 g_free(props);
00358
00359 return TRUE;
00360 }
00361
00362 gboolean midgard_object_create_storage(MgdObject *object)
00363 {
00364 GString *cmd, *cmd_modify;
00365 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(object);
00366 const gchar *pfield = midgard_object_class_get_primary_field(klass);
00367 const gchar *primary_property = midgard_object_class_get_primary_property(klass);
00368 const gchar *table = midgard_object_class_get_table(klass);
00369
00370 if(table == NULL)
00371 return FALSE;
00372
00373 GParamSpec *prop, **props;
00374 gint rv;
00375 guint propn, i = 0;
00376 gchar **real_field = NULL;
00377 const gchar *datatype;
00378 GType prop_type;
00379
00380
00381 gchar **tables = g_strsplit(
00382 midgard_object_class_get_tables(klass), ",", 0);
00383
00384 do {
00385 cmd = g_string_new("CREATE TABLE IF NOT EXISTS ");
00386 g_string_append(cmd, tables[i]);
00387
00388
00389
00390
00391 g_string_append_printf(cmd , "(%s ", pfield);
00392
00393 if ((prop = g_object_class_find_property(
00394 G_OBJECT_CLASS(klass),
00395 primary_property)) != NULL ) {
00396
00397 switch (prop->value_type){
00398 case G_TYPE_STRING:
00399 g_string_append_printf(cmd , "varchar(80) NOT NULL");
00400 break;
00401
00402 case G_TYPE_UINT:
00403 g_string_append_printf(cmd,
00404 "int(%u) NOT NULL auto_increment", 11);
00405 }
00406 }
00407
00408 g_string_append_printf(cmd , ", PRIMARY KEY(%s)) ", pfield);
00409 rv = midgard_query_execute(object->mgd, g_string_free(cmd, FALSE), NULL);
00410
00411 if (rv == -1){
00412 g_warning("Table %s not created", table);
00413 i++;
00414 return FALSE;
00415 } else {
00416 g_message("Table '%s' OK", tables[i]);
00417 i++;
00418 }
00419
00420 } while (tables[i]);
00421 g_strfreev(tables);
00422
00423
00424
00425 props = g_object_class_list_properties(
00426 G_OBJECT_CLASS(object->klass), &propn);
00427 MidgardReflectionProperty *mrp =
00428 midgard_reflection_property_new(klass);
00429
00430 for(i = 0 ; i < propn; i++){
00431 MgdSchemaPropertyAttr *prop_attr =
00432 g_hash_table_lookup(klass->data->prophash, props[i]->name);
00433 if(!prop_attr)
00434 continue;
00435
00436
00437 if (g_ascii_strcasecmp(props[i]->name, prop->name) == 0)
00438 continue;
00439
00440 prop_type =
00441 midgard_reflection_property_get_midgard_type(
00442 mrp, props[i]->name);
00443
00444 const gchar *nick = g_param_spec_get_nick (props[i]);
00445
00446
00447 if ((strlen(nick)) < 1)
00448 continue;
00449
00450
00451 real_field = g_strsplit(nick, ".", 2);
00452 cmd = g_string_new("ALTER TABLE ");
00453 g_string_append_printf(cmd, "%s ADD ", real_field[0]);
00454 datatype = prop_attr->dbtype;
00455
00456 if(datatype != NULL ) {
00457 g_string_append_printf(cmd,
00458 "%s %s "
00459 , real_field[1], datatype);
00460 } else {
00461
00462 if(prop_type == MGD_TYPE_STRING){
00463 g_string_append_printf(
00464 cmd,
00465 "%s varchar(255) NOT NULL "
00466 "default ''",
00467 real_field[1]);
00468
00469 } else if(prop_type == MGD_TYPE_LONGTEXT){
00470 g_string_append_printf(
00471 cmd,
00472 "%s longtext NOT NULL "
00473 "default ''",
00474 real_field[1]);
00475
00476 } else if(prop_type == MGD_TYPE_INT
00477 || prop_type == MGD_TYPE_UINT){
00478 g_string_append_printf(
00479 cmd,
00480 "%s int(11) NOT NULL "
00481 "default 0",
00482 real_field[1]);
00483
00484 } else if(prop_type == MGD_TYPE_FLOAT) {
00485 g_string_append_printf(
00486 cmd,
00487 "%s FLOAT NOT NULL "
00488 "default '0.0000'",
00489 real_field[1]);
00490
00491 } else if(prop_type == MGD_TYPE_BOOLEAN) {
00492 g_string_append_printf(
00493 cmd,
00494 "%s BOOLEAN NOT NULL "
00495 "default 0",
00496 real_field[1]);
00497
00498 } else if(prop_type == MGD_TYPE_TIMESTAMP) {
00499 g_string_append_printf(
00500 cmd,
00501 "%s datetime NOT NULL "
00502 "default '0000-00-00 00:00:00'",
00503 real_field[1]);
00504
00505 } else if(prop_type == MGD_TYPE_GUID){
00506 g_string_append_printf(
00507 cmd,
00508 "%s varchar(80) NOT NULL "
00509 "default ''",
00510 real_field[1]);
00511 } else {
00512 g_string_append_printf(
00513 cmd,
00514 "%s varchar(255) NOT NULL "
00515 "default ''",
00516 real_field[1]);
00517 }
00518 }
00519 rv = midgard_query_execute(
00520 object->mgd, g_string_free(cmd, FALSE), NULL);
00521 g_message("Column '%s' OK", real_field[1]);
00522 g_strfreev(real_field);
00523 }
00524 g_free(props);
00525
00526
00527 cmd_modify = g_string_new("ALTER TABLE ");
00528 g_string_append_printf(cmd_modify,
00529 "%s ADD guid varchar(80) NOT NULL", table);
00530 rv = midgard_query_execute(object->mgd, g_string_free(cmd_modify, FALSE), NULL);
00531
00532
00533 cmd_modify = g_string_new("ALTER TABLE ");
00534 g_string_append_printf(cmd_modify, "%s ADD KEY(guid)", table);
00535 rv = midgard_query_execute(object->mgd, g_string_free(cmd_modify, FALSE), NULL);
00536
00537
00538 cmd_modify = g_string_new("ALTER TABLE ");
00539 g_string_append_printf(cmd_modify,
00540 "%s ADD sitegroup int(11) NOT NULL", table);
00541 rv = midgard_query_execute(object->mgd, g_string_free(cmd_modify, FALSE), NULL);
00542
00543
00544 cmd_modify = g_string_new("ALTER TABLE ");
00545 g_string_append_printf(cmd_modify, "%s ADD KEY(sitegroup)", table);
00546 rv = midgard_query_execute(object->mgd, g_string_free(cmd_modify, FALSE), NULL);
00547
00548
00549 if (midgard_object_class_get_parent_property(klass)) {
00550 cmd_modify = g_string_new("ALTER TABLE ");
00551 g_string_append_printf(cmd_modify, "%s ADD KEY(%s)",
00552 table, midgard_object_class_get_parent_property(klass));
00553 rv = midgard_query_execute(object->mgd, g_string_free(cmd_modify, FALSE), NULL);
00554 }
00555
00556 if (midgard_object_class_get_up_property(klass)) {
00557 cmd_modify = g_string_new("ALTER TABLE ");
00558 g_string_append_printf(cmd_modify, "%s ADD KEY(%s)",
00559 table, midgard_object_class_get_up_property(klass));
00560 rv = midgard_query_execute(object->mgd, g_string_free(cmd_modify, FALSE), NULL);
00561 }
00562
00563
00564
00565
00566 guint metapropn;
00567 props = g_object_class_list_properties(
00568 G_OBJECT_GET_CLASS(object->metadata), &metapropn);
00569 const gchar *meta_field;
00570 for(i = 0 ; i < metapropn; i++){
00571
00572 meta_field = g_param_spec_get_nick (props[i]);
00573
00574 if(g_str_equal(props[i]->name, "creator") ||
00575 g_str_equal(props[i]->name, "revisor") ||
00576 g_str_equal(props[i]->name, "approver") ||
00577 g_str_equal(props[i]->name, "locker") ||
00578 g_str_equal(props[i]->name, "owner")) {
00579 cmd = g_string_new("ALTER table ");
00580 g_string_append_printf(cmd,
00581 "%s ADD (%s "
00582 "varchar(80) NOT NULL default '')",
00583 table, meta_field);
00584 midgard_query_execute(object->mgd,
00585 g_string_free(cmd, FALSE), NULL);
00586 }
00587
00588 if(g_str_equal(props[i]->name, "authors")) {
00589 cmd = g_string_new("ALTER table ");
00590 g_string_append_printf(cmd,
00591 "%s ADD (%s "
00592 "longtext NOT NULL default '')",
00593 table, meta_field);
00594 midgard_query_execute(object->mgd,
00595 g_string_free(cmd, FALSE), NULL);
00596 }
00597
00598 if(g_str_equal(props[i]->name, "created") ||
00599 g_str_equal(props[i]->name, "revised") ||
00600 g_str_equal(props[i]->name, "approved") ||
00601 g_str_equal(props[i]->name, "locked") ||
00602 g_str_equal(props[i]->name, "schedulestart") ||
00603 g_str_equal(props[i]->name, "scheduleend") ||
00604 g_str_equal(props[i]->name, "published") ||
00605 g_str_equal(props[i]->name, "exported") ||
00606 g_str_equal(props[i]->name, "imported")) {
00607 cmd = g_string_new("ALTER table ");
00608 g_string_append_printf(cmd,
00609 "%s ADD (%s "
00610 "datetime NOT NULL default '0000-00-00 00:00:00')",
00611 table, meta_field);
00612 midgard_query_execute(object->mgd,
00613 g_string_free(cmd, FALSE), NULL);
00614 }
00615
00616 if(g_str_equal(props[i]->name, "hidden") ||
00617 g_str_equal(props[i]->name, "navnoentry") ||
00618 g_str_equal(props[i]->name, "deleted")) {
00619 cmd = g_string_new("ALTER table ");
00620 g_string_append_printf(cmd,
00621 "%s ADD (%s "
00622 "BOOL default 0)",
00623 table, meta_field);
00624 midgard_query_execute(object->mgd,
00625 g_string_free(cmd, FALSE), NULL);
00626 }
00627
00628 if(g_str_equal(props[i]->name, "size") ||
00629 g_str_equal(props[i]->name, "revision") ||
00630 g_str_equal(props[i]->name, "score")) {
00631 cmd = g_string_new("ALTER table ");
00632 g_string_append_printf(cmd,
00633 "%s ADD (%s "
00634 "int(11) NOT NULL default '0')",
00635 table, meta_field);
00636 midgard_query_execute(object->mgd,
00637 g_string_free(cmd, FALSE), NULL);
00638 }
00639 }
00640 g_free(props);
00641
00642
00643 g_message("Table and columns for '%s' OK", object->cname);
00644 return TRUE;
00645 }