[libgda] New GdaDataModelSelect object



commit 92562ec98470206653652f09b7f4516e6a4962a6
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date:   Fri Feb 15 15:37:25 2019 -0600

    New GdaDataModelSelect object
    
    Wraps a statement's execution result, provinding
    a GdaDataModel API if the last execution was sucessful.
    Reacts on parameters changes by re-executing the
    statement.

 NEWS                             |   1 +
 libgda/Makefile.am               |   2 +
 libgda/gda-data-model-select.c   | 441 +++++++++++++++++++++++++++++++++++++++
 libgda/gda-data-model-select.h   |  46 ++++
 libgda/gda-data-select.c         |   3 +-
 libgda/gda-data-select.h         |   1 -
 libgda/libgda.h.in               |   2 +
 libgda/meson.build               |   2 +
 tests/data-models/check_pmodel.c | 106 +++++-----
 9 files changed, 546 insertions(+), 58 deletions(-)
---
diff --git a/NEWS b/NEWS
index f01e55de1..10662beee 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ libgda 5.91.0
  - Added support for PostgreSQL version up to 11.0
  - Added new GdaText type for large texts types support
  - Added new GdaHandlerText type for large texts types handler support
+ - Added new GdaDataModelSelect objects replacing GdaDataSelect's rerun()
  - GdaHandler now supports value transformation, if possible, before set it
  - Ported almost all public API to use g_autoptr() and remove public private struct
  - GdaHolder now is GdaAttributeManager free, replaced by GObect properties
diff --git a/libgda/Makefile.am b/libgda/Makefile.am
index abcf64d77..9458c5605 100644
--- a/libgda/Makefile.am
+++ b/libgda/Makefile.am
@@ -73,6 +73,7 @@ gda_headers = \
        gda-data-model-iter.h \
        gda-data-model-iter-extra.h \
        gda-data-model-private.h \
+       gda-data-model-select.h \
        gda-data-access-wrapper.h \
        gda-data-proxy.h \
        gda-data-select.h \
@@ -141,6 +142,7 @@ gda_sources= \
        gda-data-model-dir.c \
        gda-data-model-import.c \
        gda-data-model-iter.c \
+       gda-data-model-select.c \
        gda-data-access-wrapper.c \
        gda-data-proxy.c \
        gda-data-select.c \
diff --git a/libgda/gda-data-model-select.c b/libgda/gda-data-model-select.c
new file mode 100644
index 000000000..ac47372b0
--- /dev/null
+++ b/libgda/gda-data-model-select.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2019 Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include<gda-data-model-select.h>
+
+// GdaDataModel Interface
+static void gda_data_model_select_data_model_init (GdaDataModelIface *iface);
+
+// GdaDataModelSelect object definition
+
+enum
+{
+  PROP_VALID = 1,
+  N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void gda_data_model_select_dispose (GObject *object);
+static void gda_data_model_select_set_property (GObject      *object,
+                                                guint         property_id,
+                                                const GValue *value,
+                                                GParamSpec   *pspec);
+
+static void gda_data_model_select_get_property (GObject    *object,
+                                                guint       property_id,
+                                                GValue     *value,
+                                                GParamSpec *pspec);
+
+typedef struct {
+  GdaConnection          *cnc;
+  GdaStatement           *stm;
+  GdaDataModel           *model;
+  GdaSet                 *params;
+} GdaDataModelSelectPrivate;
+
+G_DEFINE_TYPE_WITH_CODE (GdaDataModelSelect, gda_data_model_select, G_TYPE_OBJECT,
+                         G_ADD_PRIVATE (GdaDataModelSelect)
+                         G_IMPLEMENT_INTERFACE (GDA_TYPE_DATA_MODEL, gda_data_model_select_data_model_init))
+
+
+/* signals */
+enum {
+       UPDATED,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gda_data_model_select_class_init (GdaDataModelSelectClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  object_class->dispose = gda_data_model_select_dispose;
+  object_class->get_property = gda_data_model_select_get_property;
+  object_class->set_property = gda_data_model_select_set_property;
+
+  /**
+   * GdaDataModelSelect::updated:
+   * @model: a #GdaDataModelSelect
+   *
+   * Emmited when the data model has been updated due to parameters changes
+   * in statement
+   */
+  signals[UPDATED] =  g_signal_newv ("updated",
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+                 NULL /* closure */,
+                 NULL /* accumulator */,
+                 NULL /* accumulator data */,
+                 NULL /* C marshaller */,
+                 G_TYPE_NONE /* return_type */,
+                 0     /* n_params */,
+                 NULL  /* param_types */);
+  properties[PROP_VALID] =
+    g_param_spec_boolean ("valid",
+                       "Valid",
+                       "If last statement execution was successful this is set to TRUE",
+                       FALSE  /* default value */,
+                       G_PARAM_READABLE);
+
+  g_object_class_install_properties (object_class,
+                                     N_PROPERTIES,
+                                     properties);
+}
+
+static void gda_data_model_select_init (GdaDataModelSelect *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  priv->cnc = NULL;
+  priv->stm = NULL;
+  priv->params = NULL;
+  priv->model = NULL;
+}
+
+static void gda_data_model_select_dispose (GObject *object)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(object));
+  if (priv->cnc != NULL) {
+    g_object_unref (priv->cnc);
+    priv->cnc = NULL;
+  }
+  if (priv->stm != NULL) {
+    g_object_unref (priv->stm);
+    priv->stm = NULL;
+  }
+  if (priv->params != NULL) {
+    g_object_unref (priv->params);
+    priv->params = NULL;
+  }
+  if (priv->model != NULL) {
+    g_object_unref (priv->model);
+    priv->model = NULL;
+  }
+}
+
+
+static void gda_data_model_select_set_property (GObject      *object,
+                                                guint         property_id,
+                                                const GValue *value,
+                                                GParamSpec   *pspec)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(object));
+  switch (property_id) {
+  case PROP_VALID:
+    break;
+  default:
+    /* We don't have any other property... */
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    break;
+  }
+}
+
+static void gda_data_model_select_get_property (GObject    *object,
+                                                guint       property_id,
+                                                GValue     *value,
+                                                GParamSpec *pspec)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(object));
+  switch (property_id) {
+  case PROP_VALID:
+    g_value_set_boolean (value, priv->model != NULL);
+    break;
+  default:
+    /* We don't have any other property... */
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    break;
+  }
+}
+
+static void params_changed_cb (GdaSet *params, GdaHolder *holder, GdaDataModelSelect *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  if (priv->cnc != NULL && priv->stm != NULL) {
+    if (priv->model != NULL) {
+      g_object_unref (priv->model);
+      priv->model = NULL;
+    }
+    priv->model = gda_connection_statement_execute_select (priv->cnc, priv->stm, priv->params, NULL);
+    g_signal_emit (model, signals[UPDATED], 0);
+  }
+}
+
+/**
+ * gda_data_model_select_new:
+ * @cnc: an opened #GdaConnection
+ * @stm: a SELECT SQL #GdaStatement
+ * @params: (nullable): a #GdaSet with the parameters to ejecute the SELECT SQL statement
+ *
+ * Returns: (transfer full): a new #GdaDataModelSelect object
+ */
+GdaDataModelSelect*
+gda_data_model_select_new (GdaConnection *cnc, GdaStatement *stm, GdaSet *params)
+{
+  GdaDataModelSelect* model = GDA_DATA_MODEL_SELECT (g_object_new (GDA_TYPE_DATA_MODEL_SELECT, NULL));
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+
+  priv->cnc = g_object_ref (cnc);
+  priv->stm = g_object_ref (stm);
+  if (params != NULL) {
+    priv->params = g_object_ref (params);
+    g_signal_connect (priv->params, "holder-changed", G_CALLBACK (params_changed_cb), model);
+  } else {
+    priv->params = NULL;
+  }
+  priv->model = gda_connection_statement_execute_select (priv->cnc, priv->stm, priv->params, NULL);
+  return model;
+}
+/**
+ * gda_data_model_select_new_from_string:
+ * @cnc: an opened #GdaConnection
+ * @sql: a string representing a SELECT SQL to execute
+ * @params: (nullable): a #GdaSet with the parameters to ejecute the SELECT SQL statement
+ *
+ * Returns: (transfer full): a new #GdaDataModelSelect object
+ */
+GdaDataModelSelect*
+gda_data_model_select_new_from_string (GdaConnection *cnc, const gchar *sql)
+{
+  GdaStatement *stm = gda_connection_parse_sql_string (cnc, sql, NULL, NULL);
+  if (stm == NULL) {
+    return NULL;
+  }
+
+  GdaSet *params = NULL;
+  gda_statement_get_parameters (stm, &params, NULL);
+  g_message ("Params: %s", params != NULL ? "True" : "False");
+
+  return gda_data_model_select_new (cnc, stm, params);
+}
+
+
+/**
+ * gda_data_model_select_is_valid:
+ * @model: a #GdaDataModelSelect object
+ *
+ * If at creation or after parameters change has been set, a SELECT statement
+ * is ejectuted, if unsuccess then this model is at invalid state.
+ *
+ * Returns: TRUE if a valid data model is present
+ */
+gboolean
+gda_data_model_select_is_valid (GdaDataModelSelect *model)
+{
+  g_return_if_fail (model);
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  return priv->model != NULL;
+}
+
+/**
+ * gda_data_model_select_get_parameters:
+ * @model: a #GdaDataModelSelect object
+ *
+ * Returns: (transfer full): current parameters used by internal statement
+ */
+GdaSet*
+gda_data_model_select_get_parameters  (GdaDataModelSelect *model)
+{
+  g_return_if_fail (model);
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  if (priv->params == NULL) {
+    gda_statement_get_parameters (priv->stm, &priv->params, NULL);
+    return priv->params;
+  }
+  return g_object_ref (priv->params);
+}
+
+/**
+ * gda_data_model_select_set_parameters:
+ * @model: a #GdaDataModelSelect object
+ * @params: a #GdaSet with the parameters for the statement
+ */
+void
+gda_data_model_select_set_parameters  (GdaDataModelSelect *model, GdaSet *params)
+{
+  g_return_if_fail (model);
+  g_return_if_fail (params != NULL);
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  if (priv->params != NULL) {
+    g_object_unref (priv->params);
+    priv->params = NULL;
+  }
+  priv->params = g_object_ref (priv->params);
+  g_signal_connect (priv->params, "holder-changed", G_CALLBACK (params_changed_cb), model);
+  params_changed_cb (priv->params, NULL, model);
+  g_message ("Setted parameters");
+}
+
+
+// GdaDataModel Implementation
+
+
+
+static gint
+gda_data_model_select_get_n_rows (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, 0);
+  return gda_data_model_get_n_rows (priv->model);
+}
+static gint
+gda_data_model_select_get_n_columns   (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, 0);
+  return gda_data_model_get_n_columns (priv->model);
+}
+static GdaColumn*
+gda_data_model_select_describe_column (GdaDataModel *model,
+                                       gint          col)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, NULL);
+  return gda_data_model_describe_column (priv->model, col);
+}
+static GdaDataModelAccessFlags
+gda_data_model_select_get_access_flags (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, 0);
+  return gda_data_model_get_access_flags (priv->model);
+}
+static const GValue*
+gda_data_model_select_get_value_at (GdaDataModel  *model,
+                                    gint           col,
+                                    gint           row,
+                                    GError       **error)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, NULL);
+  return gda_data_model_get_value_at (priv->model, col, row, error);
+}
+static GdaValueAttribute
+gda_data_model_select_get_attributes_at (GdaDataModel *model,
+                                         gint          col,
+                                         gint          row)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, 0);
+  return gda_data_model_get_attributes_at (priv->model, col, row);
+}
+
+static GdaDataModelIter*
+gda_data_model_select_create_iter (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, NULL);
+  return gda_data_model_create_iter (priv->model);
+}
+
+static gboolean
+gda_data_model_select_set_value_at (GdaDataModel  *model,
+                                    gint           col,
+                                    gint           row,
+                                    const GValue  *value,
+                                    GError       **error)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, FALSE);
+  return gda_data_model_set_value_at (priv->model, col, row, value, error);
+}
+
+static gboolean
+gda_data_model_select_set_values (GdaDataModel  *model,
+                                  gint           row,
+                                  GList         *values,
+                                  GError       **error)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, FALSE);
+  return gda_data_model_set_values (priv->model, row, values, error);
+}
+static gint
+gda_data_model_select_append_values (GdaDataModel  *model,
+                                     const GList   *values,
+                                     GError       **error)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, -1);
+  return gda_data_model_append_values (priv->model, values, error);
+}
+static gboolean
+gda_data_model_select_remove_row (GdaDataModel  *model,
+                                  gint           row,
+                                  GError       **error)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, FALSE);
+  return gda_data_model_remove_row (priv->model, row, error);
+}
+
+static void
+gda_data_model_select_freeze (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_if_fail (priv->model != NULL);
+  return gda_data_model_freeze (priv->model);
+}
+static void
+gda_data_model_select_thaw (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_if_fail (priv->model != NULL);
+  return gda_data_model_thaw (priv->model);
+}
+static gboolean
+gda_data_model_select_get_notify (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, FALSE);
+  return gda_data_model_get_notify (priv->model);
+}
+static GError**
+gda_data_model_select_get_exceptions (GdaDataModel *model)
+{
+  GdaDataModelSelectPrivate *priv = gda_data_model_select_get_instance_private (GDA_DATA_MODEL_SELECT 
(model));
+  g_return_val_if_fail (priv->model != NULL, FALSE);
+  return gda_data_model_get_exceptions (priv->model);
+}
+
+static void
+gda_data_model_select_data_model_init (GdaDataModelIface *iface)
+{
+       iface->get_n_rows = gda_data_model_select_get_n_rows;
+       iface->get_n_columns = gda_data_model_select_get_n_columns;
+       iface->describe_column = gda_data_model_select_describe_column;
+        iface->get_access_flags = gda_data_model_select_get_access_flags;
+       iface->get_value_at = gda_data_model_select_get_value_at;
+       iface->get_attributes_at = gda_data_model_select_get_attributes_at;
+
+       iface->create_iter = gda_data_model_select_create_iter;
+
+       iface->set_value_at = gda_data_model_select_set_value_at;
+       iface->set_values = gda_data_model_select_set_values;
+        iface->append_values = gda_data_model_select_append_values;
+       iface->append_row = NULL;
+       iface->remove_row = gda_data_model_select_remove_row;
+       iface->find_row = NULL;
+
+       iface->freeze = gda_data_model_select_freeze;
+       iface->thaw = gda_data_model_select_thaw;
+       iface->get_notify = gda_data_model_select_get_notify;
+       iface->send_hint = NULL;
+
+       iface->get_exceptions = gda_data_model_select_get_exceptions;
+}
diff --git a/libgda/gda-data-model-select.h b/libgda/gda-data-model-select.h
new file mode 100644
index 000000000..285df1043
--- /dev/null
+++ b/libgda/gda-data-model-select.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 - 2012 Vivien Malerba <malerba gnome-db org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __GDA_DATA_MODEL_SELECT_H__
+#define __GDA_DATA_MODEL_SELECT_H__
+
+#include <glib-object.h>
+#include <gda-connection.h>
+
+G_BEGIN_DECLS
+
+#define GDA_TYPE_DATA_MODEL_SELECT            (gda_data_model_select_get_type())
+
+G_DECLARE_DERIVABLE_TYPE(GdaDataModelSelect, gda_data_model_select, GDA, DATA_MODEL_SELECT, GObject)
+
+struct _GdaDataModelSelectClass {
+  GObjectClass      parent_class;
+  /* signals */
+  void              (* updated)       (GdaDataModelSelect *model);
+};
+
+GdaDataModelSelect *gda_data_model_select_new             (GdaConnection *cnc, GdaStatement *stm, GdaSet 
*params);
+GdaDataModelSelect *gda_data_model_select_new_from_string (GdaConnection *cnc, const gchar *sql);
+gboolean            gda_data_model_select_is_valid        (GdaDataModelSelect *model);
+GdaSet             *gda_data_model_select_get_parameters  (GdaDataModelSelect *model);
+void                gda_data_model_select_set_parameters  (GdaDataModelSelect *model, GdaSet *params);
+
+G_END_DECLS
+
+#endif
diff --git a/libgda/gda-data-select.c b/libgda/gda-data-select.c
index fc542ea32..d49df2ce5 100644
--- a/libgda/gda-data-select.c
+++ b/libgda/gda-data-select.c
@@ -3774,10 +3774,11 @@ gda_data_select_rerun (GdaDataSelect *model, GError **error)
        old_priv->sh->sel_stmt = priv->sh->sel_stmt;
        priv->sh->sel_stmt = (GdaStatement*) copy;
 
-       if (priv->sh->ext_params)
+       if (priv->sh->ext_params) {
                priv->ext_params_changed_sig_id =
                        g_signal_connect (priv->sh->ext_params, "holder-changed",
                                          G_CALLBACK (ext_params_holder_changed_cb), model);
+       }
 
        /* keep the same GdaColumn pointers */
        GSList *l1, *l2;
diff --git a/libgda/gda-data-select.h b/libgda/gda-data-select.h
index fd3fc934e..effc20c87 100644
--- a/libgda/gda-data-select.h
+++ b/libgda/gda-data-select.h
@@ -151,7 +151,6 @@ gboolean       gda_data_select_compute_modification_statements_ext (GdaDataSelec
 gboolean       gda_data_select_compute_columns_attributes      (GdaDataSelect *model, GError **error);
 GdaConnection *gda_data_select_get_connection                  (GdaDataSelect *model);
 
-gboolean       gda_data_select_rerun                           (GdaDataSelect *model, GError **error);
 gboolean       gda_data_select_prepare_for_offline             (GdaDataSelect *model, GError **error);
 
 #define GDA_TYPE_DATA_SELECT_ITER gda_data_select_iter_get_type()
diff --git a/libgda/libgda.h.in b/libgda/libgda.h.in
index ec1f1a30c..3f4de858b 100644
--- a/libgda/libgda.h.in
+++ b/libgda/libgda.h.in
@@ -43,6 +43,7 @@
 #include <libgda/gda-data-model-iter.h>
 #include <libgda/gda-data-model-import.h>
 #include <libgda/gda-data-model-dir.h>
+#include <libgda/gda-data-model-select.h>
 #include <libgda/gda-data-access-wrapper.h>
 #include <libgda/gda-data-proxy.h>
 #include <libgda/gda-data-select.h>
@@ -107,3 +108,4 @@ G_END_DECLS
 #endif
 
 
+
diff --git a/libgda/meson.build b/libgda/meson.build
index b33aa6193..f311d9edc 100644
--- a/libgda/meson.build
+++ b/libgda/meson.build
@@ -80,6 +80,7 @@ libgda_headers = files([
        'gda-data-model-iter.h',
        'gda-data-model-iter-extra.h',
        'gda-data-model-private.h',
+       'gda-data-model-select.h',
        'gda-data-access-wrapper.h',
        'gda-data-proxy.h',
        'gda-data-select.h',
@@ -152,6 +153,7 @@ libgda_sources= files([
        'gda-data-model-dir.c',
        'gda-data-model-import.c',
        'gda-data-model-iter.c',
+       'gda-data-model-select.c',
        'gda-data-access-wrapper.c',
        'gda-data-proxy.c',
        'gda-data-select.c',
diff --git a/tests/data-models/check_pmodel.c b/tests/data-models/check_pmodel.c
index 49a9d9c6a..faae30292 100644
--- a/tests/data-models/check_pmodel.c
+++ b/tests/data-models/check_pmodel.c
@@ -1308,8 +1308,6 @@ test12 (GdaConnection *cnc)
                g_warning ("Error: %s", error && error->message ? error->message : "No detail");
                g_assert_not_reached ();
        }
-       g_print ("Rows in Model: %d\n", gda_data_model_get_n_rows (model));
-       g_assert (gda_data_model_get_n_rows (model) > 0);
        monitor_model_signals (model);
 
        /* gda_data_select_compute_modification_statements() */
@@ -1570,13 +1568,23 @@ test15 (GdaConnection *cnc)
        GdaStatement *stmt;
        GdaSet *params;
        gint nfailed = 0;
+       gint idmax = 0;
 
        clear_signals ();
+       /* Dump all data*/
+       stmt = stmt_from_string ("SELECT id FROM customers ORDER BY id");
+       model =  gda_connection_statement_execute_select (cnc, stmt, NULL, NULL);
+       g_assert (model);
+       g_print ("Full Data Set:\n");
+       gda_data_model_dump (model, stdout);
+       g_object_unref (stmt);
+       g_object_unref (model);
 
        /* create GdaDataModelQuery */
        stmt = stmt_from_string ("SELECT * FROM customers WHERE id <= ##theid::gint");
        g_assert (gda_statement_get_parameters (stmt, &params, NULL));
 
+       g_print ("Setted parameters Set outside data set:\n");
        if (! gda_set_set_holder_value (params, &error, "theid", 9)) {
        nfailed++;
 #ifdef CHECK_EXTRA_INFO
@@ -1585,8 +1593,8 @@ test15 (GdaConnection *cnc)
 #endif
                goto out;
        }
-       model = gda_connection_statement_execute_select (cnc, stmt, params, &error);
-       g_assert (model);
+       g_print ("Created first filtered DataModel:\n");
+       model = (GdaDataModel*) gda_data_model_select_new (cnc, stmt, params);
 
        monitor_model_signals (model);
 
@@ -1594,7 +1602,7 @@ test15 (GdaConnection *cnc)
        g_object_set_data (G_OBJECT (model), "mydata", "hey");
 
        /**/
-       g_object_set (G_OBJECT (model), "auto-reset", TRUE, NULL);
+       g_print ("Change value on parameters DataModel:\n");
        if (! gda_set_set_holder_value (params, &error, "theid", 3)) {
                nfailed++;
 #ifdef CHECK_EXTRA_INFO
@@ -1603,7 +1611,9 @@ test15 (GdaConnection *cnc)
 #endif
        goto out;
        }
-       check_expected_signal (model, 'R', -1);
+       check_expected_signal (model, 'M', -1);
+       g_print ("Data Model upfter 'updated' signal\n");
+       gda_data_model_dump (model, stdout);
 
        const gchar *dstr = g_object_get_data (G_OBJECT (model), "mydata");
        if (!dstr || strcmp (dstr, "hey")) {
@@ -1615,7 +1625,7 @@ test15 (GdaConnection *cnc)
        goto out;
        }
 
-       rerun = gda_connection_statement_execute_select (cnc, stmt, params, &error);
+       rerun = gda_connection_statement_execute_select (cnc, stmt, params, NULL);
        g_assert (rerun);
        if (! compare_data_models (model, rerun, NULL)) {
                nfailed++;
@@ -1627,6 +1637,7 @@ test15 (GdaConnection *cnc)
        g_object_unref (rerun);
 
  out:
+       g_clear_error (&error);
        if (model)
                g_object_unref (model);
        g_object_unref (stmt);
@@ -1656,19 +1667,10 @@ test16 (GdaConnection *cnc)
        stmt = stmt_from_string ("SELECT * FROM customers WHERE id <= ##theid::gint");
        g_assert (gda_statement_get_parameters (stmt, &params, NULL));
 
-       model = gda_connection_statement_execute_select_full (cnc, stmt, params,
-                                                             GDA_STATEMENT_MODEL_ALLOW_NOPARAM,
-                                                             NULL, &error);
-       if (!model) {
-               nfailed++;
-#ifdef CHECK_EXTRA_INFO
-               g_print ("Can't run a SELECT with invalid parameters and the "
-                  "GDA_STATEMENT_MODEL_ALLOW_NOPARAM flag: %s\n",
-                  error && error->message ? error->message : "No detail");
-#endif
-               goto out;
-       }
+       model = (GdaDataModel*) gda_data_model_select_new (cnc, stmt, params);
+       g_assert (model);
 
+       g_assert (!gda_data_model_select_is_valid (GDA_DATA_MODEL_SELECT (model)));
        if (gda_data_model_get_n_rows (model) != 0) {
                nfailed++;
 #ifdef CHECK_EXTRA_INFO
@@ -1677,12 +1679,6 @@ test16 (GdaConnection *cnc)
 #endif
                goto out;
        }
-       g_print ("After First select ejection\n");
-       dump_data_model (model);
-
-       /* set a custom data */
-       g_object_set_data (G_OBJECT (model), "mydata", "hey");
-       monitor_model_signals (model);
 
        /**/
        g_print ("Setting a new Value in parameters: theid = 9\n");
@@ -1694,17 +1690,7 @@ test16 (GdaConnection *cnc)
 #endif
                goto out;
        }
-       check_expected_signal (model, 'R', -1);
-
-       const gchar *dstr = g_object_get_data (G_OBJECT (model), "mydata");
-       if (!dstr || strcmp (dstr, "hey")) {
-               nfailed++;
-#ifdef CHECK_EXTRA_INFO
-                g_print ("Data model lost custom added data: expected 'hey' and got '%s'\n",
-                        dstr);
-#endif
-                goto out;
-       }
+       check_expected_signal (model, 'M', -1);
 
        dump_data_model (model);
 
@@ -1718,20 +1704,12 @@ test16 (GdaConnection *cnc)
 #endif
                goto out;
        }
-       check_expected_signal (model, 'R', -1);
-
-       dstr = g_object_get_data (G_OBJECT (model), "mydata");
-       if (!dstr || strcmp (dstr, "hey")) {
-               nfailed++;
-#ifdef CHECK_EXTRA_INFO
-               g_print ("Data model lost custom added data: expected 'hey' and got '%s'\n",
-                        dstr);
-#endif
-               goto out;
-       }
+       check_expected_signal (model, 'M', -1);
 
+       g_print ("Setting a new Value in parameters: theid = 120");
        dump_data_model (model);
 
+       g_print ("Getting original data from a SELECT statement:\n");
        rerun = gda_connection_statement_execute_select (cnc, stmt, params, &error);
        g_assert (rerun);
        if (! compare_data_models (model, rerun, NULL)) {
@@ -1745,8 +1723,8 @@ test16 (GdaConnection *cnc)
 
        /**/
        gda_holder_force_invalid (GDA_HOLDER (gda_set_get_holders (params)->data));
-       check_expected_signal (model, 'R', -1);
-       dump_data_model (model);
+       check_expected_signal (model, 'M', -1);
+       g_assert (!gda_data_model_select_is_valid (GDA_DATA_MODEL_SELECT (model)));
 
  out:
        g_object_unref (model);
@@ -1768,20 +1746,34 @@ test17 (GdaConnection *cnc)
 {
        GError *error = NULL;
        GdaDataModel *model;
-       GdaStatement *stmt;
        GdaDataModelIter *iter;
        GdaSet *params;
        gint nfailed = 0;
 
        /* create GdaDataModelQuery */
-       stmt = stmt_from_string ("SELECT * FROM customers WHERE id <= ##theid::gint");
-       g_assert (gda_statement_get_parameters (stmt, &params, NULL));
 
-       model = gda_connection_statement_execute_select_full (cnc, stmt, params, 
GDA_STATEMENT_MODEL_ALLOW_NOPARAM,
-                                                             NULL, &error);
+       model = (GdaDataModel*) gda_data_model_select_new_from_string (cnc, "SELECT * FROM customers WHERE id 
<= ##theid::gint");
        g_assert (model);
+       g_assert (!gda_data_model_select_is_valid (GDA_DATA_MODEL_SELECT (model)));
+       g_print ("Get parameters\n");
+       params = gda_data_model_select_get_parameters (GDA_DATA_MODEL_SELECT (model));
+       g_assert (params != NULL);
+       g_assert (GDA_IS_SET (params));
+       g_print ("Set values to parameters\n");
+       /* Place a valid parameters to get a valid data model*/
+       if (! gda_set_set_holder_value (params, &error, "theid", 9)) {
+               nfailed++;
+#ifdef CHECK_EXTRA_INFO
+               g_print ("Can't set 'theid' value: %s \n",
+                         error && error->message ? error->message : "No detail");
+#endif
+               goto out;
+       }
+       g_assert (gda_data_model_select_is_valid (GDA_DATA_MODEL_SELECT (model)));
+       g_print ("SELECT after set parameters\n");
+       dump_data_model (model);
        iter = gda_data_model_create_iter (model);
-       
+       g_assert (iter != NULL);
        gint i, nullcol = -1;
        GdaColumn *column;
        GSList *list;
@@ -1857,7 +1849,6 @@ test17 (GdaConnection *cnc)
 
  out:
        g_object_unref (model);
-       g_object_unref (stmt);
 
        return nfailed;
 }
@@ -2229,6 +2220,9 @@ check_expected_signal (GdaDataModel *model, gchar type, gint row)
                case 'R':
                        exp = "reset";
                        break;
+               case 'M':
+                       exp = "updated";
+                       break;
                default:
                        exp = "???";
                        break;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]