libgda r3215 - in trunk: . WixInstaller doc/C doc/C/tmpl libgda libgda/providers-support libgda/sqlite po tests/data-models



Author: vivien
Date: Tue Sep 23 18:38:57 2008
New Revision: 3215
URL: http://svn.gnome.org/viewvc/libgda?rev=3215&view=rev

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

	* sqlite/gda-sqlite-recordset.c: correctly handle the situation when the object
	is created with col_types specified
	* libgda/gda-data-model-iter.c: behave correctly when the data model emits the "reset" signal
	* libgda/gda-data-select.[ch]:
	  - implemented in place re-running the SELECT statement
	    when on of the SELECT's parameters changes (this feature is optional, use the "auto-reset"
	    property to activate it), for bug #552708
	  - other corrections
	* libgda/gda-data-model-query.[ch]: removed now redundant object
	* tests/data-models/: removed the check_model_query test and added test to check_pmodel
	* libgda/gda-data-proxy.c:
	* libgda/libgda.h.in: updates due to the removal of the GdaDataModelQuery object
	* libgda/gda-data-proxy.c: free'd memory access bug corrected in commit_row_modif()
	* WixInstaller/make-zip-exe.sh: updated the generated archive's name
	* libgda/providers-support/gda-pstmt.c
	* doc/C: documentation updates and improvements


Removed:
   trunk/doc/C/tmpl/gda-data-model-query.sgml
   trunk/libgda/gda-data-model-query.c
   trunk/libgda/gda-data-model-query.h
   trunk/tests/data-models/check_model_query.c
Modified:
   trunk/ChangeLog
   trunk/WixInstaller/make-zip-exe.sh
   trunk/doc/C/gda-sql-manual.xml
   trunk/doc/C/howto.xml
   trunk/doc/C/libgda-4.0-docs.sgml
   trunk/doc/C/libgda-4.0-sections.txt
   trunk/doc/C/libgda-4.0.types.in
   trunk/doc/C/migration2.xml
   trunk/doc/C/tmpl/gda-data-select.sgml
   trunk/doc/C/tmpl/gda-pstmt.sgml
   trunk/libgda/Makefile.am
   trunk/libgda/gda-data-model-iter.c
   trunk/libgda/gda-data-proxy.c
   trunk/libgda/gda-data-select.c
   trunk/libgda/libgda.h.in
   trunk/libgda/providers-support/gda-pstmt.c
   trunk/libgda/sqlite/gda-sqlite-recordset.c
   trunk/libgda/sqlite/gda-sqlite-recordset.h
   trunk/po/POTFILES.in
   trunk/tests/data-models/   (props changed)
   trunk/tests/data-models/Makefile.am
   trunk/tests/data-models/check_pmodel.c

Modified: trunk/WixInstaller/make-zip-exe.sh
==============================================================================
--- trunk/WixInstaller/make-zip-exe.sh	(original)
+++ trunk/WixInstaller/make-zip-exe.sh	Tue Sep 23 18:38:57 2008
@@ -17,7 +17,7 @@
 cross_path=/fillme
 depend_path=/local/Win32
 prefix=/fillme
-version=3.99.4
+version=3.99.5
 
 
 
@@ -25,7 +25,7 @@
 # no modification below
 #
 current_dir=`pwd`
-archive=${current_dir}/gda-exe-${version}.zip
+archive=${current_dir}/gda-sql-${version}.zip
 
 
 # remove current archive if it exists
@@ -101,4 +101,4 @@
 #
 # The End
 #
-echo "Archive written to ${archive}"
\ No newline at end of file
+echo "Archive written to ${archive}"

Modified: trunk/doc/C/gda-sql-manual.xml
==============================================================================
--- trunk/doc/C/gda-sql-manual.xml	(original)
+++ trunk/doc/C/gda-sql-manual.xml	Tue Sep 23 18:38:57 2008
@@ -365,6 +365,12 @@
 cnc1>
       </programlisting>
     </para>
+    <para>
+      It is possible for any application to create some extra objects in that database for its own purposes, with the
+      constraint that it <emphasis>should not</emphasis> create objects with names starting with an underscore (these
+      names are reserved for &LIBGDA;'s own purposes). In the previous example, the table named "gda_sql_query_buffers"
+      is the table internally used by the console tool to store the contents of named query buffers.
+    </para>
     
     <sect2>
       <title>Information about tables</title>

Modified: trunk/doc/C/howto.xml
==============================================================================
--- trunk/doc/C/howto.xml	(original)
+++ trunk/doc/C/howto.xml	Tue Sep 23 18:38:57 2008
@@ -442,5 +442,24 @@
     </para>
   </sect1>
 
+  <sect1>
+    <title>Add your own data to a GdaMetaStore</title>
+    <para>
+      Adding your own data in the <link linkend="GdaMetaStore">GdaMetaStore</link> associated to a connection
+      is a possibility to avoid for example to have another file to store your program-specific data (which 
+      you obviously don't want to store in a connection).
+    </para>
+    <para>
+      Doing so is as easy as getting a pointer to the internal connection used by the 
+      <link linkend="GdaMetaStore">GdaMetaStore</link> associated the connection, and then use
+      that connection directly as any other connection object.
+    </para>
+    <para>
+      However &LIBGDA; has some specific API to make this easier, described in the
+      <link linkend="GdaMetaStoreCustomData">section about adding custom data</link> to
+      a GdaMetaStore.
+    </para>
+  </sect1>
+
 </chapter>
 

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	Tue Sep 23 18:38:57 2008
@@ -50,7 +50,6 @@
 <!ENTITY libgda-GdaDataModelArray SYSTEM "xml/gda-data-model-array.xml">
 <!ENTITY libgda-GdaDataModelBdb SYSTEM "xml/gda-data-model-bdb.xml">
 <!ENTITY libgda-GdaDataModelDir SYSTEM "xml/gda-data-model-dir.xml">
-<!ENTITY libgda-GdaDataModelQuery SYSTEM "xml/gda-data-model-query.xml">
 <!ENTITY libgda-GdaDataModel SYSTEM "xml/gda-data-model.xml">
 <!ENTITY libgda-GdaDataModelIter SYSTEM "xml/gda-data-model-iter.xml">
 <!ENTITY libgda-GdaDataModelImport SYSTEM "xml/gda-data-model-import.xml">
@@ -584,7 +583,6 @@
       &libgda-GdaDataModelDir;
       &libgda-GdaDataProxy;
       &libgda-GdaDataComparator;
-      &libgda-GdaDataModelQuery;
     </chapter>
 
     <chapter id="data_conv">
@@ -742,7 +740,8 @@
       <sect1 id="GdaMetaStoreCustomData">
 	<title>Adding custom data</title>
 	<para>
-	  This section explains how to add application specific data (custom data) to a #GdaMetaStore object.
+	  This section explains how to add application specific data (custom data) to a 
+	  <link linked="GdaMetaStore">GdaMetaStore</link> object.
 	</para>
 	<para>
 	  Applications of course don't need to use that feature to manage their own data but it makes sense to use
@@ -760,16 +759,29 @@
 	<sect3>
 	  <title>Declaring the new custom database objects</title>
 	  <para>
+	    The <link linkend="gda-meta-store-schema-add-custom-object">gda_meta_store_schema_add_custom_object()</link>
+	    method canbe used to add custom objects, which have to be described using an XML syntax. The advantages
+	    of using that method are:
+	    <itemizedlist>
+	      <listitem><para>The object's definition will be the same for all database types</para></listitem>
+	      <listitem><para>If another object with a different definition already exists, then a error is returned</para></listitem>
+	    </itemizedlist>
 	  </para>
 	</sect3>
 	<sect3>
 	  <title>Adding and removing data</title>
 	  <para>
+	    For the moment adding and removing data must be done as for any other database connection,
+	    using the <link linkend="GdaMetaStore's">GdaMetaStore</link>'s internal connection obtained 
+	    with <link linkend="gda_meta_store_get_internal_connection">gda_meta_store_get_internal_connection()</link>.
 	  </para>
 	</sect3>
 	<sect3>
 	  <title>Removing custom database objects</title>
 	  <para>
+	    For the moment adding and removing data must be done as for any other database connection,
+	    using the <link linkend="GdaMetaStore's">GdaMetaStore</link>'s internal connection obtained 
+	    with <link linkend="gda_meta_store_get_internal_connection">gda_meta_store_get_internal_connection()</link>.
 	  </para>
 	</sect3>
 	<para>
@@ -1025,16 +1037,7 @@
 	</programlisting>
       </para>
       <para>
-	The &gda-sql; tool uses the following environment variables, when set:
-	<itemizedlist>
-	  <listitem><para>GDA_SQL_CNC: may contain an all-in-one connection string to open upon startup</para></listitem>
-	  <listitem><para>GDA_NO_PAGER: if set, then no pager will be used</para></listitem>
-	  <listitem><para>PAGER: if set, indicates which pager program to use (the "more" program is used if not set)</para></listitem>
-	  <listitem><para>GDA_SQL_EDITOR, EDITOR, VISUAL (by precedence order): if set specifies which editor is used (the "notepad.exe" editor is used on Windows
-	      platforms or the "vi" on others if not set)</para></listitem>
-	  <listitem><para>GDA_SQL_VIEWER_PNG: specifies the viewer to use to display graphs (as PNG files)</para></listitem>
-	  <listitem><para>GDA_SQL_VIEWER_PDF: specifies the viewer to use to display graphs (as PDF files)</para></listitem>
-	</itemizedlist>
+	See the <link linkend="gda-sql">Gda SQL console tool manual section</link> for more information.
       </para>
     </chapter>
 

Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt	(original)
+++ trunk/doc/C/libgda-4.0-sections.txt	Tue Sep 23 18:38:57 2008
@@ -200,30 +200,6 @@
 </SECTION>
 
 <SECTION>
-<FILE>gda-data-model-query</FILE>
-<TITLE>GdaDataModelQuery</TITLE>
-GdaDataModelQuery
-GdaDataModelQueryError
-GdaDataModelQueryClass
-GdaDataModelQueryPrivate
-gda_data_model_query_new
-gda_data_model_query_refresh
-gda_data_model_query_set_row_selection_condition
-gda_data_model_query_set_row_selection_condition_sql
-gda_data_model_query_compute_row_selection_condition
-gda_data_model_query_set_modification_statement
-gda_data_model_query_set_modification_statement_sql
-gda_data_model_query_compute_modification_statements
-<SUBSECTION Standard>
-GDA_DATA_MODEL_QUERY
-GDA_DATA_MODEL_QUERY_CLASS
-GDA_IS_DATA_MODEL_QUERY
-GDA_IS_DATA_MODEL_QUERY_CLASS
-GDA_TYPE_DATA_MODEL_QUERY
-gda_data_model_query_get_type
-</SECTION>
-
-<SECTION>
 <FILE>gda-data-model-import</FILE>
 <TITLE>GdaDataModelImport</TITLE>
 GdaDataModelImport

Modified: trunk/doc/C/libgda-4.0.types.in
==============================================================================
--- trunk/doc/C/libgda-4.0.types.in	(original)
+++ trunk/doc/C/libgda-4.0.types.in	Tue Sep 23 18:38:57 2008
@@ -25,7 +25,6 @@
 gda_data_model_get_type
 gda_data_model_import_get_type
 gda_data_model_iter_get_type
-gda_data_model_query_get_type
 gda_data_access_wrapper_get_type
 gda_data_proxy_get_type
 gda_quark_list_get_type

Modified: trunk/doc/C/migration2.xml
==============================================================================
--- trunk/doc/C/migration2.xml	(original)
+++ trunk/doc/C/migration2.xml	Tue Sep 23 18:38:57 2008
@@ -157,6 +157,8 @@
  	  <listitem><para>GdaDataModelFilterSQL</para></listitem>
  	  <listitem><para>GdaGraph, GdaGraphItem, GdaGraphQuery</para></listitem>
  	  <listitem><para>GdaGraphviz</para></listitem>
+ 	  <listitem><para>GdaDataModelQuery (features redundant with the 
+	      <link linkend="GdaDataSelect">GdaDataSelect</link> object) </para></listitem>
 	</itemizedlist>
       </para>
     </sect2>

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	Tue Sep 23 18:38:57 2008
@@ -48,6 +48,11 @@
 </para>
 
 
+<!-- ##### ARG GdaDataSelect:auto-reset ##### -->
+<para>
+
+</para>
+
 <!-- ##### ARG GdaDataSelect:connection ##### -->
 <para>
 

Modified: trunk/doc/C/tmpl/gda-pstmt.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-pstmt.sgml	(original)
+++ trunk/doc/C/tmpl/gda-pstmt.sgml	Tue Sep 23 18:38:57 2008
@@ -24,6 +24,12 @@
   a #GdaStatement object in a connection using 
   <link linkend="gda-connection-add-prepared-statement">gda_connection_add_prepared_statement()</link>.
 </para>
+<para>
+  The #GdaPStmt object can keep a reference to the #GdaStatement object (which can be set and get using
+  the <link linkend="gda-pstmt-set-gda-statement">gda_pstmt_set_gda_statement()</link> and
+  <link linkend="gda-pstmt-get-gda-statement">gda_pstmt_get_gda_statement()</link>), however that reference
+  if a weak one (which means it will be lost if the #GdaStatement object is destroyed).
+</para>
 
 <!-- ##### SECTION See_Also ##### -->
 <para>

Modified: trunk/libgda/Makefile.am
==============================================================================
--- trunk/libgda/Makefile.am	(original)
+++ trunk/libgda/Makefile.am	Tue Sep 23 18:38:57 2008
@@ -44,7 +44,6 @@
 	gda-data-model-iter.h \
 	gda-data-model-iter-extra.h \
 	gda-data-model-private.h \
-	gda-data-model-query.h \
 	gda-data-access-wrapper.h \
 	gda-data-proxy.h \
 	gda-data-select.h \
@@ -98,7 +97,6 @@
 	gda-data-model-dsn-list.h \
 	gda-data-model-import.c \
 	gda-data-model-iter.c \
-	gda-data-model-query.c \
 	gda-data-access-wrapper.c \
 	gda-data-proxy.c \
 	gda-data-select.c \

Modified: trunk/libgda/gda-data-model-iter.c
==============================================================================
--- trunk/libgda/gda-data-model-iter.c	(original)
+++ trunk/libgda/gda-data-model-iter.c	Tue Sep 23 18:38:57 2008
@@ -50,6 +50,7 @@
 /* follow model changes */
 static void model_row_updated_cb (GdaDataModel *model, gint row, GdaDataModelIter *iter);
 static void model_row_removed_cb (GdaDataModel *model, gint row, GdaDataModelIter *iter);
+static void model_reset_cb (GdaDataModel *model, GdaDataModelIter *iter);
 
 static GError *validate_holder_change_cb (GdaSet *paramlist, GdaHolder *param, const GValue *new_value);
 static void holder_attr_changed_cb (GdaSet *paramlist, GdaHolder *param);
@@ -81,7 +82,7 @@
 struct _GdaDataModelIterPrivate
 {
 	GdaDataModel          *data_model;
-	gulong                 model_changes_signals[2];
+	gulong                 model_changes_signals[3];
 	gboolean               keep_param_changes;
 	gint                   row; /* -1 if row is unknown */
 };
@@ -185,6 +186,7 @@
 	iter->priv->row = -1;
 	iter->priv->model_changes_signals[0] = 0;
 	iter->priv->model_changes_signals[1] = 0;
+	iter->priv->model_changes_signals[2] = 0;
 	iter->priv->keep_param_changes = FALSE;
 }
 
@@ -221,6 +223,14 @@
 	}
 }
 
+static void
+model_reset_cb (GdaDataModel *model, GdaDataModelIter *iter)
+{
+	/* reset the iter to before the 1st row */
+	gda_data_model_iter_invalidate_contents (iter);
+	gda_data_model_iter_move_at_row (iter, -1);
+}
+
 /*
  * This function is called when a parameter in @paramlist is changed
  * to make sure the change is propagated to the GdaDataModel
@@ -252,7 +262,7 @@
 			}
 		}
 		else if (! gda_data_model_set_value_at ((GdaDataModel *) iter->priv->data_model, 
-							col, iter->priv->row, gda_holder_get_value (param), &error)) {
+							col, iter->priv->row, new_value, &error)) {
 			if (!error)
 				g_set_error (&error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
 					     _("GdaDataModel refused value change"));
@@ -321,6 +331,7 @@
 		if (iter->priv->data_model) { 
 			g_signal_handler_disconnect (iter->priv->data_model, iter->priv->model_changes_signals [0]);
 			g_signal_handler_disconnect (iter->priv->data_model, iter->priv->model_changes_signals [1]);
+			g_signal_handler_disconnect (iter->priv->data_model, iter->priv->model_changes_signals [2]);
 			g_object_remove_weak_pointer (G_OBJECT (iter->priv->data_model), 
 						      (gpointer*) &(iter->priv->data_model));
 			iter->priv->data_model = NULL;
@@ -496,6 +507,7 @@
 					return;
 				g_signal_handler_disconnect (iter->priv->data_model, iter->priv->model_changes_signals [0]);
 				g_signal_handler_disconnect (iter->priv->data_model, iter->priv->model_changes_signals [1]);
+				g_signal_handler_disconnect (iter->priv->data_model, iter->priv->model_changes_signals [2]);
 				g_object_remove_weak_pointer (G_OBJECT (iter->priv->data_model), 
 							      (gpointer*) &(iter->priv->data_model)); 	
 			}
@@ -507,6 +519,8 @@
 										  G_CALLBACK (model_row_updated_cb), iter);
 			iter->priv->model_changes_signals [1] = g_signal_connect (G_OBJECT (ptr), "row-removed",
 										  G_CALLBACK (model_row_removed_cb), iter);
+			iter->priv->model_changes_signals [2] = g_signal_connect (G_OBJECT (ptr), "reset",
+										  G_CALLBACK (model_reset_cb), iter);
 
 			if (GDA_IS_DATA_SELECT (iter->priv->data_model)) {
 				GdaStatement *sel_stmt;

Modified: trunk/libgda/gda-data-proxy.c
==============================================================================
--- trunk/libgda/gda-data-proxy.c	(original)
+++ trunk/libgda/gda-data-proxy.c	Tue Sep 23 18:38:57 2008
@@ -25,7 +25,7 @@
 #include "gda-data-model-array.h"
 #include "gda-data-model-extra.h"
 #include "gda-data-model-iter.h"
-#include "gda-data-model-query.h"
+#include "gda-data-select.h"
 #include "gda-holder.h"
 #include "gda-set.h"
 #include "gda-marshal.h"
@@ -1777,11 +1777,12 @@
 commit_row_modif (GdaDataProxy *proxy, RowModif *rm, gboolean adjust_display, GError **error)
 {
 	gboolean err = FALSE;
-	gint proxy_row;
+	gint proxy_row, model_row;
 	GError *lerror = NULL;
 
 	if (!rm)
 		return TRUE;
+	model_row = rm->model_row;
 
 	/* ensure that there is no sync to be done */
 	ensure_chunk_sync (proxy);
@@ -1921,12 +1922,7 @@
 					       gda_data_proxy_signals[ROW_CHANGES_APPLIED],
 					       0, proxy_row, -1);
 			}
-			else if ((proxy->priv->catched_inserted_row < 0) &&
-				 !GDA_IS_DATA_MODEL_QUERY (proxy->priv->model)) {
-				/* REM: the GdaDataModelQuery object does not emit any "row-inserted", "row-updated"
-				 * or "row_dremoved" signals but that is Ok as an exception: all the other data
-				 * model should be implemented correctly
-				 */
+			else if (proxy->priv->catched_inserted_row < 0) {
 				g_warning (_("Proxied data model reports the modifications as accepted, yet did not emit the "
 					     "corresponding \"row-inserted\", \"row-updated\" or \"row-removed\" signal. This "
 					     "is a bug of the %s's implementation (please report a bug)."),
@@ -1942,22 +1938,16 @@
 		/* signal row actually changed */
 		g_signal_emit (G_OBJECT (proxy),
 			       gda_data_proxy_signals[ROW_CHANGES_APPLIED],
-			       0, proxy_row, rm->model_row);
+			       0, proxy_row, model_row);
 		
 		/* get rid of the commited change; if the changes have been applied correctly, @rm should
 		 * have been removed from the proxy->priv->all_modifs list because the proxied model
 		 * should habe emitted the "row_{inserted,removed,updated}" signals */
 		if (rm && g_slist_find (proxy->priv->all_modifs, rm)) {
-			if (!GDA_IS_DATA_MODEL_QUERY (proxy->priv->model)) {
-				/* REM: the GdaDataModelQuery object does not emit any "row-inserted", "row-updated"
-				 * or "row_dremoved" signals but that is Ok as an exception: all the other data
-				 * model should be implemented correctly
-				 */
-				g_warning (_("Proxied data model reports the modifications as accepted, yet did not emit the "
-					     "corresponding \"row-inserted\", \"row-updated\" or \"row-removed\" signal. This "
-					     "is a bug of the %s's implementation (please report a bug)."),
-					   G_OBJECT_TYPE_NAME (proxy->priv->model));
-			}
+			g_warning (_("Proxied data model reports the modifications as accepted, yet did not emit the "
+				     "corresponding \"row-inserted\", \"row-updated\" or \"row-removed\" signal. This "
+				     "is a bug of the %s's implementation (please report a bug)."),
+				   G_OBJECT_TYPE_NAME (proxy->priv->model));
 			proxy->priv->new_rows = g_slist_remove (proxy->priv->new_rows, rm);
 			proxy->priv->all_modifs = g_slist_remove (proxy->priv->all_modifs, rm);
 			g_hash_table_remove (proxy->priv->modify_rows, GINT_TO_POINTER (rm->model_row));
@@ -3518,10 +3508,6 @@
 		return FALSE;
 	}
 
-#ifdef GDA_DEBUG_NO
-	gda_object_dump (proxy, 5);
-#endif
-
 	return TRUE;
 }
 

Modified: trunk/libgda/gda-data-select.c
==============================================================================
--- trunk/libgda/gda-data-select.c	(original)
+++ trunk/libgda/gda-data-select.c	Tue Sep 23 18:38:57 2008
@@ -72,6 +72,9 @@
         gint                    iter_row; /* G_MININT if at start, G_MAXINT if at end, "external" row number */
         GdaDataModelIter       *iter;
 
+	GdaStatement           *sel_stmt;
+	GdaSet                 *ext_params;
+	gboolean                reset_with_ext_params_change;
 	GdaDataModelAccessFlags usage_flags;
 	
 	/* attributes specific to data model modifications */
@@ -95,7 +98,8 @@
 	PROP_INS_QUERY,
 	PROP_UPD_QUERY,
 	PROP_DEL_QUERY,
-	PROP_SEL_STMT
+	PROP_SEL_STMT,
+	PROP_RESET_WITH_EXT_PARAM
 };
 
 /* module error */
@@ -132,6 +136,8 @@
 static GdaStatement *compute_single_select_stmt (GdaDataSelect *model, GError **error);
 static gint *compute_insert_select_params_mapping (GdaSet *sel_params, GdaSet *ins_values, GdaSqlExpr *row_cond);
 
+static void ext_params_holder_changed_cb (GdaSet *paramlist, GdaHolder *param, GdaDataSelect *model);
+
 
 /* GdaDataModel interface */
 static void                 gda_data_select_data_model_init (GdaDataModelClass *iface);
@@ -253,6 +259,12 @@
 							      "SELECT statement which was executed to yield to the data model",
 							      GDA_TYPE_STATEMENT, G_PARAM_READABLE));
 
+	g_object_class_install_property (object_class, PROP_RESET_WITH_EXT_PARAM,
+					 g_param_spec_boolean ("auto-reset", "Automatically reset itself",
+							       "Automatically re-run the SELECT statement if any parameter "
+							       "has chanegd since it was first executed", FALSE,
+							       G_PARAM_READABLE | G_PARAM_WRITABLE));
+
 	/* virtual functions */
 	object_class->dispose = gda_data_select_dispose;
 	object_class->finalize = gda_data_select_finalize;
@@ -297,8 +309,13 @@
 	model->priv->index = g_hash_table_new (g_direct_hash, g_direct_equal);
 	model->prep_stmt = NULL;
 	model->priv->columns = NULL;
+	model->nb_stored_rows = 0;
 	model->advertized_nrows = -1; /* unknown number of rows */
 
+	model->priv->sel_stmt = NULL;
+	model->priv->ext_params = NULL;
+	model->priv->reset_with_ext_params_change = FALSE;
+
 	model->priv->iter_row = G_MININT;
         model->priv->iter = NULL;
 
@@ -319,6 +336,94 @@
 }
 
 static void
+ext_params_holder_changed_cb (GdaSet *paramlist, GdaHolder *param, GdaDataSelect *model)
+{
+	if (model->priv->reset_with_ext_params_change) {
+		GdaDataSelect *new_model;
+		GdaStatement *select;
+		GError *error = NULL;
+
+		select = check_acceptable_statement (model, &error);
+		if (!select) {
+			g_warning (_("Could not re-run SELECT statement: %s"),
+				   error && error->message ? error->message : _("No detail"));
+			if (error)
+				g_error_free (error);
+			return;
+		}
+		g_assert (model->prep_stmt);
+		GType *types = NULL;
+		if (model->prep_stmt->types) {
+			types = g_new (GType, model->prep_stmt->ncols + 1);
+			memcpy (types, model->prep_stmt->types, sizeof (GType) * model->prep_stmt->ncols);
+			types [model->prep_stmt->ncols] = G_TYPE_NONE;
+		}
+		new_model = (GdaDataSelect*) gda_connection_statement_execute_select_full (model->priv->cnc, select, 
+											   model->priv->ext_params, 
+											   model->priv->usage_flags,
+											   types, 
+											   &error);
+		g_free (types);
+		if (!new_model) {
+			g_warning (_("Could not re-run SELECT statement: %s"),
+				   error && error->message ? error->message : _("No detail"));
+			if (error)
+				g_error_free (error);
+			return;
+		}
+
+		g_assert (G_OBJECT_TYPE (model) == G_OBJECT_TYPE (new_model));
+
+		/* Raw model and new_model contents swap (except for the GObject part) */
+		GTypeQuery tq;
+		gpointer copy;
+		gint offset = sizeof (GObject);
+		gint size;
+		g_type_query (G_OBJECT_TYPE (model), &tq);
+		size = tq.instance_size - offset;
+		copy = g_malloc (size);
+		memcpy (copy, (gint8*) new_model + offset, size);
+		memcpy ((gint8*) new_model + offset, (gint8*) model + offset, size);
+		memcpy ((gint8*) model + offset, copy, size);
+		
+		/* we need to keep some data from the old model */
+		GdaDataSelect *old_model = new_model; /* renamed for code's readability */
+		GdaDataSelectInternals *mi;
+	      
+		model->priv->reset_with_ext_params_change = old_model->priv->reset_with_ext_params_change;
+		mi = old_model->priv->modif_internals;
+		old_model->priv->modif_internals = model->priv->modif_internals;
+		model->priv->modif_internals = mi;
+
+		copy = old_model->priv->sel_stmt;
+		old_model->priv->sel_stmt = model->priv->sel_stmt;
+		model->priv->sel_stmt = (GdaStatement*) copy;
+
+		g_object_unref (old_model);
+
+		/* copy all the param's holders' values from model->priv->ext_params to 
+		   to model->priv->modif_internals->exec_set */
+		GSList *list;
+		for (list = model->priv->ext_params->holders; list; list = list->next) {
+			GdaHolder *h;
+			h = gda_set_get_holder (model->priv->modif_internals->exec_set,
+						gda_holder_get_id (list->data));
+			if (h) 
+				if (! gda_holder_set_value (h, gda_holder_get_value (GDA_HOLDER (list->data)), &error)) {
+					g_warning (_("An error has occurred, the value returned by the \"exec-params\" "
+						     "property will be wrong: %s"),
+						   error && error->message ? error->message : _("No detail"));
+					if (error)
+						g_error_free (error);
+				}
+		}
+
+		/* signal a reset */
+		gda_data_model_reset ((GdaDataModel*) model);
+	}
+}
+
+static void
 gda_data_select_dispose (GObject *object)
 {
 	GdaDataSelect *model = (GdaDataSelect *) object;
@@ -329,6 +434,18 @@
 	if (model->priv) {
 		gint i;
 
+		if (model->priv->sel_stmt) {
+			g_object_unref (model->priv->sel_stmt);
+			model->priv->sel_stmt = NULL;
+		}
+
+		if (model->priv->ext_params) {
+			g_signal_handlers_disconnect_by_func (model->priv->ext_params,
+							      G_CALLBACK (ext_params_holder_changed_cb), model);
+			g_object_unref (model->priv->ext_params);
+			model->priv->ext_params = NULL;
+		}
+
 		if (model->priv->modif_internals) {
 			_gda_data_select_internals_free (model->priv->modif_internals);
 			model->priv->modif_internals = NULL;
@@ -513,8 +630,14 @@
 			if (model->prep_stmt)
 				g_object_unref (model->prep_stmt);
 			model->prep_stmt = g_value_get_object (value);
-			if (model->prep_stmt)
+			if (model->prep_stmt) {
+				GdaStatement *sel_stmt;
 				g_object_ref (model->prep_stmt);
+				sel_stmt = gda_pstmt_get_gda_statement (model->prep_stmt);
+				if (sel_stmt &&
+				    gda_statement_get_statement_type (sel_stmt) == GDA_SQL_STATEMENT_SELECT) 
+					model->priv->sel_stmt = gda_statement_copy (sel_stmt);
+			}
 			create_columns (model);
 			break;
 		case PROP_FLAGS: {
@@ -539,8 +662,12 @@
 		case PROP_PARAMS: {
 			GdaSet *set;
 			set = g_value_get_object (value);
-			if (set) 
+			if (set) {
+				model->priv->ext_params = g_object_ref (set);
+				g_signal_connect (model->priv->ext_params, "holder-changed",
+						  G_CALLBACK (ext_params_holder_changed_cb), model);
 				model->priv->modif_internals->exec_set = gda_set_copy (set);
+			}
 			break;
 		}
 		case PROP_INS_QUERY:
@@ -564,6 +691,9 @@
 			if (model->priv->modif_internals->modif_stmts [UPD_QUERY])
 				g_object_ref (model->priv->modif_internals->modif_stmts [UPD_QUERY]);
 			break;
+		case PROP_RESET_WITH_EXT_PARAM:
+			model->priv->reset_with_ext_params_change = g_value_get_boolean (value);
+			break;
 		default:
 			break;
 		}
@@ -612,6 +742,9 @@
 		case PROP_SEL_STMT: 
 			g_value_set_object (value, check_acceptable_statement (model, NULL));
 			break;
+		case PROP_RESET_WITH_EXT_PARAM:
+			g_value_set_boolean (value, model->priv->reset_with_ext_params_change);
+			break;
 		default:
 			break;
 		}
@@ -808,6 +941,10 @@
 check_acceptable_statement (GdaDataSelect *model, GError **error)
 {
 	GdaStatement *sel_stmt;
+
+	if (model->priv->sel_stmt)
+		return model->priv->sel_stmt;
+
 	if (! model->prep_stmt) {
 		g_set_error (error, GDA_DATA_SELECT_ERROR, GDA_DATA_SELECT_MODIFICATION_STATEMENT_ERROR,
 			     _("Internal error: the \"prepared-stmt\" property has not been set"));
@@ -817,7 +954,7 @@
 	sel_stmt = gda_pstmt_get_gda_statement (model->prep_stmt);
 	if (! sel_stmt) {
 		g_set_error (error, GDA_DATA_SELECT_ERROR, GDA_DATA_SELECT_MODIFICATION_STATEMENT_ERROR,
-			     _("Internal error: can't get the prepared statement's actual statement"));
+			     _("Can't get the prepared statement's actual statement"));
 		return NULL;
 	}
 
@@ -827,7 +964,8 @@
 		return NULL;
 	}
 
-	return sel_stmt;
+	model->priv->sel_stmt = gda_statement_copy (sel_stmt);
+	return model->priv->sel_stmt;
 }
 
 /**
@@ -2020,13 +2158,7 @@
 	GdaSqlStatement *sel_sqlst;
 	GdaSqlExpr *row_cond = NULL;
 
-	if (! model->prep_stmt) {
-		g_set_error (error, GDA_DATA_SELECT_ERROR, GDA_DATA_SELECT_MODIFICATION_STATEMENT_ERROR,
-			     _("Internal error: the \"prepared-stmt\" property has not been set"));
-		return NULL;
-	}
-
-	sel_stmt = gda_pstmt_get_gda_statement (model->prep_stmt);
+	sel_stmt = model->priv->sel_stmt;
 	if (! sel_stmt) {
 		g_set_error (error, GDA_DATA_SELECT_ERROR, GDA_DATA_SELECT_MODIFICATION_STATEMENT_ERROR,
 			     _("Internal error: can't get the prepared statement's actual statement"));
@@ -2481,9 +2613,9 @@
  
 	ncols = gda_data_select_get_n_columns (model);
 	nvalues = g_list_length (values);
-	if (nvalues >= ncols) {
+	if (nvalues > ncols) {
 		g_set_error (error, GDA_DATA_SELECT_ERROR, GDA_DATA_SELECT_MISSING_MODIFICATION_STATEMENT_ERROR,
-			     _("Too many values (%d as maximum)"), ncols-1);
+			     _("Too many values (%d as maximum)"), ncols);
 		return FALSE;
 	}
 

Modified: trunk/libgda/libgda.h.in
==============================================================================
--- trunk/libgda/libgda.h.in	(original)
+++ trunk/libgda/libgda.h.in	Tue Sep 23 18:38:57 2008
@@ -35,7 +35,6 @@
 #include <libgda/gda-data-comparator.h>
 #include <libgda/gda-data-model-array.h>
 @LIBGDA_BDB_INC@
-#include <libgda/gda-data-model-query.h>
 #include <libgda/gda-data-model.h>
 #include <libgda/gda-data-model-iter.h>
 #include <libgda/gda-data-model-import.h>

Modified: trunk/libgda/providers-support/gda-pstmt.c
==============================================================================
--- trunk/libgda/providers-support/gda-pstmt.c	(original)
+++ trunk/libgda/providers-support/gda-pstmt.c	Tue Sep 23 18:38:57 2008
@@ -215,7 +215,10 @@
  * gda_pstmt_get_gda_statement
  * @pstmt: a #GdaPStmt object
  *
- * Get a pointer to the #GdaStatement which led to the creation of this prepared statement
+ * Get a pointer to the #GdaStatement which led to the creation of this prepared statement.
+ * 
+ * Note: if that statement has been modified since the creation of @pstmt, then this method
+ * will return %NULL
  *
  * Returns: the #GdaStatement
  */

Modified: trunk/libgda/sqlite/gda-sqlite-recordset.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-recordset.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-recordset.c	Tue Sep 23 18:38:57 2008
@@ -222,7 +222,7 @@
 					if (i >= _GDA_PSTMT (ps)->ncols)
 						g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
 							   _GDA_PSTMT (ps)->ncols - 1);
-					else
+					else 
 						_GDA_PSTMT (ps)->types [i] = col_types [i];
 				}
 			}
@@ -238,6 +238,8 @@
 			gda_column_set_title (column, sqlite3_column_name (ps->sqlite_stmt, i));
 			gda_column_set_name (column, sqlite3_column_name (ps->sqlite_stmt, i));
 			gda_column_set_dbms_type (column, sqlite3_column_decltype (ps->sqlite_stmt, i));
+			if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
+				gda_column_set_g_type (column, _GDA_PSTMT (ps)->types [i]);
 		}
         }
 

Modified: trunk/libgda/sqlite/gda-sqlite-recordset.h
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-recordset.h	(original)
+++ trunk/libgda/sqlite/gda-sqlite-recordset.h	Tue Sep 23 18:38:57 2008
@@ -44,7 +44,7 @@
 
 struct _GdaSqliteRecordset {
 	GdaDataSelect                  model;
-	GdaSqliteRecordsetPrivate *priv;
+	GdaSqliteRecordsetPrivate     *priv;
 };
 
 struct _GdaSqliteRecordsetClass {

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Tue Sep 23 18:38:57 2008
@@ -11,7 +11,6 @@
 libgda/gda-data-model-dsn-list.c
 libgda/gda-data-model-import.c
 libgda/gda-data-model-iter.c
-libgda/gda-data-model-query.c
 libgda/gda-data-proxy.c
 libgda/gda-data-select.c
 libgda/gda-easy.c

Modified: trunk/tests/data-models/Makefile.am
==============================================================================
--- trunk/tests/data-models/Makefile.am	(original)
+++ trunk/tests/data-models/Makefile.am	Tue Sep 23 18:38:57 2008
@@ -7,8 +7,8 @@
 	-DTOP_SRC_DIR=\""$(top_srcdir)"\" \
 	-DTOP_BUILD_DIR=\""$(top_builddir)"\"
 
-check_PROGRAMS = check_model_import check_virtual check_data_proxy check_model_copy check_pmodel check_model_query
-TESTS = check_model_import check_virtual check_data_proxy check_model_copy check_pmodel check_model_query
+check_PROGRAMS = check_model_import check_virtual check_data_proxy check_model_copy check_pmodel
+TESTS = check_model_import check_virtual check_data_proxy check_model_copy check_pmodel
 
 common_sources = 
 
@@ -43,14 +43,6 @@
 	$(top_builddir)/tests/libgda-test-4.0.la \
 	$(LIBGDA_LIBS)
 
-check_model_query_SOURCES = $(common_sources) check_model_query.c
-check_model_query_CFLAGS = \
-	-I$(top_srcdir)/libgda/sqlite
-check_model_query_LDADD = \
-	$(top_builddir)/libgda/libgda-4.0.la \
-	$(top_builddir)/tests/libgda-test-4.0.la \
-	$(LIBGDA_LIBS)
-
 EXTRA_DIST = \
 	check_virtual.csv \
 	city.csv \
@@ -61,4 +53,4 @@
 	pmodel_data_locations.xml
 
 CLEANFILES = \
-	pmodel.db modelquery.db pmodel.db-journal modelquery.db-journal
+	pmodel.db pmodel.db-journal

Modified: trunk/tests/data-models/check_pmodel.c
==============================================================================
--- trunk/tests/data-models/check_pmodel.c	(original)
+++ trunk/tests/data-models/check_pmodel.c	Tue Sep 23 18:38:57 2008
@@ -22,10 +22,10 @@
 } SigEvent;
 static GSList *signals = NULL;
 static void     monitor_model_signals (GdaDataModel *model);
-static void     signal_callback (GdaDataModel *model, gint row, gchar *type);
 static void     clear_signals (void);
 static gboolean check_expected_signal (GdaDataModel *model, gchar type, gint row);
 static gboolean check_no_expected_signal (GdaDataModel *model);
+static gboolean compare_data_models (GdaDataModel *model1, GdaDataModel *model2, GError **error);
 
 /* utility functions */
 static GdaConnection *setup_connection (void);
@@ -57,9 +57,10 @@
 static gint test12 (GdaConnection *cnc);
 static gint test13 (GdaConnection *cnc);
 static gint test14 (GdaConnection *cnc);
+static gint test15 (GdaConnection *cnc);
 
 TestFunc tests[] = {
-        test1,
+	test1,
         test2,
         test3,
 	test4,
@@ -72,7 +73,8 @@
 	test11,
 	test12,
 	test13,
-	test14
+	test14,
+	test15
 };
 
 int
@@ -1554,6 +1556,84 @@
 }
 
 /*
+ * - Create a GdaDataSelect with a missing parameter
+ * - Set modification statements
+ * - Refresh data model and compare with direct SELECT.
+ *
+ * Returns the number of failures 
+ */
+static gint
+test15 (GdaConnection *cnc)
+{
+	GError *error = NULL;
+        GdaDataModel *model, *rerun;
+        GdaStatement *stmt;
+        GdaSet *params;
+        gint nfailed = 0;
+
+	clear_signals ();
+
+        /* create GdaDataModelQuery */
+        stmt = stmt_from_string ("SELECT * FROM customers WHERE id <= ##theid::gint");
+        g_assert (gda_statement_get_parameters (stmt, &params, NULL));
+
+	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;
+        }
+        model = gda_connection_statement_execute_select (cnc, stmt, params, &error);
+        g_assert (model);
+
+	monitor_model_signals (model);
+
+	/**/
+	g_object_set_data (G_OBJECT (model), "mydata", "hey");
+
+	/**/
+	g_object_set (G_OBJECT (model), "auto-reset", TRUE, NULL);
+	if (! gda_set_set_holder_value (params, &error, "theid", 3)) {
+                nfailed++;
+#ifdef CHECK_EXTRA_INFO
+                g_print ("Can't set 'theid' value: %s \n",
+                         error && error->message ? error->message : "No detail");
+#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;
+	}
+
+	rerun = gda_connection_statement_execute_select (cnc, stmt, params, &error);
+	g_assert (rerun);
+	if (! compare_data_models (model, rerun, NULL)) {
+                nfailed++;
+#ifdef CHECK_EXTRA_INFO
+                g_print ("Data model differs after a refresh\n");
+#endif
+                goto out;
+        }
+        g_object_unref (rerun);
+
+ out:
+        g_object_unref (model);
+        g_object_unref (stmt);
+
+        return nfailed;
+}
+
+/*
  * Checking value function:
  *  - reads the value of @model at the provided column and row and compares with the expected @set_value
  *  - if @stmt is not NULL, then re-run the statement and compares with @model
@@ -1826,14 +1906,6 @@
  * signals checking 
  */
 static void
-monitor_model_signals (GdaDataModel *model)
-{
-	g_signal_connect (model, "row-updated", G_CALLBACK (signal_callback), "U");
-	g_signal_connect (model, "row-removed", G_CALLBACK (signal_callback), "D");
-	g_signal_connect (model, "row-inserted", G_CALLBACK (signal_callback), "I");
-}
-
-static void
 signal_callback (GdaDataModel *model, gint row, gchar *type)
 {
 	SigEvent *se;
@@ -1850,6 +1922,32 @@
 }
 
 static void
+signal_callback_1 (GdaDataModel *model, gchar *type)
+{
+	SigEvent *se;
+	se = g_new0 (SigEvent, 1);
+	se->model = model;
+	se->type = *type;
+	se->row = -1;
+	signals = g_slist_append (signals, se);
+#ifdef CHECK_EXTRA_INFO
+	g_print ("Received '%s' signal from model %p\n",
+		 *type == 'R' ? "reset" : "???",
+		 model);
+#endif
+}
+
+static void
+monitor_model_signals (GdaDataModel *model)
+{
+	g_signal_connect (model, "row-updated", G_CALLBACK (signal_callback), "U");
+	g_signal_connect (model, "row-removed", G_CALLBACK (signal_callback), "D");
+	g_signal_connect (model, "row-inserted", G_CALLBACK (signal_callback), "I");
+	g_signal_connect (model, "reset", G_CALLBACK (signal_callback_1), "R");
+}
+
+
+static void
 clear_signals (void)
 {
 	if (signals) {
@@ -1876,13 +1974,48 @@
 	}
 #ifdef CHECK_EXTRA_INFO
 	else {
-		g_print ("Expected signal '%s' for row %d from model %p and got ",
-			 (type == 'I') ? "row-inserted" : ((type == 'D') ? "row-removed" : "row-updated"),
+		gchar *exp;
+		switch (type) {
+		case 'I':
+			exp = "row-inserted";
+			break;
+		case 'U':
+			exp = "row-updated";
+			break;
+		case 'D':
+			exp = "row-removed";
+			break;
+		case 'R':
+			exp = "reset";
+			break;
+		default:
+			exp = "???";
+			break;
+		}
+		g_print ("Expected signal '%s' for row %d from model %p and got ", exp,
 			 row, model);
-		if (se)
+		if (se) {
+			switch (se->type) {
+			case 'I':
+				exp = "row-inserted";
+				break;
+			case 'U':
+				exp = "row-updated";
+				break;
+			case 'D':
+				exp = "row-removed";
+				break;
+			case 'R':
+				exp = "reset";
+				break;
+			default:
+				exp = "???";
+				break;
+			}
 			g_print ("signal '%s' for row %d from model %p\n",
-				 (se->type == 'I') ? "row-inserted" : ((se->type == 'D') ? "row-removed" : "row-updated"),
+				 exp,
 				 se->row, se->model);
+		}
 		else
 			g_print ("no signal\n");
 	}
@@ -1912,3 +2045,41 @@
 
 	return TRUE;
 }
+
+static gboolean
+compare_data_models (GdaDataModel *model1, GdaDataModel *model2, GError **error)
+{
+        GdaDataComparator *cmp;
+        GError *lerror = NULL;
+        cmp = (GdaDataComparator*) gda_data_comparator_new (model1, model2);
+        if (! gda_data_comparator_compute_diff (cmp, &lerror)) {
+#ifdef CHECK_EXTRA_INFO
+                g_print ("Could not compute the data model differences: %s\n",
+                         lerror && lerror->message ? lerror->message : "No detail");
+		g_print ("Model1 is:\n");
+                gda_data_model_dump (model1, stdout);
+                g_print ("Model2 is:\n");
+                gda_data_model_dump (model2, stdout);
+#endif
+                goto onerror;
+        }
+        if (gda_data_comparator_get_n_diffs (cmp) != 0) {
+#ifdef CHECK_EXTRA_INFO
+                g_print ("There are some differences when comparing data models...\n");
+                g_print ("Model1 is:\n");
+                gda_data_model_dump (model1, stdout);
+                g_print ("Model2 is:\n");
+                gda_data_model_dump (model2, stdout);
+#endif
+		g_set_error (&lerror, 0, 0,
+			     "There are some differences when comparing data models...");
+                goto onerror;
+        }
+        g_object_unref (cmp);
+
+        return TRUE;
+
+ onerror:
+        g_propagate_error (error, lerror);
+        return FALSE;
+}



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