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 "midgard/midgard_schema.h"
00022 #include "midgard/query_builder.h"
00023 #include "midgard/midgard_legacy.h"
00024 #include "query_constraint.h"
00025 #include "simple_constraint.h"
00026 #include "group_constraint.h"
00027 #include "query_order.h"
00028 #include "midgard/midgard_object_property.h"
00029 #include "midgard/midgard_object.h"
00030 #include "schema.h"
00031 #include "midgard_mysql.h"
00032 #include "midgard_core_query_builder.h"
00033 #include "midgard/midgard_error.h"
00034 #include "midgard_core_object.h"
00035
00036
00037
00038 gchar *midgard_query_builder_get_object_select(MidgardQueryBuilder *builder, guint select_type);
00039
00040 GList *_mqb_set_object_from_query(MidgardQueryBuilder *builder, guint select_type) ;
00041
00042
00043 void _midgard_core_qb_add_table(
00044 MidgardQueryBuilder *builder, const gchar *table)
00045 {
00046 g_assert(builder);
00047
00048 if(builder->tables){
00049 guint tlen = strlen(builder->tables);
00050 gchar *table_found = g_strstr_len(
00051 builder->tables,
00052 tlen,
00053 table);
00054 if(!table_found){
00055 gchar *tmptable = g_strconcat(builder->tables,
00056 ",",
00057 table,
00058 NULL);
00059 g_free(builder->tables);
00060 builder->tables = g_strdup(tmptable);
00061 g_free(tmptable);
00062 }
00063 }
00064 }
00065
00066
00067 void _midgard_core_qb_add_join(
00068 MidgardQueryBuilder *builder,
00069 const gchar *table_a, const gchar *column_a,
00070 const gchar *table_b, const gchar *column_b)
00071 {
00072 g_assert(table_a != NULL && column_a != NULL
00073 && table_b != NULL && column_b != NULL);
00074
00075 g_string_append(builder->join, " AND ");
00076 g_string_append_printf(builder->join,
00077 "%s.%s = %s.%s",
00078 table_a, column_a,
00079 table_b, column_b);
00080 }
00081
00082 static void _mqb_type_pop(MidgardQueryBuilder *builder){
00083
00084 g_assert(builder != NULL);
00085 builder->type = (guint)g_list_nth_data(builder->types, 0);
00086 }
00087
00088 static gchar **_mqb_parse_constraint_property(
00089 MidgardQueryBuilder *builder, gchar **name)
00090 {
00091 g_assert(builder != NULL);
00092
00093 if(!name[2])
00094 return name;
00095 guint i, n = 0;
00096 MgdObject *ref_object = NULL;
00097 const gchar *reftype = NULL;
00098 MidgardObjectClass *klass =
00099 (MidgardObjectClass*) g_type_class_peek(builder->type);
00100 MidgardObjectClass *ref_klass =
00101 midgard_object_property_get_link_class(
00102 klass, name[0]);
00103 if(ref_klass)
00104 reftype = G_OBJECT_CLASS_NAME(G_OBJECT_CLASS(ref_klass));
00105
00106 if (reftype != NULL)
00107 ref_object = midgard_object_new(builder->mgd, reftype, NULL);
00108 if(ref_object == NULL) {
00109 g_warning("Type %s in not registered in application schema",
00110 reftype);
00111 return NULL;
00112 }
00113 GType new_type = G_TYPE_FROM_INSTANCE(ref_object);
00114 builder->parent_type = new_type;
00115 builder->type = new_type;
00116 builder->types = g_list_append(builder->types, (gpointer)builder->type);
00117
00118 for(i = 0 ; name[i]; i++){
00119 n++;
00120 }
00121 gchar **str_array = g_new (gchar *, n);
00122 for(i = 0 ; name[i]; i++){
00123 str_array[i] = g_strdup(name[i+1]);
00124 }
00125 g_strfreev(name);
00126 return _mqb_parse_constraint_property(builder, str_array);
00127 }
00128
00129
00130
00131
00132
00133 static gchar * _mqb_get_new_property(
00134 MidgardQueryBuilder *builder, const gchar *name){
00135
00136 g_assert(builder);
00137
00138 gchar *new_name = (gchar *)name;
00139 guint strl = 0;
00140
00141 builder->ext_type = 0;
00142 builder->parent_type = 0;
00143
00144 if((strl = strlen(name)) == 0)
00145 return new_name;
00146
00147 gchar **spltd, *tmpstr;
00148 MgdObject *ref_object = NULL;
00149
00150
00151 tmpstr = g_strstr_len(name, strl, ".");
00152 if(tmpstr != NULL){
00153 spltd = g_strsplit(name, ".", 0);
00154
00155 if(spltd[2])
00156 spltd = _mqb_parse_constraint_property(builder, spltd);
00157 if(!spltd){
00158 g_strfreev(spltd);
00159 return new_name;
00160 }
00161
00162 if (spltd[1] != NULL) {
00163 new_name = g_strdup(spltd[1]);
00164
00165
00166
00167 if(g_str_equal(spltd[0], "metadata")) {
00168
00169
00170 builder->parent_type = builder->type;
00171 builder->type = g_type_from_name("midgard_metadata");
00172 builder->ext_type = builder->type;
00173 builder->types = g_list_append(builder->types, (gpointer)builder->type);
00174 g_strfreev(spltd);
00175 return new_name;
00176 }
00177
00178
00179 if(g_str_equal(spltd[0], "parameter")) {
00180 builder->parent_type = builder->type;
00181 builder->type = g_type_from_name("midgard_parameter");
00182 builder->ext_type = builder->type;
00183 builder->types = g_list_append(builder->types, (gpointer)builder->type);
00184 g_strfreev(spltd);
00185 _midgard_core_qb_add_table(builder, "record_extension");
00186 MidgardObjectClass *klass =
00187 (MidgardObjectClass*) g_type_class_peek(builder->parent_type);
00188 _midgard_core_qb_add_join(builder,
00189 midgard_object_class_get_table(klass), "guid",
00190 "record_extension", "parent_guid");
00191 return new_name;
00192 }
00193
00194
00195 if(g_str_equal(spltd[0], "attachment")) {
00196 builder->parent_type = builder->type;
00197 builder->type = g_type_from_name("midgard_attachment");
00198 builder->ext_type = builder->type;
00199 builder->types = g_list_append(builder->types, (gpointer)builder->type);
00200 g_strfreev(spltd);
00201 _midgard_core_qb_add_table(builder, "blobs");
00202 MidgardObjectClass *klass =
00203 (MidgardObjectClass*) g_type_class_peek(builder->parent_type);
00204 _midgard_core_qb_add_join(builder,
00205 midgard_object_class_get_table(klass), "guid",
00206 "blobs", "parent_guid");
00207 return new_name;
00208 }
00209
00210
00211 const gchar *reftype = NULL;
00212 MidgardObjectClass *klass =
00213 (MidgardObjectClass*) g_type_class_peek(builder->type);
00214 MidgardObjectClass *ref_klass =
00215 midgard_object_property_get_link_class(
00216 klass, spltd[0]);
00217 if(ref_klass)
00218 reftype = G_OBJECT_CLASS_NAME(G_OBJECT_CLASS(ref_klass));
00219
00220
00221 if (reftype != NULL)
00222 ref_object = midgard_object_new(builder->mgd, reftype, NULL);
00223
00224
00225
00226 if(ref_object == NULL) {
00227 g_warning("Type %s in not registered in application schema",
00228 reftype);
00229 return FALSE;
00230 }
00231
00232 const gchar *target_name;
00233 GParamSpec *spec = NULL;
00234
00235
00236 MidgardReflectionProperty *mrp =
00237 midgard_reflection_property_new(klass);
00238
00239 if(mrp) {
00240
00241 target_name =
00242 midgard_reflection_property_get_link_target(
00243 mrp, spltd[0]);
00244 g_object_unref(mrp);
00245
00246 spec = g_object_class_find_property(
00247 G_OBJECT_CLASS(g_type_class_peek(ref_object->type)),
00248 target_name);
00249 } else {
00250 g_warning("Failed to initialize midgard_reflection_property");
00251 }
00252
00253 if (spec) {
00254
00255 if(g_str_equal(target_name, "guid"))
00256 builder->link =
00257 g_strjoin(".",
00258 midgard_object_class_get_table(ref_klass),
00259 "guid", NULL);
00260 else
00261 builder->link = g_strdup(g_param_spec_get_nick(spec));
00262
00263 GParamSpec *ospec = g_object_class_find_property(
00264 G_OBJECT_CLASS(
00265 g_type_class_peek(builder->type)),
00266 spltd[0]);
00267 if(!ospec) {
00268 g_warning("Property '%s' not found for referenced "
00269 "'%s' type",
00270 spltd[0],
00271 g_type_name(builder->type));
00272 return FALSE;
00273 }
00274
00275
00276 builder->type = G_TYPE_FROM_INSTANCE(ref_object);
00277
00278
00279 g_string_append_printf(builder->join,
00280 " AND %s = ",
00281 g_param_spec_get_nick(ospec));
00282
00283 g_string_append(builder->join, builder->link);
00284
00285
00286 gchar **duptables = g_strsplit(builder->tables, ",", 0);
00287 guint i = 0, j = 0;
00288 for(i = 0 ; duptables[i]; i++){
00289 if (g_ascii_strcasecmp(duptables[i],
00290 midgard_object_class_get_table(ref_klass)) == 0 )
00291 j++;
00292 }
00293
00294
00295 if (j == 0) {
00296 gchar *tmptable = g_strconcat(builder->tables,
00297 ",",
00298 midgard_object_class_get_table(ref_klass),
00299 NULL);
00300
00301 g_free(builder->tables);
00302 builder->tables = g_strdup(tmptable);
00303 g_free(tmptable);
00304 }
00305 g_strfreev(duptables);
00306 }
00307 g_object_unref(ref_object);
00308 }
00309 g_strfreev(spltd);
00310 return new_name;
00311 }
00312 return new_name;
00313 }
00314
00315 MidgardQueryBuilder *midgard_query_builder_new(
00316 midgard *mgd, const gchar *classname)
00317 {
00318 g_assert(mgd);
00319 g_assert(classname);
00320
00321 MidgardQueryBuilder *builder =
00322 g_object_new(MIDGARD_TYPE_QUERY_BUILDER, NULL);
00323
00324 builder->mgd = mgd;
00325 builder->type = g_type_from_name(classname);
00326 builder->parent_type = 0;
00327 builder->ext_type = 0;
00328 builder->types = g_list_append(NULL, (gpointer)builder->type);
00329 builder->lang = -1;
00330 builder->unset_lang = FALSE;
00331 builder->include_deleted = FALSE;
00332 builder->tables = NULL;
00333 builder->link = NULL;
00334 builder->join = g_string_new(" ");
00335 builder->error = 0;
00336
00337 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS_BY_NAME(classname);
00338 builder->schema = klass->data;
00339 builder->tables = g_strdup(midgard_object_class_get_tables(klass));
00340
00341 MidgardGroupConstraint *group =
00342 midgard_group_constraint_new(MIDGARD_GROUP_CONSTRAINT_TYPE_AND);
00343 builder->stack = g_slist_prepend(NULL, group);
00344 builder->orders =
00345 g_array_new(FALSE, FALSE, sizeof(MidgardQueryOrder *));
00346 builder->offset = 0;
00347 builder->limit = G_MAXUINT;
00348
00349 if (builder->type && builder->schema) {
00350 return builder;
00351 } else {
00352 g_object_unref(builder);
00353 return NULL;
00354 }
00355 }
00356
00357 void midgard_query_builder_free(MidgardQueryBuilder *builder) {
00358 g_assert(builder);
00359
00360 while (g_slist_next(builder->stack) != NULL) {
00361 g_warning("Constraint groups not properly nested");
00362 GSList *item = builder->stack;
00363 builder->stack = g_slist_remove_link(builder->stack, item);
00364 g_slist_free_1(item);
00365 }
00366 g_object_unref(G_OBJECT(builder->stack->data));
00367 g_slist_free(builder->stack);
00368
00369 guint i;
00370 for (i = 0; i < builder->orders->len; i++) {
00371 midgard_query_order_free(g_array_index(
00372 builder->orders, MidgardQueryOrder *, i));
00373 }
00374 g_array_free(builder->orders, TRUE);
00375 if(builder->join) {
00376 gchar *tmpstr = g_string_free(builder->join, FALSE);
00377 g_free(tmpstr);
00378 }
00379 g_free((gchar *)builder->tables);
00380 g_free((gchar *)builder->link);
00381 }
00382
00383 gboolean midgard_query_builder_add_constraint(
00384 MidgardQueryBuilder *builder,
00385 const gchar *name, const gchar *op, const GValue *value) {
00386 g_assert(builder);
00387 g_assert(name);
00388 g_assert(op);
00389 g_assert(value);
00390
00391 GObjectClass *tmpklass = g_type_class_peek(builder->type);
00392
00393 gchar *new_name = _mqb_get_new_property(builder, name);
00394
00395 MidgardSimpleConstraint *simple = midgard_simple_constraint_new(
00396 builder->mgd, G_OBJECT_CLASS(g_type_class_peek(builder->type)),
00397 new_name, op, value);
00398
00399
00400
00401
00402 if(simple != NULL){
00403 simple->ext_type = builder->ext_type;
00404 simple->parent_type = builder->parent_type;
00405 simple->initial_klass = tmpklass;
00406 simple->types = builder->types;
00407 }
00408 _mqb_type_pop(builder);
00409
00410 if (simple != NULL) {
00411 midgard_group_constraint_add_constraint(
00412 MIDGARD_GROUP_CONSTRAINT(builder->stack->data),
00413 MIDGARD_QUERY_CONSTRAINT(simple));
00414 g_object_unref(G_OBJECT(simple));
00415 return TRUE;
00416 } else {
00417 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
00418 "Invalid query constraint specification");
00419
00420
00421
00422 builder->error = 1;
00423 return FALSE;
00424 }
00425 }
00426
00427 gboolean midgard_query_builder_begin_group(
00428 MidgardQueryBuilder *builder, const gchar *type) {
00429 g_assert(builder);
00430 g_assert(type);
00431 MidgardGroupConstraint *group = midgard_group_constraint_new(type);
00432 if (group != NULL) {
00433 midgard_group_constraint_add_constraint(
00434 MIDGARD_GROUP_CONSTRAINT(builder->stack->data),
00435 MIDGARD_QUERY_CONSTRAINT(group));
00436 builder->stack = g_slist_prepend(builder->stack, group);
00437 return TRUE;
00438 } else {
00439 g_warning("Invalid query group type: %s", type);
00440 return FALSE;
00441 }
00442 }
00443
00444 gboolean midgard_query_builder_end_group(MidgardQueryBuilder *builder) {
00445 g_assert(builder);
00446 if (g_slist_next(builder->stack) != NULL) {
00447 g_object_unref(G_OBJECT(builder->stack->data));
00448 builder->stack = g_slist_next(builder->stack);
00449 return TRUE;
00450 } else {
00451 g_warning("Invalid number of query group endings");
00452 return FALSE;
00453 }
00454 }
00455
00456 gboolean midgard_query_builder_add_order(
00457 MidgardQueryBuilder *builder, const gchar *name, const gchar *dir)
00458 {
00459 g_assert(builder);
00460 g_assert(name);
00461 g_assert(dir);
00462
00463 gchar *new_name = _mqb_get_new_property(builder, name);
00464 MidgardQueryOrder *order = midgard_query_order_new(
00465 builder->mgd, G_OBJECT_CLASS(g_type_class_peek(builder->type)),
00466 new_name, dir);
00467 _mqb_type_pop(builder);
00468
00469 if (order) {
00470 order->ext_type = builder->ext_type;
00471 order->parent_type = builder->parent_type;
00472 g_array_append_val(builder->orders, order);
00473 return TRUE;
00474 } else {
00475 g_warning("Skipping a ordering constraint specification");
00476 return FALSE;
00477 }
00478 }
00479
00480 void midgard_query_builder_set_limit(
00481 MidgardQueryBuilder *builder, guint limit)
00482 {
00483 g_assert(builder);
00484 builder->limit = limit;
00485 }
00486
00487 void midgard_query_builder_set_offset(
00488 MidgardQueryBuilder *builder, guint offset)
00489 {
00490 g_assert(builder);
00491 builder->offset = offset;
00492 }
00493
00494 void midgard_query_builder_set_lang(MidgardQueryBuilder *builder, gint lang)
00495 {
00496 g_assert(builder);
00497 builder->lang = lang;
00498 }
00499
00500 void midgard_query_builder_unset_languages(MidgardQueryBuilder *builder)
00501 {
00502 g_assert(builder);
00503 builder->unset_lang = TRUE;
00504 }
00505
00506 gint _compare_ml_guid(gconstpointer a, gconstpointer b){
00507
00508 if(g_ascii_strcasecmp(a,b) == 0) return 0;
00509 return 1;
00510 }
00511
00512 static GList *midgard_query_builder_execute_or_count(
00513 MidgardQueryBuilder *builder, guint *n_objects, guint select_type)
00514 {
00515 g_assert(builder);
00516 g_assert(n_objects);
00517
00518 GList *tmp_list = NULL;
00519
00520 GList *list = _mqb_set_object_from_query(builder, select_type);
00521 if(list == NULL){
00522 *n_objects = 0;
00523 return NULL;
00524 }
00525
00526 if (builder->schema->use_lang == 1) {
00527
00528 gchar *guid = NULL;
00529 GList *nlist = NULL;
00530
00531 if(midgard_lang_get(builder->mgd) != 0)
00532 list = g_list_reverse(list);
00533
00534 for(; list ; list = list->next){
00535
00536
00537
00538 if(select_type == MQB_SELECT_OBJECT) {
00539 g_object_get(G_OBJECT(list->data), "guid", &guid, NULL);
00540 } else if (select_type == MQB_SELECT_GUID) {
00541 guid = g_strdup((gchar *)list->data);
00542 }
00543
00544
00545
00546 if((tmp_list = g_list_find_custom(tmp_list,
00547 guid, _compare_ml_guid))) {
00548
00549 g_free((gchar *)tmp_list->data);
00550 tmp_list->data = g_strdup("");
00551
00552 if(select_type == MQB_SELECT_OBJECT) {
00553 g_object_unref(G_OBJECT(list->data));
00554 } else if (select_type == MQB_SELECT_GUID) {
00555
00556
00557 }
00558
00559 } else {
00560 nlist = g_list_append(nlist, list->data);
00561 }
00562 tmp_list = g_list_prepend(tmp_list, (gpointer)guid);
00563 }
00564
00565
00566 for(; tmp_list ; tmp_list = tmp_list->next){
00567 g_free((gchar *)tmp_list->data);
00568 }
00569 g_list_free(tmp_list);
00570 g_list_free(list);
00571 list = nlist;
00572 }
00573
00574 *n_objects = g_list_length(list);
00575 return list;
00576 }
00577
00578 GObject **midgard_query_builder_execute(
00579 MidgardQueryBuilder *builder, guint *n_objects)
00580 {
00581 guint i = 0;
00582 MIDGARD_ERRNO_SET(builder->mgd, MGD_ERR_OK);
00583 GList *list =
00584 midgard_query_builder_execute_or_count(builder, n_objects, MQB_SELECT_OBJECT);
00585 if(list == NULL)
00586 return NULL;
00587
00588 MgdObject **objects = g_new(MgdObject *, *n_objects);
00589
00590 for( ; list; list = list->next){
00591 objects[i] = list->data;
00592 i++;
00593 }
00594 g_list_free(list);
00595 return (GObject **)objects;
00596 }
00597
00598 guint midgard_query_builder_count(MidgardQueryBuilder *builder)
00599 {
00600 g_assert(builder != NULL);
00601 guint n_objects = 0;
00602 MIDGARD_ERRNO_SET(builder->mgd, MGD_ERR_OK);
00603 GList *list =
00604 midgard_query_builder_execute_or_count(builder, &n_objects, MQB_SELECT_GUID);
00605
00606 if(list != NULL){
00607
00608 for( ; list; list = list->next){
00609 g_free((gchar *)list->data);
00610 }
00611 g_list_free(list);
00612 }
00613 return n_objects;
00614 }
00615
00616 GList *midgard_query_builder_get_guid(
00617 MidgardQueryBuilder *builder)
00618 {
00619 g_assert(builder != NULL);
00620 guint n_objects = 0;
00621
00622 GList *list =
00623 midgard_query_builder_execute_or_count(builder, &n_objects, MQB_SELECT_GUID);
00624
00625 return list;
00626 }
00627
00628
00629 gchar *midgard_query_builder_get_object_select(
00630 MidgardQueryBuilder *builder, guint select_type){
00631
00632 g_assert(builder != NULL);
00633 g_assert(builder->type);
00634
00635 MidgardObjectClass *klass = (MidgardObjectClass*) g_type_class_peek(builder->type);
00636 const gchar *table = midgard_object_class_get_table(klass);
00637
00638 if (midgard_object_class_get_table(klass) == NULL){
00639 g_warning("Object '%s' has no table or storage defined!",
00640 g_type_name(builder->type));
00641 return NULL;
00642 }
00643
00644 GString *select = g_string_new("");
00645
00646
00647 if(select_type == MQB_SELECT_GUID){
00648
00649 g_string_append_printf(select, "%s.guid", table);
00650 return g_string_free(select, FALSE);
00651 }
00652
00653
00654
00655
00656
00657 g_string_append_printf(select,
00658 "%s.guid, %s.sitegroup, "
00659 "%s.metadata_creator, "
00660 "NULLIF(%s.metadata_created,'0000-00-00 00:00:00') AS metadata_created, "
00661 "%s.metadata_revisor, "
00662 "NULLIF(%s.metadata_revised,'0000-00-00 00:00:00') AS metadata_revised, "
00663 "%s.metadata_revision, "
00664 "%s.metadata_locker, "
00665 "NULLIF(%s.metadata_locked,'0000-00-00 00:00:00') AS metadata_locked, "
00666 "%s.metadata_approver, "
00667 "NULLIF(%s.metadata_approved,'0000-00-00 00:00:00') AS metadata_approved, "
00668 "%s.metadata_authors, %s.metadata_owner, "
00669 "NULLIF(%s.metadata_schedule_start,'0000-00-00 00:00:00') AS metadata_schedule_start, "
00670 "NULLIF(%s.metadata_schedule_end,'0000-00-00 00:00:00') AS metadata_schedule_end, "
00671 "%s.metadata_hidden, "
00672 "%s.metadata_nav_noentry, %s.metadata_size, %s.metadata_published, "
00673 "NULLIF(%s.metadata_exported,'0000-00-00 00:00:00') AS metadata_exported, "
00674 "NULLIF(%s.metadata_imported,'0000-00-00 00:00:00') AS metadata_imported,"
00675 "%s.metadata_deleted, %s.metadata_score, %s",
00676 table, table, table, table, table, table, table, table, table,
00677 table, table, table, table, table, table, table, table, table,
00678 table, table, table, table, table,
00679 klass->data->query->select_full);
00680
00681 return g_string_free(select, FALSE);
00682 }
00683
00684 GList *_mqb_set_object_from_query(MidgardQueryBuilder *builder, guint select_type){
00685
00686 g_assert(builder != NULL);
00687
00688 GParamSpec *prop;
00689 MgdObject *object;
00690 GValue pval = {0, };
00691 MidgardObjectClass *klass = (MidgardObjectClass*) g_type_class_peek(builder->type);;
00692 guint ret_rows, ret_fields, i, j;
00693
00694 gchar *sql = _midgard_core_qb_get_sql(
00695 builder, select_type,
00696 midgard_query_builder_get_object_select(builder, select_type));
00697
00698 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "query=%s", sql);
00699
00700 if(!sql) {
00701 g_warning("Attempted to execute NULL query");
00702 return NULL;
00703 }
00704
00705 gint sq = mysql_query(builder->mgd->msql->mysql, sql);
00706
00707 if (sq != 0) {
00708 g_warning("\n\nQUERY: \n %s \n\n FAILED: \n %s",
00709 sql,
00710 mysql_error(builder->mgd->msql->mysql));
00711 midgard_set_error(builder->mgd->_mgd,
00712 MGD_GENERIC_ERROR,
00713 MGD_ERR_INTERNAL,
00714 " SQL query failed. ");
00715 g_clear_error(&builder->mgd->_mgd->err);
00716 g_free(sql);
00717 return FALSE;
00718 }
00719 g_free(sql);
00720
00721
00722 MYSQL_ROW row;
00723 MYSQL_FIELD *field;
00724 MYSQL_RES *results = mysql_store_result(builder->mgd->msql->mysql);
00725 if (!results)
00726 return FALSE;
00727
00728 if ((ret_rows = mysql_num_rows(results)) == 0) {
00729 mysql_free_result(results);
00730 return NULL;
00731 }
00732
00733
00734 GList *list = NULL;
00735
00736
00737 if(select_type == MQB_SELECT_GUID) {
00738
00739 for(i = 0; i < ret_rows; i++){
00740 row = mysql_fetch_row(results);
00741 ret_fields = mysql_num_fields(results);
00742 for (j = 0; j < ret_fields; j++){
00743 list = g_list_append(list, g_strdup((gchar *) row[j]));
00744 }
00745 }
00746 mysql_free_result(results);
00747 return list;
00748 }
00749
00750
00751 for(i = 0; i < ret_rows; i++){
00752
00753 row = mysql_fetch_row(results);
00754 object = midgard_object_new(builder->mgd,
00755 g_type_name(builder->type), NULL);
00756 ret_fields = mysql_num_fields(results);
00757
00758
00759
00760 g_free(object->metadata->private->creator);
00761 object->metadata->private->creator = g_strdup((gchar *)row[2]);
00762 g_free(object->metadata->private->created);
00763 object->metadata->private->created = g_strdup((gchar *)row[3]);
00764 g_free(object->metadata->private->revisor);
00765 object->metadata->private->revisor = g_strdup((gchar *)row[4]);
00766 g_free(object->metadata->private->revised);
00767 object->metadata->private->revised = g_strdup((gchar *)row[5]);
00768 object->metadata->private->revision = atoi(row[6]);
00769 g_free(object->metadata->private->locker);
00770 object->metadata->private->locker = g_strdup((gchar *)row[7]);
00771 g_free(object->metadata->private->locked);
00772 object->metadata->private->locked = g_strdup((gchar *)row[8]);
00773 g_free(object->metadata->private->approver);
00774 object->metadata->private->approver = g_strdup((gchar *)row[9]);
00775 g_free(object->metadata->private->approved);
00776 object->metadata->private->approved = g_strdup((gchar *)row[10]);
00777 g_free(object->metadata->private->authors);
00778 object->metadata->private->authors = g_strdup((gchar *)row[11]);
00779 g_free(object->metadata->private->owner);
00780 object->metadata->private->owner = g_strdup((gchar *)row[12]);
00781 g_free(object->metadata->private->schedule_start);
00782 object->metadata->private->schedule_start = g_strdup((gchar *)row[13]);
00783 g_free(object->metadata->private->schedule_end);
00784 object->metadata->private->schedule_end = g_strdup((gchar *)row[14]);
00785 object->metadata->private->hidden = atoi(row[15]);
00786 object->metadata->private->nav_noentry = atoi(row[16]);
00787 object->metadata->private->size = atoi(row[17]);
00788 g_free(object->metadata->private->published);
00789 object->metadata->private->published = g_strdup((gchar *)row[18]);
00790 g_free(object->metadata->private->exported);
00791 object->metadata->private->exported = g_strdup((gchar *)row[19]);
00792 g_free(object->metadata->private->imported);
00793 object->metadata->private->imported = g_strdup((gchar *)row[20]);
00794 object->metadata->private->deleted = atoi(row[21]);
00795 object->metadata->private->score = atoi(row[22]);
00796
00797
00798 object->private->exported = g_strdup((gchar *)row[19]);
00799 object->private->imported = g_strdup((gchar *)row[20]);
00800
00801
00802
00803
00804
00805 for (j = 0; j < ret_fields; j++){
00806
00807 if(j < 22 && j > 2)
00808 continue;
00809 field = mysql_fetch_field_direct(results, j);
00810
00811 if ((prop = g_object_class_find_property(
00812 (GObjectClass *)klass, field->name)) != NULL) {
00813
00814 g_value_init(&pval,prop->value_type);
00815
00816 switch(prop->value_type){
00817
00818 case G_TYPE_STRING:
00819 g_value_set_string(&pval, (gchar *)row[j]);
00820 break;
00821
00822 case G_TYPE_UINT:
00823 g_value_set_uint(&pval, atoi(row[j]));
00824 break;
00825
00826 case G_TYPE_INT:
00827 g_value_set_int(&pval, atoi(row[j]));
00828 break;
00829
00830 case G_TYPE_FLOAT:
00831 g_value_set_float(&pval, g_ascii_strtod(row[j], NULL));
00832 break;
00833
00834 case G_TYPE_BOOLEAN:
00835 g_value_set_boolean(&pval, atoi(row[j]));
00836 break;
00837
00838 }
00839 g_object_set_property(G_OBJECT(object), field->name, &pval);
00840 g_value_unset(&pval);
00841 }
00842 }
00843 list = g_list_append(list, G_OBJECT(object));
00844 }
00845 mysql_free_result(results);
00846 return list;
00847 }
00848
00849 gboolean midgard_query_builder_join(
00850 MidgardQueryBuilder *builder, const gchar *prop,
00851 const gchar *jobject, const gchar *jprop)
00852 {
00853
00854 g_assert(prop != NULL);
00855 g_assert(jobject != NULL);
00856 g_assert(jprop != NULL);
00857
00858
00859 GParamSpec *pspec = g_object_class_find_property(
00860 G_OBJECT_CLASS(g_type_class_peek(builder->type)), prop);
00861 if(pspec == NULL) {
00862 g_warning("Invalid property '%s' for '%s'!",
00863 prop, g_type_name(builder->type));
00864 return FALSE;
00865 }
00866
00867
00868 MgdObject *obj = midgard_object_new(builder->mgd, jobject, NULL);
00869 if(obj == NULL) {
00870 g_warning("Type %s in not registered in application schema",
00871 jobject);
00872 return FALSE;
00873 }
00874
00875
00876 GParamSpec *jspec = g_object_class_find_property(
00877 G_OBJECT_GET_CLASS(G_OBJECT(obj)), jprop);
00878 if(jspec == NULL) {
00879 g_warning("Invalid property '%s' for joined type '%s'!",
00880 jprop, G_OBJECT_TYPE_NAME(G_OBJECT(obj)));
00881 return FALSE;
00882 }
00883
00884
00885 builder->link = g_strdup(g_param_spec_get_nick(jspec));
00886 g_string_append_printf(builder->join,
00887 " AND %s = %s",
00888 g_param_spec_get_nick(pspec),
00889 builder->link);
00890
00891
00892 MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(obj);
00893
00894 const gchar *table = midgard_object_class_get_table(klass);
00895
00896
00897 gchar **duptables = g_strsplit(builder->tables, ",", 0);
00898 guint i = 0, j = 0;
00899 for(i = 0 ; duptables[i]; i++){
00900 if (g_ascii_strcasecmp(duptables[i],
00901 table) == 0 )
00902 j++;
00903 }
00904
00905
00906 if (j == 0) {
00907 gchar *tmptable = g_strconcat(builder->tables,
00908 ",", table, NULL);
00909 g_free(builder->tables);
00910 builder->tables = g_strdup(tmptable);
00911 g_free(tmptable);
00912 }
00913 g_strfreev(duptables);
00914 g_free(obj);
00915
00916 return TRUE;
00917 }
00918
00919
00920
00921 const gchar *midgard_query_builder_get_type_name(
00922 MidgardQueryBuilder *builder)
00923 {
00924 g_assert(builder != NULL);
00925 return g_type_name(builder->type);
00926 }
00927
00928 void midgard_query_builder_include_deleted(MidgardQueryBuilder *builder)
00929 {
00930 g_assert(builder);
00931
00932 builder->include_deleted = TRUE;
00933 }
00934
00935
00936
00937 static void _midgard_query_builder_finalize(GObject *object)
00938 {
00939 midgard_query_builder_free(
00940 (MidgardQueryBuilder *)object);
00941 }
00942
00943 static void _midgard_query_builder_class_init(
00944 gpointer g_class, gpointer g_class_data)
00945 {
00946 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
00947 MidgardQueryBuilderClass *klass = MIDGARD_QUERY_BUILDER_CLASS (g_class);
00948
00949 gobject_class->finalize = _midgard_query_builder_finalize;
00950 klass->set_lang = midgard_query_builder_set_lang;
00951 klass->unset_languages = midgard_query_builder_unset_languages;
00952 klass->add_constraint = midgard_query_builder_add_constraint;
00953 klass->begin_group = midgard_query_builder_begin_group;
00954 klass->end_group = midgard_query_builder_end_group;
00955 klass->add_order = midgard_query_builder_add_order;
00956 klass->set_limit = midgard_query_builder_set_limit;
00957 klass->execute = midgard_query_builder_execute;
00958 klass->count = midgard_query_builder_count;
00959 }
00960
00961 static void _midgard_query_builder_instance_init(
00962 GTypeInstance *instance, gpointer g_class)
00963 {
00964
00965 }
00966
00967
00968 GType midgard_query_builder_get_type(void)
00969 {
00970 static GType type = 0;
00971 if (type == 0) {
00972 static const GTypeInfo info = {
00973 sizeof (MidgardQueryBuilderClass),
00974 NULL,
00975 NULL,
00976 (GClassInitFunc) _midgard_query_builder_class_init,
00977 NULL,
00978 NULL,
00979 sizeof (MidgardQueryBuilder),
00980 0,
00981 (GInstanceInitFunc) _midgard_query_builder_instance_init
00982 };
00983 type = g_type_register_static (G_TYPE_OBJECT,
00984 "midgard_query_builder",
00985 &info, 0);
00986 }
00987 return type;
00988 }
00989