libgda r3261 - in trunk: . libgda libgda-report po tools



Author: vivien
Date: Wed Dec 10 21:11:52 2008
New Revision: 3261
URL: http://svn.gnome.org/viewvc/libgda?rev=3261&view=rev

Log:
2008-12-10  Vivien Malerba <malerba gnome-db org>

	* libgda/libgda.symbols:
	* libgda/Makefile.am:
	* libgda-report/libgda-report.symbols:
	* libgda-report/Makefile.am:
	  - use a DEF file on Windows to only export the
	    correct symbols (in the initialized data and the text (code) sections)
	  - create import libraries (.lib) files
	* tools-input.[ch]:
	* tools/gda-sql.c: use a main loop for characters input notification instead of
	locking on a readline function
	* configure.in
	* tools/Makefile.am
	* tools/html-doc.[ch]
	* tools/web-server.[ch]: optionnally run a small embedded web server (if
	libsoup is installed) to display meta data information in a browser
	* libgda/gda-easy.[ch]: applied patch from Daniel Espinosa for bug #529794
	* libgda/gda-data-model.c: calling gda_data_model_dump() with a NULL FILE*
	now prints to stdout
	* libgda/gda-meta-struct.c:
	  - removed debug messages
	  - better API documentation


Added:
   trunk/libgda-report/libgda-report.symbols
   trunk/libgda/libgda.symbols
   trunk/tools/gda-sql.h
   trunk/tools/html-doc.c
   trunk/tools/html-doc.h
   trunk/tools/web-server.c
   trunk/tools/web-server.h
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/libgda/   (props changed)
   trunk/libgda-report/   (props changed)
   trunk/libgda-report/Makefile.am
   trunk/libgda/Makefile.am
   trunk/libgda/gda-data-model.c
   trunk/libgda/gda-easy.c
   trunk/libgda/gda-easy.h
   trunk/libgda/gda-meta-struct.c
   trunk/po/POTFILES.in
   trunk/tools/Makefile.am
   trunk/tools/gda-sql.c
   trunk/tools/tools-input.c
   trunk/tools/tools-input.h

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Wed Dec 10 21:11:52 2008
@@ -163,6 +163,8 @@
     linklibext=".dll.a"
     AC_CHECK_TOOL(WINDRES, windres, windres)
     AC_SUBST(WINDRES)
+    AC_CHECK_TOOL(DLLTOOL, dlltool, dlltool)
+    AC_SUBST(DLLTOOL)
     ;;
 *-*-darwin*)
     dnl Darwin based distributions (including Mac OS X)
@@ -1324,6 +1326,19 @@
 LIBS="$save_LIBS"
 export LD_LIBRARY_PATH="$save_LD_LIBRARY_PATH"
 
+dnl ************************
+dnl Check for libsoup
+dnl ************************
+PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4, have_libsoup=yes, have_libsoup=no)
+AM_CONDITIONAL(LIBSOUP, test x"$have_libsoup" = "xyes")
+if test x"$have_libsoup" = "xyes"
+then
+        LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DHAVE_LIBSOUP"
+fi
+AC_SUBST(LIBSOUP_CFLAGS)
+AC_SUBST(LIBSOUP_LIBS)
+
+
 dnl **************************
 dnl Check for readline/history
 dnl **************************

Modified: trunk/libgda-report/Makefile.am
==============================================================================
--- trunk/libgda-report/Makefile.am	(original)
+++ trunk/libgda-report/Makefile.am	Wed Dec 10 21:11:52 2008
@@ -18,11 +18,37 @@
 	gda-report-document-private.h \
 	gda-report-document.c
 
-libgda_report_4_0_la_LDFLAGS = -version-info $(GDA_CURRENT):$(GDA_REVISION):$(GDA_AGE) $(NO_UNDEFINED)
+libgda_report_4_0_la_LDFLAGS = -version-info $(GDA_CURRENT):$(GDA_REVISION):$(GDA_AGE) \
+	$(NO_UNDEFINED) $(LIBTOOL_EXPORT_OPTIONS)
 libgda_report_4_0_la_LIBADD = engine/libgda-report-engine-4.0.la \
 	DocBook/libgda-report-docbook-4.0.la \
 	RML/libgda-report-rml-4.0.la \
 	$(LIBGDA_LIBS)
 
+if PLATFORM_WIN32
+libgda_report_4_0_la_LDFLAGS += -export-symbols $(srcdir)/libgda-report.def
+libgda_report_4_0_la_DEPENDENCIES = libgda-report.def
+
+libgda-report.def: libgda-report.symbols
+	(echo -e EXPORTS; $(CPP) -P - <$(srcdir)/libgda-report.symbols | sed -e '/^$$/d' -e 's/^/ /' -e 's/G_GNUC_[^ ]*//g' | sort) > libgda-report.def.tmp && mv libgda-report.def.tmp libgda-report.def
+
+libgda-report-$(GDA_ABI_VERSION).lib: libgda-report.def
+	$(DLLTOOL) --dllname libgda-report-$(GDA_ABI_VERSION)-$(GDA_CURRENT).dll --def libgda-report.def --output-lib libgda-report-$(GDA_ABI_VERSION).lib
+
+install-data-local: install-def-files
+uninstall-local: uninstall-def-files
+
+install-def-files: libgda-report.def libgda-report-$(GDA_ABI_VERSION).lib
+	$(INSTALL) $(srcdir)/libgda-report.def $(DESTDIR)$(libdir)/libgda-report-$(GDA_ABI_VERSION).def
+	$(INSTALL) $(srcdir)/libgda-report-$(GDA_ABI_VERSION).lib $(DESTDIR)$(libdir)/
+
+uninstall-def-files:
+	-rm $(DESTDIR)$(libdir)/libgda-report-$(GDA_ABI_VERSION).def
+	-rm $(DESTDIR)$(libdir)/libgda-report-$(GDA_ABI_VERSION).lib
+endif
+
 gdareportincludedir=$(includedir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/libgda-report
 gdareportinclude_HEADERS= libgda-report.h $(report_headers)
+
+CLEANFILES = libgda-report.def \
+	libgda-report-$(GDA_ABI_VERSION).lib

Added: trunk/libgda-report/libgda-report.symbols
==============================================================================
--- (empty file)
+++ trunk/libgda-report/libgda-report.symbols	Wed Dec 10 21:11:52 2008
@@ -0,0 +1,18 @@
+	gda_report_docbook_document_get_type
+	gda_report_docbook_document_new
+	gda_report_document_get_type
+	gda_report_document_run_as_html
+	gda_report_document_run_as_pdf
+	gda_report_document_run_converter_argv
+	gda_report_document_run_converter_path
+	gda_report_document_set_template
+	gda_report_engine_declare_object
+	gda_report_engine_find_declared_object
+	gda_report_engine_get_type
+	gda_report_engine_new
+	gda_report_engine_new_from_file
+	gda_report_engine_new_from_string
+	gda_report_engine_run_as_doc
+	gda_report_engine_run_as_node
+	gda_report_rml_document_get_type
+	gda_report_rml_document_new

Modified: trunk/libgda/Makefile.am
==============================================================================
--- trunk/libgda/Makefile.am	(original)
+++ trunk/libgda/Makefile.am	Wed Dec 10 21:11:52 2008
@@ -5,6 +5,7 @@
 if BDB 
 GDA_BDB_H=gda-data-model-bdb.h
 GDA_BDB_S=gda-data-model-bdb.c
+DEF_FLAGS=-DHAVE_BDB
 endif
 
 AM_CPPFLAGS = \
@@ -191,6 +192,28 @@
 	$(LIBGDA_LIBS) $(FAM_LIBS) \
 	$(BDB_LIBS) $(GIO_LIBS) $(GNOMEVFS_LIBS) 
 
+if PLATFORM_WIN32
+libgda_4_0_la_LDFLAGS += -export-symbols $(srcdir)/libgda.def
+libgda_4_0_la_DEPENDENCIES = libgda.def
+
+libgda.def: libgda.symbols
+	(echo -e EXPORTS; $(CPP) -P $(DEF_FLAGS) - <$(srcdir)/libgda.symbols | sed -e '/^$$/d' -e 's/^/ /' -e 's/G_GNUC_[^ ]*//g' | sort) > libgda.def.tmp && mv libgda.def.tmp libgda.def
+
+libgda-$(GDA_ABI_VERSION).lib: libgda.def
+	$(DLLTOOL) --dllname libgda-$(GDA_ABI_VERSION)-$(GDA_CURRENT).dll --def libgda.def --output-lib libgda-$(GDA_ABI_VERSION).lib
+
+install-data-local: install-def-files
+uninstall-local: uninstall-def-files
+
+install-def-files: libgda.def libgda-$(GDA_ABI_VERSION).lib
+	$(INSTALL) $(srcdir)/libgda.def $(DESTDIR)$(libdir)/libgda-$(GDA_ABI_VERSION).def
+	$(INSTALL) $(srcdir)/libgda-$(GDA_ABI_VERSION).lib $(DESTDIR)$(libdir)/
+
+uninstall-def-files:
+	-rm $(DESTDIR)$(libdir)/libgda-$(GDA_ABI_VERSION).def
+	-rm $(DESTDIR)$(libdir)/libgda-$(GDA_ABI_VERSION).lib
+endif
+
 gdaincludedir=$(includedir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/libgda
 gdainclude_HEADERS=$(libgda_built_headers) $(gda_headers)
 
@@ -199,7 +222,9 @@
 	gda-enum-types.h \
 	s-enum-types-h \
 	gda-enum-types.c \
-	s-enum-types-c
+	s-enum-types-c \
+	libgda.def \
+	libgda-$(GDA_ABI_VERSION).lib
 
 dist-hook:
 	cd $(distdir); rm -f $(libgda_built_headers) $(libgda_built_cfiles)
@@ -213,6 +238,7 @@
 EXTRA_DIST = \
 	$(DTD_FILES) \
 	$(xml_DATA) \
-	gda-marshal.list
+	gda-marshal.list \
+	libgda.symbols
 
 DISTCLEANFILES  = .deps/*.P

Modified: trunk/libgda/gda-data-model.c
==============================================================================
--- trunk/libgda/gda-data-model.c	(original)
+++ trunk/libgda/gda-data-model.c	Wed Dec 10 21:11:52 2008
@@ -1814,7 +1814,8 @@
 	GError *error = NULL;
 
 	g_return_if_fail (GDA_IS_DATA_MODEL (model));
-	g_return_if_fail (to_stream);
+	if (!to_stream)
+		to_stream = stdout;
 
 	if (getenv ("GDA_DATA_MODEL_DUMP_ATTRIBUTES")) 
 		dump_attrs = TRUE;

Modified: trunk/libgda/gda-easy.c
==============================================================================
--- trunk/libgda/gda-easy.c	(original)
+++ trunk/libgda/gda-easy.c	Wed Dec 10 21:11:52 2008
@@ -252,6 +252,20 @@
  * @...: group of three arguments for column's name, column's #GType 
  * and a #GdaEasyCreateTableFlag flag, finished with NULL
  * 
+ * Add more arguments if the flag needs then: 
+ *
+ * GDA_EASY_CREATE_TABLE_FKEY_FLAG:
+ * <itemizedlist>
+ *   <listitem><para>string with the table's name referenced</para></listitem>
+ *   <listitem><para>an integer with the number pairs "local_field", "referenced_field" 
+ *   used in the reference</para></listitem>
+ *   <listitem><para>Pairs of "local_field", "referenced_field" to use, must match
+ *    the number specified above.</para></listitem>
+ *   <listitem><para>a string with the action for ON DELETE; can be: "RESTRICT", "CASCADE", 
+ *    "NO ACTION", "SET NULL" and "SET DEFAULT". Example: "ON UPDATE CASCADE".</para></listitem>
+ *   <listitem><para>a string with the action for ON UPDATE (see above).</para></listitem>
+ * </itemizedlist> 
+ * 
  * Create a #GdaServerOperation object using an opened connection, taking three 
  * arguments, a colum's name the column's GType and #GdaEasyCreateTableFlag 
  * flag, you need to finish the list using NULL.
@@ -286,7 +300,8 @@
 		gchar   *dbms_type;
 		GdaEasyCreateTableFlag flag;
 		gint i;
-	
+		gint refs;
+
 		op = gda_server_provider_create_operation (server, cnc, 
 							   GDA_SERVER_OPERATION_CREATE_TABLE, NULL, error);
 		gda_server_operation_set_value_at (op, table_name, error, "/TABLE_DEF_P/TABLE_NAME");
@@ -295,6 +310,7 @@
 		type = 0;
 		arg = NULL;
 		i = 0;
+		refs = -1;
 		
 		while ((arg = va_arg (args, gchar*))) {
 			/* First argument for Column's name */			
@@ -320,6 +336,42 @@
 				gda_server_operation_set_value_at (op, "TRUE", error, "/FIELDS_A/@COLUMN_NNUL/%d", i);
 			if (flag & GDA_EASY_CREATE_TABLE_AUTOINC_FLAG)
 				gda_server_operation_set_value_at (op, "TRUE", error, "/FIELDS_A/@COLUMN_AUTOINC/%d", i);
+			if (flag & GDA_EASY_CREATE_TABLE_FKEY_FLAG) {
+				gint j;
+				gint fields;
+				gchar *fkey_table;
+				gchar *fkey_ondelete;
+				gchar *fkey_onupdate;
+				
+				refs++;
+				
+				fkey_table = va_arg (args, gchar*);				
+				gda_server_operation_set_value_at (op, fkey_table, error, 
+								   "/FKEY_S/%d/FKEY_REF_TABLE", refs);
+				
+				fields = va_arg (args, gint);
+				
+				for (j = 0; j < fields; j++) {
+					gchar *field, *rfield;
+					
+					field = va_arg (args, gchar*);				
+					gda_server_operation_set_value_at (op, field, error, 
+									   "/FKEY_S/%d/FKEY_FIELDS_A/@FK_FIELD/%d", refs, j);
+					
+					rfield = va_arg (args, gchar*);
+					gda_server_operation_set_value_at (op, rfield, error, 
+									   "/FKEY_S/%d/FKEY_FIELDS_A/@FK_REF_PK_FIELD/%d", refs, j);
+					
+				}
+				
+				fkey_ondelete = va_arg (args, gchar*);
+				gda_server_operation_set_value_at (op, fkey_ondelete, error, 
+								   "/FKEY_S/%d/FKEY_ONDELETE", refs);
+				fkey_onupdate = va_arg (args, gchar*);
+				gda_server_operation_set_value_at (op, fkey_onupdate, error, 
+								   "/FKEY_S/%d/FKEY_ONUPDATE", refs);
+			}
+			
 			i++;
 		}
 	

Modified: trunk/libgda/gda-easy.h
==============================================================================
--- trunk/libgda/gda-easy.h	(original)
+++ trunk/libgda/gda-easy.h	Wed Dec 10 21:11:52 2008
@@ -46,10 +46,12 @@
 
 typedef enum
 {
-	GDA_EASY_CREATE_TABLE_PKEY_FLAG      = 1 << 0,
-	GDA_EASY_CREATE_TABLE_NOT_NULL_FLAG  = 1 << 1,
-	GDA_EASY_CREATE_TABLE_UNIQUE_FLAG    = 1 << 2,
-	GDA_EASY_CREATE_TABLE_AUTOINC_FLAG   = 1 << 3,
+	GDA_EASY_CREATE_TABLE_NOTHING_FLAG   = 1 << 0,
+	GDA_EASY_CREATE_TABLE_PKEY_FLAG      = 1 << 1,
+	GDA_EASY_CREATE_TABLE_NOT_NULL_FLAG  = 1 << 2,
+	GDA_EASY_CREATE_TABLE_UNIQUE_FLAG    = 1 << 3,
+	GDA_EASY_CREATE_TABLE_AUTOINC_FLAG   = 1 << 4,
+	GDA_EASY_CREATE_TABLE_FKEY_FLAG      = 1 << 5,
 	/* Flags combinations */
 	GDA_EASY_CREATE_TABLE_PKEY_AUTOINC_FLAG = GDA_EASY_CREATE_TABLE_PKEY_FLAG | GDA_EASY_CREATE_TABLE_AUTOINC_FLAG
 } GdaEasyCreateTableFlag;

Modified: trunk/libgda/gda-meta-struct.c
==============================================================================
--- trunk/libgda/gda-meta-struct.c	(original)
+++ trunk/libgda/gda-meta-struct.c	Wed Dec 10 21:11:52 2008
@@ -414,10 +414,10 @@
  *
  * If @catalog is not %NULL, then @schema should not be %NULL.
  *
- * If @catalog is %NULL and @schema is not %NULL, then the database object will be the one which is
+ * If both @catalog and @schema are %NULL, then the database object will be the one which is
  * "visible" by default (that is which can be accessed only by its short @name name).
  *
- * If both @catalog and @schema are %NULL, then the database object will be the one which 
+ * If @catalog is %NULL and @schema is not %NULL, then the database object will be the one which 
  * can be accessed by its @schema  name name.
  *
  * Important note: @catalog, @schema and @name must respect the following convention:
@@ -861,8 +861,8 @@
 								  "ts", ischema, 
 								  "tname", iname, 
 								  "cname", cvalue, NULL);
-				g_print ("tname=%s cvalue=%s\n", gda_value_stringify (iname),
-					 gda_value_stringify (cvalue));
+				/*g_print ("tname=%s cvalue=%s\n", gda_value_stringify (iname),
+				  gda_value_stringify (cvalue));*/
 
 				cvalue = gda_data_model_get_value_at (model, 4, i, error);
 				if (!cvalue) goto onfkerror;
@@ -871,8 +871,8 @@
 								      "ts", fk_schema,
 								      "tname", fk_name,
 								      "cname", cvalue, NULL);
-				g_print ("tname=%s cvalue=%s\n", gda_value_stringify (fk_name),
-					 gda_value_stringify (cvalue));
+				/*g_print ("tname=%s cvalue=%s\n", gda_value_stringify (fk_name),
+				  gda_value_stringify (cvalue));*/
 				
 				if (fk_cols && ref_pk_cols) {
 					gint fk_nrows, ref_pk_nrows;

Added: trunk/libgda/libgda.symbols
==============================================================================
--- (empty file)
+++ trunk/libgda/libgda.symbols	Wed Dec 10 21:11:52 2008
@@ -0,0 +1,859 @@
+	fnYM49765777344607__gda_gbr_find_bin_dir
+	fnYM49765777344607__gda_gbr_find_data_dir
+	fnYM49765777344607__gda_gbr_find_etc_dir
+	fnYM49765777344607__gda_gbr_find_exe
+	fnYM49765777344607__gda_gbr_find_exe_dir
+	fnYM49765777344607__gda_gbr_find_lib_dir
+	fnYM49765777344607__gda_gbr_find_libexec_dir
+	fnYM49765777344607__gda_gbr_find_locale_dir
+	fnYM49765777344607__gda_gbr_find_prefix
+	fnYM49765777344607__gda_gbr_find_sbin_dir
+	gda_alphanum_to_text
+	gda_attributes_manager_clear
+	gda_attributes_manager_copy
+	gda_attributes_manager_foreach
+	gda_attributes_manager_free
+	gda_attributes_manager_get
+	gda_attributes_manager_new
+	gda_attributes_manager_set
+	gda_attributes_manager_set_full
+	gda_batch_add_statement
+	gda_batch_copy
+	gda_batch_error_quark
+	gda_batch_get_parameters
+	gda_batch_get_statements
+	gda_batch_get_type
+	gda_batch_new
+	gda_batch_remove_statement
+	gda_batch_serialize
+	gda_binary_copy
+	gda_binary_free
+	gda_binary_get_type
+	gda_binary_to_string
+	gda_blob_copy
+	gda_blob_free
+	gda_blob_get_type
+	gda_blob_op_get_length
+	gda_blob_op_get_type
+	gda_blob_op_read
+	gda_blob_op_read_all
+	gda_blob_op_write
+	gda_blob_op_write_all
+	gda_blob_set_op
+	gda_blob_to_string
+	gda_column_copy
+	gda_column_get_allow_null
+	gda_column_get_attribute
+	gda_column_get_auto_increment
+	gda_column_get_dbms_type
+	gda_column_get_default_value
+	gda_column_get_description
+	gda_column_get_g_type
+	gda_column_get_name
+	gda_column_get_position
+	gda_column_get_type
+	gda_column_new
+	gda_column_set_allow_null
+	gda_column_set_attribute
+	gda_column_set_auto_increment
+	gda_column_set_dbms_type
+	gda_column_set_default_value
+	gda_column_set_description
+	gda_column_set_g_type
+	gda_column_set_name
+	gda_column_set_position
+	gda_completion_list_get
+	gda_compute_dml_statements
+	gda_compute_unique_table_row_condition
+	gda_config_can_modify_system_config
+	gda_config_define_dsn
+	gda_config_dsn_needs_authentication
+	gda_config_error_get_type
+	gda_config_error_quark
+	gda_config_get
+	gda_config_get_dsn_info
+	gda_config_get_dsn_info_at_index
+	gda_config_get_dsn_info_index
+	gda_config_get_nb_dsn
+	gda_config_get_provider
+	gda_config_get_provider_info
+	gda_config_get_type
+	gda_config_list_dsn
+	gda_config_list_providers
+	gda_config_remove_dsn
+	gda_connection_add_event
+	gda_connection_add_event_string
+	gda_connection_add_prepared_statement
+	gda_connection_add_savepoint
+	gda_connection_batch_execute
+	gda_connection_begin_transaction
+	gda_connection_clear_events_list
+	gda_connection_close
+	gda_connection_close_no_warning
+	gda_connection_commit_transaction
+	gda_connection_create_operation
+	gda_connection_create_parser
+	gda_connection_delete_savepoint
+	gda_connection_del_prepared_statement
+	gda_connection_error_get_type
+	gda_connection_error_quark
+	gda_connection_event_code_get_type
+	gda_connection_event_get_code
+	gda_connection_event_get_description
+	gda_connection_event_get_event_type
+	gda_connection_event_get_gda_code
+	gda_connection_event_get_source
+	gda_connection_event_get_sqlstate
+	gda_connection_event_get_type
+	gda_connection_event_new
+	gda_connection_event_set_code
+	gda_connection_event_set_description
+	gda_connection_event_set_event_type
+	gda_connection_event_set_gda_code
+	gda_connection_event_set_source
+	gda_connection_event_set_sqlstate
+	gda_connection_event_type_get_type
+	gda_connection_feature_get_type
+	gda_connection_get_authentication
+	gda_connection_get_cnc_string
+	gda_connection_get_dsn
+	gda_connection_get_events
+	gda_connection_get_meta_store
+	gda_connection_get_meta_store_data
+	gda_connection_get_meta_store_data_v
+	gda_connection_get_options
+	gda_connection_get_prepared_statement
+	gda_connection_get_provider
+	gda_connection_get_provider_name
+	gda_connection_get_transaction_status
+	gda_connection_get_type
+	gda_connection_internal_change_transaction_state
+	gda_connection_internal_get_provider_data
+	gda_connection_internal_savepoint_added
+	gda_connection_internal_savepoint_removed
+	gda_connection_internal_savepoint_rolledback
+	gda_connection_internal_set_provider_data
+	gda_connection_internal_statement_executed
+	gda_connection_internal_transaction_committed
+	gda_connection_internal_transaction_rolledback
+	gda_connection_internal_transaction_started
+	gda_connection_is_opened
+	gda_connection_meta_type_get_type
+	gda_connection_open
+	gda_connection_open_from_dsn
+	gda_connection_open_from_string
+	gda_connection_options_get_type
+	gda_connection_perform_operation
+	gda_connection_rollback_savepoint
+	gda_connection_rollback_transaction
+	gda_connection_schema_get_type
+	gda_connection_statement_execute
+	gda_connection_statement_execute_non_select
+	gda_connection_statement_execute_select
+	gda_connection_statement_execute_select_full
+	gda_connection_statement_execute_select_fullv
+	gda_connection_statement_prepare
+	gda_connection_statement_to_sql
+	gda_connection_string_split
+	gda_connection_supports_feature
+	gda_connection_update_meta_store
+	gda_connection_value_to_sql_string
+	gda_data_access_wrapper_get_type
+	gda_data_access_wrapper_new
+	gda_data_comparator_compute_diff
+	gda_data_comparator_error_get_type
+	gda_data_comparator_error_quark
+	gda_data_comparator_get_diff
+	gda_data_comparator_get_n_diffs
+	gda_data_comparator_get_type
+	gda_data_comparator_new
+	gda_data_comparator_set_key_columns
+	gda_data_handler_accepts_g_type
+	gda_data_handler_get_descr
+	gda_data_handler_get_g_type_index
+	gda_data_handler_get_nb_g_types
+	gda_data_handler_get_sane_init_value
+	gda_data_handler_get_sql_from_value
+	gda_data_handler_get_str_from_value
+	gda_data_handler_get_type
+	gda_data_handler_get_value_from_sql
+	gda_data_handler_get_value_from_str
+	gda_data_model_access_flags_get_type
+	gda_data_model_add_data_from_xml_node
+	gda_data_model_append_row
+	gda_data_model_append_values
+	gda_data_model_array_clear
+	gda_data_model_array_copy_model
+	gda_data_model_array_get_row
+	gda_data_model_array_get_type
+	gda_data_model_array_new
+	gda_data_model_array_new_with_g_types
+	gda_data_model_array_set_n_columns
+#ifdef HAVE_BDB
+	gda_data_model_bdb_clean_errors
+	gda_data_model_bdb_get_errors
+	gda_data_model_bdb_get_type
+	gda_data_model_bdb_new
+#endif
+	gda_data_model_create_iter
+	gda_data_model_describe_column
+	gda_data_model_dir_clean_errors
+	gda_data_model_dir_get_errors
+	gda_data_model_dir_get_type
+	gda_data_model_dir_new
+	gda_data_model_dsn_list_get_type
+	gda_data_model_dump
+	gda_data_model_dump_as_string
+	gda_data_model_error_quark
+	gda_data_model_export_to_file
+	gda_data_model_export_to_string
+	gda_data_model_freeze
+	gda_data_model_get_access_flags
+	gda_data_model_get_attributes_at
+	gda_data_model_get_column_index
+	gda_data_model_get_column_name
+	gda_data_model_get_column_title
+	gda_data_model_get_n_columns
+	gda_data_model_get_n_rows
+	gda_data_model_get_row_from_values
+	gda_data_model_get_type
+	gda_data_model_get_typed_value_at
+	gda_data_model_get_value_at
+	gda_data_model_hint_get_type
+	gda_data_model_import_clean_errors
+	gda_data_model_import_from_file
+	gda_data_model_import_from_model
+	gda_data_model_import_from_string
+	gda_data_model_import_get_errors
+	gda_data_model_import_get_type
+	gda_data_model_import_new_file
+	gda_data_model_import_new_mem
+	gda_data_model_import_new_xml_node
+	gda_data_model_io_format_get_type
+	gda_data_model_iter_error_get_type
+	gda_data_model_iter_error_quark
+	gda_data_model_iter_get_column_for_param
+	gda_data_model_iter_get_holder_for_field
+	gda_data_model_iter_get_row
+	gda_data_model_iter_get_type
+	gda_data_model_iter_get_value_at
+	gda_data_model_iter_get_value_for_field
+	gda_data_model_iter_invalidate_contents
+	gda_data_model_iter_is_valid
+	gda_data_model_iter_move_at_row
+	gda_data_model_iter_move_at_row_default
+	gda_data_model_iter_move_next
+	gda_data_model_iter_move_next_default
+	gda_data_model_iter_move_prev
+	gda_data_model_iter_move_prev_default
+	gda_data_model_iter_set_value_at
+	gda_data_model_remove_row
+	gda_data_model_reset
+	gda_data_model_row_inserted
+	gda_data_model_row_removed
+	gda_data_model_row_updated
+	gda_data_model_send_hint
+	gda_data_model_set_column_name
+	gda_data_model_set_column_title
+	gda_data_model_set_value_at
+	gda_data_model_set_values
+	gda_data_model_thaw
+	gda_data_model_to_xml_node
+	gda_data_proxy_alter_value_attributes
+	gda_data_proxy_append
+	gda_data_proxy_apply_all_changes
+	gda_data_proxy_apply_row_changes
+	gda_data_proxy_cancel_all_changes
+	gda_data_proxy_cancel_row_changes
+	gda_data_proxy_delete
+	gda_data_proxy_error_get_type
+	gda_data_proxy_error_quark
+	gda_data_proxy_get_filtered_n_rows
+	gda_data_proxy_get_filter_expr
+	gda_data_proxy_get_model
+	gda_data_proxy_get_n_modified_rows
+	gda_data_proxy_get_n_new_rows
+	gda_data_proxy_get_proxied_model
+	gda_data_proxy_get_proxied_model_n_cols
+	gda_data_proxy_get_proxied_model_n_rows
+	gda_data_proxy_get_proxied_model_row
+	gda_data_proxy_get_sample_end
+	gda_data_proxy_get_sample_size
+	gda_data_proxy_get_sample_start
+	gda_data_proxy_get_type
+	gda_data_proxy_get_value_attributes
+	gda_data_proxy_get_values
+	gda_data_proxy_has_changed
+	gda_data_proxy_is_read_only
+	gda_data_proxy_new
+	gda_data_proxy_row_has_changed
+	gda_data_proxy_row_is_deleted
+	gda_data_proxy_row_is_inserted
+	gda_data_proxy_set_filter_expr
+	gda_data_proxy_set_ordering_column
+	gda_data_proxy_set_sample_size
+	gda_data_proxy_set_sample_start
+	gda_data_proxy_undelete
+	gda_data_select_compute_columns_attributes
+	gda_data_select_compute_modification_statements
+	gda_data_select_compute_row_selection_condition
+	gda_data_select_error_quark
+	gda_data_select_get_connection
+	gda_data_select_get_stored_row
+	gda_data_select_get_type
+	gda_data_select_set_modification_statement
+	gda_data_select_set_modification_statement_sql
+	gda_data_select_set_row_selection_condition
+	gda_data_select_set_row_selection_condition_sql
+	gda_data_select_take_row
+	gda_default_escape_string
+	gda_default_unescape_string
+	gda_delete_row_from_table
+	gda_diff_type_get_type
+	gda_dir_blob_get_filename
+	gda_dir_blob_op_get_type
+	gda_dir_blob_op_new
+	gda_dir_blob_set_filename
+	gda_dsn_split
+	gda_easy_create_table_flag_get_type
+	gda_easy_error_get_type
+	gda_easy_error_quark
+	gda_error_get_type
+	gda_execute_non_select_command
+	gda_execute_select_command
+	gda_gbr_get_file_path
+	gda_gbr_init
+	gda_geometricpoint_copy
+	gda_geometricpoint_free
+	gda_geometricpoint_get_type
+	gda_get_application_exec_path
+	gda_get_default_handler
+	gda_g_type_from_string
+	gda_g_type_to_string
+	gda_handler_bin_get_type
+	gda_handler_bin_new
+	gda_handler_boolean_get_type
+	gda_handler_boolean_new
+	gda_handler_numerical_get_type
+	gda_handler_numerical_new
+	gda_handler_string_get_type
+	gda_handler_string_new
+	gda_handler_string_new_with_provider
+	gda_handler_time_get_format
+	gda_handler_time_get_no_locale_str_from_value
+	gda_handler_time_get_type
+	gda_handler_time_new
+	gda_handler_time_new_no_locale
+	gda_handler_time_set_sql_spec
+	gda_handler_type_get_type
+	gda_handler_type_new
+	gda_holder_copy
+	gda_holder_error_get_type
+	gda_holder_error_quark
+	gda_holder_force_invalid
+	gda_holder_get_alphanum_id
+	gda_holder_get_attribute
+	gda_holder_get_bind
+	gda_holder_get_default_value
+	gda_holder_get_g_type
+	gda_holder_get_id
+	gda_holder_get_not_null
+	gda_holder_get_source_model
+	gda_holder_get_type
+	gda_holder_get_value
+	gda_holder_get_value_str
+	gda_holder_is_valid
+	gda_holder_new
+	gda_holder_new_inline
+	gda_holder_set_attribute
+	gda_holder_set_bind
+	gda_holder_set_default_value
+	gda_holder_set_not_null
+	gda_holder_set_source_model
+	gda_holder_set_value
+	gda_holder_set_value_str
+	gda_holder_set_value_to_default
+	gda_holder_take_static_value
+	gda_holder_take_value
+	gda_holder_value_is_default
+	gda_identifier_equal
+	gda_identifier_hash
+	gda_init
+	gda_insert_row_into_table
+	gda_insert_row_into_table_from_string
+	gda_lang_locale
+	gda_lockable_get_type
+	gda_lockable_lock
+	gda_lockable_trylock
+	gda_lockable_unlock
+	gda_log_disable
+	gda_log_enable
+	gda_log_error
+	gda_log_is_enabled
+	gda_log_message
+	gda_meta_db_object_type_get_type
+	gda_meta_graph_info_get_type
+	gda_meta_sort_type_get_type
+	gda_meta_store_change_type_get_type
+	gda_meta_store_create_modify_data_model
+	gda_meta_store_error_get_type
+	gda_meta_store_error_quark
+	gda_meta_store_extract
+	gda_meta_store_get_attribute_value
+	gda_meta_store_get_internal_connection
+	gda_meta_store_get_type
+	gda_meta_store_get_version
+	gda_meta_store_modify
+	gda_meta_store_modify_with_context
+	gda_meta_store_new
+	gda_meta_store_new_with_file
+	gda_meta_store_schema_add_custom_object
+	gda_meta_store_schema_get_all_tables
+	gda_meta_store_schema_get_depend_tables
+	gda_meta_store_schema_get_structure
+	gda_meta_store_schema_remove_custom_object
+	gda_meta_store_set_attribute_value
+	gda_meta_struct_add_db_object
+	gda_meta_struct_complement
+	gda_meta_struct_complement_all
+	gda_meta_struct_complement_default
+	gda_meta_struct_complement_depend
+	gda_meta_struct_complement_schema
+	gda_meta_struct_dump_as_graph
+	gda_meta_struct_error_get_type
+	gda_meta_struct_error_quark
+	gda_meta_struct_feature_get_type
+	gda_meta_struct_get_all_db_objects
+	gda_meta_struct_get_db_object
+	gda_meta_struct_get_table_column
+	gda_meta_struct_get_type
+	gda_meta_struct_load_from_xml_file
+	gda_meta_struct_new
+	gda_meta_struct_sort_db_objects
+	gda_meta_table_column_foreach_attribute
+	gda_meta_table_column_get_attribute
+	gda_meta_table_column_set_attribute
+	gda_mutex_free
+	gda_mutex_lock
+	gda_mutex_new
+	gda_mutex_trylock
+	gda_mutex_unlock
+	gda_numeric_copy
+	gda_numeric_free
+	gda_numeric_get_type
+	gda_numeric_locale
+	gda_parse_iso8601_date
+	gda_parse_iso8601_time
+	gda_parse_iso8601_timestamp
+	gda_perform_create_database
+	gda_perform_create_table
+	gda_perform_drop_database
+	gda_perform_drop_table
+	gda_prepare_create_database
+	gda_prepare_create_table
+	gda_prepare_drop_database
+	gda_prepare_drop_table
+	gda_pstmt_copy_contents
+	gda_pstmt_get_gda_statement
+	gda_pstmt_get_type
+	gda_pstmt_set_gda_statement
+	gda_quark_list_add_from_string
+	gda_quark_list_clear
+	gda_quark_list_copy
+	gda_quark_list_find
+	gda_quark_list_foreach
+	gda_quark_list_free
+	gda_quark_list_get_type
+	gda_quark_list_new
+	gda_quark_list_new_from_string
+	gda_quark_list_remove
+	gda_rfc1738_decode
+	gda_rfc1738_encode
+	gda_row_get_length
+	gda_row_get_type
+	gda_row_get_value
+	gda_row_new
+	gda_select_alter_select_for_empty
+	gda_server_operation_add_item_to_sequence
+	gda_server_operation_del_item_from_sequence
+	gda_server_operation_get_node_info
+	gda_server_operation_get_node_parent
+	gda_server_operation_get_node_path_portion
+	gda_server_operation_get_node_type
+	gda_server_operation_get_op_type
+	gda_server_operation_get_root_nodes
+	gda_server_operation_get_sequence_item_names
+	gda_server_operation_get_sequence_max_size
+	gda_server_operation_get_sequence_min_size
+	gda_server_operation_get_sequence_name
+	gda_server_operation_get_sequence_size
+	gda_server_operation_get_type
+	gda_server_operation_get_value_at
+	gda_server_operation_is_valid
+	gda_server_operation_load_data_from_xml
+	gda_server_operation_new
+	gda_server_operation_node_status_get_type
+	gda_server_operation_node_type_get_type
+	gda_server_operation_op_type_to_string
+	gda_server_operation_save_data_to_xml
+	gda_server_operation_set_value_at
+	gda_server_operation_type_get_type
+	gda_server_provider_blob_list_for_delete
+	gda_server_provider_blob_list_for_update
+	gda_server_provider_create_operation
+	gda_server_provider_create_parser
+	gda_server_provider_error_get_type
+	gda_server_provider_error_quark
+	gda_server_provider_escape_string
+	gda_server_provider_find_file
+	gda_server_provider_get_data_handler_dbms
+	gda_server_provider_get_data_handler_default
+	gda_server_provider_get_data_handler_g_type
+	gda_server_provider_get_default_dbms_type
+	gda_server_provider_get_name
+	gda_server_provider_get_schema_nb_columns
+	gda_server_provider_get_server_version
+	gda_server_provider_get_type
+	gda_server_provider_get_version
+	gda_server_provider_handler_declare
+	gda_server_provider_handler_find
+	gda_server_provider_init_schema_model
+	gda_server_provider_internal_get_parser
+	gda_server_provider_load_file_contents
+	gda_server_provider_perform_operation
+	gda_server_provider_perform_operation_default
+	gda_server_provider_render_operation
+	gda_server_provider_select_query_has_blobs
+	gda_server_provider_split_update_query
+	gda_server_provider_string_to_value
+	gda_server_provider_supports_feature
+	gda_server_provider_supports_operation
+	gda_server_provider_test_schema_model
+	gda_server_provider_unescape_string
+	gda_server_provider_value_to_sql_string
+	gda_set_add_holder
+	gda_set_copy
+	gda_set_error_get_type
+	gda_set_error_quark
+	gda_set_get_group
+	gda_set_get_holder
+	gda_set_get_holder_value
+	gda_set_get_node
+	gda_set_get_source
+	gda_set_get_source_for_model
+	gda_set_get_type
+	gda_set_is_valid
+	gda_set_merge_with_set
+	gda_set_new
+	gda_set_new_from_spec_node
+	gda_set_new_from_spec_string
+	gda_set_new_inline
+	gda_set_remove_holder
+	gda_set_set_holder_value
+	gda_short_get_type
+	gda_sql_any_part_check_structure
+	gda_sql_any_part_foreach
+	gda_sql_any_part_type_get_type
+	gda_sql_case_copy
+	gda_sql_case_free
+	gda_sql_case_new
+	gda_sql_case_serialize
+	gda_sql_delimiter
+	gda_sql_delimiterAlloc
+	gda_sql_delimiterFree
+	gda_sql_delimiterTrace
+	gda_sql_error_quark
+	gda_sql_error_type_get_type
+	gda_sql_expr_check_clean
+	gda_sql_expr_copy
+	gda_sql_expr_free
+	gda_sql_expr_new
+	gda_sql_expr_serialize
+	gda_sql_expr_take_select
+	gda_sql_field_check_clean
+	gda_sql_field_copy
+	gda_sql_field_free
+	gda_sql_field_new
+	gda_sql_field_serialize
+	gda_sql_field_take_name
+	gda_sql_function_check_clean
+	gda_sql_function_copy
+	gda_sql_function_free
+	gda_sql_function_new
+	gda_sql_function_serialize
+	gda_sql_function_take_args_list
+	gda_sql_function_take_name
+	gda_sql_identifier_add_quotes
+	gda_sql_identifier_needs_quotes
+	gda_sql_identifier_remove_quotes
+	gda_sqlite_handler_bin_get_type
+	gda_sqlite_handler_bin_new
+	gda_sqlite_provider_get_type
+	gda_sqlite_pstmt_get_type
+	gda_sqlite_pstmt_new
+	gda_sqlite_recordset_get_type
+	gda_sqlite_recordset_new
+	gda_sqlite_render_ADD_COLUMN
+	gda_sqlite_render_CREATE_INDEX
+	gda_sqlite_render_CREATE_TABLE
+	gda_sqlite_render_CREATE_VIEW
+	gda_sqlite_render_DROP_INDEX
+	gda_sqlite_render_DROP_TABLE
+	gda_sqlite_render_DROP_VIEW
+	gda_sqlite_render_RENAME_TABLE
+	gda_sql_operation_copy
+	gda_sql_operation_free
+	gda_sql_operation_new
+	gda_sql_operation_operator_from_string
+	gda_sql_operation_operator_to_string
+	gda_sql_operation_serialize
+	gda_sql_operator_type_get_type
+	gda_sql_param_spec_copy
+	gda_sql_param_spec_free
+	gda_sql_param_spec_new
+	gda_sql_param_spec_serialize
+	gda_sql_param_spec_take_descr
+	gda_sql_param_spec_take_name
+	gda_sql_param_spec_take_nullok
+	gda_sql_param_spec_take_type
+	gda_sql_parser
+	gda_sql_parserAlloc
+	gda_sql_parser_error_get_type
+	gda_sql_parser_error_quark
+	gda_sql_parser_flavour_get_type
+	gda_sql_parserFree
+	gda_sql_parser_get_type
+	gda_sql_parser_mode_get_type
+	gda_sql_parser_new
+	gda_sql_parser_parse_file_as_batch
+	gda_sql_parser_parse_string
+	gda_sql_parser_parse_string_as_batch
+	gda_sql_parser_set_overflow_error
+	gda_sql_parser_set_syntax_error
+	gda_sql_parserTrace
+	gda_sql_select_field_check_clean
+	gda_sql_select_field_copy
+	gda_sql_select_field_free
+	gda_sql_select_field_new
+	gda_sql_select_field_serialize
+	gda_sql_select_field_take_alias
+	gda_sql_select_field_take_expr
+	gda_sql_select_field_take_star_value
+	gda_sql_select_from_copy
+	gda_sql_select_from_free
+	gda_sql_select_from_new
+	gda_sql_select_from_serialize
+	gda_sql_select_from_take_new_join
+	gda_sql_select_from_take_new_target
+	gda_sql_select_join_copy
+	gda_sql_select_join_free
+	gda_sql_select_join_new
+	gda_sql_select_join_serialize
+	gda_sql_select_join_type_get_type
+	gda_sql_select_join_type_to_string
+	gda_sql_select_order_copy
+	gda_sql_select_order_free
+	gda_sql_select_order_new
+	gda_sql_select_order_serialize
+	gda_sql_select_target_check_clean
+	gda_sql_select_target_copy
+	gda_sql_select_target_free
+	gda_sql_select_target_new
+	gda_sql_select_target_serialize
+	gda_sql_select_target_take_alias
+	gda_sql_select_target_take_select
+	gda_sql_select_target_take_table_name
+	gda_sql_statement_begin_get_infos
+	gda_sql_statement_check_clean
+	gda_sql_statement_check_structure
+	gda_sql_statement_check_validity
+	gda_sql_statement_commit_get_infos
+	gda_sql_statement_compound_copy
+	gda_sql_statement_compound_free
+	gda_sql_statement_compound_get_infos
+	gda_sql_statement_compound_get_n_cols
+	gda_sql_statement_compound_reduce
+	gda_sql_statement_compound_serialize
+	gda_sql_statement_compound_set_type
+	gda_sql_statement_compound_take_stmt
+	gda_sql_statement_compound_type_get_type
+	gda_sql_statement_copy
+	gda_sql_statement_delete_get_infos
+	gda_sql_statement_delete_savepoint_get_infos
+	gda_sql_statement_delete_take_condition
+	gda_sql_statement_delete_take_table_name
+	gda_sql_statement_free
+	gda_sql_statement_get_contents_infos
+	gda_sql_statement_insert_get_infos
+	gda_sql_statement_insert_take_1_values_list
+	gda_sql_statement_insert_take_extra_values_list
+	gda_sql_statement_insert_take_fields_list
+	gda_sql_statement_insert_take_on_conflict
+	gda_sql_statement_insert_take_select
+	gda_sql_statement_insert_take_table_name
+	gda_sql_statement_new
+	gda_sql_statement_normalize
+	gda_sql_statement_rollback_get_infos
+	gda_sql_statement_rollback_savepoint_get_infos
+	gda_sql_statement_savepoint_get_infos
+	gda_sql_statement_select_copy
+	gda_sql_statement_select_free
+	gda_sql_statement_select_get_infos
+	gda_sql_statement_select_new
+	gda_sql_statement_select_serialize
+	gda_sql_statement_select_take_distinct
+	gda_sql_statement_select_take_expr_list
+	gda_sql_statement_select_take_from
+	gda_sql_statement_select_take_group_by
+	gda_sql_statement_select_take_having_cond
+	gda_sql_statement_select_take_limits
+	gda_sql_statement_select_take_order_by
+	gda_sql_statement_select_take_where_cond
+	gda_sql_statement_serialize
+	gda_sql_statement_string_to_type
+	gda_sql_statement_trans_set_isol_level
+	gda_sql_statement_trans_take_mode
+	gda_sql_statement_trans_take_name
+	gda_sql_statement_type_get_type
+	gda_sql_statement_type_to_string
+	gda_sql_statement_unknown_get_infos
+	gda_sql_statement_unknown_take_expressions
+	gda_sql_statement_update_get_infos
+	gda_sql_statement_update_take_condition
+	gda_sql_statement_update_take_on_conflict
+	gda_sql_statement_update_take_set_value
+	gda_sql_statement_update_take_table_name
+	gda_sql_table_check_clean
+	gda_sql_table_copy
+	gda_sql_table_free
+	gda_sql_table_new
+	gda_sql_table_serialize
+	gda_sql_table_take_name
+	gda_sql_value_stringify
+	gda_statement_check_structure
+	gda_statement_check_validity
+	gda_statement_copy
+	gda_statement_error_get_type
+	gda_statement_error_quark
+	gda_statement_get_parameters
+	gda_statement_get_statement_type
+	gda_statement_get_type
+	gda_statement_is_useless
+	gda_statement_model_usage_get_type
+	gda_statement_new
+	gda_statement_normalize
+	gda_statement_serialize
+	gda_statement_sql_flag_get_type
+	gda_statement_to_sql_extended
+	gda_statement_to_sql_real
+	gda_string_to_binary
+	gda_string_to_blob
+	gda_text_to_alphanum
+	gda_threader_cancel
+	gda_threader_get_type
+	gda_threader_new
+	gda_threader_start_thread
+	gda_time_copy
+	gda_time_free
+	gda_time_get_type
+	gda_timestamp_copy
+	gda_timestamp_free
+	gda_timestamp_get_type
+	gda_transaction_isolation_get_type
+	gda_transaction_status_add_event_sql
+	gda_transaction_status_add_event_sub
+	gda_transaction_status_add_event_svp
+	gda_transaction_status_dump
+	gda_transaction_status_event_type_get_type
+	gda_transaction_status_find
+	gda_transaction_status_find_current
+	gda_transaction_status_free_events
+	gda_transaction_status_get_type
+	gda_transaction_status_new
+	gda_transaction_status_state_get_type
+	gda_update_value_in_table
+	gda_update_values_in_table
+	gda_ushort_get_type
+	gda_utility_check_data_model
+	gda_utility_data_model_dump_data_to_xml
+	gda_utility_holder_load_attributes
+	gda_value_attribute_get_type
+	gda_value_compare
+	gda_value_copy
+	gda_value_differ
+	gda_value_free
+	gda_value_get_binary
+	gda_value_get_blob
+	gda_value_get_geometric_point
+	gda_value_get_list
+	gda_value_get_numeric
+	gda_value_get_short
+	gda_value_get_time
+	gda_value_get_timestamp
+	gda_value_get_ushort
+	gda_value_is_null
+	gda_value_is_number
+	gda_value_list_copy
+	gda_value_list_free
+	gda_value_list_get_type
+	gda_value_new
+	gda_value_new_binary
+	gda_value_new_blob
+	gda_value_new_blob_from_file
+	gda_value_new_from_string
+	gda_value_new_from_xml
+	gda_value_new_timestamp_from_timet
+	gda_value_reset_with_type
+	gda_value_set_binary
+	gda_value_set_blob
+	gda_value_set_from_string
+	gda_value_set_from_value
+	gda_value_set_geometric_point
+	gda_value_set_list
+	gda_value_set_null
+	gda_value_set_numeric
+	gda_value_set_short
+	gda_value_set_time
+	gda_value_set_timestamp
+	gda_value_set_ushort
+	gda_value_stringify
+	gda_value_take_binary
+	gda_value_take_blob
+	gda_value_to_xml
+	gda_vconnection_data_model_add
+	gda_vconnection_data_model_add_model
+	gda_vconnection_data_model_foreach
+	gda_vconnection_data_model_get_model
+	gda_vconnection_data_model_get_table_name
+	gda_vconnection_data_model_get_type
+	gda_vconnection_data_model_remove
+	gda_vconnection_data_model_table_data_free
+	gda_vconnection_get_table_data_by_model
+	gda_vconnection_get_table_data_by_name
+	gda_vconnection_get_table_data_by_unique_name
+	gda_vconnection_hub_add
+	gda_vconnection_hub_foreach
+	gda_vconnection_hub_get_connection
+	gda_vconnection_hub_get_type
+	gda_vconnection_hub_remove
+	gda_virtual_connection_get_type
+	gda_virtual_connection_internal_get_provider_data
+	gda_virtual_connection_internal_set_provider_data
+	gda_virtual_connection_open
+	gda_virtual_provider_get_type
+	gda_vprovider_data_model_get_type
+	gda_vprovider_data_model_new
+	gda_vprovider_hub_get_type
+	gda_vprovider_hub_new
+	gda_xa_transaction_begin
+	gda_xa_transaction_commit
+	gda_xa_transaction_commit_recovered
+	gda_xa_transaction_error_get_type
+	gda_xa_transaction_error_quark
+	gda_xa_transaction_get_type
+	gda_xa_transaction_id_to_string
+	gda_xa_transaction_new
+	gda_xa_transaction_register_connection
+	gda_xa_transaction_rollback
+	gda_xa_transaction_string_to_id
+	gda_xa_transaction_unregister_connection

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Wed Dec 10 21:11:52 2008
@@ -132,4 +132,6 @@
 tools/gda-list-config.c
 tools/gda-list-server-op.c
 tools/gda-sql.c
+tools/html-doc.c
 tools/tools-input.c
+tools/web-server.c

Modified: trunk/tools/Makefile.am
==============================================================================
--- trunk/tools/Makefile.am	(original)
+++ trunk/tools/Makefile.am	Wed Dec 10 21:11:52 2008
@@ -23,6 +23,7 @@
 
 gda_sql_4_0_SOURCES = \
         gda-sql.c \
+	gda-sql.h \
 	tools-input.h \
 	tools-input.c \
 	command-exec.h \
@@ -34,6 +35,12 @@
 	$(READLINE_LIB) \
         $(HISTORY_LIB)
 
+if LIBSOUP
+gda_sql_4_0_SOURCES += web-server.h web-server.c html-doc.h html-doc.c
+AM_CPPFLAGS += $(LIBSOUP_CFLAGS)
+gda_sql_4_0_LDADD += $(LIBSOUP_LIBS)
+endif
+
 
 
 # setenv() is in libiberty in mingw

Modified: trunk/tools/gda-sql.c
==============================================================================
--- trunk/tools/gda-sql.c	(original)
+++ trunk/tools/gda-sql.c	Wed Dec 10 21:11:52 2008
@@ -19,8 +19,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <libgda/libgda.h>
-#include <sql-parser/gda-sql-parser.h>
+#include "gda-sql.h"
 #include <virtual/libgda-virtual.h>
 #include <glib/gi18n-lib.h>
 #include <glib/gprintf.h>
@@ -49,6 +48,10 @@
 #include <readline/readline.h>
 #endif
 
+#ifdef HAVE_LIBSOUP
+#include "web-server.h"
+#endif
+
 /* options */
 gboolean ask_pass = FALSE;
 
@@ -62,6 +65,10 @@
 gchar *outfile = NULL;
 gboolean has_threads;
 
+#ifdef HAVE_LIBSOUP
+gint http_port = -1;
+#endif
+
 static GOptionEntry entries[] = {
         { "no-password-ask", 'p', 0, G_OPTION_ARG_NONE, &ask_pass, "Don't ask for a password when it is empty", NULL },
 
@@ -71,6 +78,9 @@
 	{ "interractive", 'i', 0, G_OPTION_ARG_NONE, &interractive, "Keep the console opened after executing a file (-f option)", NULL },
         { "list-dsn", 'l', 0, G_OPTION_ARG_NONE, &list_configs, "List configured data sources and exit", NULL },
         { "list-providers", 'L', 0, G_OPTION_ARG_NONE, &list_providers, "List installed database providers and exit", NULL },
+#ifdef HAVE_LIBSOUP
+	{ "http-port", 's', 0, G_OPTION_ARG_INT, &http_port, "Run embedded HTTP server on specified port", "port" },
+#endif
         { NULL }
 };
 
@@ -93,19 +103,6 @@
 	OUTPUT_FORMAT_CSV
 } OutputFormat;
 
-/*
- * structure representing an opened connection
- */
-typedef struct {
-	gchar         *name;
-	GdaConnection *cnc;
-	GdaSqlParser  *parser;
-	GString       *query_buffer;
-
-	GdaThreader   *threader;
-	guint          meta_job_id;
-} ConnectionSetting;
-
 /* structure to hold program's data */
 typedef struct {
 	GSList *settings; /* list all the CncSetting */
@@ -120,11 +117,15 @@
 	GString *partial_command;
 
 	GHashTable *parameters; /* key = name, value = G_TYPE_STRING GdaParameter */
+
+#ifdef HAVE_LIBSOUP
+	WebServer *server;
+#endif
 } MainData;
 MainData *main_data;
 GString *prompt = NULL;
+GMainLoop *main_loop = NULL;
 
-static gchar   *read_a_line (MainData *data);
 static char   **completion_func (const char *text, int start, int end);
 static void     compute_prompt (MainData *data, GString *string, gboolean in_command);
 static gboolean set_output_file (MainData *data, const gchar *file, GError **error);
@@ -137,6 +138,10 @@
 static GdaDataModel *list_all_dsn (MainData *data);
 static GdaDataModel *list_all_providers (MainData *data);
 
+static gboolean treat_line_func (const gchar *cmde, MainData *data);
+static const char *prompt_func (void);
+
+
 /* commands manipulation */
 static GdaInternalCommandsList  *build_internal_commands_list (MainData *data);
 static gboolean                  command_is_complete (const gchar *command);
@@ -270,93 +275,156 @@
 	/* build internal command s list */
 	data->internal_commands = build_internal_commands_list (data);
 
-	/* loop over commands */
-	setup_sigint_handler ();
-	init_input ();
-	set_completion_func (completion_func);
-	init_history ();
-	for (;;) {
-		gchar *cmde;
+#ifdef HAVE_LIBSOUP
+	/* start HTTP server if requested */
+	if (http_port > 0) {
+		main_data->server = web_server_new (http_port);
+		if (!main_data->server) {
+			g_print (_("Can't run HTTP server on port %d\n"), http_port);
+			exit_status = EXIT_FAILURE;
+			goto cleanup;
+		}
+	}
+#endif
 
-		/* run any pending iterations */
-		while (g_main_context_iteration (NULL, FALSE));
+	/* process commands which need to be executed as specified by the command line args */
+	if (single_command) {
+		treat_line_func (single_command, data);
+		if (!data->output_stream)
+			g_print ("\n");
+		goto cleanup;
+	}
 
-		cmde = read_a_line (data);
-		if (!cmde) {
-			save_history (NULL, NULL);
+	if (data->input_stream) {
+		gchar *cmde;
+		for (;;) {
+			cmde = input_from_stream (data->input_stream);
+			if (cmde) {
+				treat_line_func (cmde, data);
+				g_free (cmde);
+			}
+			else
+				break;
+		}
+		if (interractive && !cmde && isatty (fileno (stdin)))
+			set_input_file (data, NULL, NULL);
+		else {
 			if (!data->output_stream)
 				g_print ("\n");
 			goto cleanup;
 		}
+	}
 
-		g_strchug (cmde);
-		if (*cmde) {
-			if (!data->partial_command) {
-				/* enable SIGINT handling */
-				sigint_handler_status = SIGINT_HANDLER_PARTIAL_COMMAND;
-				data->partial_command = g_string_new (cmde);
-			}
-			else {
-				g_string_append_c (data->partial_command, ' ');
-				g_string_append (data->partial_command, cmde);
-			}
-			if (command_is_complete (data->partial_command->str)) {
-				/* execute command */
-				GdaInternalCommandResult *res;
-				FILE *to_stream;
+	/* set up interractive commands */
+	setup_sigint_handler ();
+	init_input ((TreatLineFunc) treat_line_func, prompt_func, data);
+	set_completion_func (completion_func);
+	init_history ();
+
+	/* run main loop */
+	main_loop = g_main_loop_new (NULL, TRUE);
+	g_main_loop_run (main_loop);		
+	g_main_loop_unref (main_loop);
 
-				if ((*data->partial_command->str != '\\') && (*data->partial_command->str != '.')) {
-					if (data->current) {
-						if (!data->current->query_buffer)
-							data->current->query_buffer = g_string_new ("");
-						g_string_assign (data->current->query_buffer, data->partial_command->str);
-					}
-				}
 
-				if (data && data->output_stream)
-					to_stream = data->output_stream;
-				else
-					to_stream = stdout;
-				res = command_execute (data, data->partial_command->str, &error);
-				
-				if (!res) {
-					g_fprintf (to_stream,
-						   "ERROR: %s\n", 
-						   error && error->message ? error->message : _("No detail"));
-					if (error) {
-						g_error_free (error);
-						error = NULL;
-					}
-				}
-				else {
-					display_result (data, res);
-					if (res->type == GDA_INTERNAL_COMMAND_RESULT_EXIT) {
-						gda_internal_command_exec_result_free (res);
-						goto cleanup;
-					}
-					gda_internal_command_exec_result_free (res);
-				}
-				g_string_free (data->partial_command, TRUE);
-				data->partial_command = NULL;
-				
-				/* disable SIGINT handling */
-				sigint_handler_status = SIGINT_HANDLER_DISABLED;
-			}
-		}
-		g_free (cmde);
-	}
-	
-	/* cleanups */
  cleanup:
+	/* cleanups */
 	g_slist_foreach (data->settings, (GFunc) connection_settings_free, NULL);
 	set_input_file (data, NULL, NULL); 
 	set_output_file (data, NULL, NULL); 
+	end_input ();
 
 	g_free (data);
 
 	return EXIT_SUCCESS;
 }
 
+static const char *
+prompt_func (void)
+{
+	/* compute a new prompt */
+	compute_prompt (main_data, prompt, main_data->partial_command == NULL ? FALSE : TRUE);
+	return (char*) prompt->str;
+}
+
+/* @cmde is stolen here */
+static gboolean
+treat_line_func (const gchar *cmde, MainData *data)
+{
+	gchar *loc_cmde = NULL;
+	if (!cmde) {
+		save_history (NULL, NULL);
+		if (!data->output_stream)
+			g_print ("\n");
+		goto exit;
+	}
+	
+	loc_cmde = g_strdup (cmde);
+	g_strchug (loc_cmde);
+	if (*loc_cmde) {
+		add_to_history (loc_cmde);
+		if (!data->partial_command) {
+			/* enable SIGINT handling */
+			sigint_handler_status = SIGINT_HANDLER_PARTIAL_COMMAND;
+			data->partial_command = g_string_new (loc_cmde);
+		}
+		else {
+			g_string_append_c (data->partial_command, ' ');
+			g_string_append (data->partial_command, loc_cmde);
+		}
+		if (command_is_complete (data->partial_command->str)) {
+			/* execute command */
+			GdaInternalCommandResult *res;
+			FILE *to_stream;
+			GError *error = NULL;
+			
+			if ((*data->partial_command->str != '\\') && (*data->partial_command->str != '.')) {
+				if (data->current) {
+					if (!data->current->query_buffer)
+						data->current->query_buffer = g_string_new ("");
+					g_string_assign (data->current->query_buffer, data->partial_command->str);
+				}
+			}
+			
+			if (data && data->output_stream)
+				to_stream = data->output_stream;
+			else
+				to_stream = stdout;
+			res = command_execute (data, data->partial_command->str, &error);
+			
+			if (!res) {
+				g_fprintf (to_stream,
+					   "ERROR: %s\n", 
+					   error && error->message ? error->message : _("No detail"));
+				if (error) {
+					g_error_free (error);
+					error = NULL;
+				}
+			}
+			else {
+				display_result (data, res);
+				if (res->type == GDA_INTERNAL_COMMAND_RESULT_EXIT) {
+					gda_internal_command_exec_result_free (res);
+					goto exit;
+				}
+				gda_internal_command_exec_result_free (res);
+			}
+			g_string_free (data->partial_command, TRUE);
+			data->partial_command = NULL;
+			
+			/* disable SIGINT handling */
+			sigint_handler_status = SIGINT_HANDLER_DISABLED;
+		}
+	}
+	g_free (loc_cmde);
+	return TRUE;
+
+ exit:
+	g_free (loc_cmde);
+	g_main_loop_quit (main_loop);
+	return FALSE;
+}
+
 static void
 display_result (MainData *data, GdaInternalCommandResult *res)
 {
@@ -480,6 +548,8 @@
 	}
 	case GDA_INTERNAL_COMMAND_RESULT_TXT_STDOUT: 
 		g_print ("%s", res->u.txt->str);
+		if (res->u.txt->str [strlen (res->u.txt->str) - 1] != '\n')
+			g_print ("\n");
 		fflush (NULL);
 		break;
 	case GDA_INTERNAL_COMMAND_RESULT_EMPTY:
@@ -540,39 +610,6 @@
 #endif
 
 /*
- * read_a_line
- *
- * Read a line to be processed
- */
-static gchar *read_a_line (MainData *data)
-{
-	gchar *cmde;
-
-	if (single_command) {
-		if (*single_command) {
-			cmde = single_command;
-			single_command = "";
-			return cmde;
-		}
-		else
-			return NULL;
-	}
-	compute_prompt (data, prompt, data->partial_command == NULL ? FALSE : TRUE);
-	if (data->input_stream) {
-		cmde = input_from_stream (data->input_stream);
-		if (interractive && !cmde && isatty (fileno (stdin))) {
-			/* go back to console after file is over */
-			set_input_file (data, NULL, NULL);
-			cmde = input_from_console (prompt->str);
-		}
-	}
-	else
-		cmde = input_from_console (prompt->str);
-
-	return cmde;
-}
-
-/*
  * command_is_complete
  *
  * Checks if @command can be executed, or if more data is required
@@ -773,8 +810,6 @@
 	return res;
 }
 
-
-
 static void
 compute_prompt (MainData *data, GString *string, gboolean in_command)
 {
@@ -1480,6 +1515,10 @@
 
 static GdaInternalCommandResult *extra_command_graph (GdaConnection *cnc, const gchar **args,
 						      GError **error, MainData *data);
+#ifdef HAVE_LIBSOUP
+static GdaInternalCommandResult *extra_command_httpd (GdaConnection *cnc, const gchar **args,
+						      GError **error, MainData *data);
+#endif
 
 static GdaInternalCommandResult *extra_command_lo_update (GdaConnection *cnc, const gchar **args,
 							  GError **error, MainData *data);
@@ -1571,6 +1610,19 @@
 	c->unquote_args = FALSE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
+#ifdef HAVE_LIBSOUP
+	c = g_new0 (GdaInternalCommand, 1);
+	c->group = _("Information");
+	c->name = g_strdup_printf (_("%s [port]"), "http");
+	c->description = _("Start/stop embedded HTTP server (on given port or on 12345 by default)");
+	c->args = NULL;
+	c->command_func = (GdaInternalCommandFunc) extra_command_httpd;
+	c->user_data = data;
+	c->arguments_delimiter_func = NULL;
+	c->unquote_args = FALSE;
+	commands->commands = g_slist_prepend (commands->commands, c);
+#endif
+
 	/* specific commands */
 	c = g_new0 (GdaInternalCommand, 1);
 	c->group = _("General");
@@ -3672,6 +3724,49 @@
 		return NULL;
 }
 
+#ifdef HAVE_LIBSOUP
+static GdaInternalCommandResult *
+extra_command_httpd (GdaConnection *cnc, const gchar **args,
+		     GError **error, MainData *data)
+{
+	GdaInternalCommandResult *res = NULL;
+	if (data->server) {
+		/* stop server */
+		g_object_unref (data->server);
+		data->server = NULL;
+		res = g_new0 (GdaInternalCommandResult, 1);
+		res->type = GDA_INTERNAL_COMMAND_RESULT_TXT_STDOUT;
+		res->u.txt = g_string_new (_("HTTPD server stopped"));
+	}
+	else {
+		/* start new server */
+		gint port = 12345;
+		if (args[0] && *args[0]) {
+			gchar *ptr;
+			port = (gint) strtol (args[0], &ptr, 10);
+			if (ptr && *ptr)
+				port = -1;
+		}
+		if (port > 0) {
+			data->server = web_server_new (port);
+			if (!data->server) 
+				g_set_error (error, 0, 0,
+					     _("Could not start HTTPD server"));
+			else {
+				res = g_new0 (GdaInternalCommandResult, 1);
+				res->type = GDA_INTERNAL_COMMAND_RESULT_TXT_STDOUT;
+				res->u.txt = g_string_new (_("HTTPD server started"));
+			}
+		}
+		else
+			g_set_error (error, 0, 0,
+				     _("Invalid port specification"));
+	}
+
+	return res;
+}
+#endif
+
 #ifdef NONE
 static GdaInternalCommandResult *
 extra_command_lo_update (GdaConnection *cnc, const gchar **args,
@@ -3831,3 +3926,22 @@
 	return NULL;
 #endif
 }
+
+
+const GSList *
+gda_sql_get_all_connections (void)
+{
+	return main_data->settings;
+}
+
+const ConnectionSetting *
+gda_sql_get_connection (const gchar *name)
+{
+	return find_connection_from_name (main_data, name);
+}
+
+const ConnectionSetting *
+gda_sql_get_current_connection (void)
+{
+	return main_data->current;
+}

Added: trunk/tools/gda-sql.h
==============================================================================
--- (empty file)
+++ trunk/tools/gda-sql.h	Wed Dec 10 21:11:52 2008
@@ -0,0 +1,49 @@
+/* GDA - SQL console
+ * Copyright (C) 2007 - 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * 	Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDA_SQL_H_
+#define __GDA_SQL_H_
+
+#include <libgda/libgda.h>
+#include <sql-parser/gda-sql-parser.h>
+
+G_BEGIN_DECLS
+
+/*
+ * structure representing an opened connection
+ */
+typedef struct {
+	gchar         *name;
+	GdaConnection *cnc;
+	GdaSqlParser  *parser;
+	GString       *query_buffer;
+
+	GdaThreader   *threader;
+	guint          meta_job_id;
+} ConnectionSetting;
+
+const GSList            *gda_sql_get_all_connections (void);
+const ConnectionSetting *gda_sql_get_connection (const gchar *name);
+const ConnectionSetting *gda_sql_get_current_connection (void);
+
+G_END_DECLS
+
+#endif

Added: trunk/tools/html-doc.c
==============================================================================
--- (empty file)
+++ trunk/tools/html-doc.c	Wed Dec 10 21:11:52 2008
@@ -0,0 +1,89 @@
+#include "html-doc.h"
+#include <glib/gi18n-lib.h>
+
+HtmlDoc *
+html_doc_new (const gchar *title)
+{
+	HtmlDoc *hdoc;
+	xmlNodePtr topnode, head, node, div, container;
+
+	hdoc = g_new0 (HtmlDoc, 1);
+	hdoc->doc = xmlNewDoc ("1.0");
+	topnode = xmlNewDocNode (hdoc->doc, NULL, "html", NULL);
+	xmlDocSetRootElement (hdoc->doc, topnode);
+
+	/* head */
+	head = xmlNewChild (topnode, NULL, "head", NULL);
+
+	node = xmlNewChild (head, NULL, "meta", NULL);
+	xmlSetProp(node, "http-equiv", (xmlChar*)"Content-Type");
+	xmlSetProp(node, "content", (xmlChar*)"text/html; charset=UTF-8");
+
+	node = xmlNewChild (head, NULL, "meta", NULL);
+	xmlSetProp(node, "http-equiv", (xmlChar*)"refresh");
+	xmlSetProp(node, "content", (xmlChar*)"30"); /* refresh the page every 30 seconds */
+
+	node = xmlNewChild (head, NULL, "title", title);
+	node = xmlNewChild (head, NULL, "link", NULL);
+	xmlSetProp(node, "href", (xmlChar*)"/gda.css");
+	xmlSetProp(node, "rel", (xmlChar*)"stylesheet");
+	xmlSetProp(node, "type", (xmlChar*)"text/css");
+
+	/* body */
+	node = xmlNewChild (topnode, NULL, "body", NULL);
+	hdoc->body = node;
+
+	/* container */
+	container = xmlNewChild (hdoc->body, NULL, "div", NULL);
+	xmlSetProp(container, "id", (xmlChar*)"container");
+
+	/* top */
+	div = xmlNewChild (container, NULL, "div", NULL);
+	xmlSetProp (div, "id", (xmlChar*)"top");
+
+	xmlNewChild (div, NULL, "h1", title);
+	
+
+	/* leftnav */
+	div = xmlNewChild (container, NULL, "div", NULL);
+	xmlSetProp(div, "id", (xmlChar*)"leftnav");
+	hdoc->sidebar = div;
+
+	/* content */
+	div = xmlNewChild (container, NULL, "div", NULL);
+	xmlSetProp(div, "id", (xmlChar*)"content");
+	hdoc->content = div;
+
+	/* footer */
+	div = xmlNewChild (container, NULL, "div", NULL);
+	xmlSetProp(div, "id", (xmlChar*)"footer");
+	xmlNewChild (div, NULL, "p", NULL);
+
+	return hdoc;
+}
+
+void
+html_doc_free  (HtmlDoc *hdoc)
+{
+	xmlFreeDoc (hdoc->doc);
+	g_free (hdoc);
+}
+
+xmlChar *
+html_doc_to_string (HtmlDoc *hdoc, gsize *out_size)
+{
+	xmlChar *retval = NULL;
+	int size;
+	xmlNodePtr li, a, node;
+
+	node = xmlNewChild (hdoc->sidebar, NULL, "ul", "Misc");
+	li = xmlNewChild (node, NULL, "li", NULL);
+	a = xmlNewChild (li, NULL, "a", _("Help"));
+	xmlSetProp (a, "href", (xmlChar*)"/___help");
+
+	xmlDocDumpFormatMemory (hdoc->doc, &retval, &size, 1);
+	if (out_size)
+		*out_size = (gsize) size;
+
+	return retval;
+}

Added: trunk/tools/html-doc.h
==============================================================================
--- (empty file)
+++ trunk/tools/html-doc.h	Wed Dec 10 21:11:52 2008
@@ -0,0 +1,14 @@
+#include <glib.h>
+#include <libxml/tree.h>
+
+typedef struct {
+	xmlDocPtr   doc;
+	xmlNodePtr  body;
+
+	xmlNodePtr  sidebar;
+	xmlNodePtr  content;
+} HtmlDoc;
+
+HtmlDoc  *html_doc_new       (const gchar *title);
+void      html_doc_free      (HtmlDoc *hdoc);
+xmlChar  *html_doc_to_string (HtmlDoc *hdoc, gsize *out_size);

Modified: trunk/tools/tools-input.c
==============================================================================
--- trunk/tools/tools-input.c	(original)
+++ trunk/tools/tools-input.c	Wed Dec 10 21:11:52 2008
@@ -28,6 +28,7 @@
 #ifndef G_OS_WIN32
 #include <sys/ioctl.h>
 #endif
+#include <libgda/gda-debug-macros.h>
 
 #ifdef HAVE_READLINE
 #include <readline/readline.h>
@@ -38,8 +39,10 @@
 
 #define HISTORY_ENV_NAME "GDA_SQL_HISTFILE"
 #define HISTORY_FILE ".gdasql_history"
+#ifdef HAVE_HISTORY
 static gboolean history_init_done = FALSE;
 const gchar *history_file = NULL;
+#endif
 
 /**
  * input_from_console
@@ -95,18 +98,99 @@
 	}
 }
 
+static TreatLineFunc line_cb_func = NULL;
+static gpointer      line_cb_func_data = NULL;
+static ComputePromptFunc line_prompt_func = NULL;
+static GIOChannel *ioc = NULL;
+
+static gboolean
+chars_for_readline_cb (GIOChannel *ioc, GIOCondition condition, gpointer data)
+{
+#ifdef HAVE_READLINE
+        rl_callback_read_char ();
+#else
+	gchar *line; 
+	gsize tpos;
+	GError *error = NULL;
+	GIOStatus st;
+	st = g_io_channel_read_line (ioc, &line, NULL, &tpos, &error);
+	switch (st) {
+	case G_IO_STATUS_NORMAL:
+		line [tpos] = 0;
+		if (line_cb_func (line, line_cb_func_data) == TRUE) {
+			/* print prompt for next line */
+			g_print ("%s", line_prompt_func ());
+		}
+		g_free (line);
+		break;
+	case G_IO_STATUS_ERROR:
+		g_warning ("Error reading from STDIN: %s\n",
+			   error && error->message ? error->message : _("No detail"));
+		if (error)
+			g_error_free (error);
+		break;
+	case G_IO_STATUS_EOF:
+		/* send the Quit command */
+		line_cb_func (".q", line_cb_func_data);
+		return FALSE;
+		break;
+	default:
+		break;
+	}
+#endif
+        return TRUE;
+}
+
+#ifdef HAVE_READLINE
+static void
+line_read_handler (char *line)
+{
+	line_cb_func (line, line_cb_func_data); /* we don't care about the return status */
+        free (line);
+	rl_set_prompt (line_prompt_func ());
+}
+#endif
+
 /**
  * init_input
  *
  * Initializes input
  */
 void
-init_input ()
+init_input (TreatLineFunc treat_line_func, ComputePromptFunc prompt_func, gpointer data)
 {
-#ifdef HAVE_READLINE	
+	line_cb_func = treat_line_func;
+	line_cb_func_data = data;
+	line_prompt_func = prompt_func;
+
+#ifdef HAVE_READLINE
 	rl_set_signals ();
 	rl_readline_name = "gda-sql";
+	rl_callback_handler_install (prompt_func () ,  line_read_handler);
+#else
+	g_print ("%s", line_prompt_func ());
+#endif
+	if (!ioc) {
+		ioc = g_io_channel_unix_new (STDIN_FILENO);
+		g_io_add_watch (ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc) chars_for_readline_cb, NULL);
+	}
+}
+
+/**
+ * end_input
+ *
+ * Releases any data related to the input and allocated during init_input()
+ */
+void
+end_input (void)
+{
+#ifdef HAVE_READLINE
+	rl_callback_handler_remove ();
 #endif
+	if (ioc) {
+		g_io_channel_shutdown (ioc, TRUE, NULL);
+		g_io_channel_unref (ioc);
+	}
 }
 
 /**

Modified: trunk/tools/tools-input.h
==============================================================================
--- trunk/tools/tools-input.h	(original)
+++ trunk/tools/tools-input.h	Wed Dec 10 21:11:52 2008
@@ -25,13 +25,16 @@
 #include <stdio.h>
 #include <glib.h>
 
-typedef char **(*CompletionFunc) (const char *, int, int);
+typedef char       **(*CompletionFunc) (const char *, int, int);
+typedef gboolean     (*TreatLineFunc) (const gchar *, gpointer);
+typedef const  char *(*ComputePromptFunc) (void);
 
 gchar   *input_from_console (const gchar *prompt);
 gchar   *input_from_stream  (FILE *stream);
 
-void     init_input ();
+void     init_input (TreatLineFunc treat_line_func, ComputePromptFunc prompt_func, gpointer data);
 void     input_get_size (gint *width, gint *height);
+void     end_input (void);
 
 void     init_history ();
 void     add_to_history (const gchar *txt);

Added: trunk/tools/web-server.c
==============================================================================
--- (empty file)
+++ trunk/tools/web-server.c	Wed Dec 10 21:11:52 2008
@@ -0,0 +1,1681 @@
+
+/* web-server.c
+ *
+ * Copyright (C) 2008 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "web-server.h"
+#include <libsoup/soup.h>
+#include "html-doc.h"
+
+/* 
+ * Main static functions 
+ */
+static void web_server_class_init (WebServerClass * class);
+static void web_server_init (WebServer *server);
+static void web_server_dispose (GObject *object);
+static void web_server_finalize (GObject *object);
+
+/* get a pointer to the parents to be able to call their destructor */
+static GObjectClass  *parent_class = NULL;
+
+
+struct _WebServerPrivate
+{
+	SoupServer  *server;
+	GHashTable  *tmpdata_hash; /* key = a path without the starting '/', value = a TmpData pointer */
+	GSList      *tmpdata_list; /* list of the TmpData pointers in @tmpdata_hash, memory not managed here */
+	guint        timer;
+};
+
+/*
+ * Temporary available data
+ *
+ * Each TmpData structure represents a ressource which will be available for some time (until it has
+ * expired).
+ *
+ * If the expiration_date attribute is set to 0, then there is no expiration at all.
+ */
+typedef struct {
+	gchar *path;
+	gchar *data;
+	gsize  size;
+	int    expiration_date; /* 0 to avoid expiration */
+} TmpData;
+
+static gboolean
+delete_tmp_data (WebServer *server)
+{
+	GSList *list;
+	GTimeVal tv;
+	gint n_timed = 0;
+
+	g_get_current_time (&tv);
+	for (list = server->priv->tmpdata_list; list; ) {
+		TmpData *td = (TmpData *) list->data;
+		if ((td->expiration_date > 0) && (td->expiration_date < tv.tv_sec)) {
+			GSList *n = list->next;
+			g_hash_table_remove (server->priv->tmpdata_hash, td->path);
+			server->priv->tmpdata_list = g_slist_delete_link (server->priv->tmpdata_list, list);
+			list = n;
+		}
+		else {
+			if (td->expiration_date > 0)
+				n_timed ++;
+			list = list->next;
+		}
+	}
+	if (n_timed == 0) {
+		server->priv->timer = 0;
+		return FALSE;
+	}
+	else
+		return TRUE;
+}
+
+/*
+ * @data is stolen!
+ */
+static TmpData *
+tmp_data_add (WebServer *server, const gchar *path, gchar *data, gsize data_length)
+{
+	TmpData *td;
+	GTimeVal tv;
+
+	g_get_current_time (&tv);
+	td = g_new0 (TmpData, 1);
+	td->path = g_strdup (path);
+	td->data = data;
+	td->size = data_length;
+	td->expiration_date = tv.tv_sec + 30;
+	g_hash_table_insert (server->priv->tmpdata_hash, g_strdup (path), td);
+	server->priv->tmpdata_list = g_slist_prepend (server->priv->tmpdata_list, td);
+	if (!server->priv->timer)
+		server->priv->timer = g_timeout_add_seconds (5, (GSourceFunc) delete_tmp_data, server);
+	return td;
+}
+
+/*
+ * @data is static
+ */
+static TmpData *
+tmp_static_data_add (WebServer *server, const gchar *path, gchar *data, gsize data_length)
+{
+	TmpData *td;
+
+	td = g_new0 (TmpData, 1);
+	td->path = g_strdup (path);
+	td->data = data;
+	td->size = data_length;
+	td->expiration_date = 0;
+	g_hash_table_insert (server->priv->tmpdata_hash, g_strdup (path), td);
+	server->priv->tmpdata_list = g_slist_prepend (server->priv->tmpdata_list, td);
+	return td;
+}
+
+static void
+tmp_data_free (TmpData *data)
+{
+	g_free (data->data);
+	g_free (data);
+}
+
+#define GDA_CSS \
+"body {" \
+"        margin: 0px;" \
+"        background-color: white;" \
+"        font-family: sans-serif;" \
+"        color: black;" \
+"}" \
+"" \
+"a {" \
+"    color: #0000ff;" \
+"    border: 0px;" \
+"}" \
+"" \
+"a:active {" \
+"        color: #ff0000;" \
+"}" \
+"" \
+"a:visited {" \
+"        color: #551a8b;" \
+"}" \
+"" \
+"" \
+"#container" \
+"{" \
+"    width: 97%;" \
+"    margin: 1%;" \
+"    background-color: #fff;" \
+"    color: #333;" \
+"}" \
+"" \
+"" \
+"" \
+"#top" \
+"{" \
+"    background: #729FCF;" \
+"    float: left;" \
+"    width: 100%;" \
+"    font-size: 75%;" \
+"}" \
+"" \
+"#top h1" \
+"{" \
+"    margin: 0;" \
+"    margin-left: 85px;" \
+"    padding-top: 20px;" \
+"    padding-bottom: 20px;" \
+"    color: #eeeeec;" \
+"}" \
+"" \
+"#top ul {" \
+"    list-style: none;" \
+"    text-align: right;" \
+"    padding: 0 1ex;" \
+"    margin: 0;" \
+"    font-size: 85%;" \
+"}" \
+"" \
+"#top li a {" \
+"    font-weight: bold;" \
+"    color: #FFFFFF;" \
+"    margin: 0 2ex;" \
+"    text-decoration: none;" \
+"    line-height: 30px;" \
+"" \
+"}" \
+"" \
+"" \
+"/*" \
+" * Left naivgation pane" \
+" */" \
+"#leftnav" \
+"{" \
+"    float: left;" \
+"    width: 140px;" \
+"    margin: 0;" \
+"    padding-top: 5;" \
+"" \
+"    background: #2E3436;" \
+"    color: #FFFFFF;" \
+"}" \
+"" \
+"#leftnav ul {" \
+"    font-weight: bold;" \
+"    list-style: none;" \
+"    padding: 0 10px 10px;;" \
+"    margin: 0 0 0 0;" \
+"    font-size: 90%;" \
+"}" \
+"" \
+"#leftnav li a {" \
+"    font-weight: normal;" \
+"    color: #FFFFFF;" \
+"    margin: 0 0 0 0;" \
+"    padding: 0 10px;" \
+"    text-decoration: none;" \
+"    font-size: 80%;" \
+"}" \
+"" \
+"#leftnav p { margin: 0 0 1em 0; }" \
+"" \
+"/* " \
+" * Content" \
+" */" \
+"#content" \
+"{" \
+"    /*background: red;*/" \
+"    margin-left: 140px;" \
+"    padding: 5em 1em;" \
+"}" \
+"" \
+"#content h1" \
+"{ " \
+"    /*background: green;*/" \
+"    margin: 5em 0 .5em 0 0;" \
+"    font-size: 100%;" \
+"}" \
+"" \
+"#content h2" \
+"{ " \
+ "    /*background: green;*/"			\
+"    padding-left: 5;" \
+"    font-size: 80%;" \
+"}" \
+"" \
+"#content ul {" \
+"    font-weight: bold;" \
+"    list-style: none;" \
+"    padding: 0 10px 10px;;" \
+"    margin: 0 0 0 0;" \
+"    font-size: 90%;" \
+"}" \
+"" \
+"#content li {" \
+"    font-weight: normal;" \
+"    margin: 0 0 0 0;" \
+"    padding: 0 10px;" \
+"    text-decoration: none;" \
+"    font-size: 80%;" \
+"}" \
+"" \
+"div.clist" \
+"{" \
+"    /*background: blue;*/" \
+"    padding: 0;" \
+"    overflow: hidden;" \
+"}" \
+"" \
+".clist ul" \
+"{" \
+"    /*background: lightgray;*/" \
+"    margin-bottom: 0;" \
+"" \
+"    float: left;" \
+"    width: 100%;" \
+"    margin: 0;" \
+"    margin-left: 10px;" \
+"    padding: 0;" \
+"    list-style: none;" \
+"}" \
+"" \
+".clist li" \
+"{" \
+"    /*background: lightblue;*/" \
+"    float: left;" \
+"    width: 33%;" \
+"    margin: 0;" \
+"    padding: 0;" \
+"    font-size: 90%;" \
+"    /*word-wrap: break-word;*/" \
+"}" \
+"" \
+".clist a" \
+"{" \
+"    font-weight: normal;" \
+"    color: #050505;" \
+"    margin: 0 0 0 0;" \
+"    padding: 0 0 0 0;" \
+"    text-decoration: none;" \
+"}" \
+"" \
+".clist br" \
+"{" \
+"    clear: both;" \
+"}" \
+"" \
+"table.ctable" \
+"{" \
+"    font-weight: normal;" \
+"    font-size: 90%;" \
+"    width: 100%;" \
+"    background-color: #fafafa;" \
+"    border: 1px #6699CC solid;" \
+"    border-collapse: collapse;" \
+"    border-spacing: 0px;" \
+"    margin-top: 0px;" \
+"    margin-bottom: 5px;" \
+"}" \
+"" \
+".ctable th" \
+"{" \
+"    border-bottom: 2px solid #6699CC;" \
+"    background-color: #729FCF;" \
+"    text-align: center;" \
+"    font-weight: bold;" \
+"    color: #eeeeec;" \
+"}" \
+"" \
+".ctable td" \
+"{" \
+"    padding-left: 2px;" \
+"    border-left: 1px dotted #729FCF;" \
+"}" \
+"" \
+".graph" \
+"{" \
+"    /*background: lightblue;*/" \
+"    padding: 0;" \
+"}" \
+"" \
+".graph img" \
+"{" \
+"    max-width: 100%;" \
+"    height: auto;" \
+"    border: 0;" \
+"}" \
+"" \
+".pkey" \
+"{" \
+"    /*background: lightblue;*/" \
+"    color: blue;" \
+"    font-weight: bold;" \
+"}" \
+"" \
+".ccode" \
+"{" \
+"    /*background: lightblue;*/" \
+"    padding-left: 5px;" \
+"}" \
+"" \
+"/*" \
+" * Footer" \
+" */" \
+"#footer" \
+"{" \
+"    clear: both;" \
+"    margin: 0;" \
+"    padding: 2;" \
+"    color: #eeeeec;" \
+"    background: #729FCF;" \
+"}"
+
+
+/* module error */
+GQuark web_server_error_quark (void)
+{
+        static GQuark quark;
+        if (!quark)
+                quark = g_quark_from_static_string ("web_server_error");
+        return quark;
+}
+
+GType
+web_server_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (WebServerClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) web_server_class_init,
+			NULL,
+			NULL,
+			sizeof (WebServer),
+			0,
+			(GInstanceInitFunc) web_server_init
+		};
+		
+		g_static_mutex_lock (&registering);
+		if (type == 0)
+			type = g_type_register_static (G_TYPE_OBJECT, "WebServer", &info, 0);
+		g_static_mutex_unlock (&registering);
+	}
+
+	return type;
+}
+
+static void
+web_server_class_init (WebServerClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+	parent_class = g_type_class_peek_parent (class);
+
+
+	/* virtual functions */
+	object_class->dispose = web_server_dispose;
+	object_class->finalize = web_server_finalize;
+}
+
+static void
+web_server_init (WebServer *server)
+{
+	server->priv = g_new0 (WebServerPrivate, 1);
+	server->priv->timer = 0;
+	server->priv->tmpdata_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+							    g_free, (GDestroyNotify) tmp_data_free);
+	server->priv->tmpdata_list = NULL;
+
+	tmp_static_data_add (server, "gda.css", GDA_CSS, strlen (GDA_CSS));
+}
+
+
+static gboolean get_file (SoupServer *server, SoupMessage *msg, const char *path, GError **error);
+static void     get_root (SoupServer *server, SoupMessage *msg);
+static gboolean get_for_cnc (WebServer *webserver, SoupMessage *msg, 
+			     const ConnectionSetting *cs, gchar **extra, GError **error);
+
+
+static void
+server_callback (SoupServer *server, SoupMessage *msg,
+                 const char *path, GHashTable *query,
+                 SoupClientContext *context, WebServer *webserver)
+{
+	/*#define DEBUG_SERVER*/
+#ifdef DEBUG_SERVER
+        printf ("%s %s HTTP/1.%d\n", msg->method, path, soup_message_get_http_version (msg));
+        SoupMessageHeadersIter iter;
+        const char *name, *value;
+        soup_message_headers_iter_init (&iter, msg->request_headers);
+        while (soup_message_headers_iter_next (&iter, &name, &value))
+                printf ("%s: %s\n", name, value);
+        if (msg->request_body->length)
+                printf ("Request body: %s\n", msg->request_body->data);
+#endif
+	
+        if (msg->method == SOUP_METHOD_GET) {
+		GError *error = NULL;
+		gboolean ok = TRUE;
+		TmpData *tmpdata;
+		if (*path != '/') {
+			soup_message_set_status_full (msg, SOUP_STATUS_UNAUTHORIZED, "Wrong path name");
+			return;
+		}
+		path++;
+
+		if (*path == 0)
+			get_root (server, msg);
+		else if ((tmpdata = g_hash_table_lookup (webserver->priv->tmpdata_hash, path))) {
+			soup_message_body_append (msg->response_body, SOUP_MEMORY_STATIC,
+						  tmpdata->data, tmpdata->size);
+			soup_message_set_status (msg, SOUP_STATUS_OK);
+		}
+		else {
+			gchar **array = NULL;
+			array = g_strsplit (path, "/", 0);
+
+			const ConnectionSetting *cs;
+			cs = gda_sql_get_connection (array[0]);
+
+			if (cs) 
+				ok = get_for_cnc (webserver, msg, cs, array[1] ? &(array[1]) : NULL, &error);
+			else {
+				/*ok = get_file (webserver, msg, path, &error);*/
+				ok = FALSE;
+			}
+			if (array)
+				g_strfreev (array);
+		}
+
+		if (!ok) {
+			if (error) {
+				soup_message_set_status_full (msg, error->code, error->message);
+				g_error_free (error);
+			}
+			else
+				soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+		}
+	}
+        else
+                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+#ifdef DEBUG_SERVER
+        printf ("  -> %d %s\n\n", msg->status_code, msg->reason_phrase);
+#endif
+}
+
+/**
+ * web_server_new
+ * @type: the #GType requested
+ *
+ * Creates a new server of type @type
+ *
+ * Returns: a new #WebServer object
+ */
+WebServer *
+web_server_new (gint port)
+{
+	WebServer *server;
+
+	server = (WebServer*) g_object_new (WEB_TYPE_SERVER, NULL);
+	server->priv->server = soup_server_new (SOUP_SERVER_PORT, port,
+						SOUP_SERVER_SERVER_HEADER, "gda-sql-httpd ",
+						NULL);
+	soup_server_add_handler (server->priv->server, NULL,
+                                 (SoupServerCallback) server_callback, server, NULL);
+	
+	soup_server_run_async (server->priv->server);
+
+	return server;
+}
+
+
+static void
+web_server_dispose (GObject *object)
+{
+	WebServer *server;
+
+	server = WEB_SERVER (object);
+	if (server->priv) {
+		if (server->priv->tmpdata_hash) {
+			g_hash_table_destroy (server->priv->tmpdata_hash);
+			server->priv->tmpdata_hash = NULL;
+		}
+		if (server->priv->tmpdata_list) {
+			g_slist_free (server->priv->tmpdata_list);
+			server->priv->tmpdata_list = NULL;
+		}
+		if (server->priv->server) {
+			g_object_unref (server->priv->server);
+			server->priv->server = NULL;
+		}
+		if (server->priv->timer) {
+			g_source_remove (server->priv->timer);
+			server->priv->timer = 0;
+		}		
+	}
+
+	/* parent class */
+	parent_class->dispose (object);
+}
+
+static void
+web_server_finalize (GObject   * object)
+{
+	WebServer *server;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (WEB_IS_SERVER (object));
+
+	server = WEB_SERVER (object);
+	if (server->priv) {
+		g_free (server->priv);
+	}
+
+	/* parent class */
+	parent_class->finalize (object);
+}
+
+/*
+ * GET for a file
+ */
+static gboolean
+get_file (SoupServer *server, SoupMessage *msg, const char *path, GError **error)
+{
+	GMappedFile *mfile;
+        mfile = g_mapped_file_new (path, FALSE, error);
+	if (!mfile)
+		return FALSE;
+
+	SoupBuffer *buffer;
+	buffer = soup_buffer_new_with_owner (g_mapped_file_get_contents (mfile),
+					     g_mapped_file_get_length (mfile),
+					     mfile, (GDestroyNotify) g_mapped_file_free);
+	soup_message_body_append_buffer (msg->response_body, buffer);
+	soup_buffer_free (buffer);
+	soup_message_set_status (msg, SOUP_STATUS_OK);
+	return TRUE;
+}
+
+/*
+ * GET for the / path
+ */
+static void
+get_root (SoupServer *server, SoupMessage *msg)
+{
+	HtmlDoc *hdoc;
+	xmlChar *xstr;
+	SoupBuffer *buffer;
+	gsize size;
+
+	const GSList *list;
+	list = gda_sql_get_all_connections ();
+	if (0 && list && !list->next) {
+		/* only 1 connection => go to this one */
+		ConnectionSetting *cs = (ConnectionSetting*) list->data;
+		soup_message_set_status (msg, SOUP_STATUS_TEMPORARY_REDIRECT);
+		soup_message_headers_append (msg->response_headers, "Location", cs->name);
+		return;
+	}
+	hdoc = html_doc_new (_("Database information"));
+	if (!list) {
+		/* no connection at all */
+		xmlNodePtr node;
+
+		node = xmlNewChild (hdoc->content, NULL, "h1", _("No connection opened."));
+		node = xmlNewChild (hdoc->content, NULL, "p", _("Open a connection from the console and reload this page"));
+	}
+	else {
+		/* more than one connection, redirect to the current one */
+		const ConnectionSetting *cs = gda_sql_get_current_connection ();
+		soup_message_set_status (msg, SOUP_STATUS_TEMPORARY_REDIRECT);
+		soup_message_headers_append (msg->response_headers, "Location", cs->name);
+		return;
+	}
+
+	soup_message_headers_replace (msg->response_headers,
+				      "Content-Type", "text/html");
+	xstr = html_doc_to_string (hdoc, &size);
+	buffer = soup_buffer_new_with_owner (xstr, size, xstr, (GDestroyNotify)xmlFree);
+	soup_message_body_append_buffer (msg->response_body, buffer);
+	soup_buffer_free (buffer);
+	html_doc_free (hdoc);
+
+	soup_message_set_status (msg, SOUP_STATUS_OK);
+}
+
+static gboolean compute_all_objects_content (HtmlDoc *hdoc, const ConnectionSetting *cs, 
+					     const gchar *human_obj_type,
+					     const gchar *human_obj_type_in_schema,
+					     const gchar *table_name,
+					     const gchar *obj_prefix,
+					     const gchar *filter,
+					     GError **error);
+static gboolean compute_all_triggers_content (HtmlDoc *hdoc, const ConnectionSetting *cs, GError **error);
+static gboolean compute_object_content (HtmlDoc *hdoc, WebServer *webserver, const ConnectionSetting *cs,
+					const gchar *schema, const gchar *name, GError **error);
+/*
+ * GET method for a connection
+ */
+static gboolean
+get_for_cnc (WebServer *webserver, SoupMessage *msg, const ConnectionSetting *cs, gchar **extra, GError **error)
+{
+	gboolean retval = FALSE;
+	HtmlDoc *hdoc;
+	xmlChar *xstr;
+	SoupBuffer *buffer;
+	gsize size;
+	gchar *str;
+
+	gchar *rfc_cnc_name;
+
+	xmlNodePtr ul, li, a;
+
+	const GSList *clist;
+
+
+	str = g_strdup_printf (_("Database information for '%s'"), cs->name);
+	hdoc = html_doc_new (str);
+	g_free (str);
+
+	/* other connections in the sidebar */
+	ul = xmlNewChild (hdoc->sidebar, NULL, "ul", _("Connections"));
+	li = xmlNewChild (ul, NULL, "li", NULL);
+	str = g_strdup_printf ("(%s)",  _("From console"));
+	a = xmlNewChild (li, NULL, "a", str);
+	g_free (str);
+	xmlSetProp (a, "href", (xmlChar*) "/");
+
+	for (clist = gda_sql_get_all_connections (); clist; clist = clist->next) {
+		gchar *tmp;
+		ConnectionSetting *cs = (ConnectionSetting*) clist->data;
+			
+		li = xmlNewChild (ul, NULL, "li", NULL);
+		a = xmlNewChild (li, NULL, "a", cs->name);
+		tmp = gda_rfc1738_encode (cs->name);
+		str = g_strdup_printf ("/%s", tmp);
+		g_free (tmp);
+		xmlSetProp (a, "href", (xmlChar*) str);
+		g_free (str);
+	}
+
+	/* list all database object's types for which information can be obtained */
+	rfc_cnc_name = gda_rfc1738_encode (cs->name);
+	ul = xmlNewChild (hdoc->sidebar, NULL, "ul", _("Objects"));
+	li = xmlNewChild (ul, NULL, "li", NULL);
+	a = xmlNewChild (li, NULL, "a", _("Tables"));
+	str = g_strdup_printf ("/%s/___tables", rfc_cnc_name);
+	xmlSetProp (a, "href", (xmlChar*) str);
+	g_free (str);
+	li = xmlNewChild (ul, NULL, "li", NULL);
+	a = xmlNewChild (li, NULL, "a", _("Views"));
+	str = g_strdup_printf ("/%s/___views", rfc_cnc_name);
+	xmlSetProp (a, "href", (xmlChar*) str);
+	g_free (str);
+	li = xmlNewChild (ul, NULL, "li", NULL);
+	a = xmlNewChild (li, NULL, "a", _("Triggers"));
+	str = g_strdup_printf ("/%s/___triggers", rfc_cnc_name);
+	xmlSetProp (a, "href", (xmlChar*) str);
+	g_free (str);
+	g_free (rfc_cnc_name);
+	
+#ifdef GDA_DEBUG_NO
+	if (extra) {
+		gint i;
+		for (i = 0; extra[i]; i++) 
+			g_print ("EXTRA %d: #%s#\n", i, extra[i]);
+	}
+#endif
+	if (!extra || !strcmp (extra[0], "___tables")) {
+		if (! compute_all_objects_content (hdoc, cs, 
+						   _("Tables"), _("Tables in the '%s' schema"), 
+						   "_tables", "table", "table_type LIKE \"%TABLE%\"", error))
+			goto onerror;
+	}
+	else if (!strcmp (extra[0], "___views")) {
+		if (! compute_all_objects_content (hdoc, cs, 
+						   _("Views"), _("Views in the '%s' schema"), 
+						   "_tables", "table", "table_type LIKE \"%VIEW%\"", error))
+			goto onerror;
+	}
+	else if (!strcmp (extra[0], "___triggers")) {
+		if (! compute_all_triggers_content (hdoc, cs, error))
+			goto onerror;
+	}
+	else {
+		/* extra [0] has to be a schema */
+		if (extra [1]) {
+			if (! compute_object_content (hdoc, webserver, cs, extra [0], extra [1], error))
+				goto onerror;
+		}
+		else
+			xmlNewChild (hdoc->content, NULL, "h1", "Not yet implemented");
+	}
+
+	soup_message_headers_replace (msg->response_headers,
+				      "Content-Type", "text/html");
+	xstr = html_doc_to_string (hdoc, &size);
+	buffer = soup_buffer_new_with_owner (xstr, size, xstr, (GDestroyNotify)xmlFree);
+	soup_message_body_append_buffer (msg->response_body, buffer);
+	soup_buffer_free (buffer);
+	soup_message_set_status (msg, SOUP_STATUS_OK);
+	retval = TRUE;
+
+ onerror:
+	html_doc_free (hdoc);
+	return retval;
+}
+
+static void
+meta_table_column_foreach_attribute_func (const gchar *att_name, const GValue *value, GString **string)
+{
+	if (!strcmp (att_name, GDA_ATTRIBUTE_AUTO_INCREMENT) && 
+	    (G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) && 
+	    g_value_get_boolean (value)) {
+		if (*string) {
+			g_string_append (*string, ", ");
+			g_string_append (*string, _("Auto increment"));
+		}
+		else
+			*string = g_string_new (_("Auto increment"));
+	}
+}
+
+static gchar *meta_struct_dump_as_graph (const ConnectionSetting *cs, GdaMetaStruct *mstruct,
+					 GdaMetaDbObject *central_dbo, GError **error);
+static gboolean
+compute_table_details (const ConnectionSetting *cs, HtmlDoc *hdoc, WebServer *webserver,
+		       GdaMetaStruct *mstruct, GdaMetaDbObject *dbo, GError **error)
+{
+	gchar *tmp;
+	xmlNodePtr div, table, tr, td;
+	GdaMetaTable *mt = GDA_META_TABLE (dbo);
+	GSList *list;
+	GdaMetaStore *store;
+
+	tmp = g_strdup_printf (_("Columns for the '%s' table:"), dbo->obj_short_name);
+	xmlNewChild (hdoc->content, NULL, "h1", tmp);
+	g_free (tmp);
+
+	div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+	table = xmlNewChild (div, NULL, "table", NULL);
+	xmlSetProp (table, "class", (xmlChar*) "ctable");
+	tr = xmlNewChild (table, NULL, "tr", NULL);
+	td = xmlNewChild (tr, NULL, "th", _("Column"));
+	td = xmlNewChild (tr, NULL, "th", _("Type"));
+	td = xmlNewChild (tr, NULL, "th", _("Nullable"));
+	td = xmlNewChild (tr, NULL, "th", _("Default"));
+	td = xmlNewChild (tr, NULL, "th", _("Extra"));
+
+	for (list = mt->columns; list; list = list->next) {
+		GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
+		GString *string = NULL;
+		
+		tr = xmlNewChild (table, NULL, "tr", NULL);
+		td = xmlNewChild (tr, NULL, "td", tcol->column_name);
+		if (tcol->pkey)
+			xmlSetProp (td, "class", "pkey");
+		td = xmlNewChild (tr, NULL, "td", tcol->column_type);
+		td = xmlNewChild (tr, NULL, "td", tcol->nullok ? _("yes") : _("no"));
+		td = xmlNewChild (tr, NULL, "td", tcol->default_value);
+
+		gda_meta_table_column_foreach_attribute (tcol, 
+				    (GdaAttributesManagerFunc) meta_table_column_foreach_attribute_func, &string);
+		if (string) {
+			td = xmlNewChild (tr, NULL, "td", string->str);
+			g_string_free (string, TRUE);
+		}
+		else
+			td = xmlNewChild (tr, NULL, "td", NULL);
+	}
+
+	/* finished if we don't have a table */
+	if (dbo->obj_type != GDA_META_DB_TABLE)
+		return TRUE;
+
+	/* show primary key */
+	GdaMetaTable *dbo_table = GDA_META_TABLE (dbo);
+#ifdef NONO
+	if (dbo_table->pk_cols_nb > 0) {
+		gint ipk;
+		xmlNodePtr ul = NULL;
+		xmlNewChild (hdoc->content, NULL, "h1", _("Primary key:"));
+		div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+		for (ipk = 0; ipk < dbo_table->pk_cols_nb; ipk++) {
+			GdaMetaTableColumn *tcol;
+			if (!ul)
+				ul = xmlNewChild (div, NULL, "ul", NULL);
+
+			tcol = g_slist_nth_data (dbo_table->columns, ipk);
+			xmlNewChild (ul, NULL, "li", tcol->column_name);
+		}
+	}
+#endif
+
+	/* Add objects depending on this table */
+	if (!gda_meta_struct_complement_depend (mstruct, dbo, error))
+		return FALSE;
+	
+	/* Add tables from which this one depends */
+	GValue *v0, *v1;
+	GdaDataModel *model;
+	g_object_get (G_OBJECT (mstruct), "meta-store", &store, NULL);
+	g_value_set_string ((v0 = gda_value_new (G_TYPE_STRING)), dbo->obj_schema);
+	g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), dbo->obj_name);
+	model = gda_meta_store_extract (store, "SELECT table_catalog, table_schema, table_name FROM "
+					"_referential_constraints WHERE "
+					"ref_table_schema = ##tschema::string AND ref_table_name = ##tname::string",
+					error, "tschema", v0, "tname", v1, NULL);
+	gda_value_free (v0);
+	gda_value_free (v1);
+	g_object_unref (store);
+	if (model) {
+		gint i, nrows;
+		nrows = gda_data_model_get_n_rows (model);
+		for (i = 0; i < nrows; i++) {
+			const GValue *cv0, *cv1 = NULL, *cv2 = NULL;
+			cv0 = gda_data_model_get_value_at (model, 0, i, NULL);
+			if (cv0) {
+				cv1 = gda_data_model_get_value_at (model, 1, i, NULL);
+				if (cv1)
+					cv2 = gda_data_model_get_value_at (model, 2, i, NULL);
+			}
+			if (cv0 && cv1 && cv2)
+				gda_meta_struct_complement (mstruct, GDA_META_DB_TABLE, cv0, cv1, cv2, NULL);
+		}
+		g_object_unref (model);
+	}
+
+	/* create a graph */
+	gchar *graph, *tmp_filename = NULL;
+	xmlNodePtr map_node = NULL;
+	graph = meta_struct_dump_as_graph (cs, mstruct, dbo, NULL);
+	if (graph) {
+		gchar *dotname, *suffix;
+		static gint counter = 0;
+
+		suffix = g_strdup_printf (".gda_graph_tmp-%d.dot", ++counter);
+		dotname = g_build_filename (g_get_tmp_dir (), suffix, NULL);
+		g_free (suffix);
+
+		if (g_file_set_contents (dotname, graph, -1, error)) {
+			gchar *pngname, *mapname;
+			gchar *argv[] = {"dot", "-Tpng", "-o",  NULL, "-Tcmapx", "-o", NULL, NULL, NULL};
+			
+			suffix = g_strdup_printf (".gda_graph_tmp-%d", counter);
+			pngname = g_build_filename (g_get_tmp_dir (), suffix, NULL);
+			g_free (suffix);
+			
+			suffix = g_strdup_printf (".gda_graph_tmp-%d.map", counter);
+			mapname = g_build_filename (g_get_tmp_dir (), suffix, NULL);
+			g_free (suffix);
+
+			argv[3] = pngname;
+			argv[6] = mapname;
+			argv[7] = dotname;
+			if (g_spawn_sync (NULL, argv, NULL,
+					  G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, 
+					  NULL, NULL,
+					  NULL, NULL, NULL, NULL)) {
+				xmlDocPtr map;
+				map = xmlParseFile (mapname);
+				if (map) {
+					map_node = xmlDocGetRootElement (map);
+					xmlUnlinkNode (map_node);
+					xmlFreeDoc (map);
+				}
+
+				gchar *file_data;
+				gsize file_data_len;
+				if (g_file_get_contents (pngname, &file_data, &file_data_len, NULL)) {
+					tmp_filename = g_strdup_printf ("___tmp/g%d", counter);
+					tmp_data_add (webserver, tmp_filename, file_data, file_data_len);
+				}
+			}
+			g_unlink(pngname);
+			g_free (pngname);
+			g_unlink(mapname);
+			g_free (mapname);
+		}
+		g_unlink(dotname);
+		g_free (dotname);
+		g_free (graph);
+	}
+	if (tmp_filename) {
+		xmlNodePtr obj;
+		gchar *tmp;
+		xmlNewChild (hdoc->content, NULL, "h1", _("Relations:"));
+		div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+
+		if (map_node)
+			xmlAddChild (div, map_node);
+
+		xmlSetProp (div, "class", (xmlChar*) "graph");
+		obj = xmlNewChild (div, NULL, "img", NULL);
+		tmp = g_strdup_printf ("/%s", tmp_filename);
+		xmlSetProp (obj, "src", (xmlChar*) tmp);
+		xmlSetProp (obj, "usemap", (xmlChar*) "#G");
+		g_free (tmp);
+		g_free (tmp_filename);
+	}
+	else {
+		/* list foreign keys as we don't have a graph */
+		if (dbo_table->fk_list) {
+			xmlNewChild (hdoc->content, NULL, "h1", _("Foreign keys:"));
+			GSList *list;
+			for (list = dbo_table->fk_list; list; list = list->next) {
+				GdaMetaTableForeignKey *tfk = GDA_META_TABLE_FOREIGN_KEY (list->data);
+				GdaMetaDbObject *fkdbo = tfk->depend_on;
+				xmlNodePtr ul = NULL;
+				gint ifk;
+				
+				div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+				for (ifk = 0; ifk < tfk->cols_nb; ifk++) {
+					gchar *tmp;
+					if (!ul) {
+						tmp = g_strdup_printf (_("To '%s':"), fkdbo->obj_short_name);
+						ul = xmlNewChild (div, NULL, "ul", tmp);
+						g_free (tmp);
+					}
+					tmp = g_strdup_printf ("%s --> %s.%s", 
+							       tfk->fk_names_array[ifk], 
+							       fkdbo->obj_short_name, tfk->ref_pk_names_array[ifk]);
+					xmlNewChild (ul, NULL, "li", tmp);
+					g_free (tmp);
+				}
+			}
+		}
+	}
+
+	return TRUE;
+}
+
+/*
+ * Creates a new graph (in the GraphViz syntax) representation of @mstruct.
+ *
+ * Returns: a new string, or %NULL if an error occurred.
+ */
+static gchar *
+meta_struct_dump_as_graph (const ConnectionSetting *cs, GdaMetaStruct *mstruct, GdaMetaDbObject *central_dbo, 
+			   GError **error)
+{
+	GString *string;
+	gchar *result;
+	gchar *rfc_cnc_name;
+
+	g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
+
+	rfc_cnc_name = gda_rfc1738_encode (cs->name);
+	
+	string = g_string_new ("digraph G {\nrankdir = LR;\ndpi = 70;\nfontname = Helvetica;\nnode [shape = plaintext];\n");
+	GSList *dbo_list, *list;
+	dbo_list = gda_meta_struct_get_all_db_objects (mstruct);
+	for (list = dbo_list; list; list = list->next) {
+		gchar *objname, *fullname;
+		GdaMetaDbObject *dbo = GDA_META_DB_OBJECT (list->data);
+		GSList *list;
+
+		/* obj human readable name, and full name */
+		fullname = g_strdup_printf ("%s.%s.%s", dbo->obj_catalog, dbo->obj_schema, dbo->obj_name);
+		if (dbo->obj_short_name) 
+			objname = g_strdup (dbo->obj_short_name);
+		else if (dbo->obj_schema)
+			objname = g_strdup_printf ("%s.%s", dbo->obj_schema, dbo->obj_name);
+		else
+			objname = g_strdup (dbo->obj_name);
+
+		/* URL */
+		gchar *e0, *e1, *url;
+		e0 = gda_rfc1738_encode (dbo->obj_schema);
+		e1 = gda_rfc1738_encode (dbo->obj_name);
+		url = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
+		g_free (e0);
+		g_free (e1);
+
+		/* node */
+		switch (dbo->obj_type) {
+		case GDA_META_DB_UNKNOWN:
+			break;
+		case GDA_META_DB_TABLE:
+			g_string_append_printf (string, "\"%s\" [URL=\"%s\", tooltip=\"%s\", label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname, url, objname);
+			if (dbo == central_dbo) 
+				g_string_append_printf (string, "<TR><TD COLSPAN=\"2\" BGCOLOR=\"#729FCF;\" BORDER=\"3\">%s</TD></TR>", objname);
+			else
+				g_string_append_printf (string, "<TR><TD COLSPAN=\"2\" BGCOLOR=\"lightgrey\" BORDER=\"1\">%s</TD></TR>", objname);
+			break;
+		case GDA_META_DB_VIEW:
+			g_string_append_printf (string, "\"%s\" [URL=\"%s\", tooltip=\"%s\", label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname, url, objname);
+			g_string_append_printf (string, "<TR><TD BGCOLOR=\"yellow\" BORDER=\"1\">%s</TD></TR>", objname);
+			break;
+		default:
+			TO_IMPLEMENT;
+			g_string_append_printf (string, "\"%s\" [ shape = note label = \"%s\" ];", fullname, objname);
+			break;
+		}
+		g_free (url);
+
+		/* columns, only for tables */
+		if (dbo->obj_type == GDA_META_DB_TABLE) {
+			GdaMetaTable *mt = GDA_META_TABLE (dbo);
+			GSList *depend_dbo_list = NULL;
+			for (list = mt->columns; list; list = list->next) {
+				GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
+				if (tcol->pkey)
+					g_string_append_printf (string, "<TR><TD ALIGN=\"left\"><FONT COLOR=\"blue\">%s</FONT></TD></TR>", 
+								tcol->column_name);
+				else
+					g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD></TR>", 
+								tcol->column_name);
+			}
+			g_string_append (string, "</TABLE>>];\n");
+			/* foreign keys */
+			for (list = mt->fk_list; list; list = list->next) {
+				GdaMetaTableForeignKey *tfk = GDA_META_TABLE_FOREIGN_KEY (list->data);
+				GString *st = NULL;
+				gint fki;
+				for (fki = 0; fki < tfk->cols_nb; fki++) {
+					if (tfk->fk_names_array && tfk->ref_pk_names_array) {
+						if (!st)
+							st = g_string_new ("");
+						else
+							g_string_append (st, "\\n");
+						g_string_append_printf (st, "%s = %s",
+									tfk->fk_names_array [fki],
+									tfk->ref_pk_names_array [fki]);
+					}
+					else
+						break;
+				}
+				if (tfk->depend_on->obj_type != GDA_META_DB_UNKNOWN) {
+					g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\" [fontsize=12, label=\"%s\"];\n", 
+								fullname,
+								tfk->depend_on->obj_catalog, tfk->depend_on->obj_schema, 
+								tfk->depend_on->obj_name,
+								st ? st->str : "");
+					depend_dbo_list = g_slist_prepend (depend_dbo_list, tfk->depend_on);
+				}
+				if (st)
+					g_string_free (st, TRUE);
+			}
+
+			/* dependencies other than foreign keys */
+			for (list = dbo->depend_list; list; list = list->next) {
+				if (!g_slist_find (depend_dbo_list, list->data)) {
+					GdaMetaDbObject *dep_dbo = GDA_META_DB_OBJECT (list->data);
+					if (dep_dbo->obj_type != GDA_META_DB_UNKNOWN) 
+						g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n", 
+									fullname,
+									dep_dbo->obj_catalog, dep_dbo->obj_schema, 
+									dep_dbo->obj_name);
+				}
+			}
+
+			g_slist_free (depend_dbo_list);
+		}
+		else if (dbo->obj_type == GDA_META_DB_VIEW) {
+			GdaMetaTable *mt = GDA_META_TABLE (dbo);
+			for (list = mt->columns; list; list = list->next) {
+				GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
+				g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD></TR>", tcol->column_name);
+			}
+			g_string_append (string, "</TABLE>>];\n");
+			/* dependencies */
+			for (list = dbo->depend_list; list; list = list->next) {
+				GdaMetaDbObject *ddbo = GDA_META_DB_OBJECT (list->data);
+				if (ddbo->obj_type != GDA_META_DB_UNKNOWN) 
+					g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n", fullname,
+								ddbo->obj_catalog, ddbo->obj_schema, 
+								ddbo->obj_name);
+			}
+		}
+
+		g_free (objname);
+		g_free (fullname);
+	}
+	g_string_append_c (string, '}');
+	g_slist_free (dbo_list);
+
+	result = string->str;
+	g_string_free (string, FALSE);
+	return result;
+}
+
+static gboolean
+compute_view_details (const ConnectionSetting *cs, HtmlDoc *hdoc, GdaMetaStruct *mstruct,
+		      GdaMetaDbObject *dbo, GError **error)
+{
+	GdaMetaView *view = GDA_META_VIEW (dbo);
+	if (view->view_def) {
+		xmlNodePtr div, code;
+		xmlNewChild (hdoc->content, NULL, "h1", _("View definition:"));
+		div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+		code = xmlNewChild (div, NULL, "code", view->view_def);
+		xmlSetProp (code, "class", (xmlChar*) "ccode");
+	}
+	return TRUE;
+}
+
+/*
+ * compute information for an object assuming it's a trigger
+ *
+ * Returns: TRUE if the object was really a trigger
+ */
+static gboolean
+compute_trigger_content (HtmlDoc *hdoc, WebServer *webserver, const ConnectionSetting *cs,
+			 const gchar *schema, const gchar *name, GError **error)
+{
+	GdaMetaStore *store;
+	GdaDataModel *model;
+	GValue *v0, *v1;
+	GValue *tschema = NULL, *tname = NULL;
+	gint i, nrows;
+	xmlNodePtr code, div = NULL, sdiv, ul, li;
+
+	store = gda_connection_get_meta_store (cs->cnc);
+	g_value_set_string ((v0 = gda_value_new (G_TYPE_STRING)), schema);
+	g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), name);
+	model = gda_meta_store_extract (store, "SELECT trigger_short_name, action_statement, event_manipulation, "
+					"event_object_schema, event_object_table, trigger_comments, "
+					"action_orientation, condition_timing FROM _triggers "
+					"WHERE trigger_schema = ##tschema::string AND trigger_name = ##tname::string "
+					"ORDER BY event_object_schema, event_object_table, event_manipulation",
+					error, "tschema", v0, "tname", v1, NULL);
+	gda_value_free (v0);
+	gda_value_free (v1);
+	if (!model)
+		return FALSE;
+	nrows = gda_data_model_get_n_rows (model);
+	if (nrows == 0) {
+		g_object_unref (model);
+		return FALSE;
+	}
+
+	for (i = 0; i < nrows; i++) {
+		const GValue *cv0, *cv1, *cv2, *cv3, *cv4, *cv5, *cv6, *cv7;
+		gchar *tmp;
+
+		if (! (cv0 = gda_data_model_get_value_at (model, 0, i, error)))
+			break;
+		if (! (cv1 = gda_data_model_get_value_at (model, 1, i, error)))
+			break;
+		if (! (cv2 = gda_data_model_get_value_at (model, 2, i, error)))
+			break;
+		if (! (cv3 = gda_data_model_get_value_at (model, 3, i, error)))
+			break;
+		if (! (cv4 = gda_data_model_get_value_at (model, 4, i, error)))
+			break;
+		if (! (cv5 = gda_data_model_get_value_at (model, 5, i, error)))
+			break;
+		if (! (cv6 = gda_data_model_get_value_at (model, 6, i, error)))
+			break;
+		if (! (cv7 = gda_data_model_get_value_at (model, 7, i, error)))
+			break;
+
+		if ((!tschema || gda_value_differ (tschema, cv3)) ||
+		    (!tname || gda_value_differ (tname, cv4))) {
+			if (tschema) 
+				xmlNewChild (div, NULL, "br", NULL);
+			if (tschema) 
+				gda_value_free (tschema);
+			if (tname)
+				gda_value_free (tname);
+			tschema = gda_value_copy (cv3);
+			tname = gda_value_copy (cv4);
+
+			tmp = g_strdup_printf (_("Trigger '%s' for the '%s.%s' table:"),
+					       g_value_get_string (cv0),
+					       g_value_get_string (tschema),
+					       g_value_get_string (tname));
+			xmlNewChild (hdoc->content, NULL, "h1", tmp);
+			g_free (tmp);
+
+			div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+		}
+
+		if (G_VALUE_TYPE (cv5) != GDA_TYPE_NULL)
+			tmp = g_strdup_printf ("On %s (%s):", g_value_get_string (cv2), g_value_get_string (cv5));
+		else
+			tmp = g_strdup_printf ("On %s:", g_value_get_string (cv2));
+		xmlNewChild (div, NULL, "h2", tmp);
+		g_free (tmp);
+
+		sdiv = xmlNewChild (div, NULL, "div", NULL);
+		ul = xmlNewChild (sdiv, NULL, "ul", NULL);
+
+		tmp = g_strdup_printf (_("Trigger fired for: %s"), g_value_get_string (cv6));
+		li = xmlNewChild (ul, NULL, "li", tmp);
+		g_free (tmp);
+
+		tmp = g_strdup_printf (_("Time at which the trigger is fired: %s"), g_value_get_string (cv7));
+		li = xmlNewChild (ul, NULL, "li", tmp);
+		g_free (tmp);
+
+		li = xmlNewChild (ul, NULL, "li", _("Action:"));
+		code = xmlNewChild (li, NULL, "code", g_value_get_string (cv1));
+		xmlSetProp (code, "class", (xmlChar*) "ccode");
+	}
+	
+	
+	g_object_unref (model);
+	return TRUE;
+}
+
+/*
+ * Give details about a database object
+ */
+static gboolean
+compute_object_content (HtmlDoc *hdoc, WebServer *webserver, const ConnectionSetting *cs,
+			const gchar *schema, const gchar *name, GError **error)
+{
+	GdaMetaStruct *mstruct;
+	GdaMetaDbObject *dbo;
+	GValue *v0, *v1;
+	gboolean retval;
+
+	if (gda_sql_identifier_needs_quotes (schema))
+		g_value_take_string ((v0 = gda_value_new (G_TYPE_STRING)),
+				     gda_sql_identifier_add_quotes (schema));
+	else
+		g_value_set_string ((v0 = gda_value_new (G_TYPE_STRING)), schema);
+	if (gda_sql_identifier_needs_quotes (name))
+		g_value_take_string ((v1 = gda_value_new (G_TYPE_STRING)),
+				     gda_sql_identifier_add_quotes (name));
+	else
+		g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), name);
+
+	mstruct = gda_meta_struct_new (gda_connection_get_meta_store (cs->cnc),
+				       GDA_META_STRUCT_FEATURE_ALL);
+	dbo = gda_meta_struct_complement (mstruct, GDA_META_DB_UNKNOWN, NULL, v0, v1, error);
+	gda_value_free (v0);
+	gda_value_free (v1);
+	if (!dbo) {
+		if (compute_trigger_content (hdoc, webserver, cs, schema, name, error))
+			return TRUE;
+		TO_IMPLEMENT;
+		return FALSE;
+	}
+	
+	switch (dbo->obj_type) {
+	case GDA_META_DB_TABLE:
+		retval = compute_table_details (cs, hdoc, webserver, mstruct, dbo, error);
+		break;
+	case GDA_META_DB_VIEW:
+		retval = compute_table_details (cs, hdoc, webserver, mstruct, dbo, error);
+		if (retval)
+			retval = compute_view_details (cs, hdoc, mstruct, dbo, error);
+		break;
+	default:
+		TO_IMPLEMENT;
+	}
+	g_object_unref (mstruct);
+	return TRUE;
+}
+
+
+/*
+ * Lists all objects of a type (tables, view, ...)
+ */
+static gboolean
+compute_all_objects_content (HtmlDoc *hdoc, const ConnectionSetting *cs, 
+			     const gchar *human_obj_type,
+			     const gchar *human_obj_type_in_schema,
+			     const gchar *table_name,
+			     const gchar *obj_prefix,
+			     const gchar *filter,
+			     GError **error)
+{
+	gboolean retval = FALSE;
+	gchar *rfc_cnc_name;
+	GdaMetaStore *store;
+	GdaDataModel *model;
+	gint i, nrows;
+	gchar *sql;
+	GValue *schema = NULL;
+	xmlNodePtr ul, li, a, div = NULL;
+	gboolean content_added = FALSE;
+
+	rfc_cnc_name = gda_rfc1738_encode (cs->name);
+
+	store = gda_connection_get_meta_store (cs->cnc);
+
+	/* objects directly accessible */
+	if (filter)
+		sql = g_strdup_printf ("SELECT %s_schema, %s_name FROM %s WHERE %s "
+				       "AND %s_short_name != %s_full_name ORDER BY %s_schema, %s_name",
+				       obj_prefix, obj_prefix, table_name, filter, obj_prefix, obj_prefix,
+				       obj_prefix, obj_prefix);
+	else
+		sql = g_strdup_printf ("SELECT %s_schema, %s_name FROM %s WHERE "
+				       "%s_short_name != %s_full_name ORDER BY %s_schema, %s_name",
+				       obj_prefix, obj_prefix, table_name, obj_prefix, obj_prefix,
+				       obj_prefix, obj_prefix);
+
+	model = gda_meta_store_extract (store, sql, error, NULL);
+	g_free (sql);
+	if (!model)
+		goto out;
+	nrows = gda_data_model_get_n_rows (model);
+	if (nrows > 0) {
+		xmlNewChild (hdoc->content, NULL, "h1", human_obj_type);
+		div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+		xmlSetProp (div, "class", "clist");
+		ul = xmlNewChild (div, NULL, "ul", NULL);
+		content_added = TRUE;
+	}
+	for (i = 0; i < nrows; i++) {
+		const GValue *cv0, *cv1;
+		gchar *tmp, *e0, *e1;
+		cv0 = gda_data_model_get_value_at (model, 0, i, error);
+		if (!cv0)
+			goto out;
+		cv1 = gda_data_model_get_value_at (model, 1, i, error);
+		if (!cv1)
+			goto out;
+		li = xmlNewChild (ul, NULL, "li", NULL);
+		a = xmlNewChild (li, NULL, "a", g_value_get_string (cv1));
+		e0 = gda_rfc1738_encode (g_value_get_string (cv0));
+		e1 = gda_rfc1738_encode (g_value_get_string (cv1));
+		tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
+		g_free (e0);
+		g_free (e1);
+		xmlSetProp (a, "href", tmp);
+		g_free (tmp);
+		tmp = g_strdup_printf ("%s.%s", g_value_get_string (cv0), g_value_get_string (cv1));
+		xmlSetProp (a, "title", tmp);
+		g_free (tmp);
+	}
+	if (nrows > 0)
+		xmlNewChild (div, NULL, "br", NULL);
+	g_object_unref (model);
+
+	/* objects listed by schema */
+	if (filter)
+		sql = g_strdup_printf ("SELECT %s_schema, %s_name FROM %s WHERE %s "
+				       "ORDER BY %s_schema, %s_name",
+				       obj_prefix, obj_prefix, table_name, filter, obj_prefix, obj_prefix);
+	else
+		sql = g_strdup_printf ("SELECT %s_schema, %s_name FROM %s "
+				       "ORDER BY %s_schema, %s_name",
+				       obj_prefix, obj_prefix, table_name,  obj_prefix, obj_prefix);
+	model = gda_meta_store_extract (store, sql, error, NULL);
+	g_free (sql);
+	if (!model)
+		goto out;
+
+	nrows = gda_data_model_get_n_rows (model);
+	for (i = 0; i < nrows; i++) {
+		const GValue *cv0, *cv1;
+		gchar *tmp, *e0, *e1;
+
+		cv0 = gda_data_model_get_value_at (model, 0, i, error);
+		if (!cv0)
+			goto out;
+		cv1 = gda_data_model_get_value_at (model, 1, i, error);
+		if (!cv1)
+			goto out;
+		if (!schema || gda_value_differ (schema, cv0)) {
+			xmlNodePtr header;
+			gchar *tmp;
+			if (schema) {
+				xmlNewChild (div, NULL, "br", NULL);
+				gda_value_free (schema);
+			}
+			schema = gda_value_copy (cv0);
+			tmp = g_strdup_printf (human_obj_type_in_schema, g_value_get_string (schema));
+			header = xmlNewChild (hdoc->content, NULL, "h1", tmp);
+			g_free (tmp);
+			content_added = TRUE;
+			div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+			xmlSetProp (div, "class", "clist");
+			ul = xmlNewChild (div, NULL, "ul", NULL);
+		}
+
+		li = xmlNewChild (ul, NULL, "li", NULL);
+		a = xmlNewChild (li, NULL, "a", g_value_get_string (cv1));
+		e0 = gda_rfc1738_encode (g_value_get_string (cv0));
+		e1 = gda_rfc1738_encode (g_value_get_string (cv1));
+		tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
+		g_free (e0);
+		g_free (e1);
+		xmlSetProp (a, "href", tmp);
+		g_free (tmp);
+	}
+	if (nrows != 0)
+		xmlNewChild (div, NULL, "br", NULL);
+	retval = TRUE;
+
+	if (! content_added) 
+		xmlNewChild (hdoc->content, NULL, "br", NULL);
+
+ out:
+	if (schema)
+		gda_value_free (schema);
+	if (model)
+		g_object_unref (model);
+	g_free (rfc_cnc_name);
+
+	return retval;
+}
+
+/*
+ * Lists all objects of a type (tables, view, ...)
+ */
+static gboolean
+compute_all_triggers_content (HtmlDoc *hdoc, const ConnectionSetting *cs, GError **error)
+{
+	gboolean retval = FALSE;
+	gchar *rfc_cnc_name;
+	GdaMetaStore *store;
+	GdaDataModel *model;
+	gint i, nrows;
+	GValue *schema = NULL, *tschema = NULL, *tname = NULL;
+	xmlNodePtr ul, sul, li, a, div = NULL, sdiv = NULL;
+	gboolean content_added = FALSE;
+
+	rfc_cnc_name = gda_rfc1738_encode (cs->name);
+
+	store = gda_connection_get_meta_store (cs->cnc);
+
+	model = gda_meta_store_extract (store, "SELECT trigger_schema, trigger_name, event_manipulation, "
+					"event_object_schema, event_object_table FROM _triggers WHERE "
+					"trigger_short_name != trigger_full_name "
+					"ORDER BY trigger_schema, trigger_name, event_object_schema, "
+					"event_object_table, event_manipulation",
+					error, NULL);
+	if (!model)
+		goto out;
+	nrows = gda_data_model_get_n_rows (model);
+	if (nrows > 0) {
+		xmlNewChild (hdoc->content, NULL, "h1", _("Triggers:"));
+		div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+		xmlSetProp (div, "class", "clist");
+		content_added = TRUE;
+	}
+	for (i = 0; i < nrows; i++) {
+		const GValue *cv0, *cv1, *cv2, *cv3, *cv4;
+		gchar *tmp, *e0, *e1;
+
+		if (! (cv0 = gda_data_model_get_value_at (model, 0, i, error)))
+			goto out;
+		if (! (cv1 = gda_data_model_get_value_at (model, 1, i, error)))
+			goto out;
+		if (! (cv2 = gda_data_model_get_value_at (model, 2, i, error)))
+			goto out;
+		if (! (cv3 = gda_data_model_get_value_at (model, 3, i, error)))
+			goto out;
+		if (! (cv4 = gda_data_model_get_value_at (model, 4, i, error)))
+			goto out;
+		
+		if ((!tschema || gda_value_differ (tschema, cv3)) ||
+		    (!tname || gda_value_differ (tname, cv4))) {
+			gchar *tmp;
+			if (tschema) 
+				xmlNewChild (sdiv, NULL, "br", NULL);
+			if (tschema) 
+				gda_value_free (tschema);
+			if (tname)
+				gda_value_free (tname);
+			tschema = gda_value_copy (cv3);
+			tname = gda_value_copy (cv4);
+
+			tmp = g_strdup_printf (_("For the '%s.%s' table:"), g_value_get_string (tschema),
+					       g_value_get_string (tname));
+			xmlNewChild (div, NULL, "h2", tmp);
+			g_free (tmp);
+
+			sdiv = xmlNewChild (div, NULL, "div", NULL);
+			xmlSetProp (sdiv, "class", "clist");
+			sul = xmlNewChild (sdiv, NULL, "ul", NULL);
+		}
+
+		li = xmlNewChild (sul, NULL, "li", NULL);
+		tmp = g_strdup_printf ("%s (%s)", g_value_get_string (cv1), g_value_get_string (cv2));
+		a = xmlNewChild (li, NULL, "a", tmp);
+		g_free (tmp);
+
+		e0 = gda_rfc1738_encode (g_value_get_string (cv0));
+		e1 = gda_rfc1738_encode (g_value_get_string (cv1));
+		tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
+		g_free (e0);
+		g_free (e1);
+		xmlSetProp (a, "href", tmp);
+		g_free (tmp);
+	}
+	if (nrows > 0)
+		xmlNewChild (sdiv, NULL, "br", NULL);
+	g_object_unref (model);
+	if (tschema) {
+		gda_value_free (tschema);
+		tschema = NULL;
+	}
+	if (tname) {
+		gda_value_free (tname);
+		tname = NULL;
+	}
+
+	/* objects listed by schema */
+	model = gda_meta_store_extract (store, "SELECT trigger_schema, trigger_name, event_manipulation, "
+					"event_object_schema, event_object_table FROM _triggers "
+					"ORDER BY trigger_schema, trigger_name, event_object_schema, "
+					"event_object_table, event_manipulation",
+					error, NULL);
+	if (!model)
+		goto out;
+
+	nrows = gda_data_model_get_n_rows (model);
+	for (i = 0; i < nrows; i++) {
+		const GValue *cv0, *cv1, *cv2, *cv3, *cv4;
+		gchar *tmp, *e0, *e1;
+
+		if (! (cv0 = gda_data_model_get_value_at (model, 0, i, error)))
+			goto out;
+		if (! (cv1 = gda_data_model_get_value_at (model, 1, i, error)))
+			goto out;
+		if (! (cv2 = gda_data_model_get_value_at (model, 2, i, error)))
+			goto out;
+		if (! (cv3 = gda_data_model_get_value_at (model, 3, i, error)))
+			goto out;
+		if (! (cv4 = gda_data_model_get_value_at (model, 4, i, error)))
+			goto out;
+		if (!schema || gda_value_differ (schema, cv0)) {
+			gchar *tmp;
+			if (schema) {
+				xmlNewChild (sdiv, NULL, "br", NULL);
+				gda_value_free (schema);
+			}
+			schema = gda_value_copy (cv0);
+			tmp = g_strdup_printf (_("Triggers in the '%s' schema:"), g_value_get_string (schema));
+			xmlNewChild (hdoc->content, NULL, "h1", tmp);
+			g_free (tmp);
+			content_added = TRUE;
+			div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+			xmlSetProp (div, "class", "clist");
+
+			if (tschema) {
+				gda_value_free (tschema);
+				tschema = NULL;
+			}
+			if (tname) {
+				gda_value_free (tname);
+				tname = NULL;
+			}
+		}
+		if ((!tschema || gda_value_differ (tschema, cv3)) ||
+		    (!tname || gda_value_differ (tname, cv4))) {
+			gchar *tmp;
+			if (tschema) 
+				xmlNewChild (sdiv, NULL, "br", NULL);
+			if (tschema) 
+				gda_value_free (tschema);
+			if (tname)
+				gda_value_free (tname);
+			tschema = gda_value_copy (cv3);
+			tname = gda_value_copy (cv4);
+
+			tmp = g_strdup_printf (_("For the '%s.%s' table:"), g_value_get_string (tschema),
+					       g_value_get_string (tname));
+			xmlNewChild (div, NULL, "h2", tmp);
+			g_free (tmp);
+
+			sdiv = xmlNewChild (div, NULL, "div", NULL);
+			xmlSetProp (sdiv, "class", "clist");
+			sul = xmlNewChild (sdiv, NULL, "ul", NULL);
+		}
+
+		li = xmlNewChild (sul, NULL, "li", NULL);
+		tmp = g_strdup_printf ("%s (%s)", g_value_get_string (cv1), g_value_get_string (cv2));
+		a = xmlNewChild (li, NULL, "a", tmp);
+		g_free (tmp);
+
+		e0 = gda_rfc1738_encode (g_value_get_string (cv0));
+		e1 = gda_rfc1738_encode (g_value_get_string (cv1));
+		tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
+		g_free (e0);
+		g_free (e1);
+		xmlSetProp (a, "href", tmp);
+		g_free (tmp);
+	}
+	if (nrows != 0)
+		xmlNewChild (sdiv, NULL, "br", NULL);
+	retval = TRUE;
+
+	if (! content_added) 
+		xmlNewChild (hdoc->content, NULL, "br", NULL);
+
+ out:
+	if (schema)
+		gda_value_free (schema);
+	if (tschema) 
+		gda_value_free (tschema);
+	if (tname)
+		gda_value_free (tname);
+
+	if (model)
+		g_object_unref (model);
+	g_free (rfc_cnc_name);
+
+	return retval;
+}

Added: trunk/tools/web-server.h
==============================================================================
--- (empty file)
+++ trunk/tools/web-server.h	Wed Dec 10 21:11:52 2008
@@ -0,0 +1,66 @@
+/* web-server.h
+ *
+ * Copyright (C) 2008 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __WEB_SERVER_H_
+#define __WEB_SERVER_H_
+
+#include "gda-sql.h"
+
+G_BEGIN_DECLS
+
+#define WEB_TYPE_SERVER          (web_server_get_type())
+#define WEB_SERVER(obj)          G_TYPE_CHECK_INSTANCE_CAST (obj, web_server_get_type(), WebServer)
+#define WEB_SERVER_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, web_server_get_type (), WebServerClass)
+#define WEB_IS_SERVER(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, web_server_get_type ())
+
+typedef struct _WebServer WebServer;
+typedef struct _WebServerClass WebServerClass;
+typedef struct _WebServerPrivate WebServerPrivate;
+
+
+/* error reporting */
+extern GQuark web_server_error_quark (void);
+#define WEB_SERVER_ERROR web_server_error_quark ()
+
+typedef enum {
+	WEB_SERVER__ERROR,
+} WebServerError;
+
+/* struct for the object's data */
+struct _WebServer
+{
+	GObject                 object;
+	WebServerPrivate       *priv;
+};
+
+
+/* struct for the object's class */
+struct _WebServerClass
+{
+	GObjectClass               parent_class;
+};
+
+GType               web_server_get_type                (void) G_GNUC_CONST;
+WebServer          *web_server_new                     (gint port);
+
+G_END_DECLS
+
+#endif



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