libgda r3221 - in trunk: . doc/C doc/C/tmpl libgda libgda/sqlite providers/freetds providers/ibmdb2 providers/mdb providers/msql providers/mysql providers/postgres providers/sybase samples/BDB samples/TableCopy tests tests/value-holders tools



Author: vivien
Date: Thu Oct  2 18:43:14 2008
New Revision: 3221
URL: http://svn.gnome.org/viewvc/libgda?rev=3221&view=rev

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

	* tools/command-exec.[ch]:
	* tools/gda-sql.c:
	  - command arguments can be surrounded with simple or double quotes (quotes
	    can also be escaped in the string)
	  - don't output empty lines after results
	* libgda/gda-connection.[ch]: applied (modified) patch for bug #539754
	* libgda/gda-attributes-manager.[ch]: new attributes manager
	* gda-holder.[ch]:
	  - new gda_holder_get_attribute() and gda_holder_set_attribute() which use the new
	    attributes manager
	  - internally use the attributes manager to store name and desctiption
	  - removed the "plugin" property which was a left-over from V3
	* gda-column.[ch]:
	  - new gda_column_get_attribute() and gda_column_set_attribute() which use the new
	    attributes manager
	  - internally use the attributes manager to store name and desctiption
	* libgda/gda-meta-struct-io.c:
	* tools/command-exec.c:
	* libgda/gda-meta-struct.[ch]: new gda_meta_table_column_get_attribute(),
	gda_meta_table_column_set_attribute() and gda_meta_table_column_foreach_attribute() which
	replace the GdaMetaTableColumn::extra attribute (more flexibility)
	* providers/postgres/gda-postgres-recordset.c:
	* providers/mdb/gda-mdb-provider.c:
	* providers/ibmdb2/gda-ibmdb2-recordset.c:
	* providers/mysql/gda-mysql-recordset.c:
	* providers/freetds/gda-freetds-recordset.c:
	* providers/sybase/gda-sybase-recordset.c:
	* providers/msql/gda-msql-recordset.c:
	* samples/BDB/custom-bdb-model.c:
	* libgda/sqlite/gda-sqlite-recordset.c:
	* libgda/sqlite/gda-sqlite-provider.c:
	* libgda/gda-data-model-dsn-list.c:
	* libgda/gda-data-model-import.c:
	* libgda/gda-data-model.c:
	* libgda/gda-data-proxy.c:
	* libgda/gda-data-model-array.c:
	* libgda/gda-server-provider-extra.c:
	* libgda/gda-data-model-bdb.c:
	* libgda/gda-data-model-dir.c:
	* libgda/gda-data-model-iter.c:
	* gda-column.[ch]: renamed gda_column_[gs]et_title() to gda_column_[gs]et_description()
	* libgda/sqlite/gda-sqlite-meta.c: fixed a bug in the fill_key_columns_model() function
	* doc/C: doc updates


Added:
   trunk/doc/C/tmpl/gda-attributes-manager.sgml
   trunk/libgda/gda-attributes-manager.c
   trunk/libgda/gda-attributes-manager.h
Modified:
   trunk/ChangeLog
   trunk/doc/C/gda-sql-manual.xml
   trunk/doc/C/libgda-4.0-docs.sgml
   trunk/doc/C/libgda-4.0-sections.txt
   trunk/doc/C/tmpl/gda-column.sgml
   trunk/doc/C/tmpl/gda-connection.sgml
   trunk/doc/C/tmpl/gda-holder.sgml
   trunk/doc/C/tmpl/gda-meta-struct.sgml
   trunk/libgda/Makefile.am
   trunk/libgda/gda-column.c
   trunk/libgda/gda-column.h
   trunk/libgda/gda-connection.c
   trunk/libgda/gda-connection.h
   trunk/libgda/gda-data-model-array.c
   trunk/libgda/gda-data-model-bdb.c
   trunk/libgda/gda-data-model-dir.c
   trunk/libgda/gda-data-model-dsn-list.c
   trunk/libgda/gda-data-model-import.c
   trunk/libgda/gda-data-model-iter.c
   trunk/libgda/gda-data-model.c
   trunk/libgda/gda-data-proxy.c
   trunk/libgda/gda-enums.h
   trunk/libgda/gda-holder.c
   trunk/libgda/gda-holder.h
   trunk/libgda/gda-meta-struct-io.c
   trunk/libgda/gda-meta-struct.c
   trunk/libgda/gda-meta-struct.h
   trunk/libgda/gda-server-provider-extra.c
   trunk/libgda/libgda.h.in
   trunk/libgda/sqlite/gda-sqlite-meta.c
   trunk/libgda/sqlite/gda-sqlite-provider.c
   trunk/libgda/sqlite/gda-sqlite-recordset.c
   trunk/providers/freetds/gda-freetds-recordset.c
   trunk/providers/ibmdb2/gda-ibmdb2-recordset.c
   trunk/providers/mdb/gda-mdb-provider.c
   trunk/providers/msql/gda-msql-recordset.c
   trunk/providers/mysql/gda-mysql-recordset.c
   trunk/providers/postgres/gda-postgres-recordset.c
   trunk/providers/sybase/gda-sybase-recordset.c
   trunk/samples/BDB/custom-bdb-model.c
   trunk/samples/TableCopy/   (props changed)
   trunk/tests/gda-ddl-creator.c
   trunk/tests/value-holders/check_holder.c
   trunk/tools/command-exec.c
   trunk/tools/command-exec.h
   trunk/tools/gda-sql.c

Modified: trunk/doc/C/gda-sql-manual.xml
==============================================================================
--- trunk/doc/C/gda-sql-manual.xml	(original)
+++ trunk/doc/C/gda-sql-manual.xml	Thu Oct  2 18:43:14 2008
@@ -33,6 +33,7 @@
 	<listitem><para>Easy command line editing and output using the Readline library and a
 	    (parametrable) pager</para></listitem>
 	<listitem><para>Works on any platform on which &LIBGDA; has been ported to.</para></listitem>
+	<listitem><para>Can list, define or remove named data sources (DSN)</para></listitem>
       </itemizedlist>
     </para>
   </sect1>
@@ -135,7 +136,6 @@
  4 | Mark Lawrencep  | 2007-12-25 00:00:00+0 |                   | SP      | MDR 
 10 | Vladimir Zirkov | 2001-01-31 00:00:00+0 |                 4 |         |     
 (5 rows)
-
 cnc1>
       </programlisting>
       The SQL dialect to be used must be understood by the database to which the connection is opened, so
@@ -146,7 +146,6 @@
 --------------
 "$user",public
 (1 row)
-
 cnc2>
       </programlisting>
     </para>
@@ -171,6 +170,61 @@
 
 </chapter>
 
+<chapter id="gda-sql-manual-dsn">
+  <title>DSN management</title>
+  <para>
+    Named data sources (DSN) can be used (like in ODBC) to name some connections and define their connection parameters,
+    it becomes easier to use them (one just has to remember the DSN name), and it becomes possible to change the 
+    connection parameters without changing any code.
+  </para>
+  <para>
+    They can be listed using the <command>.l</command> command, and details about a DSN can be listed using the same command
+    with the DSN name as argument:
+    <programlisting>
+gda> .l
+                              DSN list
+DSN                  | Description                          | Provider  
+---------------------+--------------------------------------+-----------
+Bugzilla             | Bugzilla data source                 | MySQL     
+koha                 |                                      | PostgreSQL
+SalesTest            | Test database for a sales department | SQLite    
+(3 rows)
+gda> .l SalesTest
+                              DSN 'SalesTest' description
+Attribute         | Value                                                                 
+------------------+-----------------------------------------------------------------------
+DSN               | SalesTest                                                             
+Provider          | SQLite                                                                
+Description       | Test database for a sales department                                  
+Connection string | DB_DIR=/home/user/name/.libgda;DB_NAME=sales_test
+Username          |                                                                       
+Global            | FALSE                                                                 
+(6 rows)
+gda>
+    </programlisting>
+  </para>
+  <para>
+    The <command>.lr DSN_NAME [DSN_NAME...]</command> command removes the DSN listed as arguments, and the
+    The <command>.lc</command> command creates (or modifies an existing) DSN, such as show:
+    <programlisting>
+gda> .lc my_dsn PostgreSQL://DB_NAME=my_db;HOST=moon
+gda> .l my_dsn
+        DSN 'my_dsn' description
+Attribute         | Value                  
+------------------+------------------------
+DSN               | my_dsn                 
+Provider          | PostgreSQL             
+Description       |                        
+Connection string | DB_NAME=my_db;HOST=moon
+Username          |                        
+Global            | FALSE                  
+(6 rows)
+gda>
+    </programlisting>
+  </para>
+</chapter>
+
+
 <chapter id="gda-sql-manual-open">
   <title>Connections management</title>
   <para>
@@ -193,7 +247,6 @@
 cnc1 | SQLite   | SalesTest                |         
 ia32 | SQLite   | IA32Instructions         |         
 (2 rows)
-
 ia32>
     </programlisting>
   </para>
@@ -236,7 +289,6 @@
 cnc3 |          | namespace cnc1           |         
                   namespace cnc2                     
 (3 rows)
-
 cnc3> 
       </programlisting>
       The contents of each "customers" table in each of the bound connection is accessible:
@@ -250,7 +302,6 @@
  9 | Greg Popoff     | 2007-12-25 00:00:00+0 |                 2 | SP      | MDR 
 10 | Vladimir Zirkov | 2001-01-31 00:00:00+0 |                 4 |         |     
 (5 rows)
-
 cnc3>  select * from cnc2.customers;
 id | name            | default_served_by | country | city
 ---+-----------------+-------------------+---------+-----
@@ -260,7 +311,6 @@
  9 | Greg Popoff     |                 2 | SP      | MDR 
 10 | Vladimir Zirkov |                 4 |         |     
 (5 rows)
-
 cnc3> 
       </programlisting>
       The list of customers present in both tables are available as:
@@ -274,7 +324,6 @@
  9 | Greg Popoff     | 2007-12-25 00:00:00+0 |                 2 | SP      | MDR 
 10 | Vladimir Zirkov | 2001-01-31 00:00:00+0 |                 4 |         |     
 (5 rows)
-
 cnc3>
       </programlisting>
     </para>
@@ -332,7 +381,6 @@
 main   | _views                           | BASE TABLE |       |            
 main   | gda_sql_query_buffers            | BASE TABLE |       |            
 (25 rows)
-
 ~cnc1> SELECT table_name FROM _tables;
 table_name     
 ---------------
@@ -348,7 +396,6 @@
 products       
 products_copied
 (11 rows)
-
 ~cnc1> .c ~
 cnc1>
       </programlisting>
@@ -361,7 +408,6 @@
 cnc1  | SQLite   | SalesTest                                             |         
 ~cnc1 | SQLite   | DB_DIR=/home/vivien/.libgda;DB_NAME=gda-sql-SalesTest |         
 (2 rows)
-
 cnc1>
       </programlisting>
     </para>
@@ -394,14 +440,12 @@
 main   | salesrep        | BASE TABLE |       |            
 main   | warehouses      | BASE TABLE |       |            
 (11 rows)
-
 cnc1> .dt customers
                List of tables
 Schema | Name      | Type       | Owner | Description
 -------+-----------+------------+-------+------------
 main   | customers | BASE TABLE |       |            
 (1 row)
-
 cnc1>
 	</programlisting>
       </para>
@@ -460,7 +504,6 @@
 -------+--------------+------+-------+------------
 main   | cust_summary | VIEW |       |            
 (1 row)
-
 cnc1>
 	</programlisting>
       </para>
@@ -475,7 +518,6 @@
 name     | string | yes      |         |      
 shortcut | string | yes      |         |      
 (2 rows)
-
 View definition: CREATE VIEW cust_summary as SELECT c.name, l.shortcut FROM customers c LEFT JOIN locations l ON (c.country=l.country AND c.city=l.city)
 cnc1>
 	</programlisting>
@@ -499,7 +541,6 @@
 pg_toast_temp_1    | postgres | yes     
 public             | postgres | no      
 (6 rows)
-
 cnc1>
 	</programlisting>
       </para>
@@ -528,7 +569,6 @@
 pg_sync_pg_auth_members | DELETE             | pg_auth_members   
 pg_sync_pg_auth_members | UPDATE             | pg_auth_members   
 (9 rows)
-
 ~cnc2>
 	</programlisting>
       </para>
@@ -570,7 +610,6 @@
                     order by o.creation_date;                                                             
                                                                                                           
 (1 row)
-
 SalesTest>
       </programlisting>
     </para>
@@ -591,7 +630,6 @@
 Ed Lamton      | 2006-02-05    |      0
 Ed Lamton      | 2006-03-29    |      0
 (9 rows)
-
 SalesTest>
       </programlisting>
     </para>
@@ -617,20 +655,17 @@
 ---+------------+-------------------+---------+-----
  3 | Lew Bonito |                 1 | FR      | TLS 
 (1 row)
-
 SalesTest> .set theid 5
 SalesTest> select * from customers where id = ##theid::int;
 id | name | default_served_by | country | city
 ---+------+-------------------+---------+-----
 (0 rows)
-
 SalesTest> .set
 List of defined parameters
 Name  | Value
 ------+------
 theid | 5    
 (1 row)
-
 SalesTest>
     </programlisting>
     </para>

Modified: trunk/doc/C/libgda-4.0-docs.sgml
==============================================================================
--- trunk/doc/C/libgda-4.0-docs.sgml	(original)
+++ trunk/doc/C/libgda-4.0-docs.sgml	Thu Oct  2 18:43:14 2008
@@ -111,6 +111,7 @@
 <!ENTITY howto SYSTEM "howto.xml">
 <!ENTITY libgda-TreeIndex SYSTEM "xml/tree_index.sgml">
 <!ENTITY GdaSqlManual SYSTEM "gda-sql-manual.xml">
+<!ENTITY GdaAttributesManager SYSTEM "xml/gda-attributes-manager.xml">
 ]>
 
 <book id="index">
@@ -915,6 +916,7 @@
       &libgda-GdaMutex;
       &libgda-GdaLockable;
       &libgda-GdaThreader;
+      &GdaAttributesManager;
     </chapter>
   </part>
 

Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt	(original)
+++ trunk/doc/C/libgda-4.0-sections.txt	Thu Oct  2 18:43:14 2008
@@ -6,8 +6,8 @@
 gda_column_copy
 gda_column_get_name
 gda_column_set_name
-gda_column_get_title
-gda_column_set_title
+gda_column_get_description
+gda_column_set_description
 gda_column_get_dbms_type
 gda_column_set_dbms_type
 gda_column_get_g_type
@@ -20,6 +20,8 @@
 gda_column_set_position
 gda_column_get_default_value
 gda_column_set_default_value
+gda_column_get_attribute
+gda_column_set_attribute
 <SUBSECTION Standard>
 GDA_COLUMN
 GDA_COLUMN_CLASS
@@ -30,6 +32,24 @@
 </SECTION>
 
 <SECTION>
+<FILE>gda-attributes-manager</FILE>
+<TITLE>Attributes manager</TITLE>
+GDA_ATTRIBUTE_NAME
+GDA_ATTRIBUTE_DESCRIPTION
+GDA_ATTRIBUTE_AUTO_INCREMENT
+GDA_ATTRIBUTE_NUMERIC_PRECISION
+GDA_ATTRIBUTE_NUMERIC_SCALE
+<SUBSECTION>
+GdaAttributesManager
+gda_attributes_manager_new
+gda_attributes_manager_free
+gda_attributes_manager_set
+gda_attributes_manager_get
+gda_attributes_manager_copy
+gda_attributes_manager_clear
+</SECTION>
+
+<SECTION>
 <FILE>gda-config</FILE>
 <TITLE>Configuration</TITLE>
 GdaConfig
@@ -129,6 +149,7 @@
 gda_connection_update_meta_store
 GdaConnectionMetaType
 gda_connection_get_meta_store_data
+gda_connection_get_meta_store_data_v
 <SUBSECTION>
 gda_connection_lock
 gda_connection_trylock
@@ -1005,6 +1026,8 @@
 gda_holder_get_source_model
 gda_holder_set_bind
 gda_holder_get_bind
+gda_holder_get_attribute
+gda_holder_set_attribute
 <SUBSECTION Standard>
 GDA_IS_HOLDER
 GDA_HOLDER
@@ -1326,6 +1349,9 @@
 GdaMetaView
 GdaMetaTableColumn
 GDA_META_TABLE_COLUMN
+gda_meta_table_column_get_attribute
+gda_meta_table_column_set_attribute
+gda_meta_table_column_foreach_attribute
 GdaMetaTableForeignKey
 GDA_META_TABLE_FOREIGN_KEY
 GDA_META_STRUCT_ERROR

Added: trunk/doc/C/tmpl/gda-attributes-manager.sgml
==============================================================================
--- (empty file)
+++ trunk/doc/C/tmpl/gda-attributes-manager.sgml	Thu Oct  2 18:43:14 2008
@@ -0,0 +1,132 @@
+<!-- ##### SECTION Title ##### -->
+Attributes manager
+
+<!-- ##### SECTION Short_Description ##### -->
+Manager for lists of attributes
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+  The #GdaAttributesManager manages lists of named values (attibutes) for the benefit of 
+  others (objects or ressources for which only a pointer is known). It is used internally by &LIBGDA;
+  whenever an object or a simple structure may have several attributes.
+</para>
+<para>
+  The features are similar to those of the <link linkend="g-object-set-data">g_object_set_data()</link> and similar
+  but with the following major differences:
+  <itemizedlist>
+    <listitem><para>it works with GObject objects and also with simple pointers to data</para></listitem>
+    <listitem><para>attributes names are considered static (they are not copied) and so they must either be static strings
+	or allocated strings which exist (unchanged) while an attribute uses it as name</para></listitem>
+    <listitem><para>it is possible to iterate through the attributes</para></listitem>
+    <listitem><para>the associated values are expected to be #GValue values</para></listitem>
+  </itemizedlist>
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### MACRO GDA_ATTRIBUTE_NAME ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO GDA_ATTRIBUTE_DESCRIPTION ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO GDA_ATTRIBUTE_AUTO_INCREMENT ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO GDA_ATTRIBUTE_NUMERIC_PRECISION ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO GDA_ATTRIBUTE_NUMERIC_SCALE ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### STRUCT GdaAttributesManager ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION gda_attributes_manager_new ##### -->
+<para>
+
+</para>
+
+ for_objects: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_attributes_manager_free ##### -->
+<para>
+
+</para>
+
+ mgr: 
+
+
+<!-- ##### FUNCTION gda_attributes_manager_set ##### -->
+<para>
+
+</para>
+
+ mgr: 
+ ptr: 
+ att_name: 
+ value: 
+
+
+<!-- ##### FUNCTION gda_attributes_manager_get ##### -->
+<para>
+
+</para>
+
+ mgr: 
+ ptr: 
+ att_name: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_attributes_manager_copy ##### -->
+<para>
+
+</para>
+
+ from_mgr: 
+ from: 
+ to_mgr: 
+ to: 
+
+
+<!-- ##### FUNCTION gda_attributes_manager_clear ##### -->
+<para>
+
+</para>
+
+ mgr: 
+ ptr: 
+
+

Modified: trunk/doc/C/tmpl/gda-column.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-column.sgml	(original)
+++ trunk/doc/C/tmpl/gda-column.sgml	Thu Oct  2 18:43:14 2008
@@ -80,7 +80,7 @@
 @name: 
 
 
-<!-- ##### FUNCTION gda_column_get_title ##### -->
+<!-- ##### FUNCTION gda_column_get_description ##### -->
 <para>
 
 </para>
@@ -89,7 +89,7 @@
 @Returns: 
 
 
-<!-- ##### FUNCTION gda_column_set_title ##### -->
+<!-- ##### FUNCTION gda_column_set_description ##### -->
 <para>
 
 </para>
@@ -206,3 +206,23 @@
 @default_value: 
 
 
+<!-- ##### FUNCTION gda_column_get_attribute ##### -->
+<para>
+
+</para>
+
+ column: 
+ attribute: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_column_set_attribute ##### -->
+<para>
+
+</para>
+
+ column: 
+ attribute: 
+ value: 
+
+

Modified: trunk/doc/C/tmpl/gda-connection.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-connection.sgml	(original)
+++ trunk/doc/C/tmpl/gda-connection.sgml	Thu Oct  2 18:43:14 2008
@@ -529,3 +529,15 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION gda_connection_get_meta_store_data_v ##### -->
+<para>
+
+</para>
+
+ cnc: 
+ meta_type: 
+ filters: 
+ error: 
+ Returns: 
+
+

Modified: trunk/doc/C/tmpl/gda-holder.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-holder.sgml	(original)
+++ trunk/doc/C/tmpl/gda-holder.sgml	Thu Oct  2 18:43:14 2008
@@ -77,11 +77,6 @@
 
 </para>
 
-<!-- ##### ARG GdaHolder:plugin ##### -->
-<para>
-
-</para>
-
 <!-- ##### ARG GdaHolder:simple-bind ##### -->
 <para>
 
@@ -337,3 +332,23 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION gda_holder_get_attribute ##### -->
+<para>
+
+</para>
+
+ holder: 
+ attribute: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_holder_set_attribute ##### -->
+<para>
+
+</para>
+
+ holder: 
+ attribute: 
+ value: 
+
+

Modified: trunk/doc/C/tmpl/gda-meta-struct.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-meta-struct.sgml	(original)
+++ trunk/doc/C/tmpl/gda-meta-struct.sgml	Thu Oct  2 18:43:14 2008
@@ -208,7 +208,6 @@
 @pkey: 
 @nullok: 
 @default_value: 
- extra: 
 
 <!-- ##### MACRO GDA_META_TABLE_COLUMN ##### -->
 <para>
@@ -218,6 +217,36 @@
 @x: 
 
 
+<!-- ##### FUNCTION gda_meta_table_column_get_attribute ##### -->
+<para>
+
+</para>
+
+ tcol: 
+ att_name: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_meta_table_column_set_attribute ##### -->
+<para>
+
+</para>
+
+ tcol: 
+ att_name: 
+ value: 
+
+
+<!-- ##### FUNCTION gda_meta_table_column_foreach_attribute ##### -->
+<para>
+
+</para>
+
+ tcol: 
+ func: 
+ data: 
+
+
 <!-- ##### STRUCT GdaMetaTableForeignKey ##### -->
 <para>
 

Modified: trunk/libgda/Makefile.am
==============================================================================
--- trunk/libgda/Makefile.am	(original)
+++ trunk/libgda/Makefile.am	Thu Oct  2 18:43:14 2008
@@ -26,6 +26,7 @@
 	$(GLIB_GENMARSHAL) $< --body --prefix=gda_marshal > $@
 
 gda_headers = \
+	gda-attributes-manager.h \
 	gda-batch.h \
 	gda-blob-op.h \
 	gda-column.h \
@@ -78,6 +79,7 @@
 libgda_sources =  \
 	csv.h \
 	libcsv.c \
+	gda-attributes-manager.c \
 	gda-batch.c \
 	dir-blob-op.h \
 	dir-blob-op.c \

Added: trunk/libgda/gda-attributes-manager.c
==============================================================================
--- (empty file)
+++ trunk/libgda/gda-attributes-manager.c	Thu Oct  2 18:43:14 2008
@@ -0,0 +1,283 @@
+/* 
+ * GDA common library
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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 <string.h>
+#include <gda-attributes-manager.h>
+#include <gda-value.h>
+
+typedef struct {
+	GdaAttributesManager *mgr;
+	gpointer              ptr;
+	const gchar          *att_name;
+} Key;
+
+static guint hash_func (gconstpointer key);
+static gboolean equal_func (gconstpointer key1, gconstpointer key2);
+static void key_free (Key *key);
+
+static void obj_destroyed_cb (Key *key, GObject *where_the_object_was);
+
+struct _GdaAttributesManager {
+	gboolean    for_objects; /* TRUE if key->data are GObjects */
+	GHashTable *hash; /* key = a Key pointer, value = a GValue */
+};
+
+static guint
+hash_func (gconstpointer key)
+{
+	return GPOINTER_TO_UINT (((Key*) key)->ptr) + g_str_hash (((Key*) key)->att_name);
+}
+
+static gboolean
+equal_func (gconstpointer key1, gconstpointer key2)
+{
+	if ((((Key*) key1)->ptr == ((Key*) key2)->ptr) &&
+	    !strcmp (((Key*) key1)->att_name, ((Key*) key2)->att_name))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static void
+key_free (Key *key)
+{
+	if (key->ptr && key->mgr->for_objects)
+		g_object_weak_unref (G_OBJECT (key->ptr), (GWeakNotify) obj_destroyed_cb, key);
+	/* DON'T g_free (key->att_name) as it is static data */
+	g_free (key);
+}
+
+/**
+ * gda_attributes_manager_new
+ * @for_objects: set to TRUE if attributes will be set on objects.
+ *
+ * Creates a new #GdaAttributesManager, which can store (name, value) attributes for pointers or GObject objects
+ * (in the latter case, the attibutes are destroyed when objects are also destroyed).
+ *
+ * Returns: the new #GdaAttributesManager
+ */
+GdaAttributesManager *
+gda_attributes_manager_new (gboolean for_objects)
+{
+	GdaAttributesManager *mgr;
+
+	mgr = g_new0 (GdaAttributesManager, 1);
+	mgr->hash = g_hash_table_new_full (hash_func, equal_func, (GDestroyNotify) key_free, (GDestroyNotify) gda_value_free);
+	mgr->for_objects = for_objects;
+
+	return mgr;
+}
+
+/**
+ * gda_attributes_manager_free
+ * @mgr: a #GdaAttributesManager
+ *
+ * Frees all the resssources managed by @mgr
+ */
+void
+gda_attributes_manager_free (GdaAttributesManager *mgr)
+{
+	g_hash_table_destroy (mgr->hash);
+	g_free (mgr);
+}
+
+static void
+obj_destroyed_cb (Key *key, GObject *where_the_object_was)
+{
+	key->ptr = NULL;
+	g_hash_table_remove (key->mgr->hash, key);
+}
+
+/**
+ * gda_attributes_manager_set
+ * @mgr: a #GdaAttributesManager
+ * @ptr: a pointer to the ressources to which the attribute will apply
+ * @att_name: an attribute's name, as a *static* string
+ * @value: a #GValue, or %NULL
+ *
+ * Associates an attribute named @att_name to @ptr, with the value @value. Any previous association is replaced by
+ * this one, and if @value is %NULL then the association is removed.
+ *
+ * Note: @att_name is *not* copied, so it should be a static string, or a string which exists as long as @mgr exists (or,
+ * in case @ptr is an object, as long as that object exists). Libgda provides several predefined names for common attributes,
+ * see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
+ */
+void
+gda_attributes_manager_set (GdaAttributesManager *mgr, gpointer ptr, const gchar *att_name, const GValue *value)
+{
+	g_return_if_fail (att_name);
+	if (mgr->for_objects) 
+		g_return_if_fail (G_IS_OBJECT (ptr));
+
+	if (value) {
+		Key *key;
+
+		key = g_new (Key, 1);
+		key->mgr = mgr;
+		key->ptr = ptr;
+		key->att_name = att_name; /* NOT duplicated */
+		if (mgr->for_objects) 
+			g_object_weak_ref (G_OBJECT (key->ptr), (GWeakNotify) obj_destroyed_cb, key);
+		g_hash_table_insert (mgr->hash, key, gda_value_copy (value));
+	}
+	else {
+		Key key;
+		key.ptr = ptr;
+		key.att_name = att_name;
+		g_hash_table_remove (mgr->hash, &key);
+	}
+}
+
+/**
+ * gda_attributes_manager_get
+ * @mgr: a #GdaAttributesManager
+ * @ptr: a pointer to the ressources to which the attribute will apply
+ * @att_name: an attribute's name, as a *static* string
+ *
+ * Retreives the value of an attribute previously set using gda_attributes_manager_set().
+ *
+ * Returns: the attribute's value, or %NULL if the attribute is not set.
+ */
+const GValue *
+gda_attributes_manager_get (GdaAttributesManager *mgr, gpointer ptr, const gchar *att_name)
+{
+	Key key;
+	key.ptr = ptr;
+	key.att_name = (gchar*) att_name;
+	return g_hash_table_lookup (mgr->hash, &key);
+}
+
+typedef struct {
+	gpointer   *from;
+	gpointer   *to;
+	GSList     *names;
+	GSList     *values;
+} CopyData;
+static void foreach_copy_func (Key *key, const GValue *value, CopyData *cdata);
+
+/**
+ * gda_attributes_manager_copy
+ * @from_mgr: a #GdaAttributesManager
+ * @from:
+ * @to_mgr: a #GdaAttributesManager
+ * @to:
+ *
+ * For each attribute set for @from (in @from_mgr), set the same attribute to @to (in @to_mgr). @from_mgr and
+ * @to_mgr can be equal.
+ */
+void
+gda_attributes_manager_copy (GdaAttributesManager *from_mgr, gpointer *from, 
+			     GdaAttributesManager *to_mgr, gpointer *to)
+{
+	CopyData cdata;
+	GSList *nlist, *vlist;
+	cdata.from = from;
+	cdata.to = to;
+	cdata.names = NULL;
+	cdata.values = NULL;
+	g_hash_table_foreach (from_mgr->hash, (GHFunc) foreach_copy_func, &cdata);
+	for (nlist = cdata.names, vlist = cdata.values;
+	     nlist && vlist;
+	     nlist = nlist->next, vlist = vlist->next)
+		gda_attributes_manager_set (to_mgr, to, (gchar*) nlist->data, (GValue*) vlist->data);
+	g_slist_free (cdata.names);
+	g_slist_free (cdata.values);
+}
+
+static void
+foreach_copy_func (Key *key, const GValue *value, CopyData *cdata)
+{
+	if (key->ptr == cdata->from) {
+		cdata->names = g_slist_prepend (cdata->names, (gpointer) key->att_name);
+		cdata->values = g_slist_prepend (cdata->values, (gpointer) value);
+	}
+}
+
+static void foreach_clear_func (Key *key, const GValue *value, CopyData *cdata);
+
+/**
+ * gda_attributes_manager_clear
+ * @mgr: a #GdaAttributesManager
+ * @ptr: a pointer to the ressources for which all the attributes will be removed
+ *
+ * Remove all the attributes managed by @mgr for the @ptr ressource.
+ */
+void
+gda_attributes_manager_clear (GdaAttributesManager *mgr, gpointer ptr)
+{
+	CopyData cdata;
+	GSList *nlist;
+	cdata.from = ptr;
+	cdata.to = NULL;
+	cdata.names = NULL;
+	cdata.values = NULL;
+	g_hash_table_foreach (mgr->hash, (GHFunc) foreach_clear_func, &cdata);
+	for (nlist = cdata.names;  nlist; nlist = nlist->next)
+		gda_attributes_manager_set (mgr, ptr, (gchar*) nlist->data, NULL);
+	g_slist_free (cdata.names);
+}
+
+static void
+foreach_clear_func (Key *key, const GValue *value, CopyData *cdata)
+{
+	if (key->ptr == cdata->from) 
+		cdata->names = g_slist_prepend (cdata->names, (gpointer) key->att_name);
+}
+
+
+typedef struct {
+	gpointer ptr;
+	GdaAttributesManagerFunc func;
+	gpointer data;
+} FData;
+static void foreach_foreach_func (Key *key, const GValue *value, FData *fdata);
+
+/**
+ * gda_attributes_manager_foreach
+ * @mgr: a #GdaAttributesManager
+ * @ptr: a pointer to the ressources for which all the attributes used
+ * @func: a #GdaAttributesManagerFunc function
+ * @data: user data to be passed as last argument of @func each time it is called
+ *
+ * Calls @func for every attribute set to @ptr.
+ */
+void
+gda_attributes_manager_foreach (GdaAttributesManager *mgr, gpointer ptr, 
+				GdaAttributesManagerFunc func, gpointer data)
+{
+	FData fdata;
+	g_return_if_fail (func);
+	g_return_if_fail (ptr);
+
+	fdata.ptr = ptr;
+	fdata.func = func;
+	fdata.data = data;
+	g_hash_table_foreach (mgr->hash, (GHFunc) foreach_foreach_func, &fdata);
+}
+
+static void
+foreach_foreach_func (Key *key, const GValue *value, FData *fdata)
+{
+	if (key->ptr == fdata->ptr)
+		fdata->func (key->att_name, value, fdata->data);
+}

Added: trunk/libgda/gda-attributes-manager.h
==============================================================================
--- (empty file)
+++ trunk/libgda/gda-attributes-manager.h	Thu Oct  2 18:43:14 2008
@@ -0,0 +1,57 @@
+/* GDA common library
+ * Copyright (C) 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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 __GDA_ATTRIBUTES_MANAGER_H__
+#define __GDA_ATTRIBUTES_MANAGER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* main struct */
+typedef struct _GdaAttributesManager GdaAttributesManager;
+typedef void (*GdaAttributesManagerFunc) (const gchar *att_name, const GValue *value, gpointer data);
+
+GdaAttributesManager *gda_attributes_manager_new         (gboolean for_objects);
+void                  gda_attributes_manager_free        (GdaAttributesManager *mgr);
+
+void                  gda_attributes_manager_set         (GdaAttributesManager *mgr, gpointer ptr,
+							  const gchar *att_name, const GValue *value);
+const GValue         *gda_attributes_manager_get         (GdaAttributesManager *mgr, gpointer ptr, const gchar *att_name);
+void                  gda_attributes_manager_copy        (GdaAttributesManager *from_mgr, gpointer *from, 
+							  GdaAttributesManager *to_mgr, gpointer *to);
+void                  gda_attributes_manager_clear       (GdaAttributesManager *mgr, gpointer ptr);
+void                  gda_attributes_manager_foreach     (GdaAttributesManager *mgr, gpointer ptr, 
+							  GdaAttributesManagerFunc func, gpointer data);
+
+
+/* possible predefined attribute names for gda_holder_get_attribute() or gda_column_get_attribute() */
+#define GDA_ATTRIBUTE_DESCRIPTION "__gda_attr_descr"
+#define GDA_ATTRIBUTE_NAME "__gda_attr_name"
+#define GDA_ATTRIBUTE_NUMERIC_PRECISION "__gda_attr_numeric_precision"
+#define GDA_ATTRIBUTE_NUMERIC_SCALE "__gda_attr_numeric_scale"
+#define GDA_ATTRIBUTE_AUTO_INCREMENT "__gda_attr_autoinc"
+
+
+G_END_DECLS
+
+#endif

Modified: trunk/libgda/gda-column.c
==============================================================================
--- trunk/libgda/gda-column.c	(original)
+++ trunk/libgda/gda-column.c	Thu Oct  2 18:43:14 2008
@@ -28,14 +28,13 @@
 #include <libgda/gda-column.h>
 #include <string.h>
 #include "gda-marshal.h"
+#include <libgda/gda-attributes-manager.h>
 
 #define PARENT_TYPE G_TYPE_OBJECT
 
 struct _GdaColumnPrivate {
 	gint         defined_size;
 	gchar       *id;
-	gchar       *name;
-	gchar       *title;
 
 	gchar       *dbms_type;
 	GType        g_type;
@@ -120,6 +119,7 @@
 };
 
 static GObjectClass *parent_class = NULL;
+GdaAttributesManager *gda_column_attributes_manager;
 
 static void
 gda_column_class_init (GdaColumnClass *klass)
@@ -157,6 +157,9 @@
                                                               NULL, G_PARAM_WRITABLE | G_PARAM_READABLE));
 
 	object_class->finalize = gda_column_finalize;
+
+	/* extra */
+	gda_column_attributes_manager = gda_attributes_manager_new (TRUE);
 }
 
 static void
@@ -167,8 +170,6 @@
 	column->priv = g_new0 (GdaColumnPrivate, 1);
 	column->priv->defined_size = 0;
 	column->priv->id = NULL;
-	column->priv->name = NULL;
-	column->priv->title = NULL;
 	column->priv->g_type = G_TYPE_INVALID;
 	column->priv->allow_null = TRUE;
 	column->priv->auto_increment = FALSE;
@@ -190,8 +191,6 @@
 			gda_value_free (column->priv->default_value);
 	
 		g_free (column->priv->id);
-		g_free (column->priv->name);
-		g_free (column->priv->title);
 
 		g_free (column->priv);
 		column->priv = NULL;
@@ -305,10 +304,6 @@
 	column_copy->priv->defined_size = column->priv->defined_size;
 	if (column->priv->id)
 		column_copy->priv->id = g_strdup (column->priv->id);
-	if (column->priv->name)
-		column_copy->priv->name = g_strdup (column->priv->name);
-	if (column->priv->title)
-		column_copy->priv->title = g_strdup (column->priv->title);
 	column_copy->priv->g_type = column->priv->g_type;
 	column_copy->priv->allow_null = column->priv->allow_null;
 	column_copy->priv->auto_increment = column->priv->auto_increment;
@@ -317,7 +312,8 @@
 	column_copy->priv->position = column->priv->position;
 	if (column->priv->default_value)
 		column_copy->priv->default_value = gda_value_copy (column->priv->default_value);
-	
+	gda_attributes_manager_copy (gda_column_attributes_manager, (gpointer) column, gda_column_attributes_manager, (gpointer) column_copy);
+
 	return column_copy; 	 
 }
 
@@ -330,8 +326,13 @@
 const gchar *
 gda_column_get_name (GdaColumn *column)
 {
+	const GValue *cvalue;
 	g_return_val_if_fail (GDA_IS_COLUMN (column), NULL);
-	return (const gchar *) column->priv->name;
+	cvalue = gda_column_get_attribute (column, GDA_ATTRIBUTE_NAME);
+	if (cvalue)
+		return g_value_get_string (cvalue);
+	else
+		return NULL;
 }
 
 /**
@@ -345,53 +346,64 @@
 gda_column_set_name (GdaColumn *column, const gchar *name)
 {
 	gchar *old_name = NULL;
+	GValue *value = NULL;
 
 	g_return_if_fail (GDA_IS_COLUMN (column));
 
-	if (column->priv->name) {
-		old_name = column->priv->name;
-		column->priv->name = NULL;
-	}
+	old_name = (gchar *) gda_column_get_name (column);
+	if (old_name)
+		old_name = g_strdup (old_name);
 
 	if (name)
-		column->priv->name = g_strdup (name);
+		g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), name);
+	gda_column_set_attribute (column, GDA_ATTRIBUTE_NAME, value);
+	if (value)
+		gda_value_free (value);
 
 	g_signal_emit (G_OBJECT (column),
 		       gda_column_signals[NAME_CHANGED],
 		       0, old_name);
 
-	if (old_name)
-		g_free (old_name);
+	g_free (old_name);
 }
 
 /**
- * gda_column_get_title
+ * gda_column_get_description
  * @column: a #GdaColumn.
  *
- * Returns: the column's title
+ * Returns: the column's description, in any
  */
 const gchar *
-gda_column_get_title (GdaColumn *column)
+gda_column_get_description (GdaColumn *column)
 {
+	const GValue *cvalue;
 	g_return_val_if_fail (GDA_IS_COLUMN (column), NULL);
-	return column->priv->title;;
+	cvalue = gda_column_get_attribute (column, GDA_ATTRIBUTE_DESCRIPTION);
+	if (cvalue)
+		return g_value_get_string (cvalue);
+	else
+		return NULL;
 }
 
 /**
- * gda_column_set_title
+ * gda_column_set_description
  * @column: a #GdaColumn.
  * @title: title name.
  *
- * Sets the column's title
+ * Sets the column's description
  */
 void
-gda_column_set_title (GdaColumn *column, const gchar *title)
+gda_column_set_description (GdaColumn *column, const gchar *descr)
 {
+	GValue *value = NULL;
+
 	g_return_if_fail (GDA_IS_COLUMN (column));
 
-	if (column->priv->title != NULL)
-		g_free (column->priv->title);
-	column->priv->title = g_strdup (title);
+	if (descr)
+		g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), descr);
+	gda_column_set_attribute (column, GDA_ATTRIBUTE_DESCRIPTION, value);
+	if (value)
+		gda_value_free (value);
 }
 
 /**
@@ -573,3 +585,43 @@
 		gda_value_free (column->priv->default_value);
 	column->priv->default_value = gda_value_copy ( (GValue*)default_value);
 }
+
+/**
+ * gda_column_get_attribute
+ * @column: a #GdaColumn
+ * @attribute: attribute name as a string
+ *
+ * Get the value associated to a named attribute.
+ *
+ * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
+ *
+ * Returns: a read-only #GValue, or %NULL if not attribute named @attribute has been set for @column
+ */
+const GValue *
+gda_column_get_attribute (GdaColumn *column, const gchar *attribute)
+{
+	g_return_val_if_fail (GDA_IS_COLUMN (column), NULL);
+	return gda_attributes_manager_get (gda_column_attributes_manager, column, attribute);
+}
+
+/**
+ * gda_column_set_attribute
+ * @column: a #GdaColumn
+ * @attribute: attribute name as a static string
+ * @value: a #GValue, or %NULL
+ *
+ * Set the value associated to a named attribute.
+ *
+ * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
+ * If there is already an attribute named @attribute set, then its value is replaced with the new @value, 
+ * except if @value is %NULL, in which case the attribute is removed.
+ *
+ * Warning: @sttribute should be a static string (no copy of it is made), so the string should exist as long as the @column
+ * object exists.
+ */
+void
+gda_column_set_attribute (GdaColumn *column, const gchar *attribute, const GValue *value)
+{
+	g_return_if_fail (GDA_IS_COLUMN (column));
+	gda_attributes_manager_set (gda_column_attributes_manager, column, attribute, value);
+}

Modified: trunk/libgda/gda-column.h
==============================================================================
--- trunk/libgda/gda-column.h	(original)
+++ trunk/libgda/gda-column.h	Thu Oct  2 18:43:14 2008
@@ -45,10 +45,10 @@
 };
 
 struct _GdaColumnClass {
-	GObjectClass parent_class;
+	GObjectClass          parent_class;
 	
 	/* signals */
-	void (* name_changed)     (GdaColumn *column, const gchar *old_name);
+	void (* name_changed)   (GdaColumn *column, const gchar *old_name);
 	void (* g_type_changed) (GdaColumn *column, GType old_type, GType new_type);
 };
 
@@ -56,8 +56,8 @@
 GdaColumn      *gda_column_new                (void);
 GdaColumn      *gda_column_copy               (GdaColumn *column);
 
-const gchar    *gda_column_get_title          (GdaColumn *column);
-void            gda_column_set_title          (GdaColumn *column, const gchar *title);
+const gchar    *gda_column_get_description          (GdaColumn *column);
+void            gda_column_set_description          (GdaColumn *column, const gchar *title);
 
 const gchar    *gda_column_get_name           (GdaColumn *column);
 void            gda_column_set_name           (GdaColumn *column, const gchar *name);
@@ -80,6 +80,9 @@
 const GValue   *gda_column_get_default_value  (GdaColumn *column);
 void            gda_column_set_default_value  (GdaColumn *column, const GValue *default_value);
 
+const GValue   *gda_column_get_attribute      (GdaColumn *column, const gchar *attribute);
+void            gda_column_set_attribute      (GdaColumn *column, const gchar *attribute, const GValue *value);
+
 G_END_DECLS
 
 #endif

Modified: trunk/libgda/gda-connection.c
==============================================================================
--- trunk/libgda/gda-connection.c	(original)
+++ trunk/libgda/gda-connection.c	Thu Oct  2 18:43:14 2008
@@ -3062,7 +3062,7 @@
 						 gda_connection_get_provider (cnc),
 						 gda_connection_get_provider_name (cnc));
 					if (error && *error)
-						g_warning ("// %s\n", (*error)->message);
+						g_warning ("\t==> %s\n", (*error)->message);
 
 					WARN_META_UPDATE_FAILURE (FALSE, rmeta [i].func_name);
 					goto onerror;
@@ -3246,12 +3246,64 @@
 				    GdaConnectionMetaType meta_type,
 				    GError **error, gint nb_filters, ...)
 {
+	GList* filters = NULL;
+	GdaDataModel* model = NULL;
+	gint i;
+  
+	if (nb_filters > 0) {
+		va_list ap;
+		va_start (ap, nb_filters);
+		for (i = 0; (i < nb_filters); i++) {
+			GdaHolder *h;
+			GValue *v;
+			gchar* fname;
+      
+			fname = va_arg (ap, gchar*);
+			if (!fname)
+				break;
+			v = va_arg (ap, GValue*);
+			if (!v || gda_value_is_null (v))
+				continue;
+			h = g_object_new (GDA_TYPE_HOLDER, "g-type", G_VALUE_TYPE (v), "id", fname, NULL);
+			filters = g_list_append (filters, h);
+			if (!gda_holder_set_value (h, v, error)) {
+				va_end (ap);
+				goto onerror;
+			}
+		}
+		va_end (ap);
+	}
+	model = gda_connection_get_meta_store_data_v (cnc, meta_type, filters, error);
+
+ onerror:
+	g_list_foreach (filters, (GFunc) g_object_unref, NULL);
+	g_list_free (filters);
+
+	return model;
+}
+
+/**
+ * gda_connection_get_meta_store_data_v
+ * @cnc: a #GdaConnection object.
+ * @meta_type: describes which data to get.
+ * @error: a place to store errors, or %NULL
+ * @filters: a GList of GdaHolders
+ *
+ * see #gda_connection_get_meta_store_data
+ * 
+ * Returns: a #GdaDataModel containing the data required. The caller is responsible
+ * for freeing the returned model using g_object_unref().
+ */
+GdaDataModel *
+gda_connection_get_meta_store_data_v (GdaConnection *cnc, GdaConnectionMetaType meta_type,
+				      GList* filters, GError **error)
+{
 	GdaMetaStore *store;
 	GdaDataModel *model = NULL;
-	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
 	static GHashTable *stmt_hash = NULL;
 	GdaStatement *stmt;
 	GdaSet *set = NULL;
+	GList* node;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
 	g_return_val_if_fail (cnc->priv->provider_obj, NULL);
@@ -3263,49 +3315,26 @@
 	/* fetch the statement */
 	MetaKey key;
 	gint i;
-	gchar *fname;
-
-	g_static_mutex_lock (&mutex);
 	if (!stmt_hash)
 		stmt_hash = prepare_meta_statements_hash ();
-	g_static_mutex_unlock (&mutex);
-
 	key.meta_type = meta_type;
-	key.nb_filters = nb_filters;
+	key.nb_filters = g_list_length (filters);
 	key.filters = NULL;
-	if (nb_filters > 0) {
-		va_list ap;
-		key.filters = g_new (gchar *, nb_filters);
-		va_start (ap, nb_filters);
-		for (i = 0; (i < nb_filters); i++) {
-			GdaHolder *h;
-			GValue *v;
-			
-			fname = va_arg (ap, gchar*);
-			if (!fname)
-				break;
-			v = va_arg (ap, GValue*);
-			if (!v || gda_value_is_null (v))
-				continue;
-			if (!set)
-				set = gda_set_new (NULL);
-			h = g_object_new (GDA_TYPE_HOLDER, "g-type", G_VALUE_TYPE (v), "id", fname, NULL);
-			if (! gda_holder_set_value (h, v, error)) {
-				g_free (key.filters);
-				g_object_unref (set);
-				return NULL;
-			}
-			gda_set_add_holder (set, h);
-			g_object_unref (h);
-			key.filters[i] = fname;
-		}
-		va_end (ap);
+	if (key.nb_filters > 0)
+		key.filters = g_new (gchar *, key.nb_filters);
+	for (node = filters; filters != NULL; node = g_list_next (node)) {
+		if (!set)
+			set = g_object_new (GDA_TYPE_SET, NULL);
+		gda_set_add_holder (set, GDA_HOLDER (node->data));
+		key.filters[i] = (gchar*) gda_holder_get_id (GDA_HOLDER (node->data));
 	}
 	stmt = g_hash_table_lookup (stmt_hash, &key);
 	g_free (key.filters);
 	if (!stmt) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_MISSING_PARAM_ERROR,
 			     _("Wrong filter arguments"));
+		if (set)
+			g_object_unref (set);
 		return NULL;
 	}
 
@@ -3321,6 +3350,7 @@
 	return model;
 }
 
+
 /**
  * gda_connection_get_events
  * @cnc: a #GdaConnection.

Modified: trunk/libgda/gda-connection.h
==============================================================================
--- trunk/libgda/gda-connection.h	(original)
+++ trunk/libgda/gda-connection.h	Thu Oct  2 18:43:14 2008
@@ -199,6 +199,8 @@
 gboolean             gda_connection_update_meta_store    (GdaConnection *cnc, GdaMetaContext *context, GError **error);
 GdaDataModel        *gda_connection_get_meta_store_data  (GdaConnection *cnc, GdaConnectionMetaType meta_type,
 							  GError **error, gint nb_filters, ...);
+GdaDataModel        *gda_connection_get_meta_store_data_v(GdaConnection *cnc, GdaConnectionMetaType meta_type,
+							  GList* filters, GError **error);
 G_END_DECLS
 
 #endif

Modified: trunk/libgda/gda-data-model-array.c
==============================================================================
--- trunk/libgda/gda-data-model-array.c	(original)
+++ trunk/libgda/gda-data-model-array.c	Thu Oct  2 18:43:14 2008
@@ -349,7 +349,7 @@
 		g_object_get (G_OBJECT (srccol), "id", &colid, NULL);
 		g_object_set (G_OBJECT (copycol), "id", colid, NULL);
 		g_free (colid);
-		gda_column_set_title (copycol, gda_column_get_title (srccol));
+		gda_column_set_description (copycol, gda_column_get_description (srccol));
 		gda_column_set_name (copycol, gda_column_get_name (srccol));
 		gda_column_set_dbms_type (copycol, gda_column_get_dbms_type (srccol));
 		gda_column_set_g_type (copycol, gda_column_get_g_type (srccol));

Modified: trunk/libgda/gda-data-model-bdb.c
==============================================================================
--- trunk/libgda/gda-data-model-bdb.c	(original)
+++ trunk/libgda/gda-data-model-bdb.c	Thu Oct  2 18:43:14 2008
@@ -363,7 +363,7 @@
                         column = gda_column_new ();
                         model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "key");
-			gda_column_set_title (column, "key");
+			gda_column_set_description (column, "key");
 			gda_column_set_g_type (column, GDA_TYPE_BINARY);
 		}
 
@@ -380,7 +380,7 @@
                         column = gda_column_new ();
                         model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "data");
-			gda_column_set_title (column, "data");
+			gda_column_set_description (column, "data");
 			gda_column_set_g_type (column, GDA_TYPE_BINARY);
 		}
 		model->priv->n_columns = g_slist_length (model->priv->columns);

Modified: trunk/libgda/gda-data-model-dir.c
==============================================================================
--- trunk/libgda/gda-data-model-dir.c	(original)
+++ trunk/libgda/gda-data-model-dir.c	Thu Oct  2 18:43:14 2008
@@ -328,42 +328,42 @@
 			column = gda_column_new ();
 			model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "dir_name");
-			gda_column_set_title (column, "dir_name");
+			gda_column_set_description (column, "dir_name");
 			gda_column_set_g_type (column, G_TYPE_STRING);
 
 			/* COL_FILENAME */
 			column = gda_column_new ();
 			model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "file_name");
-			gda_column_set_title (column, "file_name");
+			gda_column_set_description (column, "file_name");
 			gda_column_set_g_type (column, G_TYPE_STRING);
 
 			/* COL_SIZE */
 			column = gda_column_new ();
 			model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "size");
-			gda_column_set_title (column, "size");
+			gda_column_set_description (column, "size");
 			gda_column_set_g_type (column, G_TYPE_UINT);
 
 			/* COL_MIME */
 			column = gda_column_new ();
 			model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "mime_type");
-			gda_column_set_title (column, "mime_type");
+			gda_column_set_description (column, "mime_type");
 			gda_column_set_g_type (column, G_TYPE_STRING);
 
 			/* COL_MD5SUM */
 			column = gda_column_new ();
 			model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "md5sum");
-			gda_column_set_title (column, "md5sum");
+			gda_column_set_description (column, "md5sum");
 			gda_column_set_g_type (column, G_TYPE_STRING);
 
 			/* COL_DATA */
 			column = gda_column_new ();
 			model->priv->columns = g_slist_append (model->priv->columns , column);
 			gda_column_set_name (column, "data");
-			gda_column_set_title (column, "data");
+			gda_column_set_description (column, "data");
 			gda_column_set_g_type (column, GDA_TYPE_BLOB);
 
 			/* number of rows */

Modified: trunk/libgda/gda-data-model-dsn-list.c
==============================================================================
--- trunk/libgda/gda-data-model-dsn-list.c	(original)
+++ trunk/libgda/gda-data-model-dsn-list.c	Thu Oct  2 18:43:14 2008
@@ -103,19 +103,19 @@
 	
 	col = gda_column_new ();
 	gda_column_set_name (col, _("DSN"));
-	gda_column_set_title (col, _("DSN"));
+	gda_column_set_description (col, _("DSN"));
 	gda_column_set_g_type (col, G_TYPE_STRING);
 	model->priv->columns = g_slist_append (NULL, col);
 
 	col = gda_column_new ();
 	gda_column_set_name (col, _("Provider"));
-	gda_column_set_title (col, _("Provider"));
+	gda_column_set_description (col, _("Provider"));
 	gda_column_set_g_type (col, G_TYPE_STRING);
 	model->priv->columns = g_slist_append (model->priv->columns, col);
 
 	col = gda_column_new ();
 	gda_column_set_name (col, _("Description"));
-	gda_column_set_title (col, _("Description"));
+	gda_column_set_description (col, _("Description"));
 	gda_column_set_g_type (col, G_TYPE_STRING);
 	model->priv->columns = g_slist_append (model->priv->columns, col);
 
@@ -123,19 +123,19 @@
 	/* To translators: a "Connection string" is a semi-colon delimited list of key=value pairs which
 	 * define the parameters for a connection, such as "DB_NAME=thedb;HOSTNAME=moon */
 	gda_column_set_name (col, _("Connection string"));
-	gda_column_set_title (col, _("Connection string"));
+	gda_column_set_description (col, _("Connection string"));
 	gda_column_set_g_type (col, G_TYPE_STRING);
 	model->priv->columns = g_slist_append (model->priv->columns, col);
 
 	col = gda_column_new ();
 	gda_column_set_name (col, _("Username"));
-	gda_column_set_title (col, _("Username"));
+	gda_column_set_description (col, _("Username"));
 	gda_column_set_g_type (col, G_TYPE_STRING);
 	model->priv->columns = g_slist_append (model->priv->columns, col);
 
 	col = gda_column_new ();
 	gda_column_set_name (col, _("Global"));
-	gda_column_set_title (col, _("Global"));
+	gda_column_set_description (col, _("Global"));
 	gda_column_set_g_type (col, G_TYPE_BOOLEAN);
 	model->priv->columns = g_slist_append (model->priv->columns, col);
 

Modified: trunk/libgda/gda-data-model-import.c
==============================================================================
--- trunk/libgda/gda-data-model-import.c	(original)
+++ trunk/libgda/gda-data-model-import.c	Thu Oct  2 18:43:14 2008
@@ -820,7 +820,7 @@
 		if (!str) 
 			str = g_strdup_printf ("column_%d", col);
 		gda_column_set_name (column, str);
-		gda_column_set_title (column, str);
+		gda_column_set_description (column, str);
 		g_free (str);			
 		
 		gda_column_set_g_type (column, G_TYPE_STRING);
@@ -1232,7 +1232,7 @@
 			column = gda_column_new ();
 			model->priv->columns = g_slist_append (model->priv->columns, column);
 			g_object_set (G_OBJECT (column), "id", spec->id, NULL);
-			gda_column_set_title (column, (gchar*)spec->title);
+			gda_column_set_description (column, (gchar*)spec->title);
 			gda_column_set_name (column, (gchar*)spec->name);
 			gda_column_set_dbms_type (column, (gchar*)spec->dbms_type);
 			gda_column_set_g_type (column, spec->gdatype);
@@ -1563,7 +1563,7 @@
 		spec = (XmlColumnSpec *)(list->data);
 		column = gda_data_model_describe_column (ramodel, pos);
 		g_object_set (G_OBJECT (column), "id", spec->id, NULL);
-		gda_column_set_title (column, (gchar*)spec->title);
+		gda_column_set_description (column, (gchar*)spec->title);
 		gda_column_set_name (column, (gchar*)spec->name);
 		gda_column_set_dbms_type (column, (gchar*)spec->dbms_type);
 		gda_column_set_g_type (column, spec->gdatype);

Modified: trunk/libgda/gda-data-model-iter.c
==============================================================================
--- trunk/libgda/gda-data-model-iter.c	(original)
+++ trunk/libgda/gda-data-model-iter.c	Thu Oct  2 18:43:14 2008
@@ -30,6 +30,9 @@
 #include "gda-enums.h"
 #include "gda-data-select.h"
 
+extern GdaAttributesManager *gda_column_attributes_manager;
+extern GdaAttributesManager *gda_holder_attributes_manager;
+
 /* 
  * Main static functions 
  */
@@ -403,6 +406,8 @@
 		goto out;
 	}
 
+	/* FIXME: also set some column attributes using gda_column_set_attribute() */
+
 	GSList *fields, *holders;
 	for (fields = select->expr_list, holders = GDA_SET (iter)->holders; 
 	     fields && holders; 
@@ -495,7 +500,7 @@
 				}
 				else {
 					const gchar *cstr;
-					cstr = gda_column_get_title (column);
+					cstr = gda_column_get_description (column);
 					if (!cstr)
 						cstr = gda_column_get_name (column);
 					if (cstr)
@@ -513,6 +518,9 @@
 					gda_holder_set_default_value (param, v);
 					gda_value_free (v);
 				}
+				/* copy extra attributes */
+				gda_attributes_manager_copy (gda_column_attributes_manager, (gpointer) column,
+							     gda_holder_attributes_manager, (gpointer) param);
 				gda_set_add_holder ((GdaSet *) iter, param);
 				g_object_set_data (G_OBJECT (param), "model_col", GINT_TO_POINTER (col + 1));
 				g_object_unref (param);

Modified: trunk/libgda/gda-data-model.c
==============================================================================
--- trunk/libgda/gda-data-model.c	(original)
+++ trunk/libgda/gda-data-model.c	Thu Oct  2 18:43:14 2008
@@ -477,8 +477,8 @@
 	column = gda_data_model_describe_column (model, col);
 	if (column) {
 		gda_column_set_name (column, name);
-		if (!gda_column_get_title (column))
-			gda_column_set_title (column, name);
+		if (!gda_column_get_description (column))
+			gda_column_set_description (column, name);
 	}
 	else 
 		g_warning ("%s(): can't get GdaColumn object for column %d\n", __FUNCTION__, col);
@@ -500,7 +500,7 @@
 
 	column = gda_data_model_describe_column (model, col);
 	if (column)
-		return gda_column_get_title (column);
+		return gda_column_get_description (column);
 	else {
 		g_warning ("%s(): can't get GdaColumn object for column %d\n", __FUNCTION__, col);
 		return NULL;
@@ -523,7 +523,7 @@
 
 	column = gda_data_model_describe_column (model, col);
 	if (column)
-		gda_column_set_title (column, title);
+		gda_column_set_description (column, title);
 	else 
 		g_warning ("%s(): can't get GdaColumn object for column %d\n", __FUNCTION__, col);
 }
@@ -1246,7 +1246,7 @@
 		xmlSetProp (field, BAD_CAST "id", BAD_CAST str);
 		g_free (str);
 		xmlSetProp (field, BAD_CAST "name", BAD_CAST gda_column_get_name (column));
-		cstr = gda_column_get_title (column);
+		cstr = gda_column_get_description (column);
 		if (cstr && *cstr)
 			xmlSetProp (field, BAD_CAST "title", BAD_CAST cstr);
 		cstr = gda_column_get_dbms_type (column);

Modified: trunk/libgda/gda-data-proxy.c
==============================================================================
--- trunk/libgda/gda-data-proxy.c	(original)
+++ trunk/libgda/gda-data-proxy.c	Thu Oct  2 18:43:14 2008
@@ -3163,7 +3163,7 @@
 		else
 			newname = g_strdup_printf ("pre%d", i);
 		gda_column_set_name (proxy->priv->columns[i], newname);
-		gda_column_set_title (proxy->priv->columns[i], newname);
+		gda_column_set_description (proxy->priv->columns[i], newname);
 		g_free (newname);
 		gda_column_set_position (proxy->priv->columns[i], i);
 	}

Modified: trunk/libgda/gda-enums.h
==============================================================================
--- trunk/libgda/gda-enums.h	(original)
+++ trunk/libgda/gda-enums.h	Thu Oct  2 18:43:14 2008
@@ -45,19 +45,6 @@
 	GDA_VALUE_ATTR_UNUSED         = 1 << 9
 } GdaValueAttribute;
 
-/* different possible types for a GdaGraph object */
-typedef enum {
-        GDA_GRAPH_DB_RELATIONS,
-	GDA_GRAPH_QUERY_JOINS,
-        GDA_GRAPH_MODELLING /* for future extensions */
-} GdaGraphType;
-
-typedef enum {
-	GDA_ENTITY_FIELD_VISIBLE   = 1 << 0,
-	GDA_ENTITY_FIELD_INVISIBLE = 1 << 1,
-	GDA_ENTITY_FIELD_ANY       = GDA_ENTITY_FIELD_VISIBLE | GDA_ENTITY_FIELD_INVISIBLE
-} GdaQueryFieldState;
-
 /* possible different keywords used when qualifying a table's column's extra attributes */
 #define GDA_EXTRA_AUTO_INCREMENT "AUTO_INCREMENT"
 

Modified: trunk/libgda/gda-holder.c
==============================================================================
--- trunk/libgda/gda-holder.c	(original)
+++ trunk/libgda/gda-holder.c	Thu Oct  2 18:43:14 2008
@@ -28,7 +28,8 @@
 #include "gda-marshal.h"
 #include "gda-util.h"
 #include <libgda.h>
-	
+#include <libgda/gda-attributes-manager.h>
+
 /* 
  * Main static functions 
  */
@@ -51,6 +52,7 @@
 
 /* get a pointer to the parents to be able to call their destructor */
 static GObjectClass  *parent_class = NULL;
+GdaAttributesManager *gda_holder_attributes_manager;
 
 /* signals */
 enum
@@ -71,7 +73,6 @@
 	PROP_ID,
 	PROP_NAME,
 	PROP_DESCR,
-	PROP_PLUGIN,
 	PROP_SIMPLE_BIND,
 	PROP_FULL_BIND,
 	PROP_SOURCE_MODEL,
@@ -84,8 +85,6 @@
 struct _GdaHolderPrivate
 {
 	gchar           *id;
-	gchar           *name;
-	gchar           *descr;
 
 	GType            g_type;
 	GdaHolder       *full_bind;     /* FULL bind to holder */
@@ -102,8 +101,6 @@
 
 	GdaDataModel    *source_model;
 	gint             source_col;
-
-	gchar           *plugin;        /* plugin to be used for user interaction */
 };
 
 /* module error */
@@ -228,9 +225,6 @@
 							   0, G_MAXULONG, GDA_TYPE_NULL,
 							   (G_PARAM_READABLE | 
 							    G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)));
-	g_object_class_install_property (object_class, PROP_PLUGIN,
-					 g_param_spec_string ("plugin", NULL, NULL, NULL, 
-							      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
 	g_object_class_install_property (object_class, PROP_NOT_NULL,
 					 g_param_spec_boolean ("not-null", NULL, NULL, FALSE,
 							       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
@@ -250,6 +244,9 @@
                                          g_param_spec_int ("source-column", NULL, NULL,
 							   0, G_MAXINT, 0,
 							   (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+	
+	/* extra */
+	gda_holder_attributes_manager = gda_attributes_manager_new (TRUE);
 }
 
 static void
@@ -258,8 +255,6 @@
 	holder->priv = g_new0 (GdaHolderPrivate, 1);
 
 	holder->priv->id = NULL;
-	holder->priv->name = NULL;
-	holder->priv->descr = NULL;
 
 	holder->priv->g_type = G_TYPE_INVALID;
 	holder->priv->full_bind = NULL;
@@ -275,7 +270,6 @@
 	holder->priv->not_null = FALSE;
 	holder->priv->source_model = NULL;
 	holder->priv->source_col = 0;
-	holder->priv->plugin = NULL;
 }
 
 /**
@@ -319,10 +313,6 @@
 
 	if (orig->priv->id)
 		holder->priv->id = g_strdup (orig->priv->id);
-	if (orig->priv->name)
-		holder->priv->name = g_strdup (orig->priv->name);
-	if (orig->priv->descr)
-		holder->priv->descr = g_strdup (orig->priv->descr);
 
 	if (orig->priv->full_bind)
 		gda_holder_set_full_bind (holder, orig->priv->full_bind);
@@ -346,8 +336,8 @@
 		if (orig->priv->default_value)
 			holder->priv->default_value = gda_value_copy (orig->priv->default_value);
 		holder->priv->not_null = orig->priv->not_null;
-		if (orig->priv->plugin)
-			holder->priv->plugin = g_strdup (orig->priv->plugin);
+		gda_attributes_manager_copy (gda_holder_attributes_manager, (gpointer) orig, gda_holder_attributes_manager, (gpointer) holder);
+
 		return holder;
 	}
 	else {
@@ -494,9 +484,6 @@
 	holder = GDA_HOLDER (object);
 	if (holder->priv) {
 		g_free (holder->priv->id);
-		g_free (holder->priv->name);
-		g_free (holder->priv->descr);
-		g_free (holder->priv->plugin);
 
 		g_free (holder->priv);
 		holder->priv = NULL;
@@ -513,7 +500,6 @@
 			 const GValue *value,
 			 GParamSpec *pspec)
 {
-	const gchar *ptr;
 	GdaHolder *holder;
 
 	holder = GDA_HOLDER (object);
@@ -524,12 +510,10 @@
 			holder->priv->id = g_value_dup_string (value);
 			break;
 		case PROP_NAME:
-			g_free (holder->priv->name);
-			holder->priv->name = g_value_dup_string (value);
+			gda_holder_set_attribute (holder, GDA_ATTRIBUTE_NAME, value);
 			break;
 		case PROP_DESCR:
-			g_free (holder->priv->descr);
-			holder->priv->descr = g_value_dup_string (value);
+			gda_holder_set_attribute (holder, GDA_ATTRIBUTE_DESCRIPTION, value);
 			break;
 		case PROP_GDA_TYPE:
 			if (holder->priv->g_type == GDA_TYPE_NULL)
@@ -537,15 +521,6 @@
 			else
 				g_warning (_("The 'g-type' property cannot be changed"));
 			break;
-		case PROP_PLUGIN:
-			ptr = g_value_get_string (value);
-			if (holder->priv->plugin) {
-				g_free (holder->priv->plugin);
-				holder->priv->plugin = NULL;
-			}
-			if (ptr)
-				holder->priv->plugin = g_strdup (ptr);
-			break;
 		case PROP_NOT_NULL: {
 			gboolean not_null = g_value_get_boolean (value);
 			if (not_null != holder->priv->not_null) {
@@ -591,6 +566,7 @@
 			 GParamSpec *pspec)
 {
 	GdaHolder *holder;
+	const GValue *cvalue;
 
 	holder = GDA_HOLDER (object);
 	if (holder->priv) {
@@ -599,20 +575,22 @@
 			g_value_set_string (value, holder->priv->id);
 			break;
 		case PROP_NAME:
-			if (holder->priv->name)
-				g_value_set_string (value, holder->priv->name);
+			cvalue = gda_holder_get_attribute (holder, GDA_ATTRIBUTE_NAME);
+			if (cvalue)
+				g_value_set_string (value, g_value_get_string (cvalue));
 			else
 				g_value_set_string (value, holder->priv->id);
 			break;
 		case PROP_DESCR:
-			g_value_set_string (value, holder->priv->descr);
+			cvalue = gda_holder_get_attribute (holder, GDA_ATTRIBUTE_DESCRIPTION);
+			if (cvalue)
+				g_value_set_string (value, g_value_get_string (cvalue));
+			else
+				g_value_set_string (value, NULL);
 			break;
 		case PROP_GDA_TYPE:
 			g_value_set_ulong (value, holder->priv->g_type);
 			break;
-		case PROP_PLUGIN:
-			g_value_set_string (value, holder->priv->plugin);
-			break;
 		case PROP_NOT_NULL:
 			g_value_set_boolean (value, gda_holder_get_not_null (holder));
 			break;
@@ -1598,3 +1576,42 @@
 	return gda_text_to_alphanum (holder->priv->id);
 }
 
+/**
+ * gda_holder_get_attribute
+ * @holder: a #GdaHolder
+ * @attribute: attribute name as a string
+ *
+ * Get the value associated to a named attribute.
+ *
+ * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
+ *
+ * Returns: a read-only #GValue, or %NULL if not attribute named @attribute has been set for @holder
+ */
+const GValue *
+gda_holder_get_attribute (GdaHolder *holder, const gchar *attribute)
+{
+	g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
+	return gda_attributes_manager_get (gda_holder_attributes_manager, holder, attribute);
+}
+
+/**
+ * gda_holder_set_attribute
+ * @holder: a #GdaHolder
+ * @attribute: attribute name as a static string
+ * @value: a #GValue, or %NULL
+ *
+ * Set the value associated to a named attribute.
+ *
+ * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
+ * If there is already an attribute named @attribute set, then its value is replaced with the new @value, 
+ * except if @value is %NULL, in which case the attribute is removed.
+ *
+ * Warning: @sttribute should be a static string (no copy of it is made), so the string should exist as long as the @holder
+ * object exists.
+ */
+void
+gda_holder_set_attribute (GdaHolder *holder, const gchar *attribute, const GValue *value)
+{
+	g_return_if_fail (GDA_IS_HOLDER (holder));
+	gda_attributes_manager_set (gda_holder_attributes_manager, holder, attribute, value);
+}

Modified: trunk/libgda/gda-holder.h
==============================================================================
--- trunk/libgda/gda-holder.h	(original)
+++ trunk/libgda/gda-holder.h	Thu Oct  2 18:43:14 2008
@@ -97,6 +97,9 @@
 gboolean            gda_holder_set_bind                 (GdaHolder *holder, GdaHolder *bind_to, GError **error);
 GdaHolder          *gda_holder_get_bind                 (GdaHolder *holder);
 
+const GValue       *gda_holder_get_attribute            (GdaHolder *holder, const gchar *attribute);
+void                gda_holder_set_attribute            (GdaHolder *holder, const gchar *attribute, const GValue *value);
+
 G_END_DECLS
 
 #endif

Modified: trunk/libgda/gda-meta-struct-io.c
==============================================================================
--- trunk/libgda/gda-meta-struct-io.c	(original)
+++ trunk/libgda/gda-meta-struct-io.c	Thu Oct  2 18:43:14 2008
@@ -24,6 +24,7 @@
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <libgda/gda-meta-struct-private.h>
+#include <libgda/gda-attributes-manager.h>
 
 #include <libgda/sql-parser/gda-statement-struct-util.h>
 
@@ -231,7 +232,6 @@
 			xmlChar *cname, *ctype, *xstr, *extra;
                         gboolean pkey = FALSE;
                         gboolean nullok = FALSE;
-			GArray *extra_array = NULL;
  
                         if (strcmp ((gchar *) cnode->name, "column"))
                                 continue;
@@ -254,14 +254,6 @@
                                 xmlFree (xstr);
                         }
                         ctype = xmlGetProp (cnode, BAD_CAST "type");
-			extra = xmlGetProp (cnode, BAD_CAST "autoinc");
-			if (extra) {
-				gchar *tmp = g_strdup (GDA_EXTRA_AUTO_INCREMENT); /* see gda-enums.h */
-				if (!extra_array)
-					extra_array = g_array_new (FALSE, FALSE, sizeof (gchar*));
-				g_array_append_val (extra_array, tmp);
-				xmlFree (extra);
-			}
 
                         /* a field */
 			GdaMetaTableColumn *tcol;
@@ -277,10 +269,18 @@
 			tcol->nullok = nullok;
 			if (pkey) 
 				g_array_append_val (pk_cols_array, colsindex);
-			tcol->extra = extra_array;
 			colsindex++;
 				
 			/* FIXME: handle default value */
+			extra = xmlGetProp (cnode, BAD_CAST "autoinc");
+			if (extra) {
+				GValue *true_value;
+				g_value_set_boolean ((true_value = gda_value_new (G_TYPE_BOOLEAN)), TRUE);
+				gda_meta_table_column_set_attribute (tcol, GDA_ATTRIBUTE_AUTO_INCREMENT, true_value);
+				gda_value_free (true_value);
+				xmlFree (extra);
+			}
+
 			mtable->columns = g_slist_append (mtable->columns, tcol);
 		}
 		else if (!strcmp ((gchar *) cnode->name, "fkey")) {

Modified: trunk/libgda/gda-meta-struct.c
==============================================================================
--- trunk/libgda/gda-meta-struct.c	(original)
+++ trunk/libgda/gda-meta-struct.c	Thu Oct  2 18:43:14 2008
@@ -25,6 +25,7 @@
 #include <sql-parser/gda-sql-parser.h>
 #include <sql-parser/gda-sql-statement.h>
 #include <sql-parser/gda-statement-struct-util.h>
+#include <libgda/gda-attributes-manager.h>
 
 /*
  * Main static functions
@@ -67,6 +68,7 @@
 
 /* get a pointer to the parents to be able to call their destructor */
 static GObjectClass  *parent_class = NULL;
+static GdaAttributesManager *att_mgr;
 
 /* properties */
 enum {
@@ -140,6 +142,9 @@
 	/* virtual methods */
 	object_class->dispose = gda_meta_struct_dispose;
 	object_class->finalize = gda_meta_struct_finalize;
+
+	/* extra */
+	att_mgr = gda_attributes_manager_new (FALSE);
 }
 
 
@@ -685,17 +690,22 @@
 			if (!gda_value_is_null (cvalue)) {
 				gchar **array, *tmp;
 				gint ai;
-				GArray *extra_array = NULL;
+				GValue *true_value;
+
+				g_value_set_boolean ((true_value = gda_value_new (G_TYPE_BOOLEAN)), TRUE);
 				cstr = g_value_get_string (cvalue);
 				array = g_strsplit (cstr, ",", 0);
 				for (ai = 0; array [ai]; ai++) {
-					if (!extra_array)
-						extra_array = g_array_new (FALSE, FALSE, sizeof (gchar*));
 					tmp = g_strstrip (array [ai]);
-					g_array_append_val (extra_array, tmp);
+					if (!strcmp (tmp, GDA_EXTRA_AUTO_INCREMENT))
+						gda_attributes_manager_set (att_mgr, tcol, GDA_ATTRIBUTE_AUTO_INCREMENT, 
+									    true_value);
+					else
+						g_message ("Unknown EXTRA attribute '%s', please report this bug to "
+							   "http://bugzilla.gnome.org/ for the \"libgda\" product.", tmp);
 				}
-				g_free (array); /* don't use g_strfreev() here because we have stolen the string pointers */
-				tcol->extra = extra_array;
+				gda_value_free (true_value);
+				g_strfreev (array);
 			}
 		}
 		mt->columns = g_slist_reverse (mt->columns);
@@ -804,6 +814,8 @@
 								  "ts", ischema, 
 								  "tname", iname, 
 								  "cname", cvalue, NULL);
+				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;
@@ -812,12 +824,18 @@
 								      "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));
+				
 				if (fk_cols && ref_pk_cols) {
 					gint fk_nrows, ref_pk_nrows;
 					fk_nrows = gda_data_model_get_n_rows (fk_cols);
 					ref_pk_nrows = gda_data_model_get_n_rows (ref_pk_cols);
-					if (fk_nrows != ref_pk_nrows)
+					if (fk_nrows != ref_pk_nrows) {
+						/*gda_data_model_dump (fk_cols, stdout);
+						  gda_data_model_dump (ref_pk_cols, stdout);*/
 						fkerror = TRUE;
+					}
 					else {
 						gint n;
 						tfk->cols_nb = fk_nrows;
@@ -1682,12 +1700,7 @@
 	g_free (tcol->column_name);
 	g_free (tcol->column_type);
 	g_free (tcol->default_value);
-	if (tcol->extra) {
-		gint i;
-		for (i = 0; i < tcol->extra->len; i++)
-			g_free (g_array_index (tcol->extra, gchar *, i));
-		g_array_free (tcol->extra, TRUE);
-	}
+	gda_attributes_manager_clear (att_mgr, tcol);
 	g_free (tcol);
 }
 
@@ -2153,3 +2166,55 @@
 		return dbo;
 	}
 }
+
+/**
+ * gda_meta_table_column_get_attribute
+ * @tcol: a #GdaMetaTableColumn
+ * @attribute: attribute name as a string
+ *
+ * Get the value associated to a named attribute.
+ *
+ * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
+ *
+ * Returns: a read-only #GValue, or %NULL if not attribute named @attribute has been set for @column
+ */
+const GValue *
+gda_meta_table_column_get_attribute (GdaMetaTableColumn *tcol, const gchar *attribute)
+{
+	return gda_attributes_manager_get (att_mgr, tcol, attribute);
+}
+
+/**
+ * gda_meta_table_column_set_attribute
+ * @tcol: a #GdaMetaTableColumn
+ * @attribute: attribute name as a static string
+ * @value: a #GValue, or %NULL
+ *
+ * Set the value associated to a named attribute.
+ *
+ * Attributes can have any name, but Libgda proposes some default names, see <link linkend="libgda-40-Attributes-manager.synopsis">this section</link>.
+ * If there is already an attribute named @attribute set, then its value is replaced with the new @value, 
+ * except if @value is %NULL, in which case the attribute is removed.
+ *
+ * Warning: @sttribute should be a static string (no copy of it is made), so the string should exist as long as the @column
+ * object exists.
+ */
+void
+gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol, const gchar *attribute, const GValue *value)
+{
+	gda_attributes_manager_set (att_mgr, tcol, attribute, value);
+}
+
+/**
+ * gda_meta_table_column_foreach_attribute
+ * @column: a #GdaMetaTableColumn
+ * @func: a #GdaAttributesManagerFunc function
+ * @data: user data to be passed as last argument of @func each time it is called
+ *
+ * Calls @func for each attribute set to tcol
+ */
+void
+gda_meta_table_column_foreach_attribute (GdaMetaTableColumn *tcol, GdaAttributesManagerFunc func, gpointer data)
+{
+	gda_attributes_manager_foreach (att_mgr, tcol, func, data);
+}

Modified: trunk/libgda/gda-meta-struct.h
==============================================================================
--- trunk/libgda/gda-meta-struct.h	(original)
+++ trunk/libgda/gda-meta-struct.h	Thu Oct  2 18:43:14 2008
@@ -25,6 +25,7 @@
 #include <libgda/gda-data-model.h>
 #include <libgda/gda-meta-store.h>
 #include <libgda/gda-decl.h>
+#include <libgda/gda-attributes-manager.h>
 
 G_BEGIN_DECLS
 
@@ -144,11 +145,13 @@
 	gchar        *column_type;
 	GType         gtype;
 	gboolean      pkey;
-        gboolean      nullok;
+	gboolean      nullok;
 	gchar        *default_value;
-	GArray       *extra; /* array of strings such as "AUTO_INCREMENT", may be NULL */
 } GdaMetaTableColumn;
 #define GDA_META_TABLE_COLUMN(x) ((GdaMetaTableColumn*)(x))
+const GValue *gda_meta_table_column_get_attribute (GdaMetaTableColumn *tcol, const gchar *att_name);
+void          gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol, const gchar *att_name, const GValue *value);
+void          gda_meta_table_column_foreach_attribute (GdaMetaTableColumn *tcol, GdaAttributesManagerFunc func, gpointer data);
 
 typedef struct {
 	GdaMetaDbObject  *meta_table;

Modified: trunk/libgda/gda-server-provider-extra.c
==============================================================================
--- trunk/libgda/gda-server-provider-extra.c	(original)
+++ trunk/libgda/gda-server-provider-extra.c	Thu Oct  2 18:43:14 2008
@@ -487,7 +487,7 @@
 	for (i = 0; i < nbcols; i++) {
                 column = gda_data_model_describe_column (GDA_DATA_MODEL (model), i);
 
-                gda_column_set_title (column, spec[i].col_name);
+                gda_column_set_description (column, spec[i].col_name);
                 gda_column_set_name (column, spec[i].col_name);
                 gda_column_set_g_type (column, spec[i].data_type);
         }
@@ -526,10 +526,10 @@
 
                 column = gda_data_model_describe_column (GDA_DATA_MODEL (model), i);
 
-		if (strcmp (gda_column_get_title (column), spec[i].col_name)) {
+		if (strcmp (gda_column_get_description (column), spec[i].col_name)) {
 			g_set_error (error, 0, 0,
 				     _("Data model for schema has a wrong column title: '%s' instead of '%s'"),
-				     gda_column_get_title (column), spec[i].col_name);
+				     gda_column_get_description (column), spec[i].col_name);
 			return FALSE;
 		}
 

Modified: trunk/libgda/libgda.h.in
==============================================================================
--- trunk/libgda/libgda.h.in	(original)
+++ trunk/libgda/libgda.h.in	Thu Oct  2 18:43:14 2008
@@ -26,6 +26,7 @@
 #ifndef __LIBGDA_H__
 #define __LIBGDA_H__
 
+#include <libgda/gda-attributes-manager.h>
 #include <libgda/gda-easy.h>
 #include <libgda/gda-column.h>
 #include <libgda/gda-config.h>

Modified: trunk/libgda/sqlite/gda-sqlite-meta.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-meta.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-meta.c	Thu Oct  2 18:43:14 2008
@@ -1735,7 +1735,8 @@
 					break;
 				}
 				constname = g_strdup_printf ("fk%d_%s", fkid, g_value_get_string (cvalue));
-				if (strcmp (g_value_get_string (constraint_name), constname)) {
+				if (strcmp (const_name, constname)) {
+					fkid = -1;
 					g_free (constname);
 					continue;
 				}
@@ -1757,7 +1758,6 @@
 					    TRUE, v1 /* ordinal_position */))
 				retval = FALSE;
 		}
-
 		g_object_unref (tmpmodel);
 	}
 	else {

Modified: trunk/libgda/sqlite/gda-sqlite-provider.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-provider.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-provider.c	Thu Oct  2 18:43:14 2008
@@ -405,13 +405,13 @@
 		recset = (GdaDataModelArray *) cdata->functions_model;
 		if (!recset) {
 			recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new, 3);
-			gda_column_set_title (0, "name");
+			gda_column_set_description (0, "name");
 			gda_column_set_name (0, "name");
 			gda_column_set_g_type (0, G_TYPE_STRING);
-			gda_column_set_title (1, "nargs");
+			gda_column_set_description (1, "nargs");
 			gda_column_set_name (1, "nargs");
 			gda_column_set_g_type (1, G_TYPE_INT);
-			gda_column_set_title (2, "specificname");
+			gda_column_set_description (2, "specificname");
 			gda_column_set_name (2, "specificname");
 			gda_column_set_g_type (2, G_TYPE_STRING);
 			cdata->functions_model = (GdaDataModel *) recset;
@@ -423,13 +423,13 @@
 		recset = (GdaDataModelArray *) cdata->aggregates_model;
 		if (!recset) {
 			recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new, 3);
-			gda_column_set_title (0, "name");
+			gda_column_set_description (0, "name");
 			gda_column_set_name (0, "name");
 			gda_column_set_g_type (0, G_TYPE_STRING);
-			gda_column_set_title (1, "nargs");
+			gda_column_set_description (1, "nargs");
 			gda_column_set_name (1, "nargs");
 			gda_column_set_g_type (1, G_TYPE_INT);
-			gda_column_set_title (2, "specificname");
+			gda_column_set_description (2, "specificname");
 			gda_column_set_name (2, "specificname");
 			gda_column_set_g_type (2, G_TYPE_STRING);
 			cdata->functions_model = (GdaDataModel *) recset;

Modified: trunk/libgda/sqlite/gda-sqlite-recordset.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-recordset.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-recordset.c	Thu Oct  2 18:43:14 2008
@@ -237,7 +237,7 @@
 			GdaColumn *column;
 			
 			column = GDA_COLUMN (list->data);
-			gda_column_set_title (column, sqlite3_column_name (ps->sqlite_stmt, i));
+			gda_column_set_description (column, sqlite3_column_name (ps->sqlite_stmt, i));
 			gda_column_set_name (column, sqlite3_column_name (ps->sqlite_stmt, i));
 			gda_column_set_dbms_type (column, sqlite3_column_decltype (ps->sqlite_stmt, i));
 			if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)

Modified: trunk/providers/freetds/gda-freetds-recordset.c
==============================================================================
--- trunk/providers/freetds/gda-freetds-recordset.c	(original)
+++ trunk/providers/freetds/gda-freetds-recordset.c	Thu Oct  2 18:43:14 2008
@@ -286,7 +286,7 @@
 	
 	attribs = gda_data_model_describe_column (model, col);
 
-	gda_column_set_title (attribs, colinfo->column_name);
+	gda_column_set_description (attribs, colinfo->column_name);
 
 	memcpy (name, colinfo->column_name,
 	        colinfo->column_namelen);

Modified: trunk/providers/ibmdb2/gda-ibmdb2-recordset.c
==============================================================================
--- trunk/providers/ibmdb2/gda-ibmdb2-recordset.c	(original)
+++ trunk/providers/ibmdb2/gda-ibmdb2-recordset.c	Thu Oct  2 18:43:14 2008
@@ -261,7 +261,7 @@
         attribs = gda_data_model_describe_column ((GdaDataModel*) model, col);
 
 	tmp = g_strndup (field->column_name, field->column_name_len);
-	gda_column_set_title (attribs, tmp);
+	gda_column_set_description (attribs, tmp);
 	g_free (tmp);
 	
 	gda_column_set_name (attribs, field->column_name);

Modified: trunk/providers/mdb/gda-mdb-provider.c
==============================================================================
--- trunk/providers/mdb/gda-mdb-provider.c	(original)
+++ trunk/providers/mdb/gda-mdb-provider.c	Thu Oct  2 18:43:14 2008
@@ -462,7 +462,7 @@
 		gda_col = gda_data_model_describe_column (model, c);
 		tmp = sanitize_name (g_strdup (mdb_col->name));
 		gda_column_set_name (gda_col, tmp);
-		gda_column_set_title (gda_col, tmp);
+		gda_column_set_description (gda_col, tmp);
 		g_free (tmp);
 		tmp = sanitize_name (g_strdup (mdb_get_coltype_string (spec->cdata->mdb->default_backend, mdb_col->col_type)));
 		gda_column_set_dbms_type (gda_col, tmp);

Modified: trunk/providers/msql/gda-msql-recordset.c
==============================================================================
--- trunk/providers/msql/gda-msql-recordset.c	(original)
+++ trunk/providers/msql/gda-msql-recordset.c	Thu Oct  2 18:43:14 2008
@@ -364,7 +364,7 @@
 	g_return_if_fail (msql_field);
 
 	if (msql_field->name) {
-		gda_column_set_title (attrs, msql_field->name);
+		gda_column_set_description (attrs, msql_field->name);
 		gda_column_set_name (attrs, msql_field->name);
 	}
 	gda_column_set_defined_size (attrs, msql_field->length);

Modified: trunk/providers/mysql/gda-mysql-recordset.c
==============================================================================
--- trunk/providers/mysql/gda-mysql-recordset.c	(original)
+++ trunk/providers/mysql/gda-mysql-recordset.c	Thu Oct  2 18:43:14 2008
@@ -377,7 +377,7 @@
 			}
 			gda_column_set_g_type (column, gtype);
 			gda_column_set_name (column, field->name);
-			gda_column_set_title (column, field->name);
+			gda_column_set_description (column, field->name);
 			
 			mysql_bind_result[i].buffer_type = field->type;
 			switch (mysql_bind_result[i].buffer_type) {

Modified: trunk/providers/postgres/gda-postgres-recordset.c
==============================================================================
--- trunk/providers/postgres/gda-postgres-recordset.c	(original)
+++ trunk/providers/postgres/gda-postgres-recordset.c	Thu Oct  2 18:43:14 2008
@@ -301,7 +301,7 @@
 			_GDA_PSTMT (ps)->types [i] = gtype;
 			gda_column_set_g_type (column, gtype);
 			gda_column_set_name (column, PQfname (pg_res, i));
-			gda_column_set_title (column, PQfname (pg_res, i));
+			gda_column_set_description (column, PQfname (pg_res, i));
 		}
         }
 }

Modified: trunk/providers/sybase/gda-sybase-recordset.c
==============================================================================
--- trunk/providers/sybase/gda-sybase-recordset.c	(original)
+++ trunk/providers/sybase/gda-sybase-recordset.c	Thu Oct  2 18:43:14 2008
@@ -79,7 +79,7 @@
 	        colinfo->namelen);
 	name[colinfo->namelen + 1] = 0;
 
-	gda_column_set_title (attribs, name);
+	gda_column_set_description (attribs, name);
 	gda_column_set_name (attribs, name);
 	gda_column_set_scale (attribs, colinfo->scale);
 	gda_column_set_g_type (attribs,

Modified: trunk/samples/BDB/custom-bdb-model.c
==============================================================================
--- trunk/samples/BDB/custom-bdb-model.c	(original)
+++ trunk/samples/BDB/custom-bdb-model.c	Thu Oct  2 18:43:14 2008
@@ -111,13 +111,13 @@
 	column = gda_column_new ();
 	list = g_slist_append (list , column);
 	gda_column_set_name (column, "color");
-	gda_column_set_title (column, "color");
+	gda_column_set_description (column, "color");
 	gda_column_set_g_type (column, G_TYPE_STRING);
 
 	column = gda_column_new ();
 	list = g_slist_append (list , column);
 	gda_column_set_name (column, "type");
-	gda_column_set_title (column, "type");
+	gda_column_set_description (column, "type");
 	gda_column_set_g_type (column, G_TYPE_INT);
 
 	return list;
@@ -132,13 +132,13 @@
 	column = gda_column_new ();
 	list = g_slist_append (list , column);
 	gda_column_set_name (column, "size");
-	gda_column_set_title (column, "size");
+	gda_column_set_description (column, "size");
 	gda_column_set_g_type (column, G_TYPE_FLOAT);
 
 	column = gda_column_new ();
 	list = g_slist_append (list , column);
 	gda_column_set_name (column, "name");
-	gda_column_set_title (column, "name");
+	gda_column_set_description (column, "name");
 	gda_column_set_g_type (column, G_TYPE_STRING);
 
 	return list;

Modified: trunk/tests/gda-ddl-creator.c
==============================================================================
--- trunk/tests/gda-ddl-creator.c	(original)
+++ trunk/tests/gda-ddl-creator.c	Thu Oct  2 18:43:14 2008
@@ -510,6 +510,26 @@
 		return expr;
 }
 
+typedef struct {
+	GdaServerOperation *op;
+	gint index;
+	GError **error;
+	gboolean allok;
+} FData;
+static void
+meta_table_column_foreach_attribute_func (const gchar *att_name, const GValue *value, FData *fdata)
+{
+	if (!fdata->allok)
+		return;
+	if (!strcmp (att_name, GDA_ATTRIBUTE_AUTO_INCREMENT) && 
+	    (G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) && 
+	    g_value_get_boolean (value)) {
+		fdata->allok = gda_server_operation_set_value_at (fdata->op, "TRUE", fdata->error,
+								  "/FIELDS_A/@COLUMN_AUTOINC/%d", 
+								  fdata->index);
+	}
+}
+
 static GdaServerOperation *
 create_server_operation_for_table (GdaDDLCreator *ddlc, GdaServerProvider *prov, GdaConnection *cnc, 
 				   GdaMetaDbObject *dbobj, GError **error)
@@ -548,25 +568,16 @@
 		if (! gda_server_operation_set_value_at (op, "FALSE", error,
 							 "/FIELDS_A/@COLUMN_UNIQUE/%d", index))
 			goto onerror;
-		if (tcol->extra) {
-			gint i;
-			for (i = 0; i < tcol->extra->len; i++) {
-				const gchar *tmp;
-				tmp = g_array_index (tcol->extra, gchar *, i);
-				if (!strcmp (tmp, GDA_EXTRA_AUTO_INCREMENT)) {
-					if (! gda_server_operation_set_value_at (op, "TRUE", error,
-										 "/FIELDS_A/@COLUMN_AUTOINC/%d", index))
-						goto onerror;
-				}
-				else {
-					g_warning ("Unknown extra keyword '%s'", tmp);
-					TO_IMPLEMENT;
-					g_set_error (error, 0, 0,
-						     "Unknown extra keyword '%s'", tmp);
-					goto onerror;
-				}
-			}
-		}
+		FData fdata;
+		fdata.op = op;
+		fdata.index = index;
+		fdata.error = error;
+		fdata.allok = TRUE;
+		gda_meta_table_column_foreach_attribute (tcol, (GdaAttributesManagerFunc) meta_table_column_foreach_attribute_func,
+							 &fdata);
+		if (!fdata.allok)
+			goto onerror;
+
 		repl = provider_specific_match (ddlc->priv->provider_specifics, prov, "dummy", "/FIELDS_A/@COLUMN_PKEY");
 		if (repl) {
 			if (! gda_server_operation_set_value_at (op, tcol->pkey ? "TRUE" : "FALSE", error,

Modified: trunk/tests/value-holders/check_holder.c
==============================================================================
--- trunk/tests/value-holders/check_holder.c	(original)
+++ trunk/tests/value-holders/check_holder.c	Thu Oct  2 18:43:14 2008
@@ -32,6 +32,7 @@
 static gboolean test9 (GError **error);
 static gboolean test10 (GError **error);
 static gboolean test11 (GError **error);
+static gboolean test12 (GError **error);
 
 TestFunc tests[] = {
 	test1,
@@ -44,7 +45,8 @@
 	test8,
 	test9,
 	test10,
-	test11
+	test11,
+	test12
 };
 
 int 
@@ -933,6 +935,70 @@
 	return TRUE;
 }
 
+static gboolean
+test12 (GError **error)
+{
+	GdaHolder *h;
+	const GValue *cvalue;
+	GValue *value;
+
+	h = gda_holder_new (GDA_TYPE_NULL);
+
+	/***/
+	value = gda_value_new_from_string ("my string", G_TYPE_STRING);
+	if (gda_holder_get_attribute (h, "attname1")) {
+		g_set_error (error, 0, 0,
+			     "gda_holder_get_attribute() should have retunred NULL");
+		return FALSE;
+	}
+	gda_holder_set_attribute (h, "attname1", value);
+	gda_value_free (value);
+	cvalue = gda_holder_get_attribute (h, "attname1");
+	if (!cvalue) {
+		g_set_error (error, 0, 0,
+			     "gda_holder_get_attribute() should have retunred a value");
+		return FALSE;
+	}
+	value = gda_value_new_from_string ("my string", G_TYPE_STRING);
+	if (gda_value_differ (cvalue, value)) {
+		g_set_error (error, 0, 0,
+			     "gda_holder_get_attribute() retunred a wrong value");
+		return FALSE;
+	}
+
+	/***/
+	GdaHolder *copy;
+	gchar *name;
+
+	g_object_set (G_OBJECT (h), "name", "thename", NULL);
+	copy = gda_holder_copy (h);
+	cvalue = gda_holder_get_attribute (copy, "attname1");
+	if (!cvalue) {
+		g_set_error (error, 0, 0,
+			     "gda_holder_get_attribute() should have retunred a value");
+		return FALSE;
+	}
+	if (gda_value_differ (cvalue, value)) {
+		g_set_error (error, 0, 0,
+			     "gda_holder_get_attribute() retunred a wrong value");
+		return FALSE;
+	}
+	gda_value_free (value);
+
+	g_object_get (G_OBJECT (copy), "name", &name, NULL);
+	if (strcmp (name, "thename")) {
+		g_set_error (error, 0, 0,
+			     "gda_holder_copy() did not copy the name");
+		return FALSE;
+	}
+	g_free (name);
+
+	g_object_unref (copy);
+	g_object_unref (h);
+
+	return TRUE;
+}
+
 
 /*
  * Signals testing

Modified: trunk/tools/command-exec.c
==============================================================================
--- trunk/tools/command-exec.c	(original)
+++ trunk/tools/command-exec.c	Thu Oct  2 18:43:14 2008
@@ -26,10 +26,84 @@
 #ifdef HAVE_HISTORY
 #include <readline/history.h>
 #endif
+#include <sql-parser/gda-statement-struct-util.h>
 
+/*
+ *  gda_internal_command_arg_remove_quotes
+ *
+ * If @str has simple or double quotes, remove those quotes, otherwise does nothing.
+ *
+ * Returns: @str
+ */
+gchar *
+gda_internal_command_arg_remove_quotes (gchar *str)
+{
+	glong total;
+        gchar *ptr;
+        glong offset = 0;
+        char delim;
+
+        if (!str)
+                return NULL;
+        delim = *str;
+        if ((delim != '\'') && (delim != '"'))
+                return str;
+
+
+        total = strlen (str);
+        if (str[total-1] == delim) {
+                /* string is correclty terminated by a double quote */
+                g_memmove (str, str+1, total-2);
+                total -=2;
+        }
+        else {
+                /* string is _not_ correclty terminated by a double quote */
+                g_memmove (str, str+1, total-1);
+                total -=1;
+        }
+        str[total] = 0;
+
+        ptr = (gchar *) str;
+        while (offset < total) {
+                /* we accept the "''" as a synonym of "\'" */
+                if (*ptr == delim) {
+                        if (*(ptr+1) == delim) {
+                                g_memmove (ptr+1, ptr+2, total - offset);
+                                offset += 2;
+                        }
+                        else {
+                                *str = 0;
+                                return str;
+                        }
+                }
+                if (*ptr == '\\') {
+                        if (*(ptr+1) == '\\') {
+                                g_memmove (ptr+1, ptr+2, total - offset);
+                                offset += 2;
+                        }
+                        else {
+                                if (*(ptr+1) == delim) {
+                                        *ptr = delim;
+                                        g_memmove (ptr+1, ptr+2, total - offset);
+                                        offset += 2;
+                                }
+                                else {
+                                        *str = 0;
+                                        return str;
+                                }
+			}
+                }
+                else
+                        offset ++;
+
+                ptr++;
+        }
+
+        return str;
+}
 
 /*
- * command_exec_result_free
+ * gda_internal_command_exec_result_free
  *
  * Clears the memory associated with @res
  */
@@ -303,6 +377,11 @@
 		args = command->arguments_delimiter_func (command_str);
 	else
 		args = default_gda_internal_commandargs_func (command_str);
+	if (command->unquote_args) {
+		gint i;
+		for (i = 1; args[i]; i++) 
+			gda_internal_command_arg_remove_quotes (args[i]);
+	}
 	res = command->command_func (cnc, (const gchar **) &(args[1]), 
 				     error, command->user_data);
 	
@@ -607,6 +686,21 @@
 	return NULL;
 }
 
+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"));
+	}
+}
+
 GdaInternalCommandResult *
 gda_internal_command_detail (GdaConnection *cnc, const gchar **args,
 			     GError **error, gpointer data)
@@ -742,7 +836,8 @@
 			GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
 			GList *values = NULL;
 			GValue *val;
-			
+			GString *string = NULL;
+
 			g_value_set_string ((val = gda_value_new (G_TYPE_STRING)), tcol->column_name);
 			values = g_list_append (values, val);
 			g_value_set_string ((val = gda_value_new (G_TYPE_STRING)), tcol->column_type);
@@ -751,28 +846,10 @@
 			values = g_list_append (values, val);
 			g_value_set_string ((val = gda_value_new (G_TYPE_STRING)), tcol->default_value);
 			values = g_list_append (values, val);
-			if (tcol->extra) {
-				GString *string;
-				gint i;
-				gboolean first = TRUE;
-				string = g_string_new ("");
-				for (i = 0; i < tcol->extra->len; i++) {
-					const gchar *tmp = g_array_index (tcol->extra, gchar *, i);
-					const gchar *astmp = NULL;
-					if (!strcmp (tmp, GDA_EXTRA_AUTO_INCREMENT)) 
-						astmp = _("Auto increment");
-					else {
-						g_warning ("Unknown extra keyword '%s'", tmp);
-						TO_IMPLEMENT;
-					}
-					if (astmp) {
-						if (first)
-							first = FALSE;
-						else
-							g_string_append (string, ", ");
-						g_string_append (string, astmp);
-					}
-				}
+
+			gda_meta_table_column_foreach_attribute (tcol, 
+					      (GdaAttributesManagerFunc) meta_table_column_foreach_attribute_func, &string);
+			if (string) {
 				g_value_take_string ((val = gda_value_new (G_TYPE_STRING)), string->str);
 				g_string_free (string, FALSE);
 			}

Modified: trunk/tools/command-exec.h
==============================================================================
--- trunk/tools/command-exec.h	(original)
+++ trunk/tools/command-exec.h	Thu Oct  2 18:43:14 2008
@@ -67,6 +67,7 @@
 	GdaInternalCommandFunc     command_func;
 	gpointer                   user_data;
 	GdaInternalCommandArgsFunc arguments_delimiter_func;
+	gboolean                   unquote_args;
 } GdaInternalCommand;
 
 typedef struct {
@@ -77,6 +78,8 @@
 	GSList    *group_ordered;
 } GdaInternalCommandsList;
 
+gchar                    *gda_internal_command_arg_remove_quotes (gchar *str);
+
 /* Commands execution */
 GdaInternalCommandResult *gda_internal_command_execute (GdaInternalCommandsList *commands_list,
 							GdaConnection *cnc, const gchar *command_str, GError **error);

Modified: trunk/tools/gda-sql.c
==============================================================================
--- trunk/tools/gda-sql.c	(original)
+++ trunk/tools/gda-sql.c	Thu Oct  2 18:43:14 2008
@@ -1291,7 +1291,7 @@
 	}
 
 	length = strlen (str);
-	if (str[length] != '\n')
+	if (str[length - 1] != '\n')
 		append_nl = TRUE;
 
 	if (data && data->output_stream)
@@ -1423,6 +1423,7 @@
 	c->command_func = gda_internal_command_history;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1433,6 +1434,7 @@
 	c->command_func = gda_internal_command_dict_sync;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1443,6 +1445,7 @@
 	c->command_func = gda_internal_command_list_tables;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = FALSE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1453,6 +1456,7 @@
 	c->command_func = gda_internal_command_list_views;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = FALSE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1463,6 +1467,7 @@
 	c->command_func = gda_internal_command_list_schemas;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = FALSE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1473,6 +1478,7 @@
 	c->command_func = gda_internal_command_detail;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = FALSE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1483,6 +1489,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_graph;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = FALSE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	/* specific commands */
@@ -1494,6 +1501,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_manage_cnc;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1504,6 +1512,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_close_cnc;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1514,6 +1523,7 @@
 	c->command_func = (GdaInternalCommandFunc)extra_command_bind_cnc;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1524,6 +1534,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_list_dsn;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1534,6 +1545,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_create_dsn;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1544,6 +1556,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_remove_dsn;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1554,6 +1567,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_list_providers;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1564,6 +1578,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_set_input;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1574,6 +1589,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_set_output;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1584,6 +1600,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_echo;
 	c->user_data = data;
 	c->arguments_delimiter_func = args_as_string_func;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1594,6 +1611,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_qecho;
 	c->user_data = data;
 	c->arguments_delimiter_func = args_as_string_func;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1604,6 +1622,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_quit;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1614,6 +1633,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_cd;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1624,6 +1644,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_copyright;
 	c->user_data = NULL;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1634,6 +1655,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_edit_buffer;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1644,6 +1666,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_reset_buffer;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1654,6 +1677,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_show_buffer;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1664,6 +1688,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_exec_buffer;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1674,6 +1699,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_write_buffer;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1684,6 +1710,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_to_dict;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1694,6 +1721,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_from_dict;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1704,6 +1732,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_delete_dict;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1714,6 +1743,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_list_dict;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1724,6 +1754,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_set;
 	c->user_data = data;
 	c->arguments_delimiter_func = args_as_string_set;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1734,6 +1765,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_unset;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	c = g_new0 (GdaInternalCommand, 1);
@@ -1744,6 +1776,7 @@
 	c->command_func = (GdaInternalCommandFunc) extra_command_set_output_format;
 	c->user_data = data;
 	c->arguments_delimiter_func = NULL;
+	c->unquote_args = TRUE;
 	commands->commands = g_slist_prepend (commands->commands, c);
 
 	/* comes last */
@@ -1761,7 +1794,7 @@
 }
 
 static GdaInternalCommandResult *
-extra_command_set_output (GdaConnection *cnc,const gchar **args,
+extra_command_set_output (GdaConnection *cnc, const gchar **args,
 			  GError **error, MainData *data)
 {
 	if (set_output_file (data, args[0], error)) {
@@ -1776,7 +1809,7 @@
 }
 
 static GdaInternalCommandResult *
-extra_command_set_output_format (GdaConnection *cnc,const gchar **args,
+extra_command_set_output_format (GdaConnection *cnc, const gchar **args,
 				 GError **error, MainData *data)
 {
 	GdaInternalCommandResult *res;
@@ -1994,13 +2027,7 @@
 	newdsn.name = (gchar *) args [0];
 	gda_connection_string_split ((gchar *) args[1], &real_cnc, &real_provider, &user, &pass);
 	newdsn.provider = real_provider;
-	newdsn.description = NULL;
-	if (args[2]) {
-		if ((*args[2] == '"') && (args[2][strlen (args[2]) - 1] == '"'))
-			newdsn.description = g_strndup (args[2] + 1, strlen (args[2]) - 2);
-		else
-			newdsn.description = g_strdup (args[2]);
-	}
+	newdsn.description = (gchar*) args[2];
 	
 	newdsn.cnc_string = real_cnc;
 	newdsn.auth_string = NULL;
@@ -2025,7 +2052,6 @@
 	g_free (real_provider);
 	g_free (user);
 	g_free (pass);
-	g_free (newdsn.description);
 
 	return res;
 }



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