libgda r3312 - in trunk: . doc/C doc/C/tmpl libgda libgda-report/engine libgda/sql-parser libgda/sqlite samples/Report



Author: vivien
Date: Tue Feb  3 19:19:32 2009
New Revision: 3312
URL: http://svn.gnome.org/viewvc/libgda?rev=3312&view=rev

Log:
2009-02-03  Vivien Malerba <malerba gnome-db org>

	* doc/C: doc fixes, for bug #570315
	* libgda/sql-parser/gda-sql-parser.c: allow more characters in parameter names
	* libgda-report/engine/gda-report-engine.c:
	* samples/Report/customers-report-spec.xml:
	* samples/Report/customers-report-rml.rml: changed the syntax of parameters
	to avoid SQL parsing confusions (replace "/@" by "|@", "/#" by "|#" and
	"/%nrows" by "|?nrows")
	* libgda/sqlite/gda-sqlite-recordset.c: debug messages
	* libgda/gda-data-select.c: applied patch for bug #570251 (thanks Armin)
	* libgda/gda-data-model.c: avoid calling twice g_set_error() on the same
	GError
	* libgda/gda-connection.c: only show database objects which are visible by
	default in gda_connection_get_meta_store_data(), fixes bug #570396


Modified:
   trunk/ChangeLog
   trunk/doc/C/libgda-4.0-docs.sgml
   trunk/doc/C/libgda-4.0-sections.txt
   trunk/doc/C/migration2.xml
   trunk/doc/C/tmpl/gda-report-document.sgml
   trunk/doc/C/tmpl/gda-report-engine.sgml
   trunk/libgda-report/engine/gda-report-engine.c
   trunk/libgda/gda-connection.c
   trunk/libgda/gda-data-model.c
   trunk/libgda/gda-data-select.c
   trunk/libgda/sql-parser/gda-sql-parser.c
   trunk/libgda/sqlite/gda-sqlite-recordset.c
   trunk/samples/Report/customers-report-rml.rml
   trunk/samples/Report/customers-report-spec.xml

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 Feb  3 19:19:32 2009
@@ -1227,6 +1227,65 @@
 	<link linkend="GdaReportRmlDocument">GdaReportRmlDocument</link> which both offer high level of
 	features when dealing with those XML dialects.
       </para>
+      <para>
+	From a programmer's point of view, the following code example shows how to convert the "report-spec.xml" file
+	to a "report.xml" report:
+	<programlisting>
+GdaConnection *cnc;
+GdaReportEngine *eng
+xmlDocPtr doc;
+GError *error = NULL;
+
+cnc = gda_connection_open_from_dsn (...);
+eng = gda_report_engine_new_from_file ("report-spec.xml");
+gda_report_engine_declare_object (eng, G_OBJECT (cnc), "main_cnc");
+
+doc = gda_report_engine_run_as_doc (eng, &amp;error);
+if (!doc) {
+    /* ERROR */
+}
+else {
+    xmlSaveFile ("report.xml", doc);
+    xmlFreeDoc (doc);
+}
+g_object_unref (eng);
+	</programlisting>
+	For example the XML "report-spec.xml" file could be:
+	<programlisting><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd";>
+<article>
+  <articleinfo>
+    <title>Customers report example</title>
+    <abstract>
+      <!-- Use the "abstract" parameter which is supposed to be defined using gda_report_engine_declare_object() -->
+      <para><gda_report_param_value param_name="abstract"/></para>
+    </abstract>
+  </articleinfo>
+
+  <!-- 
+       Start a new section, with the "customers" SELECT query, which is supposed to be defined using 
+       gda_report_engine_declare_object() 
+
+       Any <gda_report_iter> node will repeat its contents as many times as there are rows in the
+       data model returned by the "customers" SELECT query.
+    -->
+  <gda_report_section query_name="customers" cnc_name="main_cnc">
+    <sect1>
+      <!-- Will be replaced by: <title>List of customers (5)</title> if there are 5 rows for example -->
+      <title>List of customers (<gda_report_param_value param_name="customers|?nrows"/>)</title>
+
+      <!-- List all the customer's names -->
+      <ul>
+	<gda_report_iter>
+	  <li><gda_report_param_value param_name="customers|@name"/></li>
+	</gda_report_iter>
+      </ul>
+    </sect1>
+  </gda_report_section>
+</article>]]></programlisting>
+	For a more detailled example, have a look at the <filename class="directory">samples/Report</filename> of &LIBGDA;'s
+	sources.
+	</para>
     </chapter>
     <chapter>
       <title>API reference</title>

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 Feb  3 19:19:32 2009
@@ -915,6 +915,7 @@
 <SECTION>
 <FILE>gda-report-engine</FILE>
 <TITLE>GdaReportEngine</TITLE>
+<INCLUDE>gda-report-engine.h</INCLUDE>
 GdaReportEngine
 gda_report_engine_new
 gda_report_engine_new_from_string

Modified: trunk/doc/C/migration2.xml
==============================================================================
--- trunk/doc/C/migration2.xml	(original)
+++ trunk/doc/C/migration2.xml	Tue Feb  3 19:19:32 2009
@@ -6,7 +6,7 @@
 	<listitem><para>easier to understand and to use API, with less strange path usage (which were inherited
 	from modifications above modifications where no global coherence was adressed)</para></listitem>
 	<listitem><para>reduce the size of the library (now 1.3M compared to 1.7M once stripped) and the number of symbols 
-	    (860 compared to 1420) and have less complicated and thus more maintanable code (190 files compared to 250).
+	    (845 compared to 1420) and have less complicated and thus more maintanable code (190 files compared to 250).
 	</para></listitem>
 	<listitem><para>removal of the GdaClient object from which connections were created: this object did not offer
 	    any significant features and made the API more difficult to use</para></listitem>
@@ -84,6 +84,23 @@
 	    translated into INSERT, UPDATE or DELETE statements).</para></listitem>
       </itemizedlist>
     </para>
+  </sect1> 
+
+<sect1 id="migration-2-report"><title>Reports</title>
+    <para>
+      &LIBGDA;'s reports API has not changed, but the syntax of the XML nodes specific to &LIBGDA; (those nodes are
+      replaced by contents when the report is generated) has changed:
+      <itemizedlist>
+	<listitem><para>The parameter name to acces a data model's column name by its name 
+	    is now &lt;query_name&gt;|@&lt;column_name&gt;
+	    instead of &lt;query_name&gt;/@&lt;column_name&gt;</para></listitem>
+	<listitem><para>The parameter name to acces a data model's column name by its index
+	    is now &lt;query_name&gt;|#&lt;column_index&gt;
+	    instead of &lt;query_name&gt;/#&lt;column_index&gt;</para></listitem>
+	<listitem><para>The parameter name to acces the total number of rows of a data model is now
+	    &lt;query_name&gt;|?nrows instead of &lt;query_name&gt;/%nrows</para></listitem>
+      </itemizedlist>
+    </para>
   </sect1>  
 
   <sect1><title>Other changes</title>

Modified: trunk/doc/C/tmpl/gda-report-document.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-report-document.sgml	(original)
+++ trunk/doc/C/tmpl/gda-report-document.sgml	Tue Feb  3 19:19:32 2009
@@ -2,11 +2,12 @@
 GdaReportDocument
 
 <!-- ##### SECTION Short_Description ##### -->
-
+Report document
 
 <!-- ##### SECTION Long_Description ##### -->
 <para>
-
+  The #GdaReportDocument wraps the usage of a #GdaReportEngine for specific HTML or PDF targets. This class is
+  abstract (no instance be created directly), and one of its subclasses has to be used.
 </para>
 
 <!-- ##### SECTION See_Also ##### -->

Modified: trunk/doc/C/tmpl/gda-report-engine.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-report-engine.sgml	(original)
+++ trunk/doc/C/tmpl/gda-report-engine.sgml	Tue Feb  3 19:19:32 2009
@@ -6,9 +6,9 @@
 
 <!-- ##### SECTION Long_Description ##### -->
 <para>
-The #GdaReportEngine object generates a report based on a specifications file in any XML format. It browses
-through the XML file and replaces some parts of it depending on some &lt;gda_report...&gt; nodes. The generated
-XML file may then need to be processed using other post-processor tools depending on the XML file format.
+  The #GdaReportEngine object generates a report based on a specifications file in any XML format. It browses
+  through the XML file and replaces the parts of it which are &lt;gda_report...&gt; action nodes. The generated
+  XML file may then need to be processed using other post-processor tools depending on the XML file format.
 </para>
 <para>
   The following "action" tags known are:
@@ -29,13 +29,24 @@
 	    <para>Starts a section which runs a SELECT query to generate a data model (#GdaDataModel).
 	    </para>
 	    <para>
-	      A parameter named &quot;&lt;query_name&gt;/%%nrows&quot; is created and is available in any sub node
+	      A parameter named &quot;&lt;query_name&gt;|?nrows&quot; is created and is available in any sub node
 	      of the &lt;gda_report_section&gt; node, which contains the number of rows in the section's data model.
 	    </para>
 	  </entry>
-          <entry>"query_name": the name of a SELECT #GdaQuery to be run; using this attribute implies that a GdaQuery has
-	    already been created and that the query has been declared to the GdaReportEngine object with the "query_name "name. 
-	    To define a query within the report spec., add a &lt;gda_report_query&gt; sub node instead</entry>
+          <entry>
+	    <itemizedlist>
+	      <listitem><para>"query_name": the name of a SELECT #GdaStatement to be run; using this attribute
+		  implies that a GdaStatement has
+		  already been created and that the query has been declared to the GdaReportEngine object
+		  with the "query_name "name. 
+		  To define a query within the report spec., add a &lt;gda_report_query&gt;
+		  sub node instead
+	      </para></listitem>
+	      <listitem><para>"cnc_name": name of the connection to use (the #GdaConnection object has
+		  already been created and has been declared to the GdaReportEngine object with the "cnc_name" name)
+	      </para></listitem>
+	    </itemizedlist>
+	  </entry>
           <entry>
 	    <itemizedlist>
 	      <listitem><para>&lt;gda_report_query&gt; to define the SELECT query which will be run. It is also
@@ -56,9 +67,9 @@
 	    </para>
 	    <para>
 	      For each column of the data model, several parameters are created, named 
-	      &lt;query_name&gt;/@&lt;column_name&gt; (such as &quot;customers/@@name&quot; for the &quot;name&quot; column)
-	      and &lt;query_name&gt;/#&lt;column_number&gt;,
-	      (such as &quot;customers/##0&quot; for the first column). 
+	      &lt;query_name&gt;|@&lt;column_name&gt; (such as &quot;customers|@@name&quot; for the &quot;name&quot; column)
+	      and &lt;query_name&gt;|#&lt;column_number&gt;,
+	      (such as &quot;customers|##0&quot; for the first column). 
 	      Those parameters can be used in any child node (recusively),
 	      and have their value updated for each row of the data model.
 	      For more information about the parameter's syntax, 
@@ -77,11 +88,7 @@
 	      <listitem><para>"cnc_name": name of the connection to use (the #GdaConnection object has
 		  already been created and has been declared to the GdaReportEngine object with the "cnc_name" name)
 	      </para></listitem>
-	      <listitem><para>"dict_name": name of the dictionary object to use (the #GdaDict object has
-		  already been created and has been declared to the GdaReportEngine object with the "dict_name" name)
-	      </para></listitem>
 	    </itemizedlist>
-	    Note that the "query_name" attribute is mandatory and that one of "cnc_name" and "dict_name" must be specified.
 	  </entry>
           <entry></entry>
         </row>
@@ -98,9 +105,9 @@
 	  and can contain any reference to any parameter. For example the node:
 	    <programlisting><![CDATA[
 <gda_report_expr>
-##customers/@col IS NULL
+##customers|@col IS NULL
 </gda_report_expr>]]></programlisting>
-	    will return a TRUE value if the parameter named &quot;customers/@@col&quot; is not NULL. For more
+	    will return a TRUE value if the parameter named &quot;customers|@@col&quot; is not NULL. For more
 	    information about the parameter's syntax, see the <link linkend="SQL_queries">GDA SQL query syntax</link>.
 	  </entry>
           <entry></entry>

Modified: trunk/libgda-report/engine/gda-report-engine.c
==============================================================================
--- trunk/libgda-report/engine/gda-report-engine.c	(original)
+++ trunk/libgda-report/engine/gda-report-engine.c	Tue Feb  3 19:19:32 2009
@@ -31,6 +31,7 @@
 #include <libgda/gda-data-handler.h>
 #include <virtual/libgda-virtual.h>
 #include <sql-parser/gda-sql-parser.h>
+#include <sql-parser/gda-sql-statement.h>
 
 #include <libgda/handlers/gda-handler-boolean.h>
 #include <libgda/handlers/gda-handler-numerical.h>
@@ -437,6 +438,7 @@
 static gboolean command_gda_report_if (GdaReportEngine *engine, xmlNodePtr node, GSList **created_nodes,
 				       RunContext *context, GError **error);
 
+static GdaStatement *rewrite_statement (GdaReportEngine *engine, RunContext *context, GdaStatement *stmt, GError **error);
 static gboolean assign_parameters_values (GdaReportEngine *engine, RunContext *context, GdaSet *plist, GError **error);
 static GValue *evaluate_expression (GdaReportEngine *engine, RunContext *context, const gchar *expr, GError **error);
 static xmlNodePtr value_to_node (GdaReportEngine *engine, RunContext *context, const GValue *value);
@@ -724,18 +726,26 @@
 {
 	GdaDataModel *model;
 	GdaSet *plist;
+	GdaStatement *lstmt;
+	lstmt = rewrite_statement (engine, context, stmt, error);
+	if (!lstmt)
+		return NULL;
 
 	g_assert (cnc);
-	if (!gda_statement_get_parameters (stmt, &plist, error)) 
+	if (!gda_statement_get_parameters (lstmt, &plist, error)) {
+		g_object_unref (lstmt);
 		return NULL;
+	}
 
 	if (plist && !assign_parameters_values (engine, context, plist, error)) {
 		g_object_unref (plist);
+		g_object_unref (lstmt);
 		return NULL;
 	}
-	model = gda_connection_statement_execute_select (cnc, stmt, plist, error);
+	model = gda_connection_statement_execute_select (cnc, lstmt, plist, error);
 	if (plist)
 		g_object_unref (plist);
+	g_object_unref (lstmt);
 	if (!model) 
 		return NULL;
 	g_object_set_data_full (G_OBJECT (model), "name", g_strdup (stmt_name), g_free);
@@ -753,7 +763,7 @@
 		return NULL;
 	}
 	gda_value_free (value);
-	name = g_strdup_printf ("%s/%%nrows", stmt_name);
+	name = g_strdup_printf ("%s|?nrows", stmt_name);
 	g_object_set_data_full (G_OBJECT (model), name, param, g_object_unref);
 	g_free (name);
 
@@ -926,6 +936,65 @@
 	return TRUE;
 }
 
+typedef struct {
+	GdaReportEngine *engine;
+	RunContext *context;
+} ForeachData;
+
+static gboolean
+rewrite_statement_foreach_func (GdaSqlAnyPart *node, ForeachData *fdata, GError **error)
+{
+	GdaSqlParamSpec *pspec;
+	if (!node) return TRUE;
+
+	if ((node->type == GDA_SQL_ANY_EXPR) &&
+	    (pspec = ((GdaSqlExpr*) node)->param_spec)) {
+		if (pspec->g_type != 0)
+			return TRUE;
+
+		GdaHolder *source_param;
+		source_param = run_context_find_param (fdata->engine, fdata->context, pspec->name);
+		if (!source_param) {
+			g_set_error (error, 0, 0,
+				     _("Unknown parameter '%s'"), pspec->name);
+			return FALSE;
+		}
+		pspec->g_type = gda_holder_get_g_type (source_param);
+	}
+	return TRUE;
+}
+
+/*
+ * rewrite_statement
+ *
+ * If @stmt contains some variables for which the g_type is undefined, try to adjust it
+ *
+ * Returns: a new #GdaStatement if no error occurred
+ */
+static GdaStatement *
+rewrite_statement (GdaReportEngine *engine, RunContext *context,
+		   GdaStatement *stmt, GError **error)
+{
+	ForeachData fdata;
+	fdata.engine = engine;
+	fdata.context = context;
+
+	GdaSqlStatement *sql_st;
+	g_object_get (G_OBJECT (stmt), "structure", &sql_st, NULL);
+	
+	if (!gda_sql_any_part_foreach (GDA_SQL_ANY_PART (sql_st->contents),
+				       (GdaSqlForeachFunc) rewrite_statement_foreach_func, &fdata, error)) {
+		gda_sql_statement_free (sql_st);
+		return NULL;
+	}
+
+	GdaStatement *out_stmt;
+	out_stmt = (GdaStatement*) g_object_new (GDA_TYPE_STATEMENT, "structure", sql_st, NULL);
+	gda_sql_statement_free (sql_st);
+
+	return out_stmt;
+}
+
 /*
  * assign_parameters_values
  *
@@ -1036,7 +1105,14 @@
 	stmt = gda_sql_parser_parse_string (parser, sql, NULL, error);
 	if (!stmt)
 		return NULL;
+
+	GdaStatement *lstmt;
+	lstmt = rewrite_statement (engine, context, stmt, error);
+	g_object_unref (stmt);
+	if (!lstmt)
+		return NULL;
 	
+	stmt = lstmt;
 	if (!gda_statement_get_parameters (stmt, &plist, error)) {
 		g_object_unref (stmt);
 		return NULL;
@@ -1154,7 +1230,7 @@
 	gchar **array;
 
 	/*g_print ("%s (context=%p, name=%s) ", __FUNCTION__, context, name);*/
-	array = g_strsplit ((gchar *) name, "/", 0);
+	array = g_strsplit ((gchar *) name, "|", 0);
 	if (g_strv_length (array) == 2) {
 		gchar *model_name = array [0];
 		gchar *col_name = array [1];
@@ -1223,6 +1299,8 @@
 	if (name) 
 		return (GdaConnection *) gda_report_engine_find_declared_object (engine, GDA_TYPE_CONNECTION, 
 										 (gchar *) name);
-	else
+	else if (context)
 		return context->cnc;
+	else
+		return NULL;
 }

Modified: trunk/libgda/gda-connection.c
==============================================================================
--- trunk/libgda/gda-connection.c	(original)
+++ trunk/libgda/gda-connection.c	Tue Feb  3 19:19:32 2009
@@ -3208,7 +3208,7 @@
 	/* GDA_CONNECTION_META_TABLES */
 	key = g_new0 (MetaKey, 1);
 	key->meta_type = GDA_CONNECTION_META_TABLES;
-	sql = "SELECT table_short_name, table_schema, table_full_name, table_owner, table_comments FROM _tables WHERE table_type LIKE '%TABLE%'";
+	sql = "SELECT table_short_name, table_schema, table_full_name, table_owner, table_comments FROM _tables WHERE table_type LIKE '%TABLE%' AND table_short_name != table_full_name";
 	stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
 	if (!stmt)
 		g_error ("Could not parse internal statement: %s\n", sql);
@@ -3218,7 +3218,7 @@
 	key->meta_type = GDA_CONNECTION_META_TABLES;
 	key->nb_filters = 1;
 	key->filters = name_array;
-	sql = "SELECT table_short_name, table_schema, table_full_name, table_owner, table_comments FROM _tables WHERE table_type LIKE '%TABLE%' AND table_short_name=##name::string";
+	sql = "SELECT table_short_name, table_schema, table_full_name, table_owner, table_comments FROM _tables WHERE table_type LIKE '%TABLE%' AND table_short_name != table_full_name AND table_short_name=##name::string";
 	stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
 	if (!stmt)
 		g_error ("Could not parse internal statement: %s\n", sql);
@@ -3227,7 +3227,7 @@
 	/* GDA_CONNECTION_META_VIEWS */
 	key = g_new0 (MetaKey, 1);
 	key->meta_type = GDA_CONNECTION_META_VIEWS;
-	sql = "SELECT t.table_short_name, t.table_schema, t.table_full_name, t.table_owner, t.table_comments, v.view_definition FROM _views as v NATURAL JOIN _tables as t";
+	sql = "SELECT t.table_short_name, t.table_schema, t.table_full_name, t.table_owner, t.table_comments, v.view_definition FROM _views as v NATURAL JOIN _tables as t WHERE t.table_short_name != t.table_full_name";
 	stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
 	if (!stmt)
 		g_error ("Could not parse internal statement: %s\n", sql);
@@ -3237,7 +3237,7 @@
 	key->meta_type = GDA_CONNECTION_META_VIEWS;
 	key->nb_filters = 1;
 	key->filters = name_array;
-	sql = "SELECT t.table_short_name, t.table_schema, t.table_full_name, t.table_owner, t.table_comments, v.view_definition FROM _views as v NATURAL JOIN _tables as t WHERE table_short_name=##name::string";
+	sql = "SELECT t.table_short_name, t.table_schema, t.table_full_name, t.table_owner, t.table_comments, v.view_definition FROM _views as v NATURAL JOIN _tables as t WHERE t.table_short_name != t.table_full_name AND table_short_name=##name::string";
 	stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
 	if (!stmt)
 		g_error ("Could not parse internal statement: %s\n", sql);
@@ -3254,8 +3254,6 @@
 		g_error ("Could not parse internal statement: %s\n", sql);
 	g_hash_table_insert (h, key, stmt);
 
-	
-
 	return h;
 }
 

Modified: trunk/libgda/gda-data-model.c
==============================================================================
--- trunk/libgda/gda-data-model.c	(original)
+++ trunk/libgda/gda-data-model.c	Tue Feb  3 19:19:32 2009
@@ -1979,6 +1979,7 @@
 
 	gint offset = 0;
 	gint col_offset = dump_rows ? 1 : 0;
+	GdaDataModel *ramodel = NULL;
 
 	string = g_string_new ("");
 
@@ -2045,7 +2046,7 @@
 				value = gda_data_model_get_value_at (model, i, j, error);
 				if (!value) {
 					allok = FALSE;
-					break;
+					goto out;
 				}
 				str = NULL;
 				if (null_as_empty) {
@@ -2071,12 +2072,10 @@
 				g_free (str);
 			}
 		}
-		if (!allok)
-			break;
 	}
 	
 	/* actual dumping of the contents: title */
-	if (allok && dump_title) {
+	if (dump_title) {
 		const gchar *title;
 		title = g_object_get_data (G_OBJECT (model), "name");
 		if (title) {
@@ -2096,10 +2095,10 @@
 	}
 
 	/* ...column titles...*/
-	if (allok && dump_rows) 
+	if (dump_rows) 
 		g_string_append_printf (string, "%*s", cols_size [0], "#row");
 
-	for (i = 0; (i < n_cols) && allok; i++) {
+	for (i = 0; i < n_cols; i++) {
 		gint j, max;
 		str = (gchar *) gda_data_model_get_column_title (model, i);
 		if (dump_rows || (i != 0))
@@ -2119,7 +2118,7 @@
 	g_string_append_c (string, '\n');
 		
 	/* ... separation line ... */
-	for (i = 0; (i < n_cols + col_offset) && allok; i++) {
+	for (i = 0; i < n_cols + col_offset; i++) {
 		if (i != 0)
 			g_string_append_printf (string, "%s", sep_row);
 		for (j = 0; j < cols_size [i]; j++)
@@ -2128,7 +2127,6 @@
 	g_string_append_c (string, '\n');
 
 	/* ... and data */
-	GdaDataModel *ramodel;
 	if (gda_data_model_get_access_flags (model) & GDA_DATA_MODEL_ACCESS_RANDOM)
 		ramodel = g_object_ref (model);
 	else {
@@ -2136,128 +2134,129 @@
 			g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
 				      "%s", _("Data model does not support backward cursor move, not displaying data"));
 			allok = FALSE;
+			goto out;
 		}
 		ramodel = gda_data_access_wrapper_new (model);
 	}
-	if (allok) {
-		for (j = 0; j < n_rows; j++) {
-			/* determine height for each column in that row */
-			gint *cols_height = g_new (gint, n_cols + col_offset);
-			gchar ***cols_str = g_new (gchar **, n_cols + col_offset);
-			gint k, kmax = 1;
-
-			if (dump_rows) {
-				str = g_strdup_printf ("%d", j);
-				cols_str [0] = g_strsplit (str, "\n", -1);
-				cols_height [0] = 1;
-				kmax = 1;
-			}
 
-			for (i = 0; i < n_cols; i++) {
-				if (!dump_attributes) {
-					value = gda_data_model_get_value_at (ramodel, i, j, error);
-					if (!value) {
-						allok = FALSE;
-						break;
-					}
-					str = NULL;
-					if (null_as_empty) {
-						if (!value || gda_value_is_null (value))
-							str = g_strdup ("");
-					}
-					if (!str)
-						str = value ? gda_value_stringify ((GValue *)value) : g_strdup ("_null_");
-				}
-				else {
-					GdaValueAttribute attrs;
-					attrs = gda_data_model_get_attributes_at (ramodel, i, j);
-					str = g_strdup_printf ("%u", attrs);
-				}
-				if (str) {
-					cols_str [i + col_offset] = g_strsplit (str, "\n", -1);
-					g_free (str);
-					cols_height [i + col_offset] = g_strv_length (cols_str [i + col_offset]);
-					kmax = MAX (kmax, cols_height [i + col_offset]);
+	for (j = 0; j < n_rows; j++) {
+		/* determine height for each column in that row */
+		gint *cols_height = g_new (gint, n_cols + col_offset);
+		gchar ***cols_str = g_new (gchar **, n_cols + col_offset);
+		gint k, kmax = 1;
+		
+		if (dump_rows) {
+			str = g_strdup_printf ("%d", j);
+			cols_str [0] = g_strsplit (str, "\n", -1);
+			cols_height [0] = 1;
+			kmax = 1;
+		}
+		
+		for (i = 0; i < n_cols; i++) {
+			if (!dump_attributes) {
+				value = gda_data_model_get_value_at (ramodel, i, j, error);
+				if (!value) {
+					allok = FALSE;
+					goto out;
 				}
-				else {
-					cols_str [i + col_offset] = NULL;
-					cols_height [i + col_offset] = 0;
+				str = NULL;
+				if (null_as_empty) {
+					if (!value || gda_value_is_null (value))
+						str = g_strdup ("");
 				}
+				if (!str)
+					str = value ? gda_value_stringify ((GValue *)value) : g_strdup ("_null_");
 			}
-			if (!allok)
-				break;
-
-			for (k = 0; k < kmax; k++) {
-				for (i = 0; i < n_cols + col_offset; i++) {
-					gboolean align_center = FALSE;
-					if (i != 0) {
+			else {
+				GdaValueAttribute attrs;
+				attrs = gda_data_model_get_attributes_at (ramodel, i, j);
+				str = g_strdup_printf ("%u", attrs);
+			}
+			if (str) {
+				cols_str [i + col_offset] = g_strsplit (str, "\n", -1);
+				g_free (str);
+				cols_height [i + col_offset] = g_strv_length (cols_str [i + col_offset]);
+				kmax = MAX (kmax, cols_height [i + col_offset]);
+			}
+			else {
+				cols_str [i + col_offset] = NULL;
+				cols_height [i + col_offset] = 0;
+			}
+		}
+		
+		for (k = 0; k < kmax; k++) {
+			for (i = 0; i < n_cols + col_offset; i++) {
+				gboolean align_center = FALSE;
+				if (i != 0) {
 #ifdef MULTI_LINE_NO_SEPARATOR
-						if (k != 0)
-							g_string_append_printf (string, "%s", sep_col_e);
-						else
+					if (k != 0)
+						g_string_append_printf (string, "%s", sep_col_e);
+					else
 #endif
-							g_string_append_printf (string, "%s", sep_col);
-					}
-					if (k < cols_height [i]) 
-						str = (cols_str[i])[k];
-					else {
+						g_string_append_printf (string, "%s", sep_col);
+				}
+				if (k < cols_height [i]) 
+					str = (cols_str[i])[k];
+				else {
 #ifdef MULTI_LINE_NO_SEPARATOR
-						str = "";
+					str = "";
 #else
-						if (cols_height [i] == 0)
-							str = "";
-						else
-							str = ".";
-						align_center = TRUE;
+					if (cols_height [i] == 0)
+						str = "";
+					else
+						str = ".";
+					align_center = TRUE;
 #endif
-					}
+				}
+				
+				if (cols_is_num [i])
+					g_string_append_printf (string, "%*s", cols_size [i], str);
+				else {
+					gint j, max;
+					if (str) 
+						max = cols_size [i] - g_utf8_strlen (str, -1);
+					else
+						max = cols_size [i];
 					
-					if (cols_is_num [i])
-						g_string_append_printf (string, "%*s", cols_size [i], str);
-					else {
-						gint j, max;
-						if (str) 
-							max = cols_size [i] - g_utf8_strlen (str, -1);
-						else
-							max = cols_size [i];
-
-						if (!align_center) {
-							g_string_append_printf (string, "%s", str);
-							for (j = 0; j < max; j++)
-								g_string_append_c (string, ' ');
-						}
-						else {
-							for (j = 0; j < max / 2; j++)
-								g_string_append_c (string, ' ');
-							g_string_append_printf (string, "%s", str);
-							for ( j+= g_utf8_strlen (str, -1); j < cols_size [i]; j++)
-								g_string_append_c (string, ' ');
-						}
-						/*
-						gint j, max;
-						if (str) {
-							g_string_append_printf (string, "%s", str);
-							max = cols_size [i] - g_utf8_strlen (str, -1);
-						}
-						else
-							max = cols_size [i];
+					if (!align_center) {
+						g_string_append_printf (string, "%s", str);
 						for (j = 0; j < max; j++)
 							g_string_append_c (string, ' ');
-						*/
 					}
+					else {
+						for (j = 0; j < max / 2; j++)
+							g_string_append_c (string, ' ');
+						g_string_append_printf (string, "%s", str);
+						for ( j+= g_utf8_strlen (str, -1); j < cols_size [i]; j++)
+							g_string_append_c (string, ' ');
+					}
+					/*
+					  gint j, max;
+					  if (str) {
+					  g_string_append_printf (string, "%s", str);
+					  max = cols_size [i] - g_utf8_strlen (str, -1);
+					  }
+					  else
+					  max = cols_size [i];
+					  for (j = 0; j < max; j++)
+					  g_string_append_c (string, ' ');
+					*/
 				}
-				g_string_append_c (string, '\n');
 			}
-
-			g_free (cols_height);
-			for (i = 0; i < n_cols; i++) 
-				g_strfreev (cols_str [i]);
-			g_free (cols_str);
+			g_string_append_c (string, '\n');
 		}
+		
+		g_free (cols_height);
+		for (i = 0; i < n_cols; i++) 
+			g_strfreev (cols_str [i]);
+		g_free (cols_str);
+	
 		g_string_append_printf (string, ngettext("(%d row)\n", "(%d rows)\n", n_rows), n_rows);
 	}
 
-	g_object_unref (ramodel);
+ out:
+	if (ramodel)
+		g_object_unref (ramodel);
 	g_free (cols_size);
 	g_free (cols_is_num);
 

Modified: trunk/libgda/gda-data-select.c
==============================================================================
--- trunk/libgda/gda-data-select.c	(original)
+++ trunk/libgda/gda-data-select.c	Tue Feb  3 19:19:32 2009
@@ -1821,7 +1821,7 @@
 	irow = GPOINTER_TO_INT (g_hash_table_lookup (imodel->priv->index, GINT_TO_POINTER (int_row + 1)));
 	if (irow > 0)
 		prow = g_array_index (imodel->priv->rows, GdaRow *, irow - 1);
-	if (!CLASS (model)->fetch_next (imodel, &prow, int_row, NULL)) {
+	else if (!CLASS (model)->fetch_next (imodel, &prow, int_row, NULL)) {
 		/* an error occurred */
 		g_object_set (G_OBJECT (iter), "current-row", target_iter_row, NULL);
 		gda_data_model_iter_invalidate_contents (iter);
@@ -1873,7 +1873,7 @@
 	irow = GPOINTER_TO_INT (g_hash_table_lookup (imodel->priv->index, GINT_TO_POINTER (int_row + 1)));
 	if (irow > 0)
 		prow = g_array_index (imodel->priv->rows, GdaRow *, irow - 1);
-	if (!CLASS (model)->fetch_prev (imodel, &prow, int_row, NULL)) {
+	else if (!CLASS (model)->fetch_prev (imodel, &prow, int_row, NULL)) {
 		/* an error occurred */
 		g_object_set (G_OBJECT (iter), "current-row", target_iter_row, NULL);
 		gda_data_model_iter_invalidate_contents (iter);

Modified: trunk/libgda/sql-parser/gda-sql-parser.c
==============================================================================
--- trunk/libgda/sql-parser/gda-sql-parser.c	(original)
+++ trunk/libgda/sql-parser/gda-sql-parser.c	Tue Feb  3 19:19:32 2009
@@ -1304,7 +1304,9 @@
 		break;
 	case '#': {
 		if (z[1] == '#') {
-			for (i=2; (z[i]) && (IdChar (z[i]) || (z[i] == '+') || (z[i] == '-') || (z[i] == '.') || (z[i] == ':')) &&
+			for (i=2; (z[i]) && 
+				     (IdChar (z[i]) || (z[i] == '+') || (z[i] == '-') || (z[i] == '.') || (z[i] == ':') || 
+				      (z[i] == '|') || (z[i] == '@') || (z[i] == '?')) &&
 				     (z[i] != '/') && (z[i] != parser->priv->context->delimiter)
 				     /*(!isspace (z[i])) && (z[i] != '/') && 
 				       (z[i] != parser->priv->context->delimiter)*/; i++) {}

Modified: trunk/libgda/sqlite/gda-sqlite-recordset.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-recordset.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-recordset.c	Tue Feb  3 19:19:32 2009
@@ -170,10 +170,12 @@
 			}
 		}
 	}
-	/*
+
+#ifdef GDA_DEBUG_NO
 	if (nb_missing > 0)
 		g_print ("Hey!, some columns are still not known for prep stmt %p\n", pmodel->prep_stmt);
-	*/
+#endif
+
 	g_free (missing_cols);
 }
 

Modified: trunk/samples/Report/customers-report-rml.rml
==============================================================================
--- trunk/samples/Report/customers-report-rml.rml	(original)
+++ trunk/samples/Report/customers-report-rml.rml	Tue Feb  3 19:19:32 2009
@@ -26,7 +26,7 @@
        Any <gda_report_iter> node will repeat its contents as many times as there are rows in the
        data model returned by the "customers" SELECT query.
     -->
-  <gda_report_section query_name="customers">
+  <gda_report_section query_name="customers" cnc_name="main_cnc">
     
     <story>
       <title>Customers report example</title>
@@ -55,9 +55,9 @@
 	</tr>
 	<gda_report_iter>
           <tr>
-            <td><gda_report_param_value param_name="customers/@id"/></td>
-            <td><gda_report_param_value param_name="customers/@name"/></td>
-            <td><gda_report_if expr="##customers/@country IS NOT NULL"><gda_report_if_true>Country: <gda_report_param_value param_name="customers/@country"/></gda_report_if_true><gda_report_if_false>-Unknown-</gda_report_if_false></gda_report_if></td>
+            <td><gda_report_param_value param_name="customers|@id"/></td>
+            <td><gda_report_param_value param_name="customers|@name"/></td>
+            <td><gda_report_if expr="##customers|@country IS NOT NULL"><gda_report_if_true>Country: <gda_report_param_value param_name="customers|@country"/></gda_report_if_true><gda_report_if_false>-Unknown-</gda_report_if_false></gda_report_if></td>
           </tr>
 	</gda_report_iter>
       </blockTable>
@@ -68,8 +68,8 @@
 	referencing the ID of the customer. The SQL queries used here are directly defined into the spec. file.</para>
 
       <gda_report_iter>
-	<h2>Details for <gda_report_param_value param_name="customers/@name"/></h2>
-	<para>Here are the details for customer &quot;<gda_report_param_value param_name="customers/@name"/>&quot;
+	<h2>Details for <gda_report_param_value param_name="customers|@name"/></h2>
+	<para>Here are the details for customer &quot;<gda_report_param_value param_name="customers|@name"/>&quot;
           such as the salesperson assigned to it, and the orders the customer has passed.</para>
 	<!-- SalesRep -->
 	<para bulletText="s"  bulletFontName = "ZapfDingbats">
@@ -77,13 +77,13 @@
             <!-- The query is defined within the spec -->
             <gda_report_query query_name="salesrep_for_customer" cnc_name="main_cnc">SELECT s.* FROM salesrep s
               INNER JOIN customers c ON (s.id=c.default_served_by)
-              WHERE c.id=##customers/@id::gint
+              WHERE c.id=##customers|@id::gint
             </gda_report_query>
 	    
-            <gda_report_if expr="##salesrep_for_customer/%nrows::gint == 0">
+            <gda_report_if expr="##salesrep_for_customer|?nrows::gint == 0">
               <gda_report_if_true>No salesRep!</gda_report_if_true>
               <gda_report_if_false>
-                <gda_report_iter>Sales person: <gda_report_param_value param_name="salesrep_for_customer/@name"/></gda_report_iter>
+                <gda_report_iter>Sales person: <gda_report_param_value param_name="salesrep_for_customer|@name"/></gda_report_iter>
               </gda_report_if_false>
             </gda_report_if>
 	  </gda_report_section>
@@ -93,10 +93,10 @@
 	<gda_report_section>
           <gda_report_query query_name="orders_for_customer" cnc_name="main_cnc">SELECT o.*,
             (SELECT count (*) FROM order_contents oc WHERE oc.order_id = o.id) AS nb FROM ORDERS o
-            WHERE customer = ##customers/@id::gint</gda_report_query>
-          <gda_report_if expr="##orders_for_customer/%nrows::gint == 0">
+            WHERE customer = ##customers|@id::gint</gda_report_query>
+          <gda_report_if expr="##orders_for_customer|?nrows::gint == 0">
             <gda_report_if_true><para bulletText="s"  bulletFontName = "ZapfDingbats">No order yet!</para></gda_report_if_true>
-            <gda_report_if_false><para bulletText="s"  bulletFontName = "ZapfDingbats">Orders so far (<gda_report_param_value param_name="orders_for_customer/%nrows"/>):</para>
+            <gda_report_if_false><para bulletText="s"  bulletFontName = "ZapfDingbats">Orders so far (<gda_report_param_value param_name="orders_for_customer|?nrows"/>):</para>
 	      <blockTable colWidths="4cm,4cm,4cm" style="products">
                 <tr>
                   <td>Order date</td>
@@ -105,9 +105,9 @@
                 </tr>
                 <gda_report_iter>
                   <tr>
-		    <td><gda_report_param_value param_name="orders_for_customer/@creation_date"/></td>
-		    <td><gda_report_param_value param_name="orders_for_customer/@nb"/></td>
-		    <td><gda_report_param_value param_name="orders_for_customer/@delivery_date"/></td>
+		    <td><gda_report_param_value param_name="orders_for_customer|@creation_date"/></td>
+		    <td><gda_report_param_value param_name="orders_for_customer|@nb"/></td>
+		    <td><gda_report_param_value param_name="orders_for_customer|@delivery_date"/></td>
                   </tr>
                 </gda_report_iter>
               </blockTable>

Modified: trunk/samples/Report/customers-report-spec.xml
==============================================================================
--- trunk/samples/Report/customers-report-spec.xml	(original)
+++ trunk/samples/Report/customers-report-spec.xml	Tue Feb  3 19:19:32 2009
@@ -37,10 +37,10 @@
        Any <gda_report_iter> node will repeat its contents as many times as there are rows in the
        data model returned by the "customers" SELECT query.
     -->
-  <gda_report_section query_name="customers"> 
+  <gda_report_section query_name="customers" cnc_name="main_cnc"> 
 
     <sect1>
-      <title>List of customers (<gda_report_param_value param_name="customers/%nrows"/>)</title>
+      <title>List of customers (<gda_report_param_value param_name="customers|?nrows"/>)</title>
       
       <para>Here is the list of customers, as per the database. The query executed to create the list of customers
 	was created in the source code and declared to the GdaReportEngine object, so only its name is used in the report.</para>
@@ -61,13 +61,13 @@
 	  <tbody>
 	    <gda_report_iter>
 	      <row>
-		<entry><gda_report_param_value param_name="customers/@id"/></entry>
-		<entry><gda_report_param_value param_name="customers/@name"/></entry>
+		<entry><gda_report_param_value param_name="customers|@id"/></entry>
+		<entry><gda_report_param_value param_name="customers|@name"/></entry>
 		<entry>
 		  <!-- Test on the value of an expression, which needs to be a valid SQLite expression -->
-		  <gda_report_if expr="##customers/@country IS NOT NULL">
+		  <gda_report_if expr="##customers|@country IS NOT NULL">
 		    <gda_report_if_true>
-		      Country: <gda_report_param_value param_name="customers/@country"/>
+		      Country: <gda_report_param_value param_name="customers|@country"/>
 		    </gda_report_if_true>
 		    <gda_report_if_false>
 		      -Unknown-
@@ -82,15 +82,15 @@
     </sect1>
 
     <sect1>
-      <title>Detailed <gda_report_param_value param_name="customers/%nrows"/> customers' information</title>
+      <title>Detailed <gda_report_param_value param_name="customers|?nrows"/> customers' information</title>
       
       <para>This section gives detailed information for each customer, it shows how to create nested report components:
 	For each row of the data model containing the list of customers, some other SELECT queries are executed while
 	referencing the ID of the customer. The SQL queries used here are directly defined into the spec. file.</para>
       <gda_report_iter>
 	<sect2>
-	  <title>Details for <gda_report_param_value param_name="customers/@name"/></title>
-	  <para>Here are the details for customer &quot;<gda_report_param_value param_name="customers/@name"/>&quot;
+	  <title>Details for <gda_report_param_value param_name="customers|@name"/></title>
+	  <para>Here are the details for customer &quot;<gda_report_param_value param_name="customers|@name"/>&quot;
 	    such as the salesperson assigned to it, and the orders the customer has passed.</para>
 	  <itemizedlist>
 	    
@@ -100,16 +100,16 @@
 		<!-- The query is defined within the spec -->
 		<gda_report_query query_name="salesrep_for_customer" cnc_name="main_cnc">SELECT s.* FROM salesrep s 
 		  INNER JOIN customers c ON (s.id=c.default_served_by) 
-		  WHERE c.id=##customers/@id::gint
+		  WHERE c.id=##customers|@id::gint
 		</gda_report_query>
 		
-		<gda_report_if expr="##salesrep_for_customer/%nrows::gint == 0">
+		<gda_report_if expr="##salesrep_for_customer|?nrows::gint == 0">
 		  <gda_report_if_true>
 		    <para>No salesRep!</para>
 		  </gda_report_if_true>
 		  <gda_report_if_false>
 		    <gda_report_iter>
-		      <para>Sales person: <gda_report_param_value param_name="salesrep_for_customer/@name"/></para>
+		      <para>Sales person: <gda_report_param_value param_name="salesrep_for_customer|@name"/></para>
 		    </gda_report_iter>
 		  </gda_report_if_false>
 		</gda_report_if>
@@ -121,13 +121,13 @@
 	      <gda_report_section>
 		<gda_report_query query_name="orders_for_customer" cnc_name="main_cnc">SELECT o.*, 
 		  (SELECT count (*) FROM order_contents oc WHERE oc.order_id = o.id) AS nb FROM ORDERS o
-		  WHERE customer = ##customers/@id::gint</gda_report_query>
-		<gda_report_if expr="##orders_for_customer/%nrows::gint == 0">
+		  WHERE customer = ##customers|@id::gint</gda_report_query>
+		<gda_report_if expr="##orders_for_customer|?nrows::gint == 0">
 		  <gda_report_if_true>
 		    <para>No order yet!</para>
 		  </gda_report_if_true>
 		  <gda_report_if_false>
-		    <para>Orders so far (<gda_report_param_value param_name="orders_for_customer/%nrows"/>)
+		    <para>Orders so far (<gda_report_param_value param_name="orders_for_customer|?nrows"/>)
 			<informaltable frame="all">
 			  <tgroup cols="3" align="left" colsep="1" rowsep="1">
 			    <colspec colname="Order date"/>
@@ -143,9 +143,9 @@
 			    <tbody>
 			      <gda_report_iter>
 				<row>
-				  <entry><gda_report_param_value param_name="orders_for_customer/@creation_date"/></entry>
-				  <entry><gda_report_param_value param_name="orders_for_customer/@nb"/></entry>
-				  <entry><gda_report_param_value param_name="orders_for_customer/@delivery_date"/></entry>
+				  <entry><gda_report_param_value param_name="orders_for_customer|@creation_date"/></entry>
+				  <entry><gda_report_param_value param_name="orders_for_customer|@nb"/></entry>
+				  <entry><gda_report_param_value param_name="orders_for_customer|@delivery_date"/></entry>
 				</row>
 			      </gda_report_iter>
 			    </tbody>



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