1 /* 2 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com> 3 * Copyright (C) 2011 - 2013 Vivien Malerba <malerba@gnome-db.org> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #undef GDA_DISABLE_DEPRECATED 22 #include "gda-data-pivot.h" 23 24 #include <string.h> 25 #include <glib/gi18n-lib.h> 26 #include <libgda/gda-enums.h> 27 #include <libgda/gda-holder.h> 28 #include <libgda/gda-data-model.h> 29 #include <libgda/gda-data-model-array.h> 30 #include <libgda/gda-data-model-iter.h> 31 #include <libgda/gda-row.h> 32 #include <libgda/gda-util.h> 33 #include <libgda/gda-blob-op.h> 34 #include <libgda/gda-sql-builder.h> 35 #include <virtual/libgda-virtual.h> 36 #include <sql-parser/gda-sql-parser.h> 37 #include <libgda/sql-parser/gda-sql-statement.h> 38 #include <libgda/gda-debug-macros.h> 39 40 typedef struct { 41 GValue *value; 42 gint column_fields_index; 43 gint data_pos; /* index in pivot->priv->data_fields, or -1 if no index */ 44 } ColumnData; 45 static guint column_data_hash (gconstpointer key); 46 static gboolean column_data_equal (gconstpointer a, gconstpointer b); 47 static void column_data_free (ColumnData *cdata); 48 49 50 typedef struct { 51 gint row; 52 gint col; 53 GType gtype; 54 GArray *values; /* array of #GValue, none will be GDA_TYPE_NULL, and there is at least always 1 GValue */ 55 GdaDataPivotAggregate aggregate; 56 57 gint nvalues; 58 GValue *data_value; 59 GError *error; 60 } CellData; 61 static guint cell_data_hash (gconstpointer key); 62 static gboolean cell_data_equal (gconstpointer a, gconstpointer b); 63 static void cell_data_free (CellData *cdata); 64 static void cell_data_compute_aggregate (CellData *cdata); 65 66 static GValue *aggregate_get_empty_value (GdaDataPivotAggregate aggregate); 67 static gboolean aggregate_handle_new_value (CellData *cdata, const GValue *new_value); 68 69 70 struct _GdaDataPivotPrivate { 71 GdaDataModel *model; /* data to analyse */ 72 73 GdaConnection *vcnc; /* to use data in @model for row and column fields */ 74 75 GArray *row_fields; /* array of (gchar *) field specifications */ 76 GArray *column_fields; /* array of (gchar *) field specifications */ 77 GArray *data_fields; /* array of (gchar *) field specifications */ 78 GArray *data_aggregates; /* array of GdaDataPivotAggregate, corresponding to @data_fields */ 79 80 /* computed data */ 81 GArray *columns; /* Array of GdaColumn objects, for ALL columns! */ 82 GdaDataModel *results; 83 GRecMutex provider_mutex; 84 GdaVirtualProvider *virtual_provider; 85 }; 86 87 /* properties */ 88 enum 89 { 90 PROP_0, 91 PROP_MODEL, 92 }; 93 94 #define TABLE_NAME "data" 95 96 static void gda_data_pivot_class_init (GdaDataPivotClass *klass); 97 static void gda_data_pivot_init (GdaDataPivot *model, 98 GdaDataPivotClass *klass); 99 static void gda_data_pivot_dispose (GObject *object); 100 static void gda_data_pivot_finalize (GObject *object); 101 102 static void gda_data_pivot_set_property (GObject *object, 103 guint param_id, 104 const GValue *value, 105 GParamSpec *pspec); 106 static void gda_data_pivot_get_property (GObject *object, 107 guint param_id, 108 GValue *value, 109 GParamSpec *pspec); 110 111 static guint _gda_value_hash (gconstpointer key); 112 static guint _gda_row_hash (gconstpointer key); 113 static gboolean _gda_row_equal (gconstpointer a, gconstpointer b); 114 static gboolean create_vcnc (GdaDataPivot *pivot, GError **error); 115 static gboolean bind_source_model (GdaDataPivot *pivot, GError **error); 116 static void clean_previous_population (GdaDataPivot *pivot); 117 118 /* GdaDataModel interface */ 119 static void gda_data_pivot_data_model_init (GdaDataModelIface *iface); 120 static gint gda_data_pivot_get_n_rows (GdaDataModel *model); 121 static gint gda_data_pivot_get_n_columns (GdaDataModel *model); 122 static GdaColumn *gda_data_pivot_describe_column (GdaDataModel *model, gint col); 123 static GdaDataModelAccessFlags gda_data_pivot_get_access_flags(GdaDataModel *model); 124 static const GValue *gda_data_pivot_get_value_at (GdaDataModel *model, gint col, gint row, GError **error); 125 126 static GObjectClass *parent_class = NULL; 127 128 /** 129 * gda_data_pivot_get_type: 130 * 131 * Returns: the #GType of GdaDataPivot. 132 */ 133 GType 134 gda_data_pivot_get_type (void) 135 { 136 static GType type = 0; 137 138 if (G_UNLIKELY (type == 0)) { 139 static GMutex registering; 140 static const GTypeInfo info = { 141 sizeof (GdaDataPivotClass), 142 (GBaseInitFunc) NULL, 143 (GBaseFinalizeFunc) NULL, 144 (GClassInitFunc) gda_data_pivot_class_init, 145 NULL, 146 NULL, 147 sizeof (GdaDataPivot), 148 0, 149 (GInstanceInitFunc) gda_data_pivot_init, 150 0 151 }; 152 153 static const GInterfaceInfo data_model_info = { 154 (GInterfaceInitFunc) gda_data_pivot_data_model_init, 155 NULL, 156 NULL 157 }; 158 159 g_mutex_lock (®istering); 160 if (type == 0) { 161 type = g_type_register_static (G_TYPE_OBJECT, "GdaDataPivot", &info, 0); 162 g_type_add_interface_static (type, GDA_TYPE_DATA_MODEL, &data_model_info); 163 } 164 g_mutex_unlock (®istering); 165 } 166 return type; 167 } 168 169 static void 170 gda_data_pivot_class_init (GdaDataPivotClass *klass) 171 { 172 GObjectClass *object_class = G_OBJECT_CLASS (klass); 173 174 parent_class = g_type_class_peek_parent (klass); 175 176 /* properties */ 177 object_class->set_property = gda_data_pivot_set_property; 178 object_class->get_property = gda_data_pivot_get_property; 179 g_object_class_install_property (object_class, PROP_MODEL, 180 g_param_spec_object ("model", NULL, "Data model from which data is analysed", 181 GDA_TYPE_DATA_MODEL, 182 G_PARAM_READABLE | G_PARAM_WRITABLE)); 183 184 /* virtual functions */ 185 object_class->dispose = gda_data_pivot_dispose; 186 object_class->finalize = gda_data_pivot_finalize; 187 } 188 189 static void 190 gda_data_pivot_data_model_init (GdaDataModelIface *iface) 191 { 192 iface->i_get_n_rows = gda_data_pivot_get_n_rows; 193 iface->i_get_n_columns = gda_data_pivot_get_n_columns; 194 iface->i_describe_column = gda_data_pivot_describe_column; 195 iface->i_get_access_flags = gda_data_pivot_get_access_flags; 196 iface->i_get_value_at = gda_data_pivot_get_value_at; 197 iface->i_get_attributes_at = NULL; 198 199 iface->i_create_iter = NULL; 200 iface->i_iter_at_row = NULL; 201 iface->i_iter_next = NULL; 202 iface->i_iter_prev = NULL; 203 204 iface->i_set_value_at = NULL; 205 iface->i_iter_set_value = NULL; 206 iface->i_set_values = NULL; 207 iface->i_append_values = NULL; 208 iface->i_append_row = NULL; 209 iface->i_remove_row = NULL; 210 iface->i_find_row = NULL; 211 212 iface->i_set_notify = NULL; 213 iface->i_get_notify = NULL; 214 iface->i_send_hint = NULL; 215 } 216 217 static void 218 gda_data_pivot_init (GdaDataPivot *model, G_GNUC_UNUSED GdaDataPivotClass *klass) 219 { 220 g_return_if_fail (GDA_IS_DATA_PIVOT (model)); 221 model->priv = g_new0 (GdaDataPivotPrivate, 1); 222 model->priv->model = NULL; 223 model->priv->virtual_provider = NULL; 224 g_rec_mutex_init (& model->priv->provider_mutex); 225 } 226 227 static void 228 clean_previous_population (GdaDataPivot *pivot) 229 { 230 if (pivot->priv->results) { 231 g_object_unref ((GObject*) pivot->priv->results); 232 pivot->priv->results = NULL; 233 } 234 235 if (pivot->priv->columns) { 236 guint i; 237 for (i = 0; i < pivot->priv->columns->len; i++) { 238 GObject *obj; 239 obj = g_array_index (pivot->priv->columns, GObject*, i); 240 g_object_unref (obj); 241 } 242 g_array_free (pivot->priv->columns, TRUE); 243 pivot->priv->columns = NULL; 244 } 245 } 246 247 static void 248 gda_data_pivot_dispose (GObject *object) 249 { 250 GdaDataPivot *model = (GdaDataPivot *) object; 251 252 g_return_if_fail (GDA_IS_DATA_PIVOT (model)); 253 254 /* free memory */ 255 if (model->priv) { 256 clean_previous_population (model); 257 258 if (model->priv->row_fields) { 259 guint i; 260 for (i = 0; i < model->priv->row_fields->len; i++) { 261 gchar *tmp; 262 tmp = g_array_index (model->priv->row_fields, gchar*, i); 263 g_free (tmp); 264 } 265 g_array_free (model->priv->row_fields, TRUE); 266 model->priv->row_fields = NULL; 267 } 268 269 if (model->priv->column_fields) { 270 guint i; 271 for (i = 0; i < model->priv->column_fields->len; i++) { 272 gchar *tmp; 273 tmp = g_array_index (model->priv->column_fields, gchar*, i); 274 g_free (tmp); 275 } 276 g_array_free (model->priv->column_fields, TRUE); 277 model->priv->column_fields = NULL; 278 } 279 280 if (model->priv->data_fields) { 281 guint i; 282 for (i = 0; i < model->priv->data_fields->len; i++) { 283 gchar *tmp; 284 tmp = g_array_index (model->priv->data_fields, gchar*, i); 285 g_free (tmp); 286 } 287 g_array_free (model->priv->data_fields, TRUE); 288 model->priv->data_fields = NULL; 289 } 290 291 if (model->priv->data_aggregates) { 292 g_array_free (model->priv->data_aggregates, TRUE); 293 model->priv->data_aggregates = NULL; 294 } 295 296 if (model->priv->vcnc) { 297 if (G_IS_OBJECT (model->priv->vcnc)) 298 g_object_unref (model->priv->vcnc); 299 model->priv->vcnc = NULL; 300 } 301 302 if (model->priv->model) { 303 if (G_IS_OBJECT (model->priv->model)) 304 g_object_unref (model->priv->model); 305 model->priv->model = NULL; 306 } 307 308 if (model->priv->virtual_provider) { 309 if (G_IS_OBJECT (model->priv->virtual_provider)) 310 g_object_unref (model->priv->virtual_provider); 311 model->priv->model = NULL; 312 } 313 } 314 315 /* chain to parent class */ 316 parent_class->dispose (object); 317 } 318 319 static void 320 gda_data_pivot_finalize (GObject *object) 321 { 322 GdaDataPivot *model = (GdaDataPivot *) object; 323 324 g_return_if_fail (GDA_IS_DATA_PIVOT (model)); 325 326 g_rec_mutex_clear (& model->priv->provider_mutex); 327 328 /* free memory */ 329 if (model->priv) { 330 g_free (model->priv); 331 model->priv = NULL; 332 } 333 334 /* chain to parent class */ 335 parent_class->finalize (object); 336 } 337 338 /* module error */ 339 GQuark gda_data_pivot_error_quark (void) 340 { 341 static GQuark quark; 342 if (!quark) 343 quark = g_quark_from_static_string ("gda_data_pivot_error"); 344 return quark; 345 } 346 347 static void 348 gda_data_pivot_set_property (GObject *object, 349 guint param_id, 350 const GValue *value, 351 GParamSpec *pspec) 352 { 353 GdaDataPivot *model; 354 355 model = GDA_DATA_PIVOT (object); 356 if (model->priv) { 357 switch (param_id) { 358 case PROP_MODEL: { 359 GdaDataModel *mod = g_value_dup_object (value); 360 361 clean_previous_population (model); 362 363 if (mod) { 364 g_return_if_fail (GDA_IS_DATA_MODEL (mod)); 365 366 if (model->priv->model) { 367 if (model->priv->vcnc) 368 gda_vconnection_data_model_remove (GDA_VCONNECTION_DATA_MODEL (model->priv->vcnc), 369 TABLE_NAME, NULL); 370 g_object_unref (model->priv->model); 371 } 372 373 model->priv->model = mod; 374 } 375 break; 376 } 377 default: 378 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); 379 break; 380 } 381 } 382 } 383 384 static void 385 gda_data_pivot_get_property (GObject *object, 386 guint param_id, 387 GValue *value, 388 GParamSpec *pspec) 389 { 390 GdaDataPivot *model; 391 392 model = GDA_DATA_PIVOT (object); 393 if (model->priv) { 394 switch (param_id) { 395 case PROP_MODEL: 396 g_value_set_object (value, G_OBJECT (model->priv->model)); 397 break; 398 default: 399 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); 400 break; 401 } 402 } 403 } 404 405 /** 406 * gda_data_pivot_new: 407 * @model: (allow-none): a #GdaDataModel to analyse data from, or %NULL 408 * 409 * Creates a new #GdaDataModel which will contain analysed data from @model. 410 * 411 * Returns: (transfer full): a pointer to the newly created #GdaDataModel. 412 */ 413 GdaDataModel * 414 gda_data_pivot_new (GdaDataModel *model) 415 { 416 GdaDataPivot *retmodel; 417 418 g_return_val_if_fail (!model || GDA_IS_DATA_MODEL (model), NULL); 419 420 retmodel = g_object_new (GDA_TYPE_DATA_PIVOT, 421 "model", model, NULL); 422 423 return GDA_DATA_MODEL (retmodel); 424 } 425 426 /* 427 * GdaDataModel interface implementation 428 */ 429 static gint 430 gda_data_pivot_get_n_rows (GdaDataModel *model) 431 { 432 GdaDataPivot *pivot; 433 g_return_val_if_fail (GDA_IS_DATA_PIVOT (model), -1); 434 pivot = GDA_DATA_PIVOT (model); 435 g_return_val_if_fail (pivot->priv, -1); 436 437 if (pivot->priv->results) 438 return gda_data_model_get_n_rows (pivot->priv->results); 439 else 440 return -1; 441 } 442 443 static gint 444 gda_data_pivot_get_n_columns (GdaDataModel *model) 445 { 446 GdaDataPivot *pivot; 447 g_return_val_if_fail (GDA_IS_DATA_PIVOT (model), 0); 448 pivot = GDA_DATA_PIVOT (model); 449 g_return_val_if_fail (pivot->priv, 0); 450 451 if (pivot->priv->columns) 452 return (gint) pivot->priv->columns->len; 453 else 454 return 0; 455 } 456 457 static GdaColumn * 458 gda_data_pivot_describe_column (GdaDataModel *model, gint col) 459 { 460 GdaDataPivot *pivot; 461 GdaColumn *column = NULL; 462 g_return_val_if_fail (GDA_IS_DATA_PIVOT (model), NULL); 463 pivot = GDA_DATA_PIVOT (model); 464 g_return_val_if_fail (pivot->priv, NULL); 465 466 if (pivot->priv->columns && (col < (gint) pivot->priv->columns->len)) 467 column = g_array_index (pivot->priv->columns, GdaColumn*, col); 468 else { 469 if (pivot->priv->columns->len > 0) 470 g_warning ("Column %d out of range (0-%d)", col, 471 (gint) pivot->priv->columns->len); 472 else 473 g_warning ("No column defined"); 474 } 475 476 return column; 477 } 478 479 static GdaDataModelAccessFlags 480 gda_data_pivot_get_access_flags (GdaDataModel *model) 481 { 482 GdaDataPivot *pivot; 483 484 g_return_val_if_fail (GDA_IS_DATA_PIVOT (model), 0); 485 pivot = GDA_DATA_PIVOT (model); 486 g_return_val_if_fail (pivot->priv, 0); 487 488 return GDA_DATA_MODEL_ACCESS_RANDOM; 489 } 490 491 static const GValue * 492 gda_data_pivot_get_value_at (GdaDataModel *model, gint col, gint row, GError **error) 493 { 494 GdaDataPivot *pivot; 495 496 g_return_val_if_fail (GDA_IS_DATA_PIVOT (model), NULL); 497 pivot = GDA_DATA_PIVOT (model); 498 g_return_val_if_fail (pivot->priv, NULL); 499 g_return_val_if_fail (pivot->priv->model, NULL); 500 g_return_val_if_fail (row >= 0, NULL); 501 g_return_val_if_fail (col >= 0, NULL); 502 503 if (! pivot->priv->results) { 504 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_USAGE_ERROR, 505 "%s", _("Pivot model not populated")); 506 return NULL; 507 } 508 return gda_data_model_get_value_at (pivot->priv->results, col, row, error); 509 } 510 511 static GValue * 512 aggregate_get_empty_value (GdaDataPivotAggregate aggregate) 513 { 514 GValue *value; 515 switch (aggregate) { 516 case GDA_DATA_PIVOT_MIN: 517 case GDA_DATA_PIVOT_MAX: 518 case GDA_DATA_PIVOT_AVG: 519 case GDA_DATA_PIVOT_SUM: 520 return gda_value_new_null (); 521 case GDA_DATA_PIVOT_COUNT: 522 value = gda_value_new (G_TYPE_UINT); 523 g_value_set_uint (value, 0); 524 return value; 525 break; 526 default: 527 return gda_value_new_null (); 528 } 529 } 530 531 static gboolean 532 aggregate_handle_gint (CellData *cdata, gint val) 533 { 534 if (cdata->data_value) { 535 gint eval = 0; 536 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_INT) 537 eval = g_value_get_int (cdata->data_value); 538 switch (cdata->aggregate) { 539 case GDA_DATA_PIVOT_MIN: 540 if (eval > val) 541 g_value_set_int (cdata->data_value, val); 542 break; 543 case GDA_DATA_PIVOT_MAX: 544 if (eval < val) 545 g_value_set_int (cdata->data_value, val); 546 break; 547 case GDA_DATA_PIVOT_SUM: { 548 gint64 tmp; 549 tmp = eval + val; 550 if ((tmp > G_MAXINT) || (tmp < G_MININT)) 551 g_set_error (&(cdata->error), 552 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 553 "%s", _("Integer overflow")); 554 else 555 g_value_set_int (cdata->data_value, (gint) tmp); 556 break; 557 } 558 case GDA_DATA_PIVOT_AVG: { 559 gint64 tmp; 560 tmp = g_value_get_int64 (cdata->data_value) + val; 561 if ((tmp > G_MAXINT64) || (tmp < G_MININT64)) 562 /* FIXME: how to handle overflow detection ? */ 563 g_set_error (&(cdata->error), 564 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 565 "%s", _("Integer overflow")); 566 else 567 g_value_set_int64 (cdata->data_value, tmp); 568 break; 569 } 570 default: 571 return FALSE; 572 } 573 } 574 else { 575 /* new initial value */ 576 switch (cdata->aggregate) { 577 case GDA_DATA_PIVOT_MIN: 578 case GDA_DATA_PIVOT_MAX: 579 case GDA_DATA_PIVOT_SUM: 580 cdata->data_value = gda_value_new (G_TYPE_INT); 581 g_value_set_int (cdata->data_value, val); 582 break; 583 case GDA_DATA_PIVOT_AVG: 584 cdata->data_value = gda_value_new (G_TYPE_INT64); 585 g_value_set_int64 (cdata->data_value, (gint64) val); 586 break; 587 default: 588 return FALSE; 589 } 590 } 591 cdata->nvalues ++; 592 return TRUE; 593 } 594 595 static gboolean 596 aggregate_handle_guint (CellData *cdata, guint val) 597 { 598 if (cdata->data_value) { 599 guint eval = 0; 600 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_UINT) 601 eval = g_value_get_uint (cdata->data_value); 602 switch (cdata->aggregate) { 603 case GDA_DATA_PIVOT_MIN: 604 if (eval > val) 605 g_value_set_uint (cdata->data_value, val); 606 break; 607 case GDA_DATA_PIVOT_MAX: 608 if (eval < val) 609 g_value_set_uint (cdata->data_value, val); 610 break; 611 case GDA_DATA_PIVOT_SUM: { 612 guint64 tmp; 613 tmp = eval + val; 614 if (tmp > G_MAXUINT) 615 g_set_error (&(cdata->error), 616 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 617 "%s", _("Integer overflow")); 618 else 619 g_value_set_uint (cdata->data_value, (guint) tmp); 620 break; 621 } 622 case GDA_DATA_PIVOT_AVG: { 623 guint64 tmp; 624 tmp = g_value_get_uint64 (cdata->data_value) + val; 625 if (tmp > G_MAXUINT64) 626 /* FIXME: how to handle overflow detection ? */ 627 g_set_error (&(cdata->error), 628 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 629 "%s", _("Integer overflow")); 630 else 631 g_value_set_uint64 (cdata->data_value, tmp); 632 break; 633 } 634 default: 635 return FALSE; 636 } 637 } 638 else { 639 /* new initial value */ 640 switch (cdata->aggregate) { 641 case GDA_DATA_PIVOT_MIN: 642 case GDA_DATA_PIVOT_MAX: 643 case GDA_DATA_PIVOT_SUM: 644 cdata->data_value = gda_value_new (G_TYPE_UINT); 645 g_value_set_uint (cdata->data_value, val); 646 break; 647 case GDA_DATA_PIVOT_AVG: 648 cdata->data_value = gda_value_new (G_TYPE_UINT64); 649 g_value_set_uint64 (cdata->data_value, (guint64) val); 650 break; 651 default: 652 return FALSE; 653 } 654 } 655 cdata->nvalues ++; 656 return TRUE; 657 } 658 659 static gboolean 660 aggregate_handle_gint64 (CellData *cdata, gint64 val) 661 { 662 if (cdata->data_value) { 663 gint64 eval = 0; 664 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_INT64) 665 eval = g_value_get_int64 (cdata->data_value); 666 switch (cdata->aggregate) { 667 case GDA_DATA_PIVOT_MIN: 668 if (eval > val) 669 g_value_set_int64 (cdata->data_value, val); 670 break; 671 case GDA_DATA_PIVOT_MAX: 672 if (eval < val) 673 g_value_set_int64 (cdata->data_value, val); 674 break; 675 case GDA_DATA_PIVOT_SUM: 676 case GDA_DATA_PIVOT_AVG: { 677 gint64 tmp; 678 tmp = eval + val; 679 if ((tmp > G_MAXINT64) || (tmp < G_MININT64)) 680 /* FIXME: how to handle overflow detection ? */ 681 g_set_error (&(cdata->error), 682 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 683 "%s", _("Integer overflow")); 684 else 685 g_value_set_int64 (cdata->data_value, (gint64) tmp); 686 break; 687 } 688 default: 689 return FALSE; 690 } 691 } 692 else { 693 /* new initial value */ 694 switch (cdata->aggregate) { 695 case GDA_DATA_PIVOT_MIN: 696 case GDA_DATA_PIVOT_MAX: 697 case GDA_DATA_PIVOT_SUM: 698 case GDA_DATA_PIVOT_AVG: 699 cdata->data_value = gda_value_new (G_TYPE_INT64); 700 g_value_set_int64 (cdata->data_value, val); 701 break; 702 default: 703 return FALSE; 704 } 705 } 706 cdata->nvalues ++; 707 return TRUE; 708 } 709 710 static gboolean 711 aggregate_handle_guint64 (CellData *cdata, guint val) 712 { 713 if (cdata->data_value) { 714 guint64 eval = 0; 715 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_UINT64) 716 eval = g_value_get_uint64 (cdata->data_value); 717 switch (cdata->aggregate) { 718 case GDA_DATA_PIVOT_MIN: 719 if (eval > val) 720 g_value_set_uint64 (cdata->data_value, val); 721 break; 722 case GDA_DATA_PIVOT_MAX: 723 if (eval < val) 724 g_value_set_uint64 (cdata->data_value, val); 725 break; 726 case GDA_DATA_PIVOT_SUM: 727 case GDA_DATA_PIVOT_AVG: { 728 guint64 tmp; 729 tmp = eval + val; 730 if (tmp > G_MAXUINT64) 731 /* FIXME: how to handle overflow detection ? */ 732 g_set_error (&(cdata->error), 733 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 734 "%s", _("Integer overflow")); 735 else 736 g_value_set_uint64 (cdata->data_value, tmp); 737 break; 738 } 739 default: 740 return FALSE; 741 } 742 } 743 else { 744 /* new initial value */ 745 switch (cdata->aggregate) { 746 case GDA_DATA_PIVOT_MIN: 747 case GDA_DATA_PIVOT_MAX: 748 case GDA_DATA_PIVOT_SUM: 749 case GDA_DATA_PIVOT_AVG: 750 cdata->data_value = gda_value_new (G_TYPE_UINT64); 751 g_value_set_uint64 (cdata->data_value, val); 752 break; 753 default: 754 return FALSE; 755 } 756 } 757 cdata->nvalues ++; 758 return TRUE; 759 } 760 761 static gboolean 762 aggregate_handle_float (CellData *cdata, gfloat val) 763 { 764 if (cdata->data_value) { 765 gfloat eval = 0; 766 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_FLOAT) 767 eval = g_value_get_float (cdata->data_value); 768 switch (cdata->aggregate) { 769 case GDA_DATA_PIVOT_MIN: 770 if (eval > val) 771 g_value_set_float (cdata->data_value, val); 772 break; 773 case GDA_DATA_PIVOT_MAX: 774 if (eval < val) 775 g_value_set_float (cdata->data_value, val); 776 break; 777 case GDA_DATA_PIVOT_SUM: { 778 gdouble tmp; 779 tmp = eval + val; 780 if ((tmp > G_MAXDOUBLE) || (tmp < G_MINDOUBLE)) 781 g_set_error (&(cdata->error), 782 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 783 "%s", _("Float value overflow")); 784 else 785 g_value_set_float (cdata->data_value, (gfloat) tmp); 786 break; 787 } 788 case GDA_DATA_PIVOT_AVG: { 789 gdouble tmp; 790 tmp = g_value_get_double (cdata->data_value) + val; 791 if ((tmp > G_MAXDOUBLE) || (tmp < G_MINDOUBLE)) 792 g_set_error (&(cdata->error), 793 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 794 "%s", _("Float value overflow")); 795 else 796 g_value_set_double (cdata->data_value, tmp); 797 break; 798 } 799 default: 800 return FALSE; 801 } 802 } 803 else { 804 /* new initial value */ 805 switch (cdata->aggregate) { 806 case GDA_DATA_PIVOT_MIN: 807 case GDA_DATA_PIVOT_MAX: 808 case GDA_DATA_PIVOT_SUM: 809 cdata->data_value = gda_value_new (G_TYPE_FLOAT); 810 g_value_set_float (cdata->data_value, val); 811 break; 812 case GDA_DATA_PIVOT_AVG: 813 cdata->data_value = gda_value_new (G_TYPE_DOUBLE); 814 g_value_set_double (cdata->data_value, (gdouble) val); 815 break; 816 default: 817 return FALSE; 818 } 819 } 820 cdata->nvalues ++; 821 return TRUE; 822 } 823 824 static gboolean 825 aggregate_handle_double (CellData *cdata, gdouble val) 826 { 827 if (cdata->data_value) { 828 gdouble eval = 0; 829 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_DOUBLE) 830 eval = g_value_get_double (cdata->data_value); 831 switch (cdata->aggregate) { 832 case GDA_DATA_PIVOT_MIN: 833 if (eval > val) 834 g_value_set_double (cdata->data_value, val); 835 break; 836 case GDA_DATA_PIVOT_MAX: 837 if (eval < val) 838 g_value_set_double (cdata->data_value, val); 839 break; 840 case GDA_DATA_PIVOT_SUM: 841 case GDA_DATA_PIVOT_AVG: { 842 gdouble tmp; 843 tmp = eval + val; 844 if ((tmp > G_MAXDOUBLE) || (tmp < G_MINDOUBLE)) 845 /* FIXME: how to handle overflow detection ? */ 846 g_set_error (&(cdata->error), 847 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 848 "%s", _("Double value overflow")); 849 else 850 g_value_set_double (cdata->data_value, (gdouble) tmp); 851 break; 852 } 853 default: 854 return FALSE; 855 } 856 } 857 else { 858 /* new initial value */ 859 switch (cdata->aggregate) { 860 case GDA_DATA_PIVOT_MIN: 861 case GDA_DATA_PIVOT_MAX: 862 case GDA_DATA_PIVOT_SUM: 863 case GDA_DATA_PIVOT_AVG: 864 cdata->data_value = gda_value_new (G_TYPE_DOUBLE); 865 g_value_set_double (cdata->data_value, val); 866 break; 867 default: 868 return FALSE; 869 } 870 } 871 cdata->nvalues ++; 872 return TRUE; 873 } 874 875 static gboolean 876 aggregate_handle_char (CellData *cdata, 877 gint8 val 878 ) 879 { 880 if (cdata->data_value) { 881 gint8 eval = 0; 882 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_CHAR) 883 eval = g_value_get_schar (cdata->data_value); 884 switch (cdata->aggregate) { 885 case GDA_DATA_PIVOT_MIN: 886 if (eval > val) 887 g_value_set_schar (cdata->data_value, val); 888 break; 889 case GDA_DATA_PIVOT_MAX: 890 if (eval < val) 891 g_value_set_schar (cdata->data_value, val); 892 break; 893 case GDA_DATA_PIVOT_SUM: { 894 gint tmp; 895 tmp = eval + val; 896 if ((tmp > G_MAXINT8) || (tmp < G_MININT8)) 897 g_set_error (&(cdata->error), 898 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 899 "%s", _("Integer overflow")); 900 else 901 g_value_set_schar (cdata->data_value, (gint8) tmp); 902 break; 903 } 904 case GDA_DATA_PIVOT_AVG: { 905 gint64 tmp; 906 tmp = g_value_get_int64 (cdata->data_value) + val; 907 if ((tmp > G_MAXINT64) || (tmp < G_MININT64)) 908 /* FIXME: how to handle overflow detection ? */ 909 g_set_error (&(cdata->error), 910 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 911 "%s", _("Integer overflow")); 912 else 913 g_value_set_int64 (cdata->data_value, tmp); 914 break; 915 } 916 default: 917 return FALSE; 918 } 919 } 920 else { 921 /* new initial value */ 922 switch (cdata->aggregate) { 923 case GDA_DATA_PIVOT_MIN: 924 case GDA_DATA_PIVOT_MAX: 925 case GDA_DATA_PIVOT_SUM: 926 cdata->data_value = gda_value_new (G_TYPE_CHAR); 927 g_value_set_schar (cdata->data_value, val); 928 break; 929 case GDA_DATA_PIVOT_AVG: 930 cdata->data_value = gda_value_new (G_TYPE_INT64); 931 g_value_set_int64 (cdata->data_value, (gint64) val); 932 break; 933 default: 934 return FALSE; 935 } 936 } 937 cdata->nvalues ++; 938 return TRUE; 939 } 940 941 static gboolean 942 aggregate_handle_uchar (CellData *cdata, guchar val) 943 { 944 if (cdata->data_value) { 945 guchar eval = 0; 946 if (G_VALUE_TYPE (cdata->data_value) == G_TYPE_UCHAR) 947 eval = g_value_get_uchar (cdata->data_value); 948 switch (cdata->aggregate) { 949 case GDA_DATA_PIVOT_MIN: 950 if (eval > val) 951 g_value_set_uchar (cdata->data_value, val); 952 break; 953 case GDA_DATA_PIVOT_MAX: 954 if (eval < val) 955 g_value_set_uchar (cdata->data_value, val); 956 break; 957 case GDA_DATA_PIVOT_SUM: { 958 guint tmp; 959 tmp = eval + val; 960 if (tmp > G_MAXUINT8) 961 g_set_error (&(cdata->error), 962 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 963 "%s", _("Integer overflow")); 964 else 965 g_value_set_uchar (cdata->data_value, (guchar) tmp); 966 break; 967 } 968 case GDA_DATA_PIVOT_AVG: { 969 guint64 tmp; 970 tmp = g_value_get_uint64 (cdata->data_value) + val; 971 if (tmp > G_MAXUINT64) 972 /* FIXME: how to handle overflow detection ? */ 973 g_set_error (&(cdata->error), 974 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 975 "%s", _("Integer overflow")); 976 else 977 g_value_set_uint64 (cdata->data_value, tmp); 978 break; 979 } 980 default: 981 return FALSE; 982 } 983 } 984 else { 985 /* new initial value */ 986 switch (cdata->aggregate) { 987 case GDA_DATA_PIVOT_MIN: 988 case GDA_DATA_PIVOT_MAX: 989 case GDA_DATA_PIVOT_SUM: 990 cdata->data_value = gda_value_new (G_TYPE_UCHAR); 991 g_value_set_uchar (cdata->data_value, val); 992 break; 993 case GDA_DATA_PIVOT_AVG: 994 cdata->data_value = gda_value_new (G_TYPE_UINT64); 995 g_value_set_uint64 (cdata->data_value, (guint64) val); 996 break; 997 default: 998 return FALSE; 999 } 1000 } 1001 cdata->nvalues ++; 1002 return TRUE; 1003 } 1004 1005 static gboolean 1006 aggregate_handle_short (CellData *cdata, gshort val) 1007 { 1008 if (cdata->data_value) { 1009 gshort eval = 0; 1010 if (G_VALUE_TYPE (cdata->data_value) == GDA_TYPE_SHORT) 1011 eval = gda_value_get_short (cdata->data_value); 1012 switch (cdata->aggregate) { 1013 case GDA_DATA_PIVOT_MIN: 1014 if (eval > val) 1015 gda_value_set_short (cdata->data_value, val); 1016 break; 1017 case GDA_DATA_PIVOT_MAX: 1018 if (eval < val) 1019 gda_value_set_short (cdata->data_value, val); 1020 break; 1021 case GDA_DATA_PIVOT_SUM: { 1022 gint tmp; 1023 tmp = eval + val; 1024 if ((tmp > G_MAXSHORT) || (tmp < G_MINSHORT)) 1025 g_set_error (&(cdata->error), 1026 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 1027 "%s", _("Integer overflow")); 1028 else 1029 gda_value_set_short (cdata->data_value, (gshort) tmp); 1030 break; 1031 } 1032 case GDA_DATA_PIVOT_AVG: { 1033 gint64 tmp; 1034 tmp = g_value_get_int64 (cdata->data_value) + val; 1035 if ((tmp > G_MAXINT64) || (tmp < G_MININT64)) 1036 /* FIXME: how to handle overflow detection ? */ 1037 g_set_error (&(cdata->error), 1038 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 1039 "%s", _("Integer overflow")); 1040 else 1041 g_value_set_int64 (cdata->data_value, tmp); 1042 break; 1043 } 1044 default: 1045 return FALSE; 1046 } 1047 } 1048 else { 1049 /* new initial value */ 1050 switch (cdata->aggregate) { 1051 case GDA_DATA_PIVOT_MIN: 1052 case GDA_DATA_PIVOT_MAX: 1053 case GDA_DATA_PIVOT_SUM: 1054 cdata->data_value = gda_value_new (GDA_TYPE_SHORT); 1055 gda_value_set_short (cdata->data_value, val); 1056 break; 1057 case GDA_DATA_PIVOT_AVG: 1058 cdata->data_value = gda_value_new (G_TYPE_INT64); 1059 g_value_set_int64 (cdata->data_value, (gint64) val); 1060 break; 1061 default: 1062 return FALSE; 1063 } 1064 } 1065 cdata->nvalues ++; 1066 return TRUE; 1067 } 1068 1069 static gboolean 1070 aggregate_handle_ushort (CellData *cdata, gushort val) 1071 { 1072 if (cdata->data_value) { 1073 gushort eval = 0; 1074 if (G_VALUE_TYPE (cdata->data_value) == GDA_TYPE_USHORT) 1075 eval = gda_value_get_ushort (cdata->data_value); 1076 switch (cdata->aggregate) { 1077 case GDA_DATA_PIVOT_MIN: 1078 if (eval > val) 1079 gda_value_set_ushort (cdata->data_value, val); 1080 break; 1081 case GDA_DATA_PIVOT_MAX: 1082 if (eval < val) 1083 gda_value_set_ushort (cdata->data_value, val); 1084 break; 1085 case GDA_DATA_PIVOT_SUM: { 1086 guint tmp; 1087 tmp = eval + val; 1088 if (tmp > G_MAXUSHORT) 1089 g_set_error (&(cdata->error), 1090 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 1091 "%s", _("Integer overflow")); 1092 else 1093 gda_value_set_ushort (cdata->data_value, (gushort) tmp); 1094 break; 1095 } 1096 case GDA_DATA_PIVOT_AVG: { 1097 guint64 tmp; 1098 tmp = g_value_get_uint64 (cdata->data_value) + val; 1099 if (tmp > G_MAXUINT64) 1100 /* FIXME: how to handle overflow detection ? */ 1101 g_set_error (&(cdata->error), 1102 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 1103 "%s", _("Integer overflow")); 1104 else 1105 g_value_set_uint64 (cdata->data_value, tmp); 1106 break; 1107 } 1108 default: 1109 return FALSE; 1110 } 1111 } 1112 else { 1113 /* new initial value */ 1114 switch (cdata->aggregate) { 1115 case GDA_DATA_PIVOT_MIN: 1116 case GDA_DATA_PIVOT_MAX: 1117 case GDA_DATA_PIVOT_SUM: 1118 cdata->data_value = gda_value_new (GDA_TYPE_USHORT); 1119 gda_value_set_ushort (cdata->data_value, val); 1120 break; 1121 case GDA_DATA_PIVOT_AVG: 1122 cdata->data_value = gda_value_new (G_TYPE_UINT64); 1123 g_value_set_uint64 (cdata->data_value, (guint64) val); 1124 break; 1125 default: 1126 return FALSE; 1127 } 1128 } 1129 cdata->nvalues ++; 1130 return TRUE; 1131 } 1132 1133 /* 1134 * Returns: %TRUE if @new_value_has been handled (even if it created cdata->error), 1135 * or %FALSE if cdata's aggregate needs to store all the data 1136 */ 1137 static gboolean 1138 aggregate_handle_new_value (CellData *cdata, const GValue *new_value) 1139 { 1140 if (cdata->error) 1141 return TRUE; 1142 else if (cdata->values) 1143 return FALSE; 1144 1145 /* chack data type */ 1146 if (G_VALUE_TYPE (new_value) != cdata->gtype) { 1147 if (!cdata->error) 1148 g_set_error (&(cdata->error), 1149 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_INTERNAL_ERROR, 1150 "%s", _("Inconsistent data type")); 1151 return TRUE; 1152 } 1153 1154 if (cdata->aggregate == GDA_DATA_PIVOT_COUNT) { 1155 if (cdata->data_value) { 1156 guint64 tmp; 1157 tmp = g_value_get_uint (cdata->data_value) + 1; 1158 if (tmp >= G_MAXUINT) 1159 g_set_error (&(cdata->error), 1160 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_OVERFLOW_ERROR, 1161 "%s", _("Integer overflow")); 1162 else 1163 g_value_set_uint (cdata->data_value, (guint) tmp); 1164 } 1165 else { 1166 cdata->data_value = gda_value_new (G_TYPE_UINT); 1167 g_value_set_uint (cdata->data_value, 1); 1168 } 1169 return TRUE; 1170 } 1171 else if (cdata->gtype == G_TYPE_INT) 1172 return aggregate_handle_gint (cdata, g_value_get_int (new_value)); 1173 else if (cdata->gtype == G_TYPE_UINT) 1174 return aggregate_handle_guint (cdata, g_value_get_uint (new_value)); 1175 else if (cdata->gtype == G_TYPE_INT64) 1176 return aggregate_handle_gint64 (cdata, g_value_get_int64 (new_value)); 1177 else if (cdata->gtype == G_TYPE_UINT64) 1178 return aggregate_handle_guint64 (cdata, g_value_get_uint64 (new_value)); 1179 else if (cdata->gtype == G_TYPE_FLOAT) 1180 return aggregate_handle_float (cdata, g_value_get_float (new_value)); 1181 else if (cdata->gtype == G_TYPE_DOUBLE) 1182 return aggregate_handle_double (cdata, g_value_get_double (new_value)); 1183 else if (cdata->gtype == G_TYPE_CHAR) 1184 return aggregate_handle_char (cdata, g_value_get_schar (new_value)); 1185 else if (cdata->gtype == G_TYPE_UCHAR) 1186 return aggregate_handle_uchar (cdata, g_value_get_uchar (new_value)); 1187 else if (cdata->gtype == GDA_TYPE_SHORT) 1188 return aggregate_handle_short (cdata, gda_value_get_short (new_value)); 1189 else if (cdata->gtype == GDA_TYPE_USHORT) 1190 return aggregate_handle_ushort (cdata, gda_value_get_ushort (new_value)); 1191 else { 1192 /* incompatible data type for this kind of operation */ 1193 if (!cdata->error) 1194 g_set_error (&(cdata->error), 1195 GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_INTERNAL_ERROR, 1196 "%s", _("Data type does not support requested computation")); 1197 return TRUE; 1198 } 1199 } 1200 1201 /* 1202 * Sets cdata->computed_value to a #GValue 1203 * if an error occurs then cdata->computed_value is set to %NULL 1204 * 1205 * Also frees cdata->values. 1206 */ 1207 static void 1208 cell_data_compute_aggregate (CellData *cdata) 1209 { 1210 if (cdata->data_value) { 1211 /* finish computation */ 1212 if (cdata->error) { 1213 gda_value_free (cdata->data_value); 1214 cdata->data_value = NULL; 1215 } 1216 else if (cdata->aggregate == GDA_DATA_PIVOT_AVG) { 1217 gdouble dval; 1218 if ((cdata->gtype == G_TYPE_INT) || (cdata->gtype == G_TYPE_INT64) || 1219 (cdata->gtype == G_TYPE_CHAR) || (cdata->gtype == GDA_TYPE_SHORT)) { 1220 gint64 val; 1221 g_assert (G_VALUE_TYPE (cdata->data_value) == G_TYPE_INT64); 1222 val = g_value_get_int64 (cdata->data_value); 1223 dval = val / (gdouble) cdata->nvalues; 1224 } 1225 else if ((cdata->gtype == G_TYPE_UINT) || (cdata->gtype == G_TYPE_UINT64) || 1226 (cdata->gtype == G_TYPE_UCHAR) || (cdata->gtype == GDA_TYPE_USHORT)) { 1227 guint64 val; 1228 g_assert (G_VALUE_TYPE (cdata->data_value) == G_TYPE_UINT64); 1229 val = g_value_get_uint64 (cdata->data_value); 1230 dval = val / (gdouble) cdata->nvalues; 1231 } 1232 else if (cdata->gtype == G_TYPE_FLOAT) 1233 dval = g_value_get_float (cdata->data_value) / (gdouble) cdata->nvalues; 1234 else if (cdata->gtype == G_TYPE_DOUBLE) 1235 dval = g_value_get_double (cdata->data_value) / (gdouble) cdata->nvalues; 1236 else 1237 g_assert_not_reached (); 1238 1239 gda_value_free (cdata->data_value); 1240 cdata->data_value = gda_value_new (G_TYPE_DOUBLE); 1241 g_value_set_double (cdata->data_value, dval); 1242 } 1243 } 1244 else if (cdata->values) { 1245 TO_IMPLEMENT; 1246 guint i; 1247 for (i = 0; i < cdata->values->len; i++) { 1248 GValue *value; 1249 value = g_array_index (cdata->values, GValue*, i); 1250 gda_value_free (value); 1251 } 1252 g_array_free (cdata->values, TRUE); 1253 cdata->values = NULL; 1254 } 1255 } 1256 1257 static GdaSqlStatement * 1258 parse_field_spec (GdaDataPivot *pivot, const gchar *field, const gchar *alias, GError **error) 1259 { 1260 GdaSqlParser *parser; 1261 gchar *sql; 1262 GdaStatement *stmt; 1263 const gchar *remain; 1264 GError *lerror = NULL; 1265 1266 g_return_val_if_fail (field, FALSE); 1267 1268 if (! bind_source_model (pivot, error)) 1269 return NULL; 1270 1271 parser = gda_connection_create_parser (pivot->priv->vcnc); 1272 g_assert (parser); 1273 if (alias && *alias) { 1274 gchar *tmp, *ptr; 1275 tmp = g_strdup (alias); 1276 for (ptr = tmp; *ptr; ptr++) { 1277 if (g_ascii_isdigit (*ptr)) { 1278 if (ptr == tmp) 1279 *ptr = '_'; 1280 } 1281 else if (! g_ascii_isalpha (*ptr)) 1282 *ptr = '_'; 1283 } 1284 sql = g_strdup_printf ("SELECT %s AS %s FROM " TABLE_NAME, field, tmp); 1285 g_free (tmp); 1286 } 1287 else 1288 sql = g_strdup_printf ("SELECT %s FROM " TABLE_NAME, field); 1289 stmt = gda_sql_parser_parse_string (parser, sql, &remain, &lerror); 1290 g_free (sql); 1291 g_object_unref (parser); 1292 if (!stmt || remain) { 1293 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1294 _("Wrong field format error: %s"), 1295 lerror && lerror->message ? lerror->message : _("No detail")); 1296 g_clear_error (&lerror); 1297 return NULL; 1298 } 1299 1300 /* test syntax: a valid SQL expression is required */ 1301 GdaSqlStatement *sqlst = NULL; 1302 g_object_get ((GObject*) stmt, "structure", &sqlst, NULL); 1303 1304 if (sqlst->stmt_type != GDA_SQL_STATEMENT_SELECT) { 1305 g_object_unref (stmt); 1306 gda_sql_statement_free (sqlst); 1307 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1308 "%s", _("Wrong field format")); 1309 return NULL; 1310 } 1311 1312 /* 1313 gchar *tmp = gda_sql_statement_serialize (sqlst); 1314 g_print ("SQLST [%p, %s]\n", sqlst, tmp); 1315 g_free (tmp); 1316 */ 1317 1318 /* further tests */ 1319 GdaDataModel *model; 1320 model = gda_connection_statement_execute_select (pivot->priv->vcnc, stmt, NULL, &lerror); 1321 g_object_unref (stmt); 1322 if (!model) { 1323 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1324 _("Wrong field format error: %s"), 1325 lerror && lerror->message ? lerror->message : _("No detail")); 1326 g_clear_error (&lerror); 1327 return NULL; 1328 } 1329 /* 1330 g_print ("================= Pivot source:\n"); 1331 gda_data_model_dump (model, NULL); 1332 */ 1333 1334 g_object_unref (model); 1335 return sqlst; 1336 } 1337 1338 /** 1339 * gda_data_pivot_add_field: 1340 * @pivot: a #GdaDataPivot object 1341 * @field_type: the type of field to add 1342 * @field: the field description, see below 1343 * @alias: (allow-none): the field alias, or %NULL 1344 * @error: (allow-none): ta place to store errors, or %NULL 1345 * 1346 * Specifies that @field has to be included in the analysis. 1347 * @field is a field specification with the following accepted syntaxes: 1348 * <itemizedlist> 1349 * <listitem><para>a column name in the source data model (see <link linkend="gda-data-model-get-column-index">gda_data_model_get_column_index()</link>); or</para></listitem> 1350 * <listitem><para>an SQL expression involving a column name in the source data model, for example: 1351 * <programlisting> 1352 * price 1353 * firstname || ' ' || lastname 1354 * nb BETWEEN 5 AND 10</programlisting> 1355 * </para></listitem> 1356 * </itemizedlist> 1357 * 1358 * It is also possible to specify several fields to be added, while separating them by a comma (in effect 1359 * still forming a valid SQL syntax). 1360 * 1361 * Returns: %TRUE if no error occurred 1362 * 1363 * Since: 5.0 1364 */ 1365 gboolean 1366 gda_data_pivot_add_field (GdaDataPivot *pivot, GdaDataPivotFieldType field_type, 1367 const gchar *field, const gchar *alias, GError **error) 1368 { 1369 gchar *tmp; 1370 GError *lerror = NULL; 1371 1372 g_return_val_if_fail (GDA_IS_DATA_PIVOT (pivot), FALSE); 1373 g_return_val_if_fail (field, FALSE); 1374 1375 GdaSqlStatement *sqlst; 1376 sqlst = parse_field_spec (pivot, field, alias, error); 1377 if (! sqlst) 1378 return FALSE; 1379 1380 GArray *array; 1381 if (field_type == GDA_DATA_PIVOT_FIELD_ROW) { 1382 if (! pivot->priv->row_fields) 1383 pivot->priv->row_fields = g_array_new (FALSE, FALSE, sizeof (gchar*)); 1384 array = pivot->priv->row_fields; 1385 } 1386 else { 1387 if (! pivot->priv->column_fields) 1388 pivot->priv->column_fields = g_array_new (FALSE, FALSE, sizeof (gchar*)); 1389 array = pivot->priv->column_fields; 1390 } 1391 1392 GdaSqlStatementSelect *sel; 1393 GSList *sf_list; 1394 sel = (GdaSqlStatementSelect*) sqlst->contents; 1395 for (sf_list = sel->expr_list; sf_list; sf_list = sf_list->next) { 1396 GdaSqlBuilder *b; 1397 GdaSqlBuilderId bid; 1398 GdaSqlSelectField *sf; 1399 sf = (GdaSqlSelectField*) sf_list->data; 1400 b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT); 1401 gda_sql_builder_select_add_target_id (b, 1402 gda_sql_builder_add_id (b, "T"), 1403 NULL); 1404 bid = gda_sql_builder_import_expression (b, sf->expr); 1405 1406 if (bid == 0) { 1407 g_set_error (error, GDA_DATA_PIVOT_ERROR, 1408 GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1409 _("Wrong field format")); 1410 gda_sql_statement_free (sqlst); 1411 return FALSE; 1412 } 1413 gda_sql_builder_add_field_value_id (b, bid, 0); 1414 gchar *sql; 1415 GdaStatement *stmt; 1416 stmt = gda_sql_builder_get_statement (b, &lerror); 1417 g_object_unref (b); 1418 if (!stmt) { 1419 gda_sql_statement_free (sqlst); 1420 g_set_error (error, GDA_DATA_PIVOT_ERROR, 1421 GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1422 _("Wrong field format error: %s"), 1423 lerror && lerror->message ? lerror->message : _("No detail")); 1424 g_clear_error (&lerror); 1425 return FALSE; 1426 } 1427 sql = gda_statement_to_sql (stmt, NULL, NULL); 1428 g_object_unref (stmt); 1429 if (!sql) { 1430 g_set_error (error, GDA_DATA_PIVOT_ERROR, 1431 GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1432 _("Wrong field format")); 1433 gda_sql_statement_free (sqlst); 1434 return FALSE; 1435 } 1436 /*g_print ("PART [%s][%s]\n", sql, sf->as);*/ 1437 tmp = sql + 7; /* remove the "SELECT " start */ 1438 tmp [strlen (tmp) - 7] = 0; /* remove the " FROM T" end */ 1439 if (sf->as && *(sf->as)) { 1440 gchar *tmp2; 1441 tmp2 = g_strdup_printf ("%s AS %s", tmp, sf->as); 1442 g_array_append_val (array, tmp2); 1443 } 1444 else { 1445 tmp = g_strdup (tmp); 1446 g_array_append_val (array, tmp); 1447 } 1448 g_free (sql); 1449 } 1450 1451 gda_sql_statement_free (sqlst); 1452 1453 clean_previous_population (pivot); 1454 1455 return TRUE; 1456 } 1457 1458 /** 1459 * gda_data_pivot_add_data: 1460 * @pivot: a #GdaDataPivot object 1461 * @aggregate_type: the type of aggregate operation to perform 1462 * @field: the field description, see below 1463 * @alias: (allow-none): the field alias, or %NULL 1464 * @error: (allow-none): ta place to store errors, or %NULL 1465 * 1466 * Specifies that @field has to be included in the analysis. 1467 * @field is a field specification with the following accepted syntaxes: 1468 * <itemizedlist> 1469 * <listitem><para>a column name in the source data model (see <link linkend="gda-data-model-get-column-index">gda_data_model_get_column_index()</link>); or</para></listitem> 1470 * <listitem><para>an SQL expression involving a column name in the source data model, for examples: 1471 * <programlisting> 1472 * price 1473 * firstname || ' ' || lastname 1474 * nb BETWEEN 5 AND 10</programlisting> 1475 * </para></listitem> 1476 * </itemizedlist> 1477 * 1478 * It is also possible to specify several fields to be added, while separating them by a comma (in effect 1479 * still forming a valid SQL syntax). 1480 * 1481 * Returns: %TRUE if no error occurred 1482 * 1483 * Since: 5.0 1484 */ 1485 gboolean 1486 gda_data_pivot_add_data (GdaDataPivot *pivot, GdaDataPivotAggregate aggregate_type, 1487 const gchar *field, const gchar *alias, GError **error) 1488 { 1489 gchar *tmp; 1490 GError *lerror = NULL; 1491 1492 g_return_val_if_fail (GDA_IS_DATA_PIVOT (pivot), FALSE); 1493 g_return_val_if_fail (field, FALSE); 1494 1495 GdaSqlStatement *sqlst; 1496 sqlst = parse_field_spec (pivot, field, alias, error); 1497 if (! sqlst) 1498 return FALSE; 1499 1500 if (! pivot->priv->data_fields) 1501 pivot->priv->data_fields = g_array_new (FALSE, FALSE, sizeof (gchar*)); 1502 if (! pivot->priv->data_aggregates) 1503 pivot->priv->data_aggregates = g_array_new (FALSE, FALSE, sizeof (GdaDataPivotAggregate)); 1504 1505 GdaSqlStatementSelect *sel; 1506 GSList *sf_list; 1507 sel = (GdaSqlStatementSelect*) sqlst->contents; 1508 for (sf_list = sel->expr_list; sf_list; sf_list = sf_list->next) { 1509 GdaSqlBuilder *b; 1510 GdaSqlBuilderId bid; 1511 GdaSqlSelectField *sf; 1512 sf = (GdaSqlSelectField*) sf_list->data; 1513 b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT); 1514 gda_sql_builder_select_add_target_id (b, 1515 gda_sql_builder_add_id (b, "T"), 1516 NULL); 1517 bid = gda_sql_builder_import_expression (b, sf->expr); 1518 1519 if (bid == 0) { 1520 g_set_error (error, GDA_DATA_PIVOT_ERROR, 1521 GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1522 _("Wrong field format")); 1523 gda_sql_statement_free (sqlst); 1524 return FALSE; 1525 } 1526 gda_sql_builder_add_field_value_id (b, bid, 0); 1527 gchar *sql; 1528 GdaStatement *stmt; 1529 stmt = gda_sql_builder_get_statement (b, &lerror); 1530 g_object_unref (b); 1531 if (!stmt) { 1532 gda_sql_statement_free (sqlst); 1533 g_set_error (error, GDA_DATA_PIVOT_ERROR, 1534 GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1535 _("Wrong field format error: %s"), 1536 lerror && lerror->message ? lerror->message : _("No detail")); 1537 g_clear_error (&lerror); 1538 return FALSE; 1539 } 1540 sql = gda_statement_to_sql (stmt, NULL, NULL); 1541 g_object_unref (stmt); 1542 if (!sql) { 1543 g_set_error (error, GDA_DATA_PIVOT_ERROR, 1544 GDA_DATA_PIVOT_FIELD_FORMAT_ERROR, 1545 _("Wrong field format")); 1546 gda_sql_statement_free (sqlst); 1547 return FALSE; 1548 } 1549 /*g_print ("PART [%s][%s]\n", sql, sf->as);*/ 1550 tmp = sql + 7; /* remove the "SELECT " start */ 1551 tmp [strlen (tmp) - 7] = 0; /* remove the " FROM T" end */ 1552 if (sf->as && *(sf->as)) { 1553 gchar *tmp2; 1554 tmp2 = g_strdup_printf ("%s AS %s", tmp, sf->as); 1555 g_array_append_val (pivot->priv->data_fields, tmp2); 1556 } 1557 else { 1558 tmp = g_strdup (tmp); 1559 g_array_append_val (pivot->priv->data_fields, tmp); 1560 } 1561 g_array_append_val (pivot->priv->data_aggregates, aggregate_type); 1562 g_free (sql); 1563 } 1564 1565 gda_sql_statement_free (sqlst); 1566 1567 clean_previous_population (pivot); 1568 1569 return TRUE; 1570 } 1571 1572 /** 1573 * gda_data_pivot_populate: 1574 * @pivot: a #GdaDataPivot object 1575 * @error: (allow-none): ta place to store errors, or %NULL 1576 * 1577 * Acutally populates @pivot by analysing the data from the provided data model. 1578 * 1579 * Returns: %TRUE if no error occurred. 1580 * 1581 * Since: 5.0 1582 */ 1583 gboolean 1584 gda_data_pivot_populate (GdaDataPivot *pivot, GError **error) 1585 { 1586 gboolean retval = FALSE; 1587 g_return_val_if_fail (GDA_IS_DATA_PIVOT (pivot), FALSE); 1588 1589 if (!pivot->priv->row_fields || (pivot->priv->row_fields->len == 0)) { 1590 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_USAGE_ERROR, 1591 "%s", _("No row field defined")); 1592 return FALSE; 1593 } 1594 1595 clean_previous_population (pivot); 1596 1597 /* 1598 * create data model extracted using the virtual connection. 1599 * The resulting data model's columns are: 1600 * - for pivot->priv->row_fields: 0 to pivot->priv->row_fields->len - 1 1601 * - for pivot->priv->column_fields: 1602 * pivot->priv->row_fields->len to pivot->priv->row_fields->len + pivot->priv->column_fields->len - 1 1603 * - for pivot->priv->data_fields: pivot->priv->row_fields->len + pivot->priv->column_fields->len to pivot->priv->row_fields->len + pivot->priv->column_fields->len + pivot->priv->data_fields->len - 1 1604 */ 1605 GString *string; 1606 guint i; 1607 string = g_string_new ("SELECT "); 1608 for (i = 0; i < pivot->priv->row_fields->len; i++) { 1609 gchar *part; 1610 part = g_array_index (pivot->priv->row_fields, gchar *, i); 1611 if (i != 0) 1612 g_string_append (string, ", "); 1613 g_string_append (string, part); 1614 } 1615 if (pivot->priv->column_fields) { 1616 for (i = 0; i < pivot->priv->column_fields->len; i++) { 1617 gchar *part; 1618 part = g_array_index (pivot->priv->column_fields, gchar *, i); 1619 g_string_append (string, ", "); 1620 g_string_append (string, part); 1621 } 1622 } 1623 if (pivot->priv->data_fields) { 1624 for (i = 0; i < pivot->priv->data_fields->len; i++) { 1625 gchar *part; 1626 part = g_array_index (pivot->priv->data_fields, gchar *, i); 1627 g_string_append (string, ", "); 1628 g_string_append (string, part); 1629 } 1630 } 1631 g_string_append (string, " FROM " TABLE_NAME); 1632 1633 GdaStatement *stmt; 1634 stmt = gda_connection_parse_sql_string (pivot->priv->vcnc, string->str, NULL, NULL); 1635 g_string_free (string, TRUE); 1636 if (!stmt) { 1637 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_INTERNAL_ERROR, 1638 "%s", _("Could not get information from source data model")); 1639 return FALSE; 1640 } 1641 1642 GdaDataModel *model; 1643 model = gda_connection_statement_execute_select_full (pivot->priv->vcnc, stmt, NULL, 1644 GDA_STATEMENT_MODEL_CURSOR_FORWARD, 1645 //GDA_STATEMENT_MODEL_RANDOM_ACCESS, 1646 NULL, NULL); 1647 g_object_unref (stmt); 1648 if (!model) { 1649 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_INTERNAL_ERROR, 1650 "%s", _("Could not get information from source data model")); 1651 return FALSE; 1652 } 1653 1654 /* 1655 g_print ("========== Iterable data model\n"); 1656 gda_data_model_dump (model, NULL); 1657 */ 1658 1659 /* iterate through the data model */ 1660 GdaDataModelIter *iter; 1661 gint col; 1662 iter = gda_data_model_create_iter (model); 1663 if (!iter) { 1664 g_object_unref (model); 1665 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_INTERNAL_ERROR, 1666 "%s", _("Could not get information from source data model")); 1667 return FALSE; 1668 } 1669 1670 pivot->priv->columns = g_array_new (FALSE, FALSE, sizeof (GdaColumn*)); 1671 for (col = 0; col < (gint) pivot->priv->row_fields->len; col++) { 1672 GdaColumn *column; 1673 GdaHolder *holder; 1674 column = gda_column_new (); 1675 holder = GDA_HOLDER (g_slist_nth_data (GDA_SET (iter)->holders, col)); 1676 1677 gda_column_set_name (column, gda_holder_get_id (holder)); 1678 gda_column_set_description (column, gda_holder_get_id (holder)); 1679 gda_column_set_g_type (column, gda_holder_get_g_type (holder)); 1680 gda_column_set_position (column, col); 1681 g_array_append_val (pivot->priv->columns, column); 1682 } 1683 1684 /* 1685 * actual computation 1686 */ 1687 GHashTable *column_values_index; /* key = a #GValue (ref held in @column_values), 1688 * value = pointer to a guint containing the position 1689 * in @columns of the column */ 1690 1691 GArray *first_rows; /* Array of GdaRow objects, the size of each GdaRow is 1692 * the number of row fields defined */ 1693 GHashTable *first_rows_index; /* key = a #GdaRow (ref held in @first_rows), 1694 * value = pointer to a guint containing the position 1695 * in @first_rows of the row. */ 1696 GHashTable *data_hash; /* key = a CellData pointer, value = The CellData pointer 1697 * as ref'ed in @data */ 1698 1699 first_rows = g_array_new (FALSE, FALSE, sizeof (GdaRow*)); 1700 first_rows_index = g_hash_table_new_full (_gda_row_hash, _gda_row_equal, NULL, g_free); 1701 column_values_index = g_hash_table_new_full (column_data_hash, column_data_equal, 1702 (GDestroyNotify) column_data_free, g_free); 1703 data_hash = g_hash_table_new_full (cell_data_hash, cell_data_equal, 1704 (GDestroyNotify) cell_data_free, NULL); 1705 1706 for (;gda_data_model_iter_move_next (iter);) { 1707 /* 1708 * Row handling 1709 */ 1710 GdaRow *nrow; 1711 #ifdef GDA_DEBUG_ROWS_HASH 1712 g_print ("read from iter: "); 1713 #endif 1714 nrow = gda_row_new ((gint) pivot->priv->row_fields->len); 1715 for (col = 0; col < (gint) pivot->priv->row_fields->len; col++) { 1716 const GValue *ivalue; 1717 GValue *rvalue; 1718 GError *lerror = NULL; 1719 ivalue = gda_data_model_iter_get_value_at_e (iter, col, &lerror); 1720 if (!ivalue || lerror) { 1721 clean_previous_population (pivot); 1722 g_object_unref (nrow); 1723 g_propagate_error (error, lerror); 1724 goto out; 1725 } 1726 rvalue = gda_row_get_value (nrow, col); 1727 gda_value_reset_with_type (rvalue, G_VALUE_TYPE (ivalue)); 1728 g_value_copy (ivalue, rvalue); 1729 #ifdef GDA_DEBUG_ROWS_HASH 1730 gchar *tmp; 1731 tmp = gda_value_stringify (rvalue); 1732 g_print ("[%s]", tmp); 1733 g_free (tmp); 1734 #endif 1735 } 1736 1737 gint *rowindex; /* *rowindex will contain the actual row of the resulting data mode */ 1738 rowindex = g_hash_table_lookup (first_rows_index, nrow); 1739 if (rowindex) 1740 g_object_unref (nrow); 1741 else { 1742 g_array_append_val (first_rows, nrow); 1743 rowindex = g_new (gint, 1); 1744 *rowindex = first_rows->len - 1; 1745 g_hash_table_insert (first_rows_index, nrow, 1746 rowindex); 1747 } 1748 #ifdef GDA_DEBUG_ROWS_HASH 1749 g_print (" => @row %d\n", *rowindex); 1750 #endif 1751 1752 /* 1753 * Column handling 1754 */ 1755 gint colsmax; 1756 if (pivot->priv->column_fields) 1757 colsmax = (gint) pivot->priv->column_fields->len; 1758 else 1759 colsmax = 1; 1760 for (col = 0; col < colsmax; col++) { 1761 const GValue *ivalue = NULL; 1762 GError *lerror = NULL; 1763 if (pivot->priv->column_fields) { 1764 ivalue = gda_data_model_iter_get_value_at_e (iter, 1765 col + pivot->priv->row_fields->len, 1766 &lerror); 1767 if (!ivalue || lerror) { 1768 clean_previous_population (pivot); 1769 g_propagate_error (error, lerror); 1770 goto out; 1771 } 1772 } 1773 1774 gint di, dimax; 1775 if (pivot->priv->data_fields && pivot->priv->data_fields->len > 0) { 1776 di = 0; 1777 dimax = pivot->priv->data_fields->len; 1778 } 1779 else { 1780 di = -1; 1781 dimax = 0; 1782 } 1783 for (; di < dimax; di++) { 1784 ColumnData coldata; 1785 gint *colindex; 1786 GdaDataPivotAggregate aggregate; 1787 coldata.value = (GValue*) ivalue; 1788 coldata.column_fields_index = col; 1789 coldata.data_pos = di; 1790 colindex = g_hash_table_lookup (column_values_index, &coldata); 1791 if (di >= 0) 1792 aggregate = g_array_index (pivot->priv->data_aggregates, 1793 GdaDataPivotAggregate, di); 1794 else 1795 aggregate = GDA_DATA_PIVOT_SUM; 1796 1797 if (!colindex) { 1798 /* create new column */ 1799 GdaColumn *column; 1800 GString *name; 1801 1802 name = g_string_new (""); 1803 if (pivot->priv->column_fields && 1804 pivot->priv->column_fields->len > 1) { 1805 GdaColumn *column; 1806 column = gda_data_model_describe_column (model, 1807 pivot->priv->row_fields->len + col); 1808 g_string_append_printf (name, "[%s]", 1809 gda_column_get_name (column)); 1810 } 1811 if (ivalue) { 1812 gchar *tmp; 1813 tmp = gda_value_stringify (ivalue); 1814 g_string_append (name, tmp); 1815 g_free (tmp); 1816 } 1817 if ((di >= 0) && (dimax > 0)) { 1818 GdaColumn *column; 1819 gint vcol; 1820 vcol = pivot->priv->row_fields->len + di; 1821 if (pivot->priv->column_fields) 1822 vcol += pivot->priv->column_fields->len; 1823 column = gda_data_model_describe_column (model, vcol); 1824 if (pivot->priv->column_fields) 1825 g_string_append_printf (name, "[%s]", 1826 gda_column_get_name (column)); 1827 else 1828 g_string_append (name, 1829 gda_column_get_name (column)); 1830 } 1831 1832 column = gda_column_new (); 1833 g_object_set_data ((GObject*) column, "agg", 1834 GINT_TO_POINTER (aggregate)); 1835 gda_column_set_name (column, name->str); 1836 gda_column_set_description (column, name->str); 1837 g_array_append_val (pivot->priv->columns, column); 1838 gda_column_set_position (column, pivot->priv->columns->len - 1); 1839 /* don't set the column's type now */ 1840 /*g_print ("New column [%s] @real column %d, type %s\n", name->str, pivot->priv->columns->len - 1, gda_g_type_to_string (gda_column_get_g_type (column)));*/ 1841 g_string_free (name, TRUE); 1842 1843 ColumnData *ncoldata; 1844 ncoldata = g_new (ColumnData, 1); 1845 ncoldata->value = ivalue ? gda_value_copy ((GValue*) ivalue) : NULL; 1846 ncoldata->column_fields_index = col; 1847 ncoldata->data_pos = di; 1848 colindex = g_new (gint, 1); 1849 *colindex = pivot->priv->columns->len - 1; 1850 g_hash_table_insert (column_values_index, ncoldata, 1851 colindex); 1852 } 1853 1854 /* compute value to take into account */ 1855 GValue *value = NULL; 1856 if (di >= 0) { 1857 const GValue *cvalue; 1858 GError *lerror = NULL; 1859 gint vcol; 1860 vcol = pivot->priv->row_fields->len + di; 1861 if (pivot->priv->column_fields) 1862 vcol += pivot->priv->column_fields->len; 1863 cvalue = gda_data_model_iter_get_value_at_e (iter, vcol, &lerror); 1864 if (!cvalue || lerror) { 1865 g_propagate_error (error, lerror); 1866 goto out; 1867 } 1868 if (G_VALUE_TYPE (cvalue) != GDA_TYPE_NULL) 1869 value = gda_value_copy (cvalue); 1870 } 1871 else { 1872 value = gda_value_new (G_TYPE_INT); 1873 g_value_set_int (value, 1); 1874 } 1875 1876 if (value) { 1877 /* accumulate data */ 1878 CellData ccdata, *pcdata; 1879 ccdata.row = *rowindex; 1880 ccdata.col = *colindex; 1881 ccdata.values = NULL; 1882 ccdata.data_value = NULL; 1883 pcdata = g_hash_table_lookup (data_hash, &ccdata); 1884 if (!pcdata) { 1885 pcdata = g_new (CellData, 1); 1886 pcdata->row = *rowindex; 1887 pcdata->col = *colindex; 1888 pcdata->error = NULL; 1889 pcdata->values = NULL; 1890 pcdata->gtype = G_VALUE_TYPE (value); 1891 pcdata->nvalues = 0; 1892 pcdata->data_value = NULL; 1893 pcdata->aggregate = aggregate; 1894 g_hash_table_insert (data_hash, pcdata, pcdata); 1895 } 1896 if (!aggregate_handle_new_value (pcdata, value)) { 1897 if (!pcdata->values) 1898 pcdata->values = g_array_new (FALSE, FALSE, 1899 sizeof (GValue*)); 1900 g_array_append_val (pcdata->values, value); 1901 } 1902 /*g_print ("row %d col %d => [%s]\n", pcdata->row, pcdata->col, 1903 gda_value_stringify (value));*/ 1904 } 1905 } 1906 } 1907 } 1908 if (gda_data_model_iter_get_row (iter) != -1) { 1909 /* an error occurred! */ 1910 goto out; 1911 } 1912 1913 /* compute real data model's values from all the collected data */ 1914 GdaDataModel *results; 1915 gint ncols, nrows; 1916 ncols = pivot->priv->columns->len; 1917 nrows = first_rows->len; 1918 results = gda_data_model_array_new (ncols); 1919 for (i = 0; i < pivot->priv->row_fields->len; i++) { 1920 GdaColumn *acolumn, *ecolumn; 1921 ecolumn = g_array_index (pivot->priv->columns, GdaColumn*, i); 1922 acolumn = gda_data_model_describe_column (results, i); 1923 gda_column_set_g_type (acolumn, gda_column_get_g_type (ecolumn)); 1924 1925 gint j; 1926 for (j = 0; j < nrows; j++) { 1927 GdaRow *arow, *erow; 1928 erow = g_array_index (first_rows, GdaRow*, j); 1929 arow = gda_data_model_array_get_row ((GdaDataModelArray*) results, j, NULL); 1930 if (!arow) { 1931 g_assert (gda_data_model_append_row (results, NULL) == j); 1932 arow = gda_data_model_array_get_row ((GdaDataModelArray*) results, j, 1933 NULL); 1934 g_assert (arow); 1935 } 1936 GValue *av, *ev; 1937 av = gda_row_get_value (arow, i); 1938 ev = gda_row_get_value (erow, i); 1939 gda_value_reset_with_type (av, G_VALUE_TYPE (ev)); 1940 g_value_copy (ev, av); 1941 } 1942 } 1943 for (; i < (guint) ncols; i++) { 1944 GdaColumn *ecolumn; 1945 ecolumn = g_array_index (pivot->priv->columns, GdaColumn*, i); 1946 1947 gint j; 1948 for (j = 0; j < nrows; j++) { 1949 GdaRow *arow; 1950 GValue *av; 1951 arow = gda_data_model_array_get_row ((GdaDataModelArray*) results, j, NULL); 1952 av = gda_row_get_value (arow, i); 1953 1954 CellData ccdata, *pcdata; 1955 GType coltype = GDA_TYPE_NULL; 1956 ccdata.row = j; 1957 ccdata.col = i; 1958 ccdata.values = NULL; 1959 ccdata.data_value = NULL; 1960 pcdata = g_hash_table_lookup (data_hash, &ccdata); 1961 if (pcdata) { 1962 cell_data_compute_aggregate (pcdata); 1963 if (pcdata->data_value) { 1964 coltype = G_VALUE_TYPE (pcdata->data_value); 1965 gda_value_reset_with_type (av, coltype); 1966 g_value_copy (pcdata->data_value, av); 1967 } 1968 else 1969 gda_row_invalidate_value (arow, av); 1970 } 1971 else { 1972 GValue *empty; 1973 GdaDataPivotAggregate agg; 1974 agg = GPOINTER_TO_INT (g_object_get_data ((GObject*) ecolumn, "agg")); 1975 empty = aggregate_get_empty_value (agg); 1976 coltype = G_VALUE_TYPE (empty); 1977 gda_value_reset_with_type (av, coltype); 1978 g_value_copy (empty, av); 1979 } 1980 if (coltype != GDA_TYPE_NULL) 1981 gda_column_set_g_type (ecolumn, coltype); 1982 } 1983 } 1984 pivot->priv->results = results; 1985 1986 retval = TRUE; 1987 1988 out: 1989 if (!retval) 1990 clean_previous_population (pivot); 1991 1992 if (data_hash) 1993 g_hash_table_destroy (data_hash); 1994 1995 if (first_rows) { 1996 guint i; 1997 for (i = 0; i < first_rows->len; i++) { 1998 GObject *obj; 1999 obj = g_array_index (first_rows, GObject*, i); 2000 if (obj) 2001 g_object_unref (obj); 2002 } 2003 g_array_free (first_rows, TRUE); 2004 } 2005 2006 if (first_rows_index) 2007 g_hash_table_destroy (first_rows_index); 2008 2009 g_hash_table_destroy (column_values_index); 2010 2011 g_object_unref (iter); 2012 g_object_unref (model); 2013 2014 return retval; 2015 } 2016 2017 static guint 2018 _gda_value_hash (gconstpointer key) 2019 { 2020 GValue *v; 2021 GType vt; 2022 guint res = 0; 2023 v = (GValue *) key; 2024 vt = G_VALUE_TYPE (v); 2025 if ((vt == G_TYPE_BOOLEAN) || (vt == G_TYPE_INT) || (vt == G_TYPE_UINT) || 2026 (vt == G_TYPE_FLOAT) || (vt == G_TYPE_DOUBLE) || 2027 (vt == G_TYPE_INT64) || (vt == G_TYPE_INT64) || 2028 (vt == GDA_TYPE_SHORT) || (vt == GDA_TYPE_USHORT) || 2029 (vt == G_TYPE_CHAR) || (vt == G_TYPE_UCHAR) || 2030 (vt == GDA_TYPE_NULL) || (vt == G_TYPE_GTYPE) || 2031 (vt == G_TYPE_LONG) || (vt == G_TYPE_ULONG)) { 2032 const signed char *p, *data; 2033 data = (signed char*) v; 2034 res = 5381; 2035 for (p = data; p < data + sizeof (GValue); p++) 2036 res = (res << 5) + res + *p; 2037 } 2038 else if (vt == G_TYPE_STRING) { 2039 const gchar *tmp; 2040 tmp = g_value_get_string (v); 2041 if (tmp) 2042 res += g_str_hash (tmp); 2043 } 2044 else if ((vt == GDA_TYPE_BINARY) || (vt == GDA_TYPE_BLOB)) { 2045 const GdaBinary *bin; 2046 if (vt == GDA_TYPE_BLOB) { 2047 GdaBlob *blob; 2048 blob = (GdaBlob*) gda_value_get_blob ((GValue *) v); 2049 bin = (GdaBinary *) blob; 2050 if (blob->op && 2051 (bin->binary_length != gda_blob_op_get_length (blob->op))) 2052 gda_blob_op_read_all (blob->op, blob); 2053 } 2054 else 2055 bin = gda_value_get_binary ((GValue *) v); 2056 if (bin) { 2057 glong l; 2058 for (l = 0; l < bin->binary_length; l++) 2059 res += (guint) bin->data [l]; 2060 } 2061 } 2062 else { 2063 gchar *tmp; 2064 tmp = gda_value_stringify (v); 2065 res += g_str_hash (tmp); 2066 g_free (tmp); 2067 } 2068 return res; 2069 } 2070 2071 static guint 2072 _gda_row_hash (gconstpointer key) 2073 { 2074 gint i, len; 2075 GdaRow *r; 2076 guint res = 0; 2077 r = (GdaRow*) key; 2078 len = gda_row_get_length (r); 2079 for (i = 0; i < len ; i++) { 2080 GValue *v; 2081 v = gda_row_get_value (r, i); 2082 res = (res << 5) + res + _gda_value_hash (v); 2083 } 2084 return res; 2085 } 2086 2087 static gboolean 2088 _gda_row_equal (gconstpointer a, gconstpointer b) 2089 { 2090 gint i, len; 2091 GdaRow *ra, *rb; 2092 ra = (GdaRow*) a; 2093 rb = (GdaRow*) b; 2094 len = gda_row_get_length (ra); 2095 g_assert (len == gda_row_get_length (rb)); 2096 for (i = 0; i < len ; i++) { 2097 GValue *va, *vb; 2098 va = gda_row_get_value (ra, i); 2099 vb = gda_row_get_value (rb, i); 2100 if (gda_value_differ (va, vb)) 2101 return FALSE; 2102 } 2103 return TRUE; 2104 } 2105 2106 /* 2107 * Create a new virtual connection for @pivot 2108 */ 2109 static gboolean 2110 create_vcnc (GdaDataPivot *pivot, GError **error) 2111 { 2112 GdaConnection *vcnc; 2113 GError *lerror = NULL; 2114 if (!pivot->priv->vcnc && GDA_IS_CONNECTION (pivot->priv->vcnc)) 2115 return TRUE; 2116 2117 g_rec_mutex_lock (&pivot->priv->provider_mutex); 2118 if (!pivot->priv->virtual_provider) 2119 pivot->priv->virtual_provider = gda_vprovider_data_model_new (); 2120 2121 vcnc = gda_virtual_connection_open (pivot->priv->virtual_provider, &lerror); 2122 if (! vcnc) { 2123 g_print ("Virtual ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail"); 2124 if (lerror) 2125 g_error_free (lerror); 2126 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_INTERNAL_ERROR, 2127 "%s", _("Could not create virtual connection")); 2128 return FALSE; 2129 } 2130 2131 pivot->priv->vcnc = vcnc; 2132 g_rec_mutex_unlock (&pivot->priv->provider_mutex); 2133 return TRUE; 2134 } 2135 2136 /* 2137 * Bind @pivot->priv->model as a table named TABLE_NAME in @pivot's virtual connection 2138 */ 2139 static gboolean 2140 bind_source_model (GdaDataPivot *pivot, GError **error) 2141 { 2142 if (! pivot->priv->model) { 2143 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_SOURCE_MODEL_ERROR, 2144 "%s", _("No source defined")); 2145 return FALSE; 2146 } 2147 if (! create_vcnc (pivot, error)) 2148 return FALSE; 2149 2150 if (gda_vconnection_data_model_get_model (GDA_VCONNECTION_DATA_MODEL (pivot->priv->vcnc), 2151 TABLE_NAME) == pivot->priv->model) { 2152 /* already bound */ 2153 return TRUE; 2154 } 2155 2156 if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (pivot->priv->vcnc), 2157 pivot->priv->model, 2158 TABLE_NAME, NULL)) { 2159 g_set_error (error, GDA_DATA_PIVOT_ERROR, GDA_DATA_PIVOT_SOURCE_MODEL_ERROR, 2160 "%s", 2161 _("Invalid source data model (may have incompatible column names)")); 2162 return FALSE; 2163 } 2164 2165 return TRUE; 2166 } 2167 2168 static 2169 guint column_data_hash (gconstpointer key) 2170 { 2171 ColumnData *cd; 2172 cd = (ColumnData*) key; 2173 if (cd->value) 2174 return _gda_value_hash (cd->value) + cd->column_fields_index + cd->data_pos; 2175 else 2176 return cd->column_fields_index + cd->data_pos; 2177 } 2178 2179 static gboolean 2180 column_data_equal (gconstpointer a, gconstpointer b) 2181 { 2182 ColumnData *cda, *cdb; 2183 cda = (ColumnData*) a; 2184 cdb = (ColumnData*) b; 2185 if ((cda->column_fields_index != cdb->column_fields_index) || 2186 (cda->data_pos != cdb->data_pos)) 2187 return FALSE; 2188 if (cda->value && cdb->value) 2189 return gda_value_differ (cda->value, cdb->value) ? FALSE : TRUE; 2190 else if (cda->value || cdb->value) 2191 return FALSE; 2192 else 2193 return TRUE; 2194 } 2195 2196 static void 2197 column_data_free (ColumnData *cdata) 2198 { 2199 gda_value_free (cdata->value); 2200 g_free (cdata); 2201 } 2202 2203 static guint 2204 cell_data_hash (gconstpointer key) 2205 { 2206 CellData *cd; 2207 cd = (CellData*) key; 2208 return g_int_hash (&(cd->row)) + g_int_hash (&(cd->col)); 2209 } 2210 2211 static gboolean 2212 cell_data_equal (gconstpointer a, gconstpointer b) 2213 { 2214 CellData *cda, *cdb; 2215 cda = (CellData*) a; 2216 cdb = (CellData*) b; 2217 if ((cda->row == cdb->row) && (cda->col == cdb->col)) 2218 return TRUE; 2219 else 2220 return FALSE; 2221 } 2222 2223 static void 2224 cell_data_free (CellData *cdata) 2225 { 2226 if (cdata->values) { 2227 guint i; 2228 for (i = 0; i < cdata->values->len; i++) { 2229 GValue *value; 2230 value = g_array_index (cdata->values, GValue*, i); 2231 gda_value_free (value); 2232 } 2233 g_array_free (cdata->values, TRUE); 2234 } 2235 gda_value_free (cdata->data_value); 2236 g_free (cdata); 2237 } 2238