void _propagate_columns (MidgardSqlQueryResult *self, guint *n_objects, GError **error) { /* No model, no columns. Return NULL and set error */ if (self->model == NULL || self->n_columns == 0) { g_set_error (error, MIDGARD_VALIDATION_ERROR, MIDGARD_VALIDATION_ERROR_INTERNAL, "QueryResult holds empty data model"); return; } guint i = 0; if (self->columns != NULL) { *n_objects = self->n_columns; return; } g_set_error (error, MIDGARD_VALIDATION_ERROR, MIDGARD_VALIDATION_ERROR_INTERNAL, "Columns should be propagated with temporary midgard_sql_query_result_set_columns()"); return; GdaDataModel *model = GDA_DATA_MODEL (self->model); self->n_columns = gda_data_model_get_n_columns (model); *n_objects = self->n_columns; if (self->n_columns == 0) return; self->columns = g_new (MidgardSqlQueryColumn*, self->n_columns); for (i = 0; i < self->n_columns; i++) { MidgardQueryProperty *query_property = midgard_query_property_new (gda_data_model_get_column_title (model, i), NULL); self->columns[i] = midgard_sql_query_column_new (query_property, "FIXME", gda_data_model_get_column_name (model, i)); } return; }
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; }
/** * base_tool_output_data_model_to_string: */ gchar * base_tool_output_data_model_to_string (GdaDataModel *model, ToolOutputFormat format, FILE *stream, GdaSet *options) { if (!GDA_IS_DATA_MODEL (model)) return NULL; if (format & BASE_TOOL_OUTPUT_FORMAT_DEFAULT) { gchar *tmp; GdaSet *local_options; gint width; base_tool_input_get_size (&width, NULL); local_options = gda_set_new_inline (6, "NAME", G_TYPE_BOOLEAN, TRUE, "NULL_AS_EMPTY", G_TYPE_BOOLEAN, TRUE, "MAX_WIDTH", G_TYPE_INT, width, "COLUMN_SEPARATORS", G_TYPE_BOOLEAN, TRUE, "SEPARATOR_LINE", G_TYPE_BOOLEAN, TRUE, "NAMES_ON_FIRST_LINE", G_TYPE_BOOLEAN, TRUE); if (options) gda_set_merge_with_set (local_options, options); tmp = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_TEXT_TABLE, NULL, 0, NULL, 0, local_options); g_object_unref (local_options); if (GDA_IS_DATA_SELECT (model)) { gchar *tmp2, *tmp3; gdouble etime; g_object_get ((GObject*) model, "execution-delay", &etime, NULL); tmp2 = g_strdup_printf ("%s: %.03f s", _("Execution delay"), etime); tmp3 = g_strdup_printf ("%s\n%s", tmp, tmp2); g_free (tmp); g_free (tmp2); return tmp3; } else return tmp; } else if (format & BASE_TOOL_OUTPUT_FORMAT_XML) return gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_DATA_ARRAY_XML, NULL, 0, NULL, 0, NULL); else if (format & BASE_TOOL_OUTPUT_FORMAT_CSV) { gchar *retval; GdaSet *optexp; optexp = make_options_set_from_string ("csv", options); retval = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_TEXT_SEPARATED, NULL, 0, NULL, 0, optexp); if (optexp) g_object_unref (optexp); return retval; } else if (format & BASE_TOOL_OUTPUT_FORMAT_HTML) { xmlBufferPtr buffer; xmlNodePtr top, div, table, node, row_node, col_node, header, meta; gint ncols, nrows, i, j; gchar *str; top = xmlNewNode (NULL, BAD_CAST "html"); header = xmlNewChild (top, NULL, BAD_CAST "head", NULL); meta = xmlNewChild (header, NULL, BAD_CAST "meta", NULL); xmlSetProp (meta, BAD_CAST "http-equiv", BAD_CAST "content-type"); xmlSetProp (meta, BAD_CAST "content", BAD_CAST "text/html; charset=UTF-8"); div = xmlNewChild (top, NULL, BAD_CAST "body", NULL); table = xmlNewChild (div, NULL, BAD_CAST "table", NULL); xmlSetProp (table, BAD_CAST "border", BAD_CAST "1"); if (g_object_get_data (G_OBJECT (model), "name")) xmlNewTextChild (table, NULL, BAD_CAST "caption", g_object_get_data (G_OBJECT (model), "name")); ncols = gda_data_model_get_n_columns (model); nrows = gda_data_model_get_n_rows (model); row_node = xmlNewChild (table, NULL, BAD_CAST "tr", NULL); for (j = 0; j < ncols; j++) { const gchar *cstr; cstr = gda_data_model_get_column_title (model, j); col_node = xmlNewTextChild (row_node, NULL, BAD_CAST "th", BAD_CAST cstr); xmlSetProp (col_node, BAD_CAST "align", BAD_CAST "center"); } for (i = 0; i < nrows; i++) { row_node = xmlNewChild (table, NULL, BAD_CAST "tr", NULL); xmlSetProp (row_node, BAD_CAST "valign", BAD_CAST "top"); for (j = 0; j < ncols; j++) { const GValue *value; value = gda_data_model_get_value_at (model, j, i, NULL); if (!value) { col_node = xmlNewChild (row_node, NULL, BAD_CAST "td", BAD_CAST "ERROR"); xmlSetProp (col_node, BAD_CAST "align", BAD_CAST "left"); } else { str = gda_value_stringify (value); col_node = xmlNewTextChild (row_node, NULL, BAD_CAST "td", BAD_CAST str); xmlSetProp (col_node, BAD_CAST "align", BAD_CAST "left"); g_free (str); } } } node = xmlNewChild (div, NULL, BAD_CAST "p", NULL); str = g_strdup_printf (ngettext ("(%d row)", "(%d rows)", nrows), nrows); xmlNodeSetContent (node, BAD_CAST str); g_free (str); buffer = xmlBufferCreate (); xmlNodeDump (buffer, NULL, top, 0, 1); str = g_strdup ((gchar *) xmlBufferContent (buffer)); xmlBufferFree (buffer); xmlFreeNode (top); return str; } else TO_IMPLEMENT; return NULL; }