[libgda] libgda VAPI update for GdaMetaContext. Reimplementing GdaData.Object.



commit e0f14698ac8a8a6ff1c97a3272c94085c16a28f7
Author: Daniel Espinosa <despinosa src gnome org>
Date:   Wed Jan 4 10:02:40 2012 -0600

    libgda VAPI update for GdaMetaContext. Reimplementing GdaData.Object.
    
    * Added missing annotations to gda-meta-store.h for GIR generation with no
    effect see bug #667236
    * Modified Gda-5.0.metadata to deal with bug above.
    * GdaData.ObjectSingleId implements GdaData.Object for tables with one ID field
    * GdaData.Object now have most of its members as abstracts and implemented
    by ObjectSingleId for tables with just one ID field. Future ObjectMultipleId
    must handle multiple ID fields.
    * GdaData.Object reimplemented to use Field new object to avoid Gda.DataModel
    and allow to create 'off line' objects and add them to the database.
    * GdaData.Object.append is implemented by GdaData.ObjectSingleId.
    * New Field<G> generig class to manage records fields.
    * Updated DbField and DbRecord interfaces.
    * Added a class UML diagram using Gaphor to show classes and interfaces design.

 libgda/Gda-5.0.metadata                |    4 +
 libgda/data/DataObject.vala            |  100 +----
 libgda/data/DataObjectSingleId.vala    |  119 +++++
 libgda/data/DbField.vala               |    7 +-
 libgda/data/DbObject.vala              |   41 ++
 libgda/data/DbRecord.vala              |    6 +-
 libgda/data/Field.vala                 |   56 +++
 libgda/data/GdaData-5.0.gir            |  315 ++++++++++---
 libgda/data/GdaData-UML.gaphor         |  841 ++++++++++++++++++++++++++++++++
 libgda/data/Makefile.am                |    3 +
 libgda/gda-meta-store.h                |    4 +-
 libgda/libgda-5.0.vapi                 |    6 +-
 samples/vala/Makefile                  |    2 +-
 samples/vala/SampleDataObject.vala     |   90 ++--
 tests/vala/CheckDataModelIterator.vala |    7 +-
 tests/vala/CheckDataObject.vala        |   60 ++-
 tests/vala/Makefile.am                 |    4 +-
 17 files changed, 1440 insertions(+), 225 deletions(-)
---
diff --git a/libgda/Gda-5.0.metadata b/libgda/Gda-5.0.metadata
index b064b52..778867d 100644
--- a/libgda/Gda-5.0.metadata
+++ b/libgda/Gda-5.0.metadata
@@ -19,6 +19,10 @@ Set.nodes_list type="GLib.List<Gda.SetNode>"
 Set.sources_list type="GLib.List<Gda.SetSource>"
 Set.get_holder_value nullable=true
 TransactionStatus.events type="GLib.List<Gda.TransactionStatusEvent>"
+MetaContext.column_names array=true
+MetaContext.column_names array_length_field="size"
+MetaContext.column_values array=true
+MetaContext.column_values array_length_field="size"
 MetaDbObject.depend_list type="GLib.List<Gda.MetaDbObject>"
 MetaTable.columns type="GLib.List<Gda.MetaTableColumn>"
 MetaTable.reverse_fk_list type="GLib.List<Gda.MetaTableForeignKey>"
diff --git a/libgda/data/DataObject.vala b/libgda/data/DataObject.vala
index 3a62efd..37ace8d 100644
--- a/libgda/data/DataObject.vala
+++ b/libgda/data/DataObject.vala
@@ -21,122 +21,52 @@ using Gda;
 
 namespace GdaData {
 
-    public errordomain ObjectError {
-    	APPEND
-    }
     public abstract class Object<G> : GLib.Object {
         
-        private string? _field_id;
-        private Value? _id_value;
-        private DataModel _model;
-        
+        protected Gee.HashMap<string,Field<Value?>> _model;
         /**
          * Derived classes must implement this property to set the table used to get data from.
          */
         public abstract string table { get; }
-        
         /**
          * Returns a Gda.DataModel with the data stored by this object.
          */
-        public DataModel record {
-        	get {
-        		return this._model;
-        	}
-        }
-        
+        public abstract DataModel record { get; }
         /**
          * Set the connection to be used to get/set data.
          */
         public Connection connection { get; set; }
-        
-        public string get_field_id ()
-        {
-        	return this._field_id;
-        }
-        
-        public Value get_value_id ()
-        {
-        	return this._id_value;
-        }
-        
-        /* 
-         * Set a condition to get only one row data from the table in the database.
-         */
-        public void set_id (string field, Value v)
-        	throws Error
-        	requires (this.table != "")
-        {
-        	this._field_id = field;
-        	this._id_value = v;
-        	var q = this.sql ();
-        	var s = q.get_statement ();
-        	var m = this.connection.statement_execute_select (s, null);
-        	((DataSelect) m).compute_modification_statements ();
-        	this._model= (DataModel) DataProxy.new (m);
-        }
-        
         /**
          * Returns a GLib.Value containing the value stored in the given field.
          */
-        public unowned Value? get_value (string field)
+        public Value? get_value (string field)
         	throws Error
         {
-        	return this._model.get_value_at (this._model.get_column_index (field), 0);
+        	return (this._model.get (field)).value;
         }
-        
-        /**
-         * Set the value to a field with the given @name
+		/**
+         * Set the value to a field with the given @name.
          */
         public void set_value (string field, Value v)
         	throws Error
         {
-        	this._model.set_value_at (this._model.get_column_index (field), 0, v);
+        	var f = _model.get (field);
+        	f.value = v;
+        	this._model.set (field, f);
         }
-        
         /**
          * Saves any modficiation made to in memory representation of the data directly to
          * the database.
          */
-        public void save ()
-        	throws Error
-        {
-        	((DataProxy) this._model).apply_all_changes ();
-        }
-        
-        /**
-         * Re-load the data stored in the dabase.
-         */
-        public void update ()
-        	throws Error
-        	requires (this.table != "")
-        {
-        	set_id (this._field_id, this._id_value);
-        }
-        
+        public abstract void save () throws Error;
         /**
-         * Returns a #SqlBuilder object with the query used to select the data in the used
-         * that points this object to.
+         * Updates values stored in database.
          */
-        public SqlBuilder sql ()
-        	requires (this.table != null || this.table != "")
-        	requires (this._field_id != null || this._field_id != "")
-        	requires (this._id_value != null)
-        {
-        	var q = new SqlBuilder (SqlStatementType.SELECT);
-        	q.select_add_target (this.table, null);
-        	var f_id = q.add_id (this._field_id);
-			var e_id = q.add_expr_value (null, this._id_value);
-			var c_id = q.add_cond (SqlOperatorType.EQ, f_id, e_id, 0);
-			q.set_where (c_id);
-			q.select_add_field ("*", null, null);
-			return q;			
-        }
-        
+        public abstract void update () throws Error;
         /**
-         * abstract function to be implemented in derived classes to add new objects to the database.<BR>
-         * 
-         * Error code must be ObjectError.APPEND.
+         * Append a new row to the defined table and returns its ID. If defaults is set to true,
+         * default value for each field is set.
          */
-        public abstract G append () throws ObjectError;
+        public abstract void append (out G id) throws Error;
     }
 }
diff --git a/libgda/data/DataObjectSingleId.vala b/libgda/data/DataObjectSingleId.vala
new file mode 100644
index 0000000..eb5f46c
--- /dev/null
+++ b/libgda/data/DataObjectSingleId.vala
@@ -0,0 +1,119 @@
+/* -*- Mode: Vala; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * libgdavala
+ * Copyright (C) Daniel Espinosa Ortiz 2011 <esodan gmail com>
+ * 
+ * libgda is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * libgda 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 Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gda;
+
+namespace GdaData {
+
+	public abstract class ObjectSingleId : GdaData.Object<Value?> 
+	{
+		private Value? _id_value;
+        
+        /**
+         * Field's name used as ID in the row
+         */
+        public abstract string field_id { get; }
+        /* 
+         * ID Field's default index, returned when an INSERT statement is used.
+         */
+        public abstract int field_id_index { get; }
+        
+        public Value get_id ()
+        {
+        	return this._id_value;
+        }
+        
+        /* 
+         * Set a condition to get only one row data from the table in the database.
+         */
+        public void set_id (Value v)
+        	throws Error
+        	requires (this.table != "")
+        {
+        	this._id_value = v;
+        	var q = this.sql ();
+        	var s = q.get_statement ();
+        	var m = this.connection.statement_execute_select (s, null);
+        	for (int r = 0; r < m.get_n_rows (); r++) {
+        		for (int c = 0; c < m.get_n_columns (); c++) {
+        			Gda.ValueAttribute attr = m.get_attributes_at (c, r);
+        			string col_name = m.get_column_name (c);
+        			var f = new Field<Value?> (col_name, (DbField.Attribute) attr);
+        			f.value = m.get_value_at (c, r);
+        		}
+        	}
+        }
+        
+        /**
+         * Returns a #SqlBuilder object with the query used to select the data in the used
+         * that points this object to.
+         */
+        public SqlBuilder sql ()
+        	requires (this.table != null || this.table != "")
+        	requires (this.field_id != null || this.field_id != "")
+        	requires (this._id_value != null)
+        {
+        	var q = new SqlBuilder (SqlStatementType.SELECT);
+        	q.select_add_target (this.table, null);
+        	var f_id = q.add_id (this.field_id);
+			var e_id = q.add_expr_value (null, this._id_value);
+			var c_id = q.add_cond (SqlOperatorType.EQ, f_id, e_id, 0);
+			q.set_where (c_id);
+			q.select_add_field ("*", null, null);
+			return q;			
+        }
+        
+        public override void save () throws Error
+        {
+        	var sql = new SqlBuilder (SqlStatementType.UPDATE);
+			sql.set_table (this.table);
+			foreach (Field<Value?> f in _model.values) {
+				sql.add_field_value_as_gvalue (f.column_name, f.value);
+			}
+			var f_id = sql.add_id (this.field_id);
+			var e_id = sql.add_expr_value (null, this._id_value);
+			var c_id = sql.add_cond (SqlOperatorType.EQ, f_id, e_id, 0);
+			var i = this.connection.statement_execute_non_select (sql.get_statement (), null, null);
+			if (i != 1) {
+				throw new DbObjectError.APPEND ("Have been saved more or less rows than expected");
+			}
+        }
+        public override void append (out Value? id) throws Error
+        {
+        	var sql = new SqlBuilder (SqlStatementType.INSERT);
+			sql.set_table (this.table);
+			// FIXME: MetaData is required
+			foreach (Field<Value?> f in _model.values) {
+				sql.add_field_value_as_gvalue (f.column_name, f.value);
+			}
+			Set last_inserted;
+			var i = this.connection.statement_execute_non_select (sql.get_statement (), null, out last_inserted);
+			if (i != 1) {
+				throw new DbObjectError.APPEND ("Have been added more or less rows than expected");
+			}
+			id = last_inserted.get_holder_value (this.field_id_index.to_string ());
+        }
+		public override void update ()
+        	throws Error
+        	requires (this.table != "")
+        {
+        	set_id (this._id_value);
+        }
+	}
+}
diff --git a/libgda/data/DbField.vala b/libgda/data/DbField.vala
index 18da3a2..4d6ed72 100644
--- a/libgda/data/DbField.vala
+++ b/libgda/data/DbField.vala
@@ -22,13 +22,12 @@ using Gda;
 
 namespace GdaData
 {
-	public abstract class DbField<G> : GLib.Object
+	public interface DbField<G> : GLib.Object
 	{
-		public abstract DbRecord record { get; set construct; }
 		public abstract G value { get; set; }
 		public abstract string name { get; set; }
-		public abstract string column_name { get; set; }
-		public abstract DbField.Attribute attributes { get; set construct; }
+		public abstract string column_name { get; construct; }
+		public abstract DbField.Attribute attributes { get; construct; }
 		
 		[Flags]
 		public enum Attribute {
diff --git a/libgda/data/DbObject.vala b/libgda/data/DbObject.vala
new file mode 100644
index 0000000..71e2d2c
--- /dev/null
+++ b/libgda/data/DbObject.vala
@@ -0,0 +1,41 @@
+/* -*- Mode: Vala; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * libgdadata
+ * Copyright (C) Daniel Espinosa Ortiz 2011 <esodan gmail com>
+ * 
+ * libgda is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * libgda 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 Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gee;
+using Gda;
+
+namespace GdaData {
+	public interface DbObject : GLib.Object {
+		public abstract Connection   connection { get; set; }
+		public abstract DbObject     append ();
+		public abstract void         update ();
+		public abstract void         save ();
+	}
+	
+	public interface DbNamedObject : DbObject {
+		public abstract string       name { get; set; }
+	}
+	
+	public errordomain DbObjectError {
+    	APPEND,
+    	UPDATE,
+    	SAVE
+    }
+
+}
diff --git a/libgda/data/DbRecord.vala b/libgda/data/DbRecord.vala
index 759874e..1ac672f 100644
--- a/libgda/data/DbRecord.vala
+++ b/libgda/data/DbRecord.vala
@@ -22,9 +22,9 @@ using Gda;
 
 namespace GdaData
 {
-	public interface DbRecord : GLib.Object
+	public interface DbRecord : DbObject
 	{
-		public abstract DbTable table { get; set construct; }
-		public abstract Collection<DbField> fields { get; }
+		public abstract DbTable              table { get; set construct; }
+		public abstract Collection<DbField>  fields { get; }
 	}
 }
diff --git a/libgda/data/Field.vala b/libgda/data/Field.vala
new file mode 100644
index 0000000..3cda30e
--- /dev/null
+++ b/libgda/data/Field.vala
@@ -0,0 +1,56 @@
+/* -*- Mode: Vala; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * libgdadata
+ * Copyright (C) Daniel Espinosa Ortiz 2011 <esodan gmail com>
+ * 
+ * libgda is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * libgda 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 Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gee;
+using Gda;
+
+namespace GdaData
+{
+	public class Field<G> : GLib.Object
+	{
+		private G                 val;
+		private string            _name;
+		private string            _column_name;
+		private DbField.Attribute _attributes;
+		
+		public G value { 
+			get { return val; } 
+			set { val = value; }
+		}
+		public string name { 
+			get { return _name; } 
+			set { _name = value; }
+		}
+		public string column_name { 
+			get { return _column_name; } 
+			construct { _column_name = value; }
+		}
+		public DbField.Attribute attributes { 
+			get { return _attributes; } 
+			construct {
+				_attributes = value;
+			}
+		}
+		public Field (string col_name, DbField.Attribute attr) 
+		{
+			GLib.Object (column_name: col_name, attributes: attr);
+			_name = col_name;
+		}
+	}
+}
diff --git a/libgda/data/GdaData-5.0.gir b/libgda/data/GdaData-5.0.gir
index 7a04cb4..09bd5be 100644
--- a/libgda/data/GdaData-5.0.gir
+++ b/libgda/data/GdaData-5.0.gir
@@ -1,18 +1,20 @@
 <?xml version="1.0"?>
 <repository version="1.2" xmlns="http://www.gtk.org/introspection/core/1.0"; xmlns:c="http://www.gtk.org/introspection/c/1.0"; xmlns:glib="http://www.gtk.org/introspection/glib/1.0";>
 <include name="GObject" version="2.0"/>
-<include name="Gda" version="5.0"/>
 <include name="Gee" version="0.8"/>
+<include name="Gda" version="5.0"/>
 <package name="gdadata-5.0"/>
 <c:include name="libgda/libgdadata.h"/>
 <namespace name="GdaData" version="5.0" c:prefix="GdaData">
 	<annotation key="ccode.gir-version" value="5.0"/>
 	<annotation key="ccode.cheader-filename" value="libgda/libgdadata.h"/>
 	<annotation key="ccode.gir-namespace" value="GdaData"/>
-	<errordomain name="ObjectError" get-quark="gda_data_object_error_quark" codes="ObjectError">
+	<errordomain name="DbObjectError" get-quark="gda_data_db_object_error_quark" codes="DbObjectError">
 </errordomain>
-	<enumeration name="ObjectError" c:type="GdaDataObjectError">
-		<member name="append" c:identifier="GDA_DATA_OBJECT_ERROR_APPEND" value="0"/>
+	<enumeration name="DbObjectError" c:type="GdaDataDbObjectError">
+		<member name="append" c:identifier="GDA_DATA_DB_OBJECT_ERROR_APPEND" value="0"/>
+		<member name="update" c:identifier="GDA_DATA_DB_OBJECT_ERROR_UPDATE" value="1"/>
+		<member name="save" c:identifier="GDA_DATA_DB_OBJECT_ERROR_SAVE" value="2"/>
 	</enumeration>
 	<class name="Object" c:type="GdaDataObject" glib:type-name="GdaDataObject" glib:get-type="gda_data_object_get_type" glib:type-struct="ObjectClass" parent="GObject.Object" abstract="1">
 		<field name="parent_instance">
@@ -21,41 +23,21 @@
 		<field name="priv">
 			<type name="ObjectPrivate" c:type="GdaDataObjectPrivate*"/>
 		</field>
-		<method name="get_field_id" c:identifier="gda_data_object_get_field_id">
-			<return-value transfer-ownership="full">
+		<field name="_model">
+			<type name="Gee.HashMap" c:type="GeeHashMap*">
 				<type name="utf8" c:type="gchar*"/>
-			</return-value>
-		</method>
-		<method name="get_value_id" c:identifier="gda_data_object_get_value_id">
-			<parameters>
-				<parameter name="result" direction="out" transfer-ownership="full" caller-allocates="1">
-					<type name="GObject.Value" c:type="GValue"/>
-				</parameter>
-			</parameters>
-			<return-value transfer-ownership="none">
-				<type name="none"/>
-			</return-value>
-		</method>
-		<method name="set_id" c:identifier="gda_data_object_set_id" throws="1">
-			<parameters>
-				<parameter name="field" transfer-ownership="none">
-					<type name="utf8" c:type="const gchar*"/>
-				</parameter>
-				<parameter name="v" transfer-ownership="none">
-					<type name="GObject.Value" c:type="GValue"/>
-				</parameter>
-			</parameters>
-			<return-value transfer-ownership="full">
-				<type name="none"/>
-			</return-value>
-		</method>
+				<type name="GdaData.Field" c:type="GdaDataField*">
+					<type name="GObject.Value" c:type="GValue*"/>
+				</type>
+			</type>
+		</field>
 		<method name="get_value" c:identifier="gda_data_object_get_value" throws="1">
 			<parameters>
 				<parameter name="field" transfer-ownership="none">
 					<type name="utf8" c:type="const gchar*"/>
 				</parameter>
 			</parameters>
-			<return-value transfer-ownership="none" allow-none="1">
+			<return-value transfer-ownership="full" allow-none="1">
 				<type name="GObject.Value" c:type="GValue*"/>
 			</return-value>
 		</method>
@@ -77,24 +59,39 @@
 				<type name="none"/>
 			</return-value>
 		</method>
+		<virtual-method name="save" invoker="save" throws="1">
+			<return-value transfer-ownership="full">
+				<type name="none"/>
+			</return-value>
+		</virtual-method>
 		<method name="update" c:identifier="gda_data_object_update" throws="1">
 			<return-value transfer-ownership="full">
 				<type name="none"/>
 			</return-value>
 		</method>
-		<method name="sql" c:identifier="gda_data_object_sql">
+		<virtual-method name="update" invoker="update" throws="1">
 			<return-value transfer-ownership="full">
-				<type name="Gda.SqlBuilder" c:type="GdaSqlBuilder*"/>
+				<type name="none"/>
 			</return-value>
-		</method>
+		</virtual-method>
 		<method name="append" c:identifier="gda_data_object_append" throws="1">
-			<return-value transfer-ownership="full" allow-none="1">
-				<type name="gpointer" c:type="gpointer"/>
+			<parameters>
+				<parameter name="id" direction="out" transfer-ownership="full" allow-none="1">
+					<type name="gpointer" c:type="gpointer"/>
+				</parameter>
+			</parameters>
+			<return-value transfer-ownership="full">
+				<type name="none"/>
 			</return-value>
 		</method>
 		<virtual-method name="append" invoker="append" throws="1">
-			<return-value transfer-ownership="full" allow-none="1">
-				<type name="gpointer" c:type="gpointer"/>
+			<parameters>
+				<parameter name="id" direction="out" transfer-ownership="full" allow-none="1">
+					<type name="gpointer" c:type="gpointer"/>
+				</parameter>
+			</parameters>
+			<return-value transfer-ownership="full">
+				<type name="none"/>
 			</return-value>
 		</virtual-method>
 		<property name="table">
@@ -111,62 +108,131 @@
 		<field name="parent_class">
 			<type name="GObject.ObjectClass" c:type="GObjectClass"/>
 		</field>
+				<field name="save">
+			<callback name="save" c:type="save" throws="1">
+				<parameters>
+					<parameter name="self" transfer-ownership="none">
+						<type name="GdaData.Object" c:type="GdaDataObject*"/>
+					</parameter>
+				</parameters>
+				<return-value transfer-ownership="full">
+					<type name="none"/>
+				</return-value>
+			</callback>
+		</field>
+				<field name="update">
+			<callback name="update" c:type="update" throws="1">
+				<parameters>
+					<parameter name="self" transfer-ownership="none">
+						<type name="GdaData.Object" c:type="GdaDataObject*"/>
+					</parameter>
+				</parameters>
+				<return-value transfer-ownership="full">
+					<type name="none"/>
+				</return-value>
+			</callback>
+		</field>
 				<field name="append">
 			<callback name="append" c:type="append" throws="1">
 				<parameters>
 					<parameter name="self" transfer-ownership="none">
 						<type name="GdaData.Object" c:type="GdaDataObject*"/>
 					</parameter>
+					<parameter name="id" direction="out" transfer-ownership="full" allow-none="1">
+						<type name="gpointer" c:type="gpointer"/>
+					</parameter>
 				</parameters>
-				<return-value transfer-ownership="full" allow-none="1">
-					<type name="gpointer" c:type="gpointer"/>
+				<return-value transfer-ownership="full">
+					<type name="none"/>
 				</return-value>
 			</callback>
 		</field>
 	</record>
 	<record name="ObjectPrivate" c:type="GdaDataObjectPrivate" disguised="1"/>
-	<class name="DbField" c:type="GdaDataDbField" glib:type-name="GdaDataDbField" glib:get-type="gda_data_db_field_get_type" glib:type-struct="DbFieldClass" parent="GObject.Object" abstract="1">
+	<class name="ObjectSingleId" c:type="GdaDataObjectSingleId" glib:type-name="GdaDataObjectSingleId" glib:get-type="gda_data_object_single_id_get_type" glib:type-struct="ObjectSingleIdClass" parent="GdaData.Object" abstract="1">
 		<field name="parent_instance">
-			<type name="GObject.Object" c:type="GObject"/>
+			<type name="GdaData.Object" c:type="GdaDataObject"/>
 		</field>
 		<field name="priv">
-			<type name="DbFieldPrivate" c:type="GdaDataDbFieldPrivate*"/>
+			<type name="ObjectSingleIdPrivate" c:type="GdaDataObjectSingleIdPrivate*"/>
 		</field>
-		<property name="record" writable="1" construct="1">
-			<type name="GdaData.DbRecord" c:type="GdaDataDbRecord*"/>
+		<method name="get_id" c:identifier="gda_data_object_single_id_get_id">
+			<parameters>
+				<parameter name="result" direction="out" transfer-ownership="full" caller-allocates="1">
+					<type name="GObject.Value" c:type="GValue"/>
+				</parameter>
+			</parameters>
+			<return-value transfer-ownership="none">
+				<type name="none"/>
+			</return-value>
+		</method>
+		<method name="set_id" c:identifier="gda_data_object_single_id_set_id" throws="1">
+			<parameters>
+				<parameter name="v" transfer-ownership="none">
+					<type name="GObject.Value" c:type="GValue"/>
+				</parameter>
+			</parameters>
+			<return-value transfer-ownership="full">
+				<type name="none"/>
+			</return-value>
+		</method>
+		<method name="sql" c:identifier="gda_data_object_single_id_sql">
+			<return-value transfer-ownership="full">
+				<type name="Gda.SqlBuilder" c:type="GdaSqlBuilder*"/>
+			</return-value>
+		</method>
+		<property name="field-id">
+			<type name="utf8" c:type="gchar*"/>
 		</property>
+		<property name="field-id-index">
+			<type name="gint" c:type="gint"/>
+		</property>
+	</class>
+	<record name="ObjectSingleIdClass" c:type="GdaDataObjectSingleIdClass" glib:is-gtype-struct-for="ObjectSingleId">
+		<field name="parent_class">
+			<type name="GdaData.ObjectClass" c:type="GdaDataObjectClass"/>
+		</field>
+	</record>
+	<record name="ObjectSingleIdPrivate" c:type="GdaDataObjectSingleIdPrivate" disguised="1"/>
+	<class name="Field" c:type="GdaDataField" glib:type-name="GdaDataField" glib:get-type="gda_data_field_get_type" glib:type-struct="FieldClass" parent="GObject.Object">
+		<field name="parent_instance">
+			<type name="GObject.Object" c:type="GObject"/>
+		</field>
+		<field name="priv">
+			<type name="FieldPrivate" c:type="GdaDataFieldPrivate*"/>
+		</field>
+		<constructor name="new" c:identifier="gda_data_field_new">
+			<parameters>
+				<parameter name="col_name" transfer-ownership="none">
+					<type name="utf8" c:type="const gchar*"/>
+				</parameter>
+				<parameter name="attr" transfer-ownership="none">
+					<type name="GdaData.DbFieldAttribute" c:type="GdaDataDbFieldAttribute"/>
+				</parameter>
+			</parameters>
+			<return-value transfer-ownership="full">
+				<type name="GdaData.Field" c:type="GdaDataField*"/>
+			</return-value>
+		</constructor>
 		<property name="value" writable="1">
 			<type name="gpointer" c:type="gpointer"/>
 		</property>
 		<property name="name" writable="1">
 			<type name="utf8" c:type="gchar*"/>
 		</property>
-		<property name="column-name" writable="1">
+		<property name="column-name" writable="1" construct-only="1">
 			<type name="utf8" c:type="gchar*"/>
 		</property>
-		<property name="attributes" writable="1" construct="1">
+		<property name="attributes" writable="1" construct-only="1">
 			<type name="GdaData.DbFieldAttribute" c:type="GdaDataDbFieldAttribute"/>
 		</property>
 	</class>
-	<record name="DbFieldClass" c:type="GdaDataDbFieldClass" glib:is-gtype-struct-for="DbField">
+	<record name="FieldClass" c:type="GdaDataFieldClass" glib:is-gtype-struct-for="Field">
 		<field name="parent_class">
 			<type name="GObject.ObjectClass" c:type="GObjectClass"/>
 		</field>
 	</record>
-	<record name="DbFieldPrivate" c:type="GdaDataDbFieldPrivate" disguised="1"/>
-	<bitfield name="DbFieldAttribute" c:type="GdaDataDbFieldAttribute" glib:type-name="GdaDataDbFieldAttribute" glib:get-type="gda_data_db_field_attribute_get_type">
-		<member name="none" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_NONE" value="1"/>
-		<member name="is_null" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_IS_NULL" value="2"/>
-		<member name="can_be_null" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_CAN_BE_NULL" value="4"/>
-		<member name="is_default" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_IS_DEFAULT" value="8"/>
-		<member name="can_be_default" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_CAN_BE_DEFAULT" value="16"/>
-		<member name="is_unchanged" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_IS_UNCHANGED" value="32"/>
-		<member name="actions_shown" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_ACTIONS_SHOWN" value="64"/>
-		<member name="data_non_valid" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_DATA_NON_VALID" value="128"/>
-		<member name="has_value_orig" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_HAS_VALUE_ORIG" value="256"/>
-		<member name="no_modif" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_NO_MODIF" value="512"/>
-		<member name="unused" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_UNUSED" value="1024"/>
-	</bitfield>
+	<record name="FieldPrivate" c:type="GdaDataFieldPrivate" disguised="1"/>
 	<class name="DataModelIterator" c:type="GdaDataDataModelIterator" glib:type-name="GdaDataDataModelIterator" glib:get-type="gda_data_data_model_iterator_get_type" glib:type-struct="DataModelIteratorClass" parent="GObject.Object">
 		<implements name="Gee.Traversable"/>
 		<implements name="Gee.Iterator"/>
@@ -240,6 +306,94 @@
 		</field>
 	</record>
 	<record name="DataModelIterablePrivate" c:type="GdaDataDataModelIterablePrivate" disguised="1"/>
+	<interface name="DbObject" c:type="GdaDataDbObject" glib:type-name="GdaDataDbObject" glib:get-type="gda_data_db_object_get_type" glib:type-struct="DbObjectIface">
+		<prerequisite name="GObject.Object"/>
+		<method name="append" c:identifier="gda_data_db_object_append">
+			<return-value transfer-ownership="full">
+				<type name="GdaData.DbObject" c:type="GdaDataDbObject*"/>
+			</return-value>
+		</method>
+		<virtual-method name="append" invoker="append">
+			<return-value transfer-ownership="full">
+				<type name="GdaData.DbObject" c:type="GdaDataDbObject*"/>
+			</return-value>
+		</virtual-method>
+		<method name="update" c:identifier="gda_data_db_object_update">
+			<return-value transfer-ownership="full">
+				<type name="none"/>
+			</return-value>
+		</method>
+		<virtual-method name="update" invoker="update">
+			<return-value transfer-ownership="full">
+				<type name="none"/>
+			</return-value>
+		</virtual-method>
+		<method name="save" c:identifier="gda_data_db_object_save">
+			<return-value transfer-ownership="full">
+				<type name="none"/>
+			</return-value>
+		</method>
+		<virtual-method name="save" invoker="save">
+			<return-value transfer-ownership="full">
+				<type name="none"/>
+			</return-value>
+		</virtual-method>
+		<property name="connection" writable="1">
+			<type name="Gda.Connection" c:type="GdaConnection*"/>
+		</property>
+	</interface>
+	<record name="DbObjectIface" c:type="GdaDataDbObjectIface" glib:is-gtype-struct-for="DbObject">
+		<field name="parent_iface">
+			<type name="GObject.TypeInterface" c:type="GTypeInterface"/>
+		</field>
+		<field name="append">
+			<callback name="append" c:type="append">
+				<parameters>
+					<parameter name="self" transfer-ownership="none">
+						<type name="GdaData.DbObject" c:type="GdaDataDbObject*"/>
+					</parameter>
+				</parameters>
+				<return-value transfer-ownership="full">
+					<type name="GdaData.DbObject" c:type="GdaDataDbObject*"/>
+				</return-value>
+			</callback>
+		</field>
+		<field name="update">
+			<callback name="update" c:type="update">
+				<parameters>
+					<parameter name="self" transfer-ownership="none">
+						<type name="GdaData.DbObject" c:type="GdaDataDbObject*"/>
+					</parameter>
+				</parameters>
+				<return-value transfer-ownership="full">
+					<type name="none"/>
+				</return-value>
+			</callback>
+		</field>
+		<field name="save">
+			<callback name="save" c:type="save">
+				<parameters>
+					<parameter name="self" transfer-ownership="none">
+						<type name="GdaData.DbObject" c:type="GdaDataDbObject*"/>
+					</parameter>
+				</parameters>
+				<return-value transfer-ownership="full">
+					<type name="none"/>
+				</return-value>
+			</callback>
+		</field>
+	</record>
+	<interface name="DbNamedObject" c:type="GdaDataDbNamedObject" glib:type-name="GdaDataDbNamedObject" glib:get-type="gda_data_db_named_object_get_type" glib:type-struct="DbNamedObjectIface">
+		<prerequisite name="GdaData.DbObject"/>
+		<property name="name" writable="1">
+			<type name="utf8" c:type="gchar*"/>
+		</property>
+	</interface>
+	<record name="DbNamedObjectIface" c:type="GdaDataDbNamedObjectIface" glib:is-gtype-struct-for="DbNamedObject">
+		<field name="parent_iface">
+			<type name="GObject.TypeInterface" c:type="GTypeInterface"/>
+		</field>
+	</record>
 	<interface name="DbCollection" c:type="GdaDataDbCollection" glib:type-name="GdaDataDbCollection" glib:get-type="gda_data_db_collection_get_type" glib:type-struct="DbCollectionIface">
 		<prerequisite name="GObject.Object"/>
 		<method name="get_tables" c:identifier="gda_data_db_collection_get_tables">
@@ -352,7 +506,7 @@
 		</field>
 	</record>
 	<interface name="DbRecord" c:type="GdaDataDbRecord" glib:type-name="GdaDataDbRecord" glib:get-type="gda_data_db_record_get_type" glib:type-struct="DbRecordIface">
-		<prerequisite name="GObject.Object"/>
+		<prerequisite name="GdaData.DbObject"/>
 		<property name="table" writable="1" construct="1">
 			<type name="GdaData.DbTable" c:type="GdaDataDbTable*"/>
 		</property>
@@ -367,6 +521,39 @@
 			<type name="GObject.TypeInterface" c:type="GTypeInterface"/>
 		</field>
 	</record>
+	<interface name="DbField" c:type="GdaDataDbField" glib:type-name="GdaDataDbField" glib:get-type="gda_data_db_field_get_type" glib:type-struct="DbFieldIface">
+		<prerequisite name="GObject.Object"/>
+		<property name="value" writable="1">
+			<type name="gpointer" c:type="gpointer"/>
+		</property>
+		<property name="name" writable="1">
+			<type name="utf8" c:type="gchar*"/>
+		</property>
+		<property name="column-name" writable="1" construct-only="1">
+			<type name="utf8" c:type="gchar*"/>
+		</property>
+		<property name="attributes" writable="1" construct-only="1">
+			<type name="GdaData.DbFieldAttribute" c:type="GdaDataDbFieldAttribute"/>
+		</property>
+	</interface>
+	<record name="DbFieldIface" c:type="GdaDataDbFieldIface" glib:is-gtype-struct-for="DbField">
+		<field name="parent_iface">
+			<type name="GObject.TypeInterface" c:type="GTypeInterface"/>
+		</field>
+	</record>
+	<bitfield name="DbFieldAttribute" c:type="GdaDataDbFieldAttribute" glib:type-name="GdaDataDbFieldAttribute" glib:get-type="gda_data_db_field_attribute_get_type">
+		<member name="none" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_NONE" value="1"/>
+		<member name="is_null" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_IS_NULL" value="2"/>
+		<member name="can_be_null" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_CAN_BE_NULL" value="4"/>
+		<member name="is_default" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_IS_DEFAULT" value="8"/>
+		<member name="can_be_default" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_CAN_BE_DEFAULT" value="16"/>
+		<member name="is_unchanged" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_IS_UNCHANGED" value="32"/>
+		<member name="actions_shown" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_ACTIONS_SHOWN" value="64"/>
+		<member name="data_non_valid" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_DATA_NON_VALID" value="128"/>
+		<member name="has_value_orig" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_HAS_VALUE_ORIG" value="256"/>
+		<member name="no_modif" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_NO_MODIF" value="512"/>
+		<member name="unused" c:identifier="GDA_DATA_DB_FIELD_ATTRIBUTE_UNUSED" value="1024"/>
+	</bitfield>
 	<interface name="DbSchema" c:type="GdaDataDbSchema" glib:type-name="GdaDataDbSchema" glib:get-type="gda_data_db_schema_get_type" glib:type-struct="DbSchemaIface">
 		<prerequisite name="GObject.Object"/>
 		<property name="name" writable="1">
diff --git a/libgda/data/GdaData-UML.gaphor b/libgda/data/GdaData-UML.gaphor
new file mode 100644
index 0000000..e8cc155
--- /dev/null
+++ b/libgda/data/GdaData-UML.gaphor
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gaphor xmlns="http://gaphor.sourceforge.net/model"; version="3.0" gaphor-version="0.15.0">
+<Package id="636fb4ee-362f-11e1-a9fe-0026b913ee39">
+<name>
+<val><![CDATA[GdaData]]></val>
+</name>
+<ownedClassifier>
+<reflist>
+<ref refid="6f80e320-362f-11e1-a9fe-0026b913ee39"/>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+<ref refid="619fdd00-3630-11e1-a9fe-0026b913ee39"/>
+<ref refid="a7de0aa8-3630-11e1-a9fe-0026b913ee39"/>
+<ref refid="aea614e8-3630-11e1-a9fe-0026b913ee39"/>
+<ref refid="8cdbde28-3631-11e1-a9fe-0026b913ee39"/>
+<ref refid="916d80b8-3631-11e1-a9fe-0026b913ee39"/>
+<ref refid="a5cc34f8-3642-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</ownedClassifier>
+<ownedDiagram>
+<reflist>
+<ref refid="63727116-362f-11e1-a9fe-0026b913ee39"/>
+<ref refid="0bc49ea8-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</ownedDiagram>
+</Package>
+<Diagram id="63727116-362f-11e1-a9fe-0026b913ee39">
+<name>
+<val><![CDATA[DbCollections]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<canvas>
+<item type="InterfaceItem" id="f71f000a-362f-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 194.0, 204.0)</val>
+</matrix>
+<width>
+<val>111.0</val>
+</width>
+<height>
+<val>61.0</val>
+</height>
+<subject>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="InterfaceItem" id="2196ff9a-3630-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 315.0, 75.0)</val>
+</matrix>
+<width>
+<val>100.0</val>
+</width>
+<height>
+<val>61.0</val>
+</height>
+<subject>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="InterfaceItem" id="619ff6f0-3630-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 341.0, 206.0)</val>
+</matrix>
+<width>
+<val>100.0</val>
+</width>
+<height>
+<val>60.0</val>
+</height>
+<subject>
+<ref refid="619fdd00-3630-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="InterfaceItem" id="a7de2574-3630-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 90.00000000000006, 366.00000000000006)</val>
+</matrix>
+<width>
+<val>100.0</val>
+</width>
+<height>
+<val>60.0</val>
+</height>
+<subject>
+<ref refid="a7de0aa8-3630-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="InterfaceItem" id="aea630a4-3630-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 296.0000000000001, 375.00000000000006)</val>
+</matrix>
+<width>
+<val>134.0</val>
+</width>
+<height>
+<val>60.0</val>
+</height>
+<subject>
+<ref refid="aea614e8-3630-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="DependencyItem" id="ee262bf8-3630-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="f2b79d3c-3630-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 353.00000000000006, 375.00000000000006)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (0.0, -109.00000000000006)]</val>
+</points>
+<head-connection>
+<ref refid="aea630a4-3630-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="619ff6f0-3630-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+<auto_dependency>
+<val>1</val>
+</auto_dependency>
+</item>
+<item type="DependencyItem" id="207f6722-3631-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="24390a08-3631-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 396.00000000000006, 136.0)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (5.684341886080802e-14, 70.00000000000003)]</val>
+</points>
+<head-connection>
+<ref refid="2196ff9a-3630-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="619ff6f0-3630-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+<auto_dependency>
+<val>1</val>
+</auto_dependency>
+</item>
+<item type="DependencyItem" id="3bc3638a-3631-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="3ccefc58-3631-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 352.00000000000006, 136.00000000000003)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (-99.0, 68.0)]</val>
+</points>
+<head-connection>
+<ref refid="2196ff9a-3630-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="f71f000a-362f-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+<auto_dependency>
+<val>1</val>
+</auto_dependency>
+</item>
+<item type="DependencyItem" id="4001cb8a-3631-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="40f63c60-3631-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 242.00000000000006, 265.0)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (-101.00000000000006, 101.00000000000006)]</val>
+</points>
+<head-connection>
+<ref refid="f71f000a-362f-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="a7de2574-3630-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+<auto_dependency>
+<val>1</val>
+</auto_dependency>
+</item>
+<item type="DependencyItem" id="442ce4f6-3631-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="44fb5a2a-3631-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 288.00000000000006, 265.0)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (1.0, 76.00000000000006), (32.120000000000005, 110.00000000000006)]</val>
+</points>
+<head-connection>
+<ref refid="f71f000a-362f-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="aea630a4-3630-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+<auto_dependency>
+<val>1</val>
+</auto_dependency>
+</item>
+<item type="InterfaceItem" id="a5d3ec0c-3642-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 557.0000000000001, 82.00000000000001)</val>
+</matrix>
+<width>
+<val>100.0</val>
+</width>
+<height>
+<val>60.0</val>
+</height>
+<subject>
+<ref refid="a5cc34f8-3642-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="DependencyItem" id="b09898a4-3642-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="b27766fa-3642-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 415.0, 106.00000000000003)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (142.00000000000006, -1.4210854715202004e-14)]</val>
+</points>
+<head-connection>
+<ref refid="2196ff9a-3630-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="a5d3ec0c-3642-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+<auto_dependency>
+<val>1</val>
+</auto_dependency>
+</item>
+<item type="DependencyItem" id="5095d9f2-3643-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="518dc23e-3643-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 384.0000000000001, 266.0)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (27.23999999999984, 109.00000000000006)]</val>
+</points>
+<head-connection>
+<ref refid="619ff6f0-3630-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="aea630a4-3630-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+<auto_dependency>
+<val>1</val>
+</auto_dependency>
+</item>
+</canvas>
+</Diagram>
+<Class id="6f80e320-362f-11e1-a9fe-0026b913ee39">
+<generalization>
+<reflist>
+<ref refid="94feb2b2-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</generalization>
+<name>
+<val><![CDATA[MultipleId]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="1d6806f4-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+</Class>
+<Interface id="f71d4ce2-362f-11e1-a9fe-0026b913ee39">
+<clientDependency>
+<reflist>
+<ref refid="3ccefc58-3631-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</clientDependency>
+<name>
+<val><![CDATA[DbNamedObject]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="f71f000a-362f-11e1-a9fe-0026b913ee39"/>
+<ref refid="2196ff9a-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplierDependency>
+<reflist>
+<ref refid="24390a08-3631-11e1-a9fe-0026b913ee39"/>
+<ref refid="3ccefc58-3631-11e1-a9fe-0026b913ee39"/>
+<ref refid="40f63c60-3631-11e1-a9fe-0026b913ee39"/>
+<ref refid="44fb5a2a-3631-11e1-a9fe-0026b913ee39"/>
+<ref refid="b27766fa-3642-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplierDependency>
+</Interface>
+<Interface id="619fdd00-3630-11e1-a9fe-0026b913ee39">
+<clientDependency>
+<reflist>
+<ref refid="f2b79d3c-3630-11e1-a9fe-0026b913ee39"/>
+<ref refid="24390a08-3631-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</clientDependency>
+<name>
+<val><![CDATA[DbRecord]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="619ff6f0-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplierDependency>
+<reflist>
+<ref refid="518dc23e-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplierDependency>
+</Interface>
+<Interface id="a7de0aa8-3630-11e1-a9fe-0026b913ee39">
+<clientDependency>
+<reflist>
+<ref refid="40f63c60-3631-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</clientDependency>
+<name>
+<val><![CDATA[DbSchema]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="a7de2574-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+</Interface>
+<Interface id="aea614e8-3630-11e1-a9fe-0026b913ee39">
+<clientDependency>
+<reflist>
+<ref refid="44fb5a2a-3631-11e1-a9fe-0026b913ee39"/>
+<ref refid="518dc23e-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</clientDependency>
+<name>
+<val><![CDATA[DbTable]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="aea630a4-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplierDependency>
+<reflist>
+<ref refid="f2b79d3c-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplierDependency>
+</Interface>
+<Usage id="f2b79d3c-3630-11e1-a9fe-0026b913ee39">
+<client>
+<reflist>
+<ref refid="619fdd00-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</client>
+<presentation>
+<reflist>
+<ref refid="ee262bf8-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplier>
+<reflist>
+<ref refid="aea614e8-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplier>
+</Usage>
+<Usage id="24390a08-3631-11e1-a9fe-0026b913ee39">
+<client>
+<reflist>
+<ref refid="619fdd00-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</client>
+<presentation>
+<reflist>
+<ref refid="207f6722-3631-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplier>
+<reflist>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplier>
+</Usage>
+<Usage id="3ccefc58-3631-11e1-a9fe-0026b913ee39">
+<client>
+<reflist>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</client>
+<presentation>
+<reflist>
+<ref refid="3bc3638a-3631-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplier>
+<reflist>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplier>
+</Usage>
+<Usage id="40f63c60-3631-11e1-a9fe-0026b913ee39">
+<client>
+<reflist>
+<ref refid="a7de0aa8-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</client>
+<presentation>
+<reflist>
+<ref refid="4001cb8a-3631-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplier>
+<reflist>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplier>
+</Usage>
+<Usage id="44fb5a2a-3631-11e1-a9fe-0026b913ee39">
+<client>
+<reflist>
+<ref refid="aea614e8-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</client>
+<presentation>
+<reflist>
+<ref refid="442ce4f6-3631-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplier>
+<reflist>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplier>
+</Usage>
+<Class id="8cdbde28-3631-11e1-a9fe-0026b913ee39">
+<generalization>
+<reflist>
+<ref refid="98c75674-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</generalization>
+<name>
+<val><![CDATA[SingleId]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="1fb583dc-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+</Class>
+<Class id="916d80b8-3631-11e1-a9fe-0026b913ee39">
+<name>
+<val><![CDATA[Record]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="1e9b8adc-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+</Class>
+<Interface id="a5cc34f8-3642-11e1-a9fe-0026b913ee39">
+<clientDependency>
+<reflist>
+<ref refid="b27766fa-3642-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</clientDependency>
+<name>
+<val><![CDATA[DbField]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<presentation>
+<reflist>
+<ref refid="a5d3ec0c-3642-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+</Interface>
+<Usage id="b27766fa-3642-11e1-a9fe-0026b913ee39">
+<client>
+<reflist>
+<ref refid="a5cc34f8-3642-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</client>
+<presentation>
+<reflist>
+<ref refid="b09898a4-3642-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplier>
+<reflist>
+<ref refid="f71d4ce2-362f-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplier>
+</Usage>
+<Diagram id="0bc49ea8-3643-11e1-a9fe-0026b913ee39">
+<name>
+<val><![CDATA[DataObject]]></val>
+</name>
+<package>
+<ref refid="636fb4ee-362f-11e1-a9fe-0026b913ee39"/>
+</package>
+<canvas>
+<item type="ClassItem" id="1d6806f4-3643-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 225.0, 261.0)</val>
+</matrix>
+<width>
+<val>100.0</val>
+</width>
+<height>
+<val>51.0</val>
+</height>
+<subject>
+<ref refid="6f80e320-362f-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="ClassItem" id="1e9b8adc-3643-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 303.0, 112.0)</val>
+</matrix>
+<width>
+<val>100.0</val>
+</width>
+<height>
+<val>50.0</val>
+</height>
+<subject>
+<ref refid="916d80b8-3631-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="ClassItem" id="1fb583dc-3643-11e1-a9fe-0026b913ee39">
+<show-attributes>
+<val>1</val>
+</show-attributes>
+<show-operations>
+<val>1</val>
+</show-operations>
+<drawing-style>
+<val>1</val>
+</drawing-style>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 382.0, 261.0)</val>
+</matrix>
+<width>
+<val>100.0</val>
+</width>
+<height>
+<val>51.0</val>
+</height>
+<subject>
+<ref refid="8cdbde28-3631-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+</item>
+<item type="GeneralizationItem" id="9412b97a-3643-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="94feb2b2-3643-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 346.0, 162.0)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (0.0, 67.0), (-71.0, 66.0), (-71.0, 99.0)]</val>
+</points>
+<head-connection>
+<ref refid="1e9b8adc-3643-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="1d6806f4-3643-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+</item>
+<item type="GeneralizationItem" id="97c880c2-3643-11e1-a9fe-0026b913ee39">
+<subject>
+<ref refid="98c75674-3643-11e1-a9fe-0026b913ee39"/>
+</subject>
+<show_stereotypes_attrs>
+<val>0</val>
+</show_stereotypes_attrs>
+<matrix>
+<val>(1.0, 0.0, 0.0, 1.0, 346.0, 162.0)</val>
+</matrix>
+<orthogonal>
+<val>0</val>
+</orthogonal>
+<horizontal>
+<val>0</val>
+</horizontal>
+<points>
+<val>[(0.0, 0.0), (0.0, 66.0), (88.0, 67.0), (88.0, 99.0)]</val>
+</points>
+<head-connection>
+<ref refid="1e9b8adc-3643-11e1-a9fe-0026b913ee39"/>
+</head-connection>
+<tail-connection>
+<ref refid="1fb583dc-3643-11e1-a9fe-0026b913ee39"/>
+</tail-connection>
+</item>
+</canvas>
+</Diagram>
+<Usage id="518dc23e-3643-11e1-a9fe-0026b913ee39">
+<client>
+<reflist>
+<ref refid="aea614e8-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</client>
+<presentation>
+<reflist>
+<ref refid="5095d9f2-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<supplier>
+<reflist>
+<ref refid="619fdd00-3630-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</supplier>
+</Usage>
+<Generalization id="94feb2b2-3643-11e1-a9fe-0026b913ee39">
+<general>
+<ref refid="916d80b8-3631-11e1-a9fe-0026b913ee39"/>
+</general>
+<presentation>
+<reflist>
+<ref refid="9412b97a-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<specific>
+<ref refid="6f80e320-362f-11e1-a9fe-0026b913ee39"/>
+</specific>
+</Generalization>
+<Generalization id="98c75674-3643-11e1-a9fe-0026b913ee39">
+<general>
+<ref refid="916d80b8-3631-11e1-a9fe-0026b913ee39"/>
+</general>
+<presentation>
+<reflist>
+<ref refid="97c880c2-3643-11e1-a9fe-0026b913ee39"/>
+</reflist>
+</presentation>
+<specific>
+<ref refid="8cdbde28-3631-11e1-a9fe-0026b913ee39"/>
+</specific>
+</Generalization>
+</gaphor>
\ No newline at end of file
diff --git a/libgda/data/Makefile.am b/libgda/data/Makefile.am
index b129436..675df50 100644
--- a/libgda/data/Makefile.am
+++ b/libgda/data/Makefile.am
@@ -33,15 +33,18 @@ VALAFLAGS = \
 
 object_persistance_sources = \
 	DataObject.vala \
+	DataObjectSingleId.vala \
 	SelectQuery.vala \
 	$(NULL)
 
 db_collection_sources = \
+	DbObject.vala \
 	DbCollection.vala \
 	DbTable.vala \
 	DbRecord.vala \
 	DbField.vala \
 	DbSchema.vala \
+	Field.vala \
 	$(NULL)
 
 selectable_sources = \
diff --git a/libgda/gda-meta-store.h b/libgda/gda-meta-store.h
index c3a27d4..f9f2d61 100644
--- a/libgda/gda-meta-store.h
+++ b/libgda/gda-meta-store.h
@@ -73,8 +73,8 @@ typedef struct {
  * GdaMetaContext:
  * @table_name: the name of the table <emphasis>in the GdaMetaStore's internal database</emphasis>
  * @size: the size of the @column_names and @column_values arrays
- * @column_names: an array of column names (columns of the @table_name table)
- * @column_values: an array of values, one for each column named in @column_names
+ * @column_names: (array length=size): an array of column names (columns of the @table_name table)
+ * @column_values: (array length=size): an array of values, one for each column named in @column_names
  *
  * The <structname>GdaMetaContext</structname> represents a meta data modification
  * context: the <emphasis>how</emphasis> when used with gda_meta_store_modify_with_context(),
diff --git a/libgda/libgda-5.0.vapi b/libgda/libgda-5.0.vapi
index d214b04..96747df 100644
--- a/libgda/libgda-5.0.vapi
+++ b/libgda/libgda-5.0.vapi
@@ -1270,8 +1270,10 @@ namespace Gda {
 	public struct MetaContext {
 		public weak string table_name;
 		public int size;
-		public weak string column_names;
-		public GLib.Value column_values;
+		[CCode (array_length_cname = "size")]
+		public weak string[] column_names;
+		[CCode (array_length_cname = "size")]
+		public weak GLib.Value[] column_values;
 	}
 	[CCode (cheader_filename = "libgda/libgda.h")]
 	public struct MetaDbObject {
diff --git a/samples/vala/Makefile b/samples/vala/Makefile
index 12f76b2..351a53f 100644
--- a/samples/vala/Makefile
+++ b/samples/vala/Makefile
@@ -6,7 +6,7 @@ CFLAGS = \
 
 LDFLAGS = `pkg-config --libs libgdadata-5.0` 
 
-VALAFLAGS = --pkg libgda-5.0 --pkg gdadata-5.0 --pkg gee-0.8 --pkg libxml-2.0
+VALAFLAGS = -g --save-temps --pkg libgda-5.0 --pkg gdadata-5.0 --pkg gee-0.8 --pkg libxml-2.0
 
 all: sampledataobject sampledatamodeliterable
 
diff --git a/samples/vala/SampleDataObject.vala b/samples/vala/SampleDataObject.vala
index a75e967..afb60f0 100644
--- a/samples/vala/SampleDataObject.vala
+++ b/samples/vala/SampleDataObject.vala
@@ -22,7 +22,7 @@ using GdaData;
 
 namespace Sample {
 
-	class DbRecord : GdaData.Object<DbRecord> {
+	class Record : GdaData.ObjectSingleId<string> {
 		private static string dbtable = "user";
 		
 		/**
@@ -33,7 +33,16 @@ namespace Sample {
 		public override string table { 
 			get { return this.dbtable; }
 		}
-		
+		/**
+		 * On derived classes you must implement this property.
+		 * Is intended that implementors set ID field's name and its column index
+		 */
+		public override string field_id {
+			get { return "name";}
+		}
+		public override int field_id_index {
+			get { return 0; }
+		}
 		/**
 		 * Wrapping database fields.
 		 * You can define properties that use database stored values.
@@ -65,41 +74,6 @@ namespace Sample {
 				catch {}
 			}
 		}
-		
-		public override DbRecord append ()
-			throws ObjectError
-		{
-			var sql = new SqlBuilder (SqlStatementType.INSERT);
-			sql.set_table (this.table);
-			sql.add_field_value_as_gvalue ("functions", functions);
-			sql.add_field_value_as_gvalue ("name", name);
-			Set last_inserted;
-			var i = this.connection.statement_execute_non_select (sql.get_statement (), null, out last_inserted);
-			if (i != 1) {
-				throw new GdaData.ObjectError.APPEND ("Have been added more or less rows than expected");
-			}
-			var id = last_inserted.get_holder_value ("0");
-			var n = new DbRecord ();
-			n.connection = this.connection;
-			n.set_id ("id", id);
-			return n;
-		}
-		
-		/**
-		 * This function is a wrapper to set the id field
-		 * and id value used to retrieve a record from the
-		 * database.
-		 * 
-		 * In this example 'user' table have two keys, id and
-		 * name (declared as UNIQUE), then we can use the last
-		 * to identify any record.
-		 */
-		public void open (Value name) 
-			throws Error
-		{
-			this.set_id ("name", name);
-		}
-		
 	}
 
 	class App : GLib.Object {
@@ -114,9 +88,9 @@ namespace Sample {
 								"DB_DIR=.;DB_NAME=dataobject", null, 
 								Gda.ConnectionOptions.NONE);
 			stdout.printf("Creating table 'user'...\n");
-			this.connection.execute_non_select_command("CREATE TABLE user (id INTEGER PRIMARY KEY, name string UNIQUE, functions string, security_number integer)");
-			this.connection.execute_non_select_command("INSERT INTO user (id, name, functions, security_number) VALUES (1, \"Martin Stewart\", \"Programmer, QA\", 2334556)");
-			this.connection.execute_non_select_command("INSERT INTO user (id, name, functions, security_number) VALUES (2, \"Jane Castle\", \"Accountant\", 3002884)");
+			this.connection.execute_non_select_command("CREATE TABLE user (name string PRIMARY KEY, functions string, security_number integer)");
+			this.connection.execute_non_select_command("INSERT INTO user (name, functions, security_number) VALUES (\"Martin Stewart\", \"Programmer, QA\", 2334556)");
+			this.connection.execute_non_select_command("INSERT INTO user (name, functions, security_number) VALUES (\"Jane Castle\", \"Accountant\", 3002884)");
 			
 			this.connection.update_meta_store(null);
 		}
@@ -125,9 +99,9 @@ namespace Sample {
 			throws Error
 		{
 			stdout.printf (">>> DEMO: Modifying Records\n");
-			var rcd = new DbRecord ();
+			var rcd = new Record ();
 			rcd.connection = this.connection;
-			try { rcd.open (name); }
+			try { rcd.set_id (name); }
 			catch (Error e) { stdout.printf ("ERROR: Record no opened\n" + e.message + "\n"); }
 			
 			stdout.printf ("Initial Values for: " + rcd.name + "\n" + rcd.record.dump_as_string () + "\n");
@@ -154,14 +128,34 @@ namespace Sample {
 				throws Error
 		{
 			stdout.printf (">>> DEMO: Updating Records modified externally\n");
-			var rcd = new DbRecord ();
+			var rcd = new Record ();
 			rcd.connection = this.connection;
-			rcd.open ("Jane Castle PhD.");
+			rcd.set_id ("Jane Castle PhD.");
 			stdout.printf ("Initial Values for: " + rcd.name + "\n" + rcd.record.dump_as_string () + "\n");
-			this.connection.execute_non_select_command("UPDATE user SET functions = \"Secretary\" WHERE id = 2");
+			this.connection.execute_non_select_command("UPDATE user SET functions = \"Secretary\" WHERE name = \"Jane Castle PhD.\"");
 			rcd.update ();
 			stdout.printf ("Updated Values for: " + rcd.name + "\n" + rcd.record.dump_as_string () + "\n");
 		}
+		
+		public void append_objects (string name, string functions)
+			throws Error
+		{
+			stdout.printf("DEMO: Appending Objects...\n");
+			var ob = new Record ();
+			ob.connection = this.connection;
+			ob.set_id ("Jane Castle PhD.");
+			string id;
+			ob.append (out id);
+			var m = this.connection.execute_select_command ("SELECT * FROM user");
+			stdout.printf ("Appended Values:\n" + m.dump_as_string () + "\n");
+			var o = new Record ();
+			o.connection = this.connection;
+			o.set_id (id);
+			o.name = name;
+			o.functions = functions;
+			stdout.printf ("name = " + o.name + "\nfunctions = " + o.functions);
+			o.save ();
+		}
 			
 		public static int main (string[] args) {
 			stdout.printf ("Gda.DataObject Example...\n");
@@ -182,6 +176,12 @@ namespace Sample {
 				}
 				catch (Error e) { stdout.printf ("Can't update record\nERROR: " + e.message + "\n"); }
 				
+				try {
+					/* Append a new object with the same */
+					app.append_objects ("Jack MacJason", "Maintener");
+				}
+				catch (Error e) { stdout.printf ("Can't append record\nERROR: " + e.message + "\n"); }
+				
 				return 0;
 			}
 			catch (Error e) 
diff --git a/tests/vala/CheckDataModelIterator.vala b/tests/vala/CheckDataModelIterator.vala
index 9155afe..d5651d9 100644
--- a/tests/vala/CheckDataModelIterator.vala
+++ b/tests/vala/CheckDataModelIterator.vala
@@ -202,7 +202,12 @@ namespace Check {
 							+ ">>> Testing Collection Interface\n");
 			int fails = 0;
 			var model = this.connection.execute_select_command ("SELECT * FROM user");
-			var itermodel = new DataModelIterable (model);
+			((DataSelect) model).compute_modification_statements ();
+			var pxy = (Gda.DataModel) Gda.DataProxy.new (model);
+			
+			var itermodel = new DataModelIterable (pxy);
+			if ( !itermodel.add (1))
+				fails++;
 			
 			return fails;
 		}
diff --git a/tests/vala/CheckDataObject.vala b/tests/vala/CheckDataObject.vala
index d58e3e1..feca886 100644
--- a/tests/vala/CheckDataObject.vala
+++ b/tests/vala/CheckDataObject.vala
@@ -21,11 +21,18 @@ using Gda;
 using GdaData;
 
 namespace Check {
-	class Tests : GdaData.Object {
+	class Tests : GdaData.ObjectSingleId<int> {
 		private static string t = "user";
 		public override string table { 
 			get { return this.t; }
 		}
+		public override string field_id {
+			get { return "id";}
+		}
+		public override int field_id_index {
+			get { return 0;}
+		}
+		
 		Tests()
 		{
 			try {
@@ -33,7 +40,7 @@ namespace Check {
 				stdout.printf("Creating Database...\n");
 				this.connection = Connection.open_from_string("SQLite", "DB_DIR=.;DB_NAME=dataobject", null, Gda.ConnectionOptions.NONE);
 				stdout.printf("Creating table 'user'...\n");
-				this.connection.execute_non_select_command("CREATE TABLE user (id int PRIMARY KEY, name string, city string)");
+				this.connection.execute_non_select_command("CREATE TABLE user (id int PRIMARY KEY AUTOINCREMENT, name string, city string)");
 				this.connection.execute_non_select_command("INSERT INTO user (id, name, city) VALUES (1, \"Daniel\", \"Mexico\")");
 				this.connection.execute_non_select_command("INSERT INTO user (id, name, city) VALUES (2, \"Jhon\", \"USA\")");
 				
@@ -53,15 +60,9 @@ namespace Check {
 		{
 			stdout.printf(">>> NEW TEST: Gda.DataObject API tests\n");
 			int fails = 0;
-			Value v = 1;
-			stdout.printf("Setting ID to %i\n", (int) v);
+			stdout.printf("Setting ID to 1\n");
 			try {
-				this.set_id ("id", v);
-				var f = this.get_field_id();
-				if ( f != "id") {
-					fails++;
-					stdout.printf("FAILS: %i\n", fails);
-				}
+				this.set_id (1);
 			}
 			catch (Error e) {
 				fails++;
@@ -72,7 +73,7 @@ namespace Check {
 			stdout.printf("%s\n", this.record.dump_as_string());
 			
 			stdout.printf("Getting ID value...\n");
-			var i = (int) this.get_value_id();
+			var i = (int) this.get_id ();
 			if (i != 1 ){
 				fails++;
 				stdout.printf("FAILS: %i\n", fails);
@@ -139,10 +140,9 @@ namespace Check {
 				stdout.printf ("Couln't UPDATE...\nFAILS: %i\nERROR: %s\n", fails, e.message);
 			}
 			
-			v = 2;
-			stdout.printf("Setting ID to %i\n", (int) v);
+			stdout.printf("Setting ID to 2\n");
 			try {
-				this.set_id ("id", v);
+				this.set_id (2);
 				stdout.printf("DataObject points to actual stored values, in table '%s':\n", this.table);
 				stdout.printf("%s\n", this.record.dump_as_string());
 			}
@@ -150,7 +150,31 @@ namespace Check {
 				fails++;
 				stdout.printf ("Couln't set ID...\nFAILS: %i\nERROR: %s\n", fails, e.message);
 			}
-			
+			this.t = "user"; // Reset to default
+			return fails;
+		}
+		
+		public int t2()
+			throws Error
+		{
+			stdout.printf(">>> NEW TEST: Gda.DataObject Adding new objects to DB\n");
+			int fails = 0;
+			try {
+				Value id;
+				this.append (out id);
+				var n = new Tests ();
+				n.set_value ("id", 3);
+				n.set_value ("name", "GdaDataNewName");
+				n.set_value ("city", "GdaDataNewCity");
+				n.save ();
+				var m = n.connection.execute_select_command ("SELECT * FROM user");
+				if (m.get_n_rows () != 3) fails++;
+				stdout.printf ("All records:\n" + m.dump_as_string () + "\n");
+			}
+			catch (Error e) {
+				fails++;
+				stdout.printf ("Couln't set ID...\nFAILS: %i\nERROR: %s\n", fails, e.message);
+			}
 			return fails;
 		}
 		
@@ -158,7 +182,11 @@ namespace Check {
 			stdout.printf ("Checking Gda.DataObject implementation...\n");
 			int failures = 0;
 			var app = new Tests ();
-			failures += app.t1 ();
+			try {
+				failures += app.t1 ();
+				failures += app.t2 ();
+			}
+			catch (Error e) { stdout.printf ("ERROR: " + e.message); }
 			return failures != 0 ? 1 : 0;
 		}
 	}
diff --git a/tests/vala/Makefile.am b/tests/vala/Makefile.am
index 0f7f735..4cbfdc9 100644
--- a/tests/vala/Makefile.am
+++ b/tests/vala/Makefile.am
@@ -53,7 +53,7 @@ check_datamodeliterator.vala.stamp: $(check_datamodeliterator_VALASOURCES)
 
 check_dataobject_SOURCES = $(check_dataobject_VALASOURCES:.vala=.c) check_dataobject.h
 check_dataobject_CFLAGS= \
-    -I$(top_builddir)/libgda/data \
+    -I$(top_builddir) \
     $(NULL)
 check_dataobject_LDADD = \
     $(top_builddir)/libgda/libgda-5.0.la \
@@ -62,7 +62,7 @@ check_dataobject_LDADD = \
 
 check_datamodeliterator_SOURCES = $(check_datamodeliterator_VALASOURCES:.vala=.c) check_datamodeliterator.h
 check_datamodeliterator_CFLAGS= \
-    -I$(top_builddir)/libgda/data \
+    -I$(top_builddir) \
     $(NULL)
 check_datamodeliterator_LDADD = \
     $(top_builddir)/libgda/libgda-5.0.la \



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