libgda r3217 - in trunk: . doc/C doc/C/tmpl libgda libgda/sqlite providers/postgres providers/skel-implementation/capi tests/data-models tests/value-holders



Author: vivien
Date: Fri Sep 26 19:05:32 2008
New Revision: 3217
URL: http://svn.gnome.org/viewvc/libgda?rev=3217&view=rev

Log:
2008-09-26  Vivien Malerba <malerba gnome-db org>

	* providers/postgres/gda-postgres-provider.c:
	* libgda/sqlite/gda-sqlite-provider.c: code cleanup
	* providers/skel-implementation/capi/gda-capi-provider.c: adapted skeleton implementation
	to support the GDA_STATEMENT_MODEL_ALLOW_NOPARAM flag
	* libgda/gda-holder.c:
	  - the "g-type" property can now be set after construction, but only if it initially was
	    GDA_TYPE_NULL
	  - fixed a bug when the GdaHolder remained invalid even though it was not anymore
	* libgda/gda-set.c: indentation correction
	* libgda/gda-data-model-iter.c: adjust the GdaHolder's type when the data model
	is reset (in case it was GDA_TYPE_NULL)
	* tests/: new test cases
	* doc/C:
	* libgda/gda-connection.c: doc. updates
	* libgda/gda-data-proxy.c: made find_or_create_row_modif() static
	* libgda/gda-connection.c: made build_downstream_context_templates() and
	build_upstream_context_templates() static
	* README: point to the COPYING and COPYING.LIB files for the actual GPL and
	LGPL text


Added:
   trunk/doc/C/data_select.xml
Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/README
   trunk/doc/C/libgda-4.0-docs.sgml
   trunk/doc/C/limitations.xml
   trunk/doc/C/tmpl/gda-data-select.sgml
   trunk/libgda/gda-connection.c
   trunk/libgda/gda-data-model-iter.c
   trunk/libgda/gda-data-proxy.c
   trunk/libgda/gda-holder.c
   trunk/libgda/gda-set.c
   trunk/libgda/sqlite/gda-sqlite-provider.c
   trunk/providers/postgres/gda-postgres-provider.c
   trunk/providers/skel-implementation/capi/gda-capi-provider.c
   trunk/tests/data-models/check_pmodel.c
   trunk/tests/value-holders/check_holder.c

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Fri Sep 26 19:05:32 2008
@@ -1,3 +1,6 @@
+
+ - bug fixes: #508407, #552708
+
 libgda 3.99.4, 2008-09-16
 
  This version includes:

Modified: trunk/README
==============================================================================
--- trunk/README	(original)
+++ trunk/README	Fri Sep 26 19:05:32 2008
@@ -24,6 +24,10 @@
 allows for commercial applications to be developed based on libgda. Its 
 command-line tools are under the GPL.
 
+See COPYING for the GPL license.
+See COPYING.LIB for the LGPL license.
+
+
 Dependencies
 ------------
 To compile libgda, you must have the following packages installed:

Added: trunk/doc/C/data_select.xml
==============================================================================
--- (empty file)
+++ trunk/doc/C/data_select.xml	Fri Sep 26 19:05:32 2008
@@ -0,0 +1,107 @@
+<sect1 id="data-select">
+  <title>Advanced GdaDataSelect usage</title>
+  <para>
+    Whenever a SELECT statement is successfully executed (using the <link linkend="GdaConnection">GdaConnection</link>'s methods),
+    a new <link linkend="GdaDataSelect">GdaDataSelect</link> object is created, which can be used as any other
+    <link linkend="GdaDataModel">GdaDataModel</link> object. However this object has some extra features which are
+    described in this section.
+  </para>
+
+  <sect2 id="data-select-rerun">
+    <title>Automatic re-run of the SELECT statement</title>
+    <para>
+      If the SELECT statement which has been executed contained some parameters, then the 
+      <link linkend="GdaDataSelect--auto-reset">auto-reset</link> property controls whether the
+      <link linkend="GdaDataSelect">GdaDataSelect</link> object should re-run the SELECT statement
+      to have an up-to-date contents. This feature is disabled by default but can be enabled anytime.
+    </para>
+    <para>
+      For example the following code (errors checking omitted for readability):
+      <programlisting>
+GdaStatement *stmt;
+GdaSqlParser *parser = ...;
+GdaDataModel *model;
+
+stmt = gda_sql_parser_parse_from_string (parser,
+       "SELECT * FROM customers WHERE id &lt;= ##theid::gint",
+       NULL, NULL);
+gda_statement_get_parameters (stmt, &amp;params, NULL);
+gda_set_set_holder_value (params, NULL, "theid", 9);
+model = gda_connection_statement_execute_select (cnc, stmt, params, NULL);
+g_object_set (G_OBJECT (model), "auto-reset", TRUE, NULL);
+g_object_unref (stmt);
+      </programlisting>
+      would create a <link linkend="GdaDataSelect">GdaDataSelect</link> object (the 'model' variable) with the
+      following contents:
+      <programlisting>
+id | name           | default_served_by | country | city
+---+----------------+-------------------+---------+-----
+ 2 | Ed Lamton      |                 4 | SP      | MDR 
+ 3 | Lew Bonito     |                 1 | FR      | TLS 
+ 4 | Mark Lawrencep |                   | SP      | MDR 
+ 9 | Greg Popoff    |                 2 | SP      | MDR 
+      </programlisting>
+      and with the following changes:
+      <programlisting>
+gda_set_set_holder_value (params, NULL, "theid", 4);
+      </programlisting>
+      the contents of the data model will automatically be set to:
+      <programlisting>
+id | name           | default_served_by | country | city
+---+----------------+-------------------+---------+-----
+ 2 | Ed Lamton      |                 4 | SP      | MDR 
+ 3 | Lew Bonito     |                 1 | FR      | TLS 
+ 4 | Mark Lawrencep |                   | SP      | MDR
+      </programlisting>
+    </para>
+    <para>
+      Important note: with some database providers (such as SQLite), the column's types (if not specified when the statement
+      is run) cannot be determined untill there is a value in the column. This means that a column's type may change
+      over time from the GDA_TYPE_NULL type to its correct type.
+    </para>
+  </sect2>
+
+  <sect2 id="data-select-empty-rs">
+    <title>Invalid parameters</title>
+    <para>
+      If the SELECT statement which has been executed contained some parameters, and if it is not possible to
+      give correct values to the parameters when the data model resulting from the execution of the SELECT must be
+      created, then the execution should fail and no data model should be created (see the
+      <link linkend="gda-connection-statement-execute">gda_connection_statement_execute()</link>'s documentation).
+      However that default behaviour can be changed using the GDA_STATEMENT_MODEL_ALLOW_NOPARAM flag: the returned
+      data model will have no row and will automatically update its contents (re-run the SELECT statement)
+      when parameters are changed.
+    </para>
+    <para>
+      The example above can be modified as follows, note that the value of the 'theid' parameter is not set
+      which makes it invalid:
+      <programlisting>
+	GdaStatement *stmt;
+GdaSqlParser *parser = ...;
+GdaDataModel *model;
+
+stmt = gda_sql_parser_parse_from_string (parser, 
+       "SELECT * FROM customers WHERE id &lt;= ##theid::gint",
+        NULL, NULL);
+gda_statement_get_parameters (stmt, &amp;params, NULL);
+model = gda_connection_statement_execute_select_full (cnc, stmt, params,
+                                                      GDA_STATEMENT_MODEL_ALLOW_NOPARAM,
+                                                      NULL, NULL);
+g_object_unref (stmt);
+      </programlisting>
+      The created data model contains no row, and with the following changes:
+      <programlisting>
+gda_set_set_holder_value (params, NULL, "theid", 4);
+      </programlisting>
+      the contents of the data model will automatically be set to:
+      <programlisting>
+id | name           | default_served_by | country | city
+---+----------------+-------------------+---------+-----
+ 2 | Ed Lamton      |                 4 | SP      | MDR 
+ 3 | Lew Bonito     |                 1 | FR      | TLS 
+ 4 | Mark Lawrencep |                   | SP      | MDR
+      </programlisting>
+    </para>
+  </sect2>
+  
+</sect1>

Modified: trunk/doc/C/libgda-4.0-docs.sgml
==============================================================================
--- trunk/doc/C/libgda-4.0-docs.sgml	(original)
+++ trunk/doc/C/libgda-4.0-docs.sgml	Fri Sep 26 19:05:32 2008
@@ -39,6 +39,7 @@
 <!ENTITY migration SYSTEM "migration.xml">
 <!ENTITY migration2 SYSTEM "migration2.xml">
 <!ENTITY data-validation SYSTEM "data_validation.xml">
+<!ENTITY data-select SYSTEM "data_select.xml">
 <!ENTITY limitations SYSTEM "limitations.xml">
 <!ENTITY libgda-GdaCommand SYSTEM "xml/gda-command.xml">
 <!ENTITY libgda-config SYSTEM "xml/gda-config.xml">
@@ -506,7 +507,6 @@
       &libgda-GdaSqlParser;
       &libgda-GdaStatement;
       &libgda-GdaBatch;
-      &libgda-GdaDataSelect;
       &libgda-GdaHolder;
       &libgda-GdaSet;
       &libgda-GdaSqlStatement;
@@ -571,8 +571,10 @@
       </para>
       &libgda-GValue;
       &data-validation;
+      &data-select;
       &libgda-GdaBlobOp;
       &libgda-GdaDataModel;
+      &libgda-GdaDataSelect;
       &libgda-GdaColumn;
       &libgda-GdaDataModelIter;
       &libgda-GdaDataModelImport;

Modified: trunk/doc/C/limitations.xml
==============================================================================
--- trunk/doc/C/limitations.xml	(original)
+++ trunk/doc/C/limitations.xml	Fri Sep 26 19:05:32 2008
@@ -37,6 +37,16 @@
       </para>
     </sect2>
 
+    <sect2><title>Statements execution</title>
+      <para>
+	<itemizedlist>
+	  <listitem><para>It is not possible to execute a SELECT statement with invalid parameters and
+	      with the GDA_STATEMENT_MODEL_ALLOW_NOPARAM flag as this feature is currently not implemented.
+	      </para></listitem>
+	</itemizedlist>
+      </para>
+    </sect2>
+
   </sect1>
 
   <sect1 id="limitations_oracle"><title>For Oracle</title>
@@ -84,6 +94,16 @@
 	connections to be opened from the thread which initializes &LIBGDA;. Otherwise there is no limitation.
       </para>
     </sect2>
+
+    <sect2><title>Statements execution</title>
+      <para>
+	<itemizedlist>
+	  <listitem><para>It is not possible to execute a SELECT statement with invalid parameters and
+	      with the GDA_STATEMENT_MODEL_ALLOW_NOPARAM flag if the GDA_STATEMENT_MODEL_CURSOR_FORWARD
+	      flag is also specified</para></listitem>
+	</itemizedlist>
+      </para>
+    </sect2>
   </sect1>
 
   <sect1 id="limitations_sqlite"><title>For SQLite</title>

Modified: trunk/doc/C/tmpl/gda-data-select.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-data-select.sgml	(original)
+++ trunk/doc/C/tmpl/gda-data-select.sgml	Fri Sep 26 19:05:32 2008
@@ -36,7 +36,7 @@
 
 <!-- ##### SECTION See_Also ##### -->
 <para>
-
+  The <link linkend="data-select">Advanced GdaDataSelect usage</link> section.
 </para>
 
 <!-- ##### SECTION Stability_Level ##### -->

Modified: trunk/libgda/gda-connection.c
==============================================================================
--- trunk/libgda/gda-connection.c	(original)
+++ trunk/libgda/gda-connection.c	Fri Sep 26 19:05:32 2008
@@ -1550,7 +1550,11 @@
  * then the resulting data model will re-run itself, see the GdaDataSelect's 
  * <link linkend="GdaDataSelect--auto-reset">auto-reset</link> property for more information.
  *
- * Also see the <link linkend="limitations">provider's limitations</link> section.
+ * Note4: if @model_usage does not contain the GDA_STATEMENT_MODEL_RANDOM_ACCESS or GDA_STATEMENT_MODEL_CURSOR_FORWARD
+ * flags, then the default will be to return a random access data model
+ *
+ * Also see the <link linkend="limitations">provider's limitations</link>, and the
+ * <link linkend="data-select">Advanced GdaDataSelect usage</link> sections.
  *
  * Returns: a #GObject, or %NULL if an error occurred 
  */
@@ -1997,7 +2001,7 @@
 
 /* builds a list of #GdaMetaContext contexts templates: contexts which have a non NULL table_name,
  * and empty or partially filled column names and values specifications */
-GSList *
+static GSList *
 build_upstream_context_templates (GdaMetaStore *store, GdaMetaContext *context, GSList *elist, GError **error)
 {
 	GSList *depend_on_contexts;
@@ -2027,7 +2031,7 @@
 
 /* builds a list of #GdaMetaContext contexts templates: contexts which have a non NULL table_name,
  * and empty or partially filled column names and values specifications */
-GSList *
+static GSList *
 build_downstream_context_templates (GdaMetaStore *store, GdaMetaContext *context, GSList *elist, GError **error)
 {
 	GSList *depending_contexts;

Modified: trunk/libgda/gda-data-model-iter.c
==============================================================================
--- trunk/libgda/gda-data-model-iter.c	(original)
+++ trunk/libgda/gda-data-model-iter.c	Fri Sep 26 19:05:32 2008
@@ -229,6 +229,22 @@
 	/* reset the iter to before the 1st row */
 	gda_data_model_iter_invalidate_contents (iter);
 	gda_data_model_iter_move_at_row (iter, -1);
+	
+	/* adjust GdaHolder's type if a column's type has changed from GDA_TYPE_NULL
+	 * to something else */
+	gint i;
+	GSList *list;
+	for (i = 0, list = ((GdaSet*) iter)->holders;
+	     list;
+	     i++, list = list->next) {
+		if (gda_holder_get_g_type ((GdaHolder *) list->data) == GDA_TYPE_NULL) {
+			GdaColumn *col;
+			col = gda_data_model_describe_column (model, i);
+			if (gda_column_get_g_type (col) != GDA_TYPE_NULL)
+				g_object_set (G_OBJECT (list->data), "g-type",
+					      gda_column_get_g_type (col), NULL);
+		}
+	}
 }
 
 /*

Modified: trunk/libgda/gda-data-proxy.c
==============================================================================
--- trunk/libgda/gda-data-proxy.c	(original)
+++ trunk/libgda/gda-data-proxy.c	Fri Sep 26 19:05:32 2008
@@ -1137,13 +1137,13 @@
 }
 
 
-RowModif *find_or_create_row_modif (GdaDataProxy *proxy, gint proxy_row, gint col, RowValue **ret_rv);
+static RowModif *find_or_create_row_modif (GdaDataProxy *proxy, gint proxy_row, gint col, RowValue **ret_rv);
 
 
 /*
  * Stores the new RowValue in @rv
  */
-RowModif *
+static RowModif *
 find_or_create_row_modif (GdaDataProxy *proxy, gint proxy_row, gint col, RowValue **ret_rv)
 {
 	RowModif *rm = NULL;

Modified: trunk/libgda/gda-holder.c
==============================================================================
--- trunk/libgda/gda-holder.c	(original)
+++ trunk/libgda/gda-holder.c	Fri Sep 26 19:05:32 2008
@@ -226,7 +226,7 @@
                                          g_param_spec_ulong ("g-type", NULL, NULL,
 							   0, G_MAXULONG, GDA_TYPE_NULL,
 							   (G_PARAM_READABLE | 
-							    G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+							    G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)));
 	g_object_class_install_property (object_class, PROP_PLUGIN,
 					 g_param_spec_string ("plugin", NULL, NULL, NULL, 
 							      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
@@ -289,8 +289,6 @@
 {
 	GObject   *obj;
 
-	g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
-
         obj = g_object_new (GDA_TYPE_HOLDER, "g-type", type, NULL);
 
         return (GdaHolder *) obj;
@@ -530,7 +528,10 @@
 			holder->priv->descr = g_value_dup_string (value);
 			break;
 		case PROP_GDA_TYPE:
-			holder->priv->g_type = g_value_get_ulong (value);
+			if (holder->priv->g_type == GDA_TYPE_NULL)
+				holder->priv->g_type = g_value_get_ulong (value);
+			else
+				g_warning (_("The 'g-type' property cannot be changed"));
 			break;
 		case PROP_PLUGIN:
 			ptr = g_value_get_string (value);
@@ -901,6 +902,7 @@
 		if (!do_copy && value)
 			gda_value_free (value);
 		holder->priv->invalid_forced = FALSE;
+		holder->priv->valid = newvalid;
 		return TRUE;
 	}
 

Modified: trunk/libgda/gda-set.c
==============================================================================
--- trunk/libgda/gda-set.c	(original)
+++ trunk/libgda/gda-set.c	Fri Sep 26 19:05:32 2008
@@ -1450,21 +1450,21 @@
 			retval = FALSE;
 		}
 		
-	if (retval) {
+		if (retval) {
 		/* signal the holder validate-set */
-		GError *lerror = NULL;
+			GError *lerror = NULL;
 #ifdef GDA_DEBUG_signal
-		g_print (">> 'VALIDATE_SET' from %s\n", __FUNCTION__);
+			g_print (">> 'VALIDATE_SET' from %s\n", __FUNCTION__);
 #endif
-		g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_SET], 0, &lerror);
+			g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_SET], 0, &lerror);
 #ifdef GDA_DEBUG_signal
-		g_print ("<< 'VALIDATE_SET' from %s\n", __FUNCTION__);
+			g_print ("<< 'VALIDATE_SET' from %s\n", __FUNCTION__);
 #endif
-		if (lerror) {
-			g_propagate_error (error, lerror);
-			retval = FALSE;
+			if (lerror) {
+				g_propagate_error (error, lerror);
+				retval = FALSE;
+			}
 		}
-	}
 
 #ifdef GDA_DEBUG_NO
 		g_print ("== HOLDER %p: valid= %d, value=%s\n", holders->data, gda_holder_is_valid (GDA_HOLDER (holders->data)),

Modified: trunk/libgda/sqlite/gda-sqlite-provider.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-provider.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-provider.c	Fri Sep 26 19:05:32 2008
@@ -1957,14 +1957,12 @@
 			break;
 		}
 
-		if (params) {
-			h = gda_set_get_holder (params, pname);
-			if (!h) {
-				gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
-				if (tmp) {
-					h = gda_set_get_holder (params, tmp);
-					g_free (tmp);
-				}
+		h = gda_set_get_holder (params, pname);
+		if (!h) {
+			gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
+			if (tmp) {
+				h = gda_set_get_holder (params, tmp);
+				g_free (tmp);
 			}
 		}
 		if (!h) {

Modified: trunk/providers/postgres/gda-postgres-provider.c
==============================================================================
--- trunk/providers/postgres/gda-postgres-provider.c	(original)
+++ trunk/providers/postgres/gda-postgres-provider.c	Fri Sep 26 19:05:32 2008
@@ -2042,14 +2042,12 @@
 			break;
 		}
 
-		if (params) {
-			h = gda_set_get_holder (params, pname);
-			if (!h) {
-				gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
-				if (tmp) {
-					h = gda_set_get_holder (params, tmp);
-					g_free (tmp);
-				}
+		h = gda_set_get_holder (params, pname);
+		if (!h) {
+			gchar *tmp = gda_alphanum_to_text (g_strdup (pname + 1));
+			if (tmp) {
+				h = gda_set_get_holder (params, tmp);
+				g_free (tmp);
 			}
 		}
 		if (!h) {

Modified: trunk/providers/skel-implementation/capi/gda-capi-provider.c
==============================================================================
--- trunk/providers/skel-implementation/capi/gda-capi-provider.c	(original)
+++ trunk/providers/skel-implementation/capi/gda-capi-provider.c	Fri Sep 26 19:05:32 2008
@@ -950,6 +950,9 @@
 {
 	GdaCapiPStmt *ps;
 	CapiConnectionData *cdata;
+	gboolean allow_noparam;
+        gboolean empty_rs = FALSE; /* TRUE when @allow_noparam is TRUE and there is a problem with @params
+                                      => resulting data model will be empty (0 row) */
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
@@ -962,6 +965,17 @@
                 return FALSE;
 	}
 
+	if (! (model_usage & GDA_STATEMENT_MODEL_RANDOM_ACCESS) &&
+            ! (model_usage & GDA_STATEMENT_MODEL_CURSOR_FORWARD))
+                model_usage |= GDA_STATEMENT_MODEL_RANDOM_ACCESS;
+	
+        allow_noparam = (model_usage & GDA_STATEMENT_MODEL_ALLOW_NOPARAM) &&
+                (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT);
+	
+        if (last_inserted_row)
+                *last_inserted_row = NULL;
+
+	/* Get private data */
 	cdata = (CapiConnectionData*) gda_connection_internal_get_provider_data (cnc);
 	if (!cdata) 
 		return FALSE;
@@ -1014,24 +1028,41 @@
 			}
 		}
 		if (!h) {
-			gchar *str;
-			str = g_strdup_printf (_("Missing parameter '%s' to execute query"), pname);
-			event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-			gda_connection_event_set_description (event, str);
-			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
-				     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, str);
-			g_free (str);
-			break;
+			if (! allow_noparam) {
+				gchar *str;
+				str = g_strdup_printf (_("Missing parameter '%s' to execute query"), pname);
+				event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, str);
+				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, str);
+				g_free (str);
+				break;
+			}
+			else {
+                                /* bind param to NULL */
+                                TO_IMPLEMENT;
+                                empty_rs = TRUE;
+                                continue;
+                        }
+
 		}
 		if (!gda_holder_is_valid (h)) {
-			gchar *str;
-			str = g_strdup_printf (_("Parameter '%s' is invalid"), pname);
-			event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
-			gda_connection_event_set_description (event, str);
-			g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
-				     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, str);
-			g_free (str);
-			break;
+			if (! allow_noparam) {
+				gchar *str;
+				str = g_strdup_printf (_("Parameter '%s' is invalid"), pname);
+				event = gda_connection_event_new (GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, str);
+				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+					     GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR, str);
+				g_free (str);
+				break;
+			}
+			else {
+                                /* bind param to NULL */
+				TO_IMPLEMENT;
+                                empty_rs = TRUE;
+                                continue;
+                        }
 		}
 
 		/* actual binding using the C API, for parameter at position @i */
@@ -1048,6 +1079,32 @@
 	event = gda_connection_event_new (GDA_CONNECTION_EVENT_COMMAND);
         gda_connection_event_set_description (event, _GDA_PSTMT (ps)->sql);
         gda_connection_add_event (cnc, event);
+
+	if (empty_rs) {
+		/* There are some missing parameters, so the SQL can't be executed but we still want
+		 * to execute something to get the columns correctly. A possibility is to actually
+		 * execute another SQL which is the code shown here.
+		 *
+		 * To adapt depending on the C API and its features */
+		GdaStatement *estmt;
+                gchar *esql;
+                estmt = gda_select_alter_select_for_empty (stmt, error);
+                if (!estmt)
+                        return NULL;
+                esql = gda_statement_to_sql (estmt, NULL, error);
+                g_object_unref (estmt);
+                if (!esql)
+                        return NULL;
+
+		/* Execute the 'esql' SQL code */
+                g_free (esql);
+
+		TO_IMPLEMENT;
+	}
+	else {
+		/* Execute the _GDA_PSTMT (ps)->sql SQL code */
+		TO_IMPLEMENT;
+	}
 	
 	/* execute prepared statement using C API depending on its kind */
 	if (! g_ascii_strncasecmp (_GDA_PSTMT (ps)->sql, "SELECT", 6) ||

Modified: trunk/tests/data-models/check_pmodel.c
==============================================================================
--- trunk/tests/data-models/check_pmodel.c	(original)
+++ trunk/tests/data-models/check_pmodel.c	Fri Sep 26 19:05:32 2008
@@ -60,6 +60,7 @@
 static gint test14 (GdaConnection *cnc);
 static gint test15 (GdaConnection *cnc);
 static gint test16 (GdaConnection *cnc);
+static gint test17 (GdaConnection *cnc);
 
 TestFunc tests[] = {
 	test1,
@@ -77,7 +78,8 @@
 	test13,
 	test14,
 	test15,
-	test16
+	test16,
+	test17
 };
 
 int
@@ -104,10 +106,9 @@
 	}
 
 	g_object_unref (cnc);
-	if (number_failed == 0)
-		g_print ("Ok.\n");
-	else
-		g_print ("%d failed\n", number_failed);
+	
+	g_print ("TESTS COUNT: %d\n", i);
+	g_print ("FAILURES: %d\n", number_failed);
 
 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
@@ -1754,6 +1755,114 @@
         return nfailed;
 }
 
+/*
+ * - Create a GdaDataSelect with a missing parameter
+ * - run it to be empty and create an iterator
+ * - set param's value so it refreshes
+ * - make sure the iterator's types are up to date with the data model ones.
+ *
+ * Returns the number of failures 
+ */
+static gint
+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);
+	g_assert (model);
+	iter = gda_data_model_create_iter (model);
+	
+	gint i, nullcol = -1;
+	GdaColumn *column;
+	GSList *list;
+	for (i = 0, list = ((GdaSet*) iter)->holders;
+	     list;
+	     i++, list = list->next) {
+		if (gda_holder_get_g_type ((GdaHolder *) list->data) == GDA_TYPE_NULL) 
+			nullcol = i;
+		column = gda_data_model_describe_column (model, i);
+		if (gda_holder_get_g_type ((GdaHolder *) list->data) != 
+		    gda_column_get_g_type (column)) {
+			nfailed++;
+#ifdef CHECK_EXTRA_INFO
+			g_print ("Iter's GdaHolder for column %d reports the '%s' type when it should be '%s'",
+				 nullcol, 
+				 g_type_name (gda_holder_get_g_type ((GdaHolder *) list->data)),
+				 g_type_name (gda_column_get_g_type (column)));
+#endif
+			goto out;
+		}
+	}
+	if (nullcol == -1) {
+#ifdef CHECK_EXTRA_INFO
+                g_print ("Could not find a GDA_TYPE_NULL column, test will be invalid");
+#endif
+		goto out;
+	}
+
+	/**/
+	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;
+        }
+
+	column = gda_data_model_describe_column (model, nullcol);
+	if (gda_holder_get_g_type ((GdaHolder *) g_slist_nth_data (((GdaSet*) iter)->holders, nullcol)) !=
+	    gda_column_get_g_type (column)) {
+		nfailed++;
+#ifdef CHECK_EXTRA_INFO
+                g_print ("Iter's GdaHolder for column %d reports the '%s' type when it should be '%s'",
+			 nullcol, 
+			 g_type_name (gda_holder_get_g_type ((GdaHolder *) g_slist_nth_data (((GdaSet*) iter)->holders, 
+											     nullcol))),
+			 g_type_name (gda_column_get_g_type (column)));
+#endif
+                goto out;
+	}
+
+	/**/
+	if (gda_data_model_iter_is_valid (iter)) {
+		nfailed++;
+#ifdef CHECK_EXTRA_INFO
+                g_print ("Iter should be invalid, and it is at row %d\n",
+			 gda_data_model_iter_get_row (iter));
+#endif
+                goto out;
+	}
+	dump_data_model (model);
+	while (gda_data_model_iter_move_next (iter));
+	if (gda_data_model_iter_is_valid (iter)) {
+		nfailed++;
+#ifdef CHECK_EXTRA_INFO
+                g_print ("Iter could not be moved up to the end, and remained 'locked' at row %d\n",
+			 gda_data_model_iter_get_row (iter));
+#endif
+                goto out;
+	}
+
+
+ out:
+        g_object_unref (model);
+        g_object_unref (stmt);
+
+        return nfailed;
+}
+
+
 static void
 dump_data_model (GdaDataModel *model)
 {

Modified: trunk/tests/value-holders/check_holder.c
==============================================================================
--- trunk/tests/value-holders/check_holder.c	(original)
+++ trunk/tests/value-holders/check_holder.c	Fri Sep 26 19:05:32 2008
@@ -31,6 +31,7 @@
 static gboolean test8 (GError **error);
 static gboolean test9 (GError **error);
 static gboolean test10 (GError **error);
+static gboolean test11 (GError **error);
 
 TestFunc tests[] = {
 	test1,
@@ -42,7 +43,8 @@
 	test7,
 	test8,
 	test9,
-	test10
+	test10,
+	test11
 };
 
 int 
@@ -878,6 +880,59 @@
 	return TRUE;
 }
 
+static gboolean
+test11 (GError **error)
+{
+	GdaHolder *h;
+	const GValue *cvalue;
+	GValue *value;
+
+	h = gda_holder_new (GDA_TYPE_NULL);
+	emitted_signals_monitor_holder (h);
+
+	/***/
+	value = gda_value_new_from_string ("my string", G_TYPE_STRING);
+	emitted_signals_reset ();
+	if (gda_holder_set_value (h, value, NULL)) {
+		g_set_error (error, 0, 0,
+			     "GdaHolder's change should have failed");
+		return FALSE;
+	}
+	gda_value_free (value);
+
+	/***/
+	if (!gda_holder_set_value (h, NULL, error))
+		return FALSE;
+	if (!emitted_signals_find (h, "changed", error))
+		return FALSE;
+	if (!emitted_signals_chech_empty (NULL, "changed", error))
+		return FALSE;
+	
+	/***/
+	g_object_set (G_OBJECT (h), "g-type", G_TYPE_STRING, NULL);
+	value = gda_value_new_from_string ("my other string", G_TYPE_STRING);
+	emitted_signals_reset ();
+	if (!gda_holder_set_value (h, value, error))
+		return FALSE;
+	if (!emitted_signals_find (h, "changed", error))
+		return FALSE;
+	if (!emitted_signals_chech_empty (NULL, "changed", error))
+		return FALSE;
+
+	/***/
+	cvalue = gda_holder_get_value (h);
+	if (!cvalue || gda_value_differ (value, cvalue)) {
+		g_set_error (error, 0, 0,
+			     "GdaHolder's value is incorrect");
+		return FALSE;
+	}
+	gda_value_free (value);
+
+	g_object_unref (h);
+
+	return TRUE;
+}
+
 
 /*
  * Signals testing



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